From e6c9e0725c321b5de6f26a93713c7967ef7ede49 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sun, 18 Feb 2024 23:28:29 -0500 Subject: [PATCH] scripting: remove ReflectedLuaTableProxy and slightly modify ReflectLuaProxy to replace it --- lyra-scripting/elua | 2 +- lyra-scripting/src/lua/dynamic_iter.rs | 17 ++--- lyra-scripting/src/lua/mod.rs | 20 ++--- lyra-scripting/src/lua/providers/ecs.rs | 6 +- lyra-scripting/src/lua/providers/math.rs | 8 +- lyra-scripting/src/lua/providers/util.rs | 4 +- lyra-scripting/src/lua/proxy.rs | 97 +++++++++++------------- lyra-scripting/src/lua/script.rs | 3 +- lyra-scripting/src/lua/world.rs | 83 +++++++++----------- 9 files changed, 105 insertions(+), 135 deletions(-) diff --git a/lyra-scripting/elua b/lyra-scripting/elua index 2fe5dca..9b542fb 160000 --- a/lyra-scripting/elua +++ b/lyra-scripting/elua @@ -1 +1 @@ -Subproject commit 2fe5dca6c4337f1528e4671d1f79464481739c61 +Subproject commit 9b542fb523a3dc5d2eb77b246136111ad8bc4dd2 diff --git a/lyra-scripting/src/lua/dynamic_iter.rs b/lyra-scripting/src/lua/dynamic_iter.rs index 7b8f250..c504470 100644 --- a/lyra-scripting/src/lua/dynamic_iter.rs +++ b/lyra-scripting/src/lua/dynamic_iter.rs @@ -156,9 +156,6 @@ impl ReflectedIterator { pub fn next_lua<'a>(&mut self, lua: &'a elua::State) -> Option> { use elua::AsLua; - use super::ReflectedLuaTableProxy; - - let n = self.dyn_view.next(); if let Some(row) = n { @@ -176,15 +173,11 @@ impl ReflectedIterator { let reg_type = reflected_components.get_type(id) .expect("Requested type was not found in TypeRegistry"); - let value = if let Some(proxy) = reg_type.get_data::() { - (proxy.fn_as_uservalue)(lua, d.ptr).unwrap() - .as_lua(lua).unwrap() - } else if let Some(proxy) = reg_type.get_data::() { - (proxy.fn_as_table)(lua, d.ptr.cast()).unwrap() - .as_lua(lua).unwrap() - } else { - panic!("Type does not have ReflectLuaProxy or ReflectedLuaTableProxy as a TypeData"); - }; + let proxy = reg_type.get_data::() + // TODO: properly handle this error + .expect("Type does not have ReflectLuaProxy as a TypeData"); + let value = (proxy.fn_as_lua)(lua, d.ptr.cast()).unwrap() + .as_lua(lua).unwrap(); dynamic_row.push(ReflectedItem { comp_ptr: d.ptr, diff --git a/lyra-scripting/src/lua/mod.rs b/lyra-scripting/src/lua/mod.rs index cf11dc6..5ef88a8 100644 --- a/lyra-scripting/src/lua/mod.rs +++ b/lyra-scripting/src/lua/mod.rs @@ -23,16 +23,16 @@ pub use system::*; use std::{any::TypeId, sync::Mutex}; use lyra_ecs::{ - Component, ComponentInfo, DynamicBundle, World + Component, ComponentInfo, World }; -use lyra_reflect::{FromType, Reflect, TypeRegistry}; +use lyra_reflect::{Reflect, TypeRegistry}; pub type LuaContext = Mutex; pub const FN_NAME_INTERNAL_REFLECT_TYPE: &str = "__lyra_internal_reflect_type"; pub const FN_NAME_INTERNAL_REFLECT: &str = "__lyra_internal_reflect"; -use crate::{ScriptBorrow, ScriptDynamicBundle}; +use crate::ScriptBorrow; /// A trait used for registering a Lua type with the world. pub trait RegisterLuaType { @@ -64,8 +64,7 @@ impl RegisterLuaType for World { let type_id = TypeId::of::(); let reg_type = registry.get_type_or_default(type_id); - reg_type.add_data(>::from_type()); - //reg_type.add_data(>::from_type()); + reg_type.add_data(ReflectLuaProxy::from_lua_proxy::()); } fn register_lua_wrapper<'a, W>(&mut self) @@ -75,7 +74,7 @@ impl RegisterLuaType for World { let mut registry = self.get_resource_mut::(); let reg_type = registry.get_type_or_default(W::wrapped_type_id()); - reg_type.add_data(>::from_type()); + reg_type.add_data(ReflectLuaProxy::from_lua_proxy::()); } fn register_lua_table_proxy<'a, T, C>(&mut self) @@ -85,15 +84,16 @@ impl RegisterLuaType for World { { let mut registry = self.get_resource_mut::(); - let type_id = TypeId::of::(); let reg_type = registry.get_type_or_default(TypeId::of::()); - reg_type.add_data(>::from_type()); + 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); lookup.typeid_from_name.insert(T::table_name(), TypeId::of::()); - let mut info = ComponentInfo::new::(); + let info = ComponentInfo::new::(); lookup.comp_info_from_name.insert(T::table_name(), info); } } @@ -122,7 +122,7 @@ impl elua::Userdata for ScriptBorrow { "ScriptBorrow".to_string() } - fn build<'a>(state: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> { + fn build<'a>(_: &elua::State, _: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> { Ok(()) } } diff --git a/lyra-scripting/src/lua/providers/ecs.rs b/lyra-scripting/src/lua/providers/ecs.rs index 7b0a0be..43c26a8 100644 --- a/lyra-scripting/src/lua/providers/ecs.rs +++ b/lyra-scripting/src/lua/providers/ecs.rs @@ -10,7 +10,7 @@ impl ScriptApiProvider for LyraEcsApiProvider { world.register_lua_wrapper::(); } - fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn expose_api(&mut self, _: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { let ctx = ctx.lock().unwrap(); let globals = ctx.globals()?; @@ -22,11 +22,11 @@ impl ScriptApiProvider for LyraEcsApiProvider { Ok(()) } - fn setup_script(&mut self, data: &crate::ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn setup_script(&mut self, _: &crate::ScriptData, _: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { Ok(()) } - fn update_script_environment(&mut self, world: crate::ScriptWorldPtr, data: &crate::ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn update_script_environment(&mut self, _: crate::ScriptWorldPtr, _: &crate::ScriptData, _: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { Ok(()) } } \ No newline at end of file diff --git a/lyra-scripting/src/lua/providers/math.rs b/lyra-scripting/src/lua/providers/math.rs index c8118c9..ac767ee 100644 --- a/lyra-scripting/src/lua/providers/math.rs +++ b/lyra-scripting/src/lua/providers/math.rs @@ -1,6 +1,6 @@ -use elua::{TableProxy, Userdata}; +use elua::TableProxy; use lyra_ecs::World; -use lyra_game::math::{self, Quat, Transform, Vec3}; +use lyra_game::math::{Quat, Transform, Vec3}; use crate::ScriptData; use crate::lua::RegisterLuaType; @@ -42,11 +42,11 @@ impl ScriptApiProvider for LyraMathApiProvider { Ok(()) } - fn setup_script(&mut self, data: &crate::ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn setup_script(&mut self, _: &crate::ScriptData, _: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { Ok(()) } - fn update_script_environment(&mut self, world: crate::ScriptWorldPtr, data: &crate::ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { + fn update_script_environment(&mut self, _: crate::ScriptWorldPtr, _: &crate::ScriptData, _: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { Ok(()) } } diff --git a/lyra-scripting/src/lua/providers/util.rs b/lyra-scripting/src/lua/providers/util.rs index 905f123..2ef6bc9 100644 --- a/lyra-scripting/src/lua/providers/util.rs +++ b/lyra-scripting/src/lua/providers/util.rs @@ -1,6 +1,6 @@ use std::sync::{Mutex, Arc}; -use tracing::{debug_span, debug, span, Level}; +use tracing::{debug_span, debug}; use crate::{ScriptApiProvider, ScriptData}; @@ -51,7 +51,7 @@ impl ScriptApiProvider for UtilityApiProvider { } }, elua::Value::None => "None".to_string(), - elua::Value::Multi(v) => { + elua::Value::Multi(_) => { return Err(elua::Error::runtime("unable to get string representation of ValueVec")); }, }, diff --git a/lyra-scripting/src/lua/proxy.rs b/lyra-scripting/src/lua/proxy.rs index 5980814..d60efba 100644 --- a/lyra-scripting/src/lua/proxy.rs +++ b/lyra-scripting/src/lua/proxy.rs @@ -1,8 +1,8 @@ use std::{any::TypeId, collections::HashMap, ptr::NonNull}; -use elua::{FromLua, TableProxy}; +use elua::{FromLua, TableProxy, AsLua}; use lyra_ecs::{ComponentInfo, DynamicBundle}; -use lyra_reflect::{Reflect, FromType}; +use lyra_reflect::Reflect; use crate::{ScriptBorrow, ScriptDynamicBundle}; @@ -18,12 +18,12 @@ pub trait LuaProxy { fn as_lua_value<'lua>( lua: &'lua elua::State, this: &dyn Reflect, - ) -> elua::Result>; + ) -> elua::Result>; fn apply( lua: &elua::State, this: &mut dyn Reflect, - apply: &elua::AnyUserdata, + value: &elua::Value, ) -> elua::Result<()>; } @@ -34,18 +34,21 @@ where fn as_lua_value<'lua>( lua: &'lua elua::State, this: &dyn Reflect, - ) -> elua::Result> { + ) -> elua::Result> { let this = this.as_any().downcast_ref::().unwrap(); lua.create_userdata(this.clone()) + .and_then(|ud| ud.as_lua(lua)) } fn apply( _: &elua::State, this: &mut dyn Reflect, - apply: &elua::AnyUserdata, + apply: &elua::Value, ) -> elua::Result<()> { let this = this.as_any_mut().downcast_mut::().unwrap(); - let apply = apply.as_ref::()?; + let apply = apply.as_userdata() + .expect("Somehow a non-userdata Lua Value was provided to a LuaProxy") + .as_ref::()?; *this = apply.clone(); @@ -60,59 +63,26 @@ pub struct LuaTableProxyLookup { pub(crate) comp_info_from_name: HashMap, } -/// A struct used for converting types that implement `TableProxy` to and from Lua. +/// A struct used for Proxying types to and from Lua. #[derive(Clone)] -pub struct ReflectedLuaTableProxy { - pub table_name: String, - pub fn_as_table: - for<'a> fn(lua: &'a elua::State, this_ptr: NonNull<()>) -> elua::Result>, +pub struct ReflectLuaProxy { + pub fn_as_lua: + for<'a> fn(lua: &'a elua::State, this_ptr: NonNull<()>) -> elua::Result>, pub fn_apply: for<'a> fn( lua: &'a elua::State, this_ptr: NonNull<()>, - table: &'a elua::Table<'a>, + value: &'a elua::Value<'a>, ) -> elua::Result<()>, } -impl<'a, T> FromType for ReflectedLuaTableProxy -where - T: TableProxy -{ - fn from_type() -> Self { +impl ReflectLuaProxy { + /// Create from a type that implements LuaProxy (among some other required traits) + pub fn from_lua_proxy<'a, T>() -> Self + where + T: Reflect + LuaProxy + { Self { - table_name: T::table_name(), - fn_as_table: |lua, this| -> elua::Result { - let this = unsafe { this.cast::().as_ref() }; - this.as_table(lua) - }, - fn_apply: |lua, ptr, table| { - let this = unsafe { ptr.cast::().as_mut() }; - let tbl = T::from_table(lua, table.clone())?; - *this = tbl; - Ok(()) - }, - } - } -} - -/// A struct used for converting types that implement `LuaProxy` to and from Lua. -#[derive(Clone)] -pub struct ReflectLuaProxy { - pub fn_as_uservalue: - for<'a> fn(lua: &'a elua::State, this_ptr: NonNull) -> elua::Result>, - pub fn_apply: for<'a> fn( - lua: &'a elua::State, - this_ptr: NonNull, - apply: &'a elua::AnyUserdata<'a>, - ) -> elua::Result<()>, -} - -impl<'a, T> FromType for ReflectLuaProxy -where - T: Reflect + LuaProxy + Clone + elua::FromLua<'a> + elua::Userdata -{ - fn from_type() -> Self { - Self { - fn_as_uservalue: |lua, this| -> elua::Result { + fn_as_lua: |lua, this| -> elua::Result { let this = unsafe { this.cast::().as_ref() }; ::as_lua_value(lua, this) }, @@ -122,6 +92,29 @@ where }, } } + + pub fn from_table_proxy() -> Self + where + T: TableProxy + { + Self { + fn_as_lua: |lua, this| -> elua::Result { + let this = unsafe { this.cast::().as_ref() }; + this.as_table(lua) + .and_then(|t| t.as_lua(lua)) + }, + fn_apply: |lua, ptr, value| { + let this = unsafe { ptr.cast::().as_mut() }; + let table = value.as_table() + .expect("Somehow a non-Table Lua Value was provided to a TableProxy"); + let new_val = T::from_table(lua, table.clone())?; + + *this = new_val; + + Ok(()) + }, + } + } } impl<'lua> elua::FromLua<'lua> for ScriptDynamicBundle { diff --git a/lyra-scripting/src/lua/script.rs b/lyra-scripting/src/lua/script.rs index b0d1cc6..3dccd70 100644 --- a/lyra-scripting/src/lua/script.rs +++ b/lyra-scripting/src/lua/script.rs @@ -1,7 +1,6 @@ use std::sync::Mutex; -use elua::{AsLua, StdLibraries, StdLibrary}; -use tracing::{debug, trace}; +use elua::{AsLua, StdLibrary}; use crate::{ScriptHost, ScriptError, ScriptWorldPtr, ScriptEntity}; diff --git a/lyra-scripting/src/lua/world.rs b/lyra-scripting/src/lua/world.rs index dff4f95..0f874a8 100644 --- a/lyra-scripting/src/lua/world.rs +++ b/lyra-scripting/src/lua/world.rs @@ -1,11 +1,11 @@ -use std::{any::Any, ptr::NonNull, sync::Arc}; +use std::{ptr::NonNull, sync::Arc}; use elua::AsLua; use lyra_ecs::query::dynamic::QueryDynamicType; use lyra_reflect::{TypeRegistry, ReflectWorldExt, RegisteredType}; use crate::{ScriptWorldPtr, ScriptEntity, ScriptDynamicBundle, ScriptBorrow}; -use super::{reflect_user_data, DynamicViewIter, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, ReflectedLuaTableProxy, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}; +use super::{reflect_user_data, DynamicViewIter, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_REFLECT_TYPE}; impl<'lua> elua::FromLua<'lua> for ScriptEntity { fn from_lua(_: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result { @@ -22,7 +22,7 @@ impl elua::Userdata for ScriptEntity { "Entity".to_string() } - fn build<'a>(state: &elua::State, builder: &mut elua::userdata::UserdataBuilder<'a, Self>) -> elua::Result<()> { + fn build<'a>(_: &elua::State, builder: &mut elua::userdata::UserdataBuilder<'a, Self>) -> elua::Result<()> { builder.meta_method(elua::MetaMethod::ToString, |_, this, ()| { Ok(format!("{:?}", this.0)) }); @@ -38,7 +38,7 @@ pub enum WorldError { } impl<'a> elua::FromLua<'a> for ScriptWorldPtr { - fn from_lua(lua: &'a elua::State, val: elua::Value<'a>) -> elua::Result { + fn from_lua(_: &'a elua::State, val: elua::Value<'a>) -> elua::Result { match val { elua::Value::Userdata(ud) => Ok(ud.as_ref::()?.clone()), elua::Value::Nil => Err(elua::Error::type_mismatch("ScriptWorldPtr", "Nil")), @@ -52,7 +52,7 @@ impl elua::Userdata for ScriptWorldPtr { "World".to_string() } - fn build<'a>(state: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> { + fn build<'a>(_: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> { builder .method_mut("spawn", |_, this, bundle: ScriptDynamicBundle| { let world = this.as_mut(); @@ -73,7 +73,7 @@ impl elua::Userdata for ScriptWorldPtr { for (idx, comp) in queries.into_iter().enumerate() { match comp { elua::Value::Table(t) => { - let name: String = t.get("__name")?; + let name: String = t.get(elua::MetaMethod::Name)?; let lookup = world.get_resource::(); let info = lookup.comp_info_from_name.get(&name) @@ -115,9 +115,9 @@ impl elua::Userdata for ScriptWorldPtr { while let Some(row) = reflected_iter.next_lua(lua) { let r = row.row.into_iter() - .map(|r| (r.comp_val, r.comp_ptr)) + .map(|r| (r.comp_val, r.comp_ptr.cast::<()>())) .collect::>(); - let (values, ptrs) = itertools::multiunzip::<(Vec, Vec>), _>(r); + let (values, ptrs) = itertools::multiunzip::<(Vec, Vec>), _>(r); let mult_val = elua::ValueVec::from(values); let res: elua::ValueVec = system.exec(mult_val)?; @@ -129,55 +129,40 @@ impl elua::Userdata for ScriptWorldPtr { has_ticked = true; } - for (i, comp) in res.into_iter().enumerate() { - let ptr = ptrs[i]; - - match comp { + for (comp, ptr) in res.into_iter().zip(ptrs) { + let lua_typeid = match &comp { elua::Value::Userdata(ud) => { - let lua_comp = reflect_user_data(&ud); + let lua_comp = reflect_user_data(ud); let refl_comp = lua_comp.reflect_branch.as_component_unchecked(); - let lua_typeid = refl_comp.info.type_id.as_rust(); - - // update the component tick - let world = unsafe { this.inner.as_mut() }; - let arch = world.entity_archetype_mut(row.entity).unwrap(); - let idx = arch.entities().get(&row.entity).unwrap().clone(); - let c = arch.get_column_mut(refl_comp.type_id.into()).unwrap(); - c.entity_ticks[idx.0 as usize] = current; - - // apply the new component data - let reg = this.as_ref().get_resource::(); - let reg_type = reg.get_type(lua_typeid).unwrap(); - - let proxy = reg_type.get_data::() - .expect("Type does not have ReflectLuaProxy as a TypeData"); - (proxy.fn_apply)(lua, ptr, &ud)?; + refl_comp.info.type_id.as_rust() }, elua::Value::Table(tbl) => { - let name: String = tbl.get("__name")?; + let name: String = tbl.get(elua::MetaMethod::Name)?; let lookup = world.get_resource::(); - let tyid = lookup.typeid_from_name.get(&name).unwrap(); - - // update the component tick - let world = unsafe { this.inner.as_mut() }; - let arch = world.entity_archetype_mut(row.entity).unwrap(); - let idx = arch.entities().get(&row.entity).unwrap().clone(); - let c = arch.get_column_mut(tyid.clone().into()).unwrap(); - c.entity_ticks[idx.0 as usize] = current; - - // apply the new component data - let reg = this.as_ref().get_resource::(); - let reg_type = reg.get_type(*tyid).unwrap(); - - let proxy = reg_type.get_data::() - .expect("Type does not have ReflectLuaProxy as a TypeData"); - (proxy.fn_apply)(lua, ptr.cast(), &tbl)?; + *lookup.typeid_from_name.get(&name).unwrap() }, _ => { - panic!("A userdata or table value was not returned!"); + panic!("A userdata or table value was not returned!"); // TODO: Handle properly } - } + }; + + // update the component tick + let world = unsafe { this.inner.as_mut() }; + let arch = world.entity_archetype_mut(row.entity).unwrap(); + let idx = arch.entities().get(&row.entity).unwrap().clone(); + let c = arch.get_column_mut(lua_typeid.into()).unwrap(); + c.entity_ticks[idx.0 as usize] = current; + + // apply the new component data + let reg = this.as_ref().get_resource::(); + let reg_type = reg.get_type(lua_typeid).unwrap(); + + let proxy = reg_type.get_data::() + // this should actually be safe since the ReflectedIterator + // attempts to get the type data before it is tried here + .expect("Type does not have ReflectLuaProxy as a TypeData"); + (proxy.fn_apply)(lua, ptr, &comp)?; } } else { let msg = format!("Too many arguments were returned from the World view! @@ -200,7 +185,7 @@ impl elua::Userdata for ScriptWorldPtr { let proxy = reg_type.get_data::() .expect("Type does not have ReflectLuaProxy as a TypeData"); - (proxy.fn_as_uservalue)(lua, res_ptr) + (proxy.fn_as_lua)(lua, res_ptr.cast()) .and_then(|ud| ud.as_lua(lua)) } else { // if the resource is not found in the world, return nil