diff --git a/examples/testbed/scripts/test.lua b/examples/testbed/scripts/test.lua index 5751366..4c0bec0 100644 --- a/examples/testbed/scripts/test.lua +++ b/examples/testbed/scripts/test.lua @@ -26,13 +26,14 @@ function on_update() Transform ) ]] + ---@type number local dt = world:resource(DeltaTime) --print("DeltaTime was " .. tostring(dt) .. "s") world:view(function (t) --print("Found entity at a really cool place: " .. tostring(t)) --t.translation = t.translation + (Vec3.new(0, 0.5, 0) * dt:get()) - t.translation:move_by(0, 0.5 * dt:get(), 0) + t.translation:move_by(0, 0.5 * dt, 0) return t end, Transform) diff --git a/lyra-scripting/src/lua/mod.rs b/lyra-scripting/src/lua/mod.rs index 5ef88a8..ed8e36e 100644 --- a/lyra-scripting/src/lua/mod.rs +++ b/lyra-scripting/src/lua/mod.rs @@ -47,6 +47,11 @@ pub trait RegisterLuaType { where W: Reflect + LuaProxy + LuaWrapper + Clone + elua::FromLua<'a> + elua::Userdata; + /// Registers a type to Lua that can be converted into and from Lua types. + fn register_lua_convert(&mut self) + where + T: Clone + for<'a> elua::FromLua<'a> + for<'a> elua::AsLua<'a> + LuaWrapper + 'static; + /// Registers a type to Lua that implements [`elua::TableProxy`] fn register_lua_table_proxy<'a, T, W>(&mut self) where @@ -77,6 +82,16 @@ impl RegisterLuaType for World { reg_type.add_data(ReflectLuaProxy::from_lua_proxy::()); } + fn register_lua_convert(&mut self) + where + T: Clone + for<'a> elua::FromLua<'a> + for<'a> elua::AsLua<'a> + LuaWrapper + 'static, + { + let mut registry = self.get_resource_mut::(); + + let reg_type = registry.get_type_or_default(T::wrapped_type_id()); + reg_type.add_data(ReflectLuaProxy::from_as_and_from_lua::()); + } + fn register_lua_table_proxy<'a, T, C>(&mut self) where T: elua::TableProxy + 'static, @@ -86,8 +101,6 @@ impl RegisterLuaType for World { let reg_type = registry.get_type_or_default(TypeId::of::()); reg_type.add_data(ReflectLuaProxy::from_table_proxy::()); - /* let reg_type = registry.get_type_or_default(TypeId::of::()); - reg_type.add_data(>::from_type()); */ drop(registry); let mut lookup = self.get_resource_or_else::(LuaTableProxyLookup::default); diff --git a/lyra-scripting/src/lua/providers/ecs.rs b/lyra-scripting/src/lua/providers/ecs.rs index 43c26a8..7b3cb2b 100644 --- a/lyra-scripting/src/lua/providers/ecs.rs +++ b/lyra-scripting/src/lua/providers/ecs.rs @@ -1,4 +1,7 @@ -use crate::{lua::{LuaContext, wrappers::LuaDeltaTime, RegisterLuaType}, ScriptApiProvider, ScriptWorldPtr, ScriptDynamicBundle, ScriptData}; +use lyra_ecs::ResourceObject; +use lyra_reflect::Reflect; + +use crate::{lua::{wrappers::LuaDeltaTime, LuaContext, RegisterLuaType, FN_NAME_INTERNAL_REFLECT_TYPE}, ScriptApiProvider, ScriptBorrow, ScriptData, ScriptDynamicBundle, ScriptWorldPtr}; #[derive(Default)] pub struct LyraEcsApiProvider; @@ -7,7 +10,7 @@ impl ScriptApiProvider for LyraEcsApiProvider { type ScriptContext = LuaContext; fn prepare_world(&mut self, world: &mut lyra_ecs::World) { - world.register_lua_wrapper::(); + world.register_lua_convert::(); } fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { @@ -17,7 +20,8 @@ impl ScriptApiProvider for LyraEcsApiProvider { globals.set("World", ctx.create_proxy::()?)?; globals.set("DynamicBundle", ctx.create_proxy::()?)?; - globals.set("DeltaTime", ctx.create_proxy::()?)?; + let dt_table = create_reflect_table::(&ctx)?; + globals.set("DeltaTime", dt_table)?; Ok(()) } @@ -29,4 +33,13 @@ impl ScriptApiProvider for LyraEcsApiProvider { fn update_script_environment(&mut self, _: crate::ScriptWorldPtr, _: &crate::ScriptData, _: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { Ok(()) } +} + +fn create_reflect_table(lua: &elua::State) -> elua::Result { + let table = lua.create_table()?; + table.set(FN_NAME_INTERNAL_REFLECT_TYPE, lua.create_function(|_, ()| { + Ok(ScriptBorrow::from_resource::(None)) + })?)?; + + Ok(table) } \ No newline at end of file diff --git a/lyra-scripting/src/lua/proxy.rs b/lyra-scripting/src/lua/proxy.rs index d60efba..8372cb5 100644 --- a/lyra-scripting/src/lua/proxy.rs +++ b/lyra-scripting/src/lua/proxy.rs @@ -115,6 +115,27 @@ impl ReflectLuaProxy { }, } } + + /// Create from a type that implements FromLua and AsLua + pub fn from_as_and_from_lua() -> Self + where + T: for<'a> elua::FromLua<'a> + for<'a> elua::AsLua<'a> + Clone + { + Self { + fn_as_lua: |lua, this| -> elua::Result { + let this = unsafe { this.cast::().as_ref() }; + this.clone().as_lua(lua) + }, + fn_apply: |lua, ptr, value| { + let this = unsafe { ptr.cast::().as_mut() }; + let new_val = T::from_lua(lua, value.clone())?; + + *this = new_val; + + Ok(()) + }, + } + } } impl<'lua> elua::FromLua<'lua> for ScriptDynamicBundle { diff --git a/lyra-scripting/src/lua/world.rs b/lyra-scripting/src/lua/world.rs index 0f874a8..8f0778f 100644 --- a/lyra-scripting/src/lua/world.rs +++ b/lyra-scripting/src/lua/world.rs @@ -173,10 +173,24 @@ impl elua::Userdata for ScriptWorldPtr { Ok(()) }) - .method_mut("resource", |lua, this, (ty,): (elua::AnyUserdata,)| { - let reflect = ty + .method_mut("resource", |lua, this, (ty,): (elua::Value,)| { + let reflect = match ty { + elua::Value::Userdata(ud) => { + ud.execute_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ()) + .expect("Type does not implement 'reflect_type' properly") + } + elua::Value::Table(t) => { + let f: elua::Function = t.get(FN_NAME_INTERNAL_REFLECT_TYPE)?; + f.exec::<_, ScriptBorrow>(()) + .expect("Type does not implement 'reflect_type' properly") + } + _ => { + panic!("how"); + } + }; + /* let reflect = ty .execute_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ()) - .expect("Type does not implement 'reflect_type' properly"); + .expect("Type does not implement 'reflect_type' properly"); */ let res = reflect.reflect_branch.as_resource_unchecked(); if let Some(res_ptr) = res.reflect_ptr(this.as_mut()) { diff --git a/lyra-scripting/src/lua/wrappers/delta_time.rs b/lyra-scripting/src/lua/wrappers/delta_time.rs index c02ea4a..da6e850 100644 --- a/lyra-scripting/src/lua/wrappers/delta_time.rs +++ b/lyra-scripting/src/lua/wrappers/delta_time.rs @@ -1,10 +1,11 @@ + use std::any::TypeId; use lyra_game::DeltaTime; -use crate::{lyra_engine, lua::{FN_NAME_INTERNAL_REFLECT_TYPE, LuaWrapper}, ScriptBorrow}; +use crate::lua::LuaWrapper; -#[derive(Clone, lyra_reflect::Reflect, Default)] -pub struct LuaDeltaTime(#[reflect(skip)] pub(crate) DeltaTime); +#[derive(Clone, Default)] +pub struct LuaDeltaTime(pub(crate) DeltaTime); impl std::ops::Deref for LuaDeltaTime { type Target = DeltaTime; @@ -22,31 +23,13 @@ impl std::ops::DerefMut for LuaDeltaTime { impl<'lua> elua::FromLua<'lua> for LuaDeltaTime { fn from_lua(lua: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result { - match value { - elua::Value::Userdata(ud) => Ok(ud.as_ref::()?.clone()), - _ => unreachable!(), - } + todo!() } } -impl elua::Userdata for LuaDeltaTime { - fn name() -> String { - "DeltaTime".to_string() - } - - fn build<'a>(state: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> { - builder - .method("get", |_, this, ()| { - Ok(*this.0) - }) - .meta_method(elua::MetaMethod::ToString, |_, this, ()| { - Ok(format!("{}", *this.0)) - }) - .function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { - Ok(ScriptBorrow::from_resource::(None)) - }); - - Ok(()) +impl<'lua> elua::AsLua<'lua> for LuaDeltaTime { + fn as_lua(self, lua: &'lua elua::State) -> elua::Result> { + Ok(elua::Value::Number(*self.0 as f64)) } } @@ -54,4 +37,4 @@ impl LuaWrapper for LuaDeltaTime { fn wrapped_type_id() -> std::any::TypeId { TypeId::of::() } -} \ No newline at end of file +} \ No newline at end of file