engine: rewrite component metatable setup to lua
parent
9c2c2c1f3c
commit
1553bdce9b
|
@ -1,10 +1,4 @@
|
|||
sent = {}
|
||||
sent.newindex = function(t, k, v)
|
||||
return __sent_components_newindex(t, k, v)
|
||||
end
|
||||
sent.index = function(t, k)
|
||||
return __sent_components_index(t, k)
|
||||
end
|
||||
sent.register = function (cfg)
|
||||
if cfg.name == nil then
|
||||
error("sent.register: needs name")
|
||||
|
@ -32,11 +26,35 @@ sent.register = function (cfg)
|
|||
cls.__sent_class_id = sent_class_id
|
||||
cls.new = function(...)
|
||||
local arg = {...}
|
||||
local res = __sent_new(sent_class_id)
|
||||
if res.init ~= nil then
|
||||
res:init(unpack(arg))
|
||||
|
||||
-- Make object table, instantiate with runtime.
|
||||
local table = {}
|
||||
local sent_id = __sent_new(table, sent_class_id)
|
||||
table.__sent_id = sent_id
|
||||
|
||||
-- Configure components dispatcher.
|
||||
table.components = {}
|
||||
table.components.__sent_id = sent_id
|
||||
local components_meta = {}
|
||||
components_meta.__index = function(t, k)
|
||||
return __sent_components_index(t, k)
|
||||
end
|
||||
return res
|
||||
components_meta.__newindex = function(t, k, v)
|
||||
return __sent_components_newindex(t, k, v)
|
||||
end
|
||||
setmetatable(table.components, components_meta)
|
||||
|
||||
-- Make table deref via table to class.
|
||||
local metatable = {}
|
||||
metatable.__index = cls
|
||||
setmetatable(table, metatable)
|
||||
|
||||
-- Call initializer, if present.
|
||||
if table.init ~= nil then
|
||||
table:init(unpack(arg))
|
||||
end
|
||||
|
||||
return table
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -52,14 +52,12 @@ struct ScriptedEntity {
|
|||
internal_id: u64,
|
||||
status: ScriptedEntityStatus,
|
||||
table: mlua::RegistryKey,
|
||||
cls: mlua::RegistryKey,
|
||||
}
|
||||
|
||||
impl ScriptedEntity {
|
||||
fn new(
|
||||
class_name: String,
|
||||
table: mlua::RegistryKey,
|
||||
cls: mlua::RegistryKey,
|
||||
components: BTreeMap<String, Box<dyn ecs::Component>>,
|
||||
) -> Self {
|
||||
let internal_id = GLOBAL_SCRIPTED_ENTITY_ID.fetch_add(1, atomic::Ordering::SeqCst) + 1;
|
||||
|
@ -68,69 +66,8 @@ impl ScriptedEntity {
|
|||
internal_id,
|
||||
status: ScriptedEntityStatus::QueuedForCreation(components),
|
||||
table,
|
||||
cls,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_metatable(
|
||||
&self,
|
||||
lua: &mlua::Lua,
|
||||
world: &ecs::World,
|
||||
) -> mlua::Result<()>
|
||||
{
|
||||
// (meta)table tree for entity objects:
|
||||
//
|
||||
// table: { }
|
||||
// | metatable
|
||||
// V
|
||||
// metatable: { __index }
|
||||
// |
|
||||
// .-------------'
|
||||
// V
|
||||
// dispatch: { components.{...}, ... }
|
||||
// | metadata
|
||||
// V
|
||||
// metametatable: { __index }
|
||||
// |
|
||||
// .-----------------'
|
||||
// V
|
||||
// cls: { init, tick, ... }
|
||||
|
||||
let table: mlua::Table = lua.registry_value(&self.table)?;
|
||||
let cls: mlua::Table = lua.registry_value(&self.cls)?;
|
||||
|
||||
let meta = lua.create_table()?;
|
||||
let dispatch = lua.create_table()?;
|
||||
let metameta = lua.create_table()?;
|
||||
|
||||
table.set_metatable(Some(meta.clone()));
|
||||
meta.set("__index", dispatch.clone())?;
|
||||
dispatch.set_metatable(Some(metameta.clone()));
|
||||
metameta.set("__index", cls)?;
|
||||
|
||||
table.set("__sent_id", ScriptedEntityID {
|
||||
internal_id: self.internal_id,
|
||||
});
|
||||
|
||||
let components = lua.create_table()?;
|
||||
dispatch.set("components", components.clone())?;
|
||||
|
||||
let componentsmeta = lua.create_table()?;
|
||||
componentsmeta.set(
|
||||
"__index",
|
||||
lua.globals().get::<_, mlua::Table>("sent")?.get::<_, mlua::Function>("index")?,
|
||||
)?;
|
||||
componentsmeta.set(
|
||||
"__newindex",
|
||||
lua.globals().get::<_, mlua::Table>("sent")?.get::<_, mlua::Function>("newindex")?,
|
||||
)?;
|
||||
components.set_metatable(Some(componentsmeta));
|
||||
components.raw_set("__sent_id", ScriptedEntityID {
|
||||
internal_id: self.internal_id,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -465,32 +402,31 @@ impl WorldContext {
|
|||
{
|
||||
let classes = self.classes.clone();
|
||||
let instances = self.instances.clone();
|
||||
globals.set("__sent_new", scope.create_function(move |lua, args: mlua::AnyUserData| {
|
||||
globals.set("__sent_new", scope.create_function(move |lua, args: (mlua::Table, mlua::AnyUserData)| {
|
||||
let classes = classes.lock().unwrap();
|
||||
|
||||
let secid = args.borrow::<ScriptedEntityClassID>()?;
|
||||
let table = args.0;
|
||||
let secid = args.1.borrow::<ScriptedEntityClassID>()?;
|
||||
|
||||
let sec = match classes.get(&secid.name) {
|
||||
Some(el) => el,
|
||||
None => return Err(RuntimeError(format!("lost secid {:?}", secid.name))),
|
||||
};
|
||||
|
||||
let cls: mlua::Table = lua.registry_value(&sec.cls)?;
|
||||
let table = lua.create_table()?;
|
||||
|
||||
let components: BTreeMap<String, Box<dyn ecs::Component>> = sec.components.iter().map(|(k, v)| {
|
||||
(k.clone(), v.clone_dyn())
|
||||
}).collect();
|
||||
let sent = ScriptedEntity::new(
|
||||
secid.name.clone(),
|
||||
lua.create_registry_value(table.clone())?,
|
||||
lua.create_registry_value(cls.clone())?,
|
||||
components,
|
||||
);
|
||||
sent.set_metatable(lua, world)?;
|
||||
|
||||
let seid = ScriptedEntityID {
|
||||
internal_id: sent.internal_id,
|
||||
};
|
||||
instances.write().unwrap().queue.push(sent);
|
||||
|
||||
Ok(table)
|
||||
Ok(seid)
|
||||
})?)?;
|
||||
}
|
||||
|
||||
|
@ -556,7 +492,7 @@ where
|
|||
self.scope_resourcemanager(scope, world)?;
|
||||
self.scope_time(scope, world)?;
|
||||
// Copy out functions refs to release lock.
|
||||
let mut to_run: Vec<(ecs::EntityID, mlua::Function)> = vec![];
|
||||
let mut tickers: Vec<(ecs::EntityID, mlua::Function)> = vec![];
|
||||
{
|
||||
let instances = instances.read().unwrap();
|
||||
for (ecsid, sent) in instances.ecs.iter() {
|
||||
|
@ -581,10 +517,11 @@ where
|
|||
continue;
|
||||
},
|
||||
};
|
||||
to_run.push((*ecsid, cb));
|
||||
tickers.push((*ecsid, cb));
|
||||
}
|
||||
}
|
||||
for (ecsid, cb) in to_run.into_iter() {
|
||||
|
||||
for (ecsid, cb) in tickers.into_iter() {
|
||||
match cb.call::<mlua::Value, mlua::Value>(mlua::Value::Nil) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
|
|
Loading…
Reference in New Issue