From e88758f59d27b304f17a863ab1c99d2ad1efb892 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sat, 20 Jan 2024 00:54:36 -0500 Subject: [PATCH] scripting: expose resources to the world --- examples/testbed/scripts/test.lua | 5 +- lyra-ecs/src/resource.rs | 2 +- lyra-ecs/src/world.rs | 8 +- lyra-game/src/delta_time.rs | 5 +- lyra-game/src/lib.rs | 1 + lyra-reflect/src/component.rs | 70 ++ lyra-reflect/src/lib.rs | 101 ++- lyra-reflect/src/resource.rs | 50 ++ lyra-scripting/src/lib.rs | 50 +- lyra-scripting/src/lua/mod.rs | 123 +--- lyra-scripting/src/lua/providers/ecs.rs | 8 +- lyra-scripting/src/lua/proxy.rs | 92 +++ lyra-scripting/src/lua/world.rs | 25 +- lyra-scripting/src/lua/wrappers/delta_time.rs | 52 ++ lyra-scripting/src/lua/wrappers/math.rs | 605 ++++++++++++++++++ lyra-scripting/src/lua/wrappers/mod.rs | 569 +--------------- 16 files changed, 1030 insertions(+), 736 deletions(-) create mode 100644 lyra-reflect/src/component.rs create mode 100644 lyra-reflect/src/resource.rs create mode 100644 lyra-scripting/src/lua/proxy.rs create mode 100644 lyra-scripting/src/lua/wrappers/delta_time.rs create mode 100644 lyra-scripting/src/lua/wrappers/math.rs diff --git a/examples/testbed/scripts/test.lua b/examples/testbed/scripts/test.lua index ea5bdc6..ffc46c5 100644 --- a/examples/testbed/scripts/test.lua +++ b/examples/testbed/scripts/test.lua @@ -15,9 +15,12 @@ end ]] function on_update() --print("Lua's update function was called") + 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.0008, 0) + t.translation = t.translation + (Vec3.new(0, 0.5, 0) * dt:get()) return t end, Transform) diff --git a/lyra-ecs/src/resource.rs b/lyra-ecs/src/resource.rs index 019067b..ae48fc6 100644 --- a/lyra-ecs/src/resource.rs +++ b/lyra-ecs/src/resource.rs @@ -6,7 +6,7 @@ impl ResourceObject for T {} /// A type erased storage for a Resource. pub struct ResourceData { - data: Box>, + pub(crate) data: Box>, type_id: TypeId, } diff --git a/lyra-ecs/src/world.rs b/lyra-ecs/src/world.rs index f6a3274..cbc1695 100644 --- a/lyra-ecs/src/world.rs +++ b/lyra-ecs/src/world.rs @@ -1,6 +1,6 @@ use std::{collections::{HashMap, VecDeque}, any::TypeId, cell::{Ref, RefMut}, ptr::NonNull}; -use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, query::{Query, ViewIter, View, AsQuery}, resource::ResourceData, query::{dynamic::DynamicView, ViewOne}, ComponentInfo, DynTypeId, TickTracker, Tick}; +use crate::{archetype::{ArchetypeId, Archetype}, bundle::Bundle, query::{Query, ViewIter, View, AsQuery}, resource::ResourceData, query::{dynamic::DynamicView, ViewOne}, ComponentInfo, DynTypeId, TickTracker, Tick, ResourceObject}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct EntityId(pub u64); @@ -306,6 +306,12 @@ impl World { pub fn tick_tracker(&self) -> &TickTracker { &self.tracker } + + /// Attempts to find a resource in the world and returns a NonNull pointer to it + pub unsafe fn try_get_resource_ptr(&self) -> Option> { + self.resources.get(&TypeId::of::()) + .map(|d| unsafe { NonNull::new_unchecked(d.data.as_ptr() as *mut T) }) + } } #[cfg(test)] diff --git a/lyra-game/src/delta_time.rs b/lyra-game/src/delta_time.rs index 9dbbff7..f64735a 100644 --- a/lyra-game/src/delta_time.rs +++ b/lyra-game/src/delta_time.rs @@ -1,10 +1,11 @@ use instant::Instant; use lyra_ecs::{Component, world::World}; +use lyra_reflect::Reflect; use crate::{plugin::Plugin, game::GameStages}; -#[derive(Clone, Component)] -pub struct DeltaTime(f32, Option); +#[derive(Clone, Component, Default, Reflect)] +pub struct DeltaTime(f32, #[reflect(skip)] Option); impl std::ops::Deref for DeltaTime { type Target = f32; diff --git a/lyra-game/src/lib.rs b/lyra-game/src/lib.rs index 3c70bc4..85b2922 100644 --- a/lyra-game/src/lib.rs +++ b/lyra-game/src/lib.rs @@ -26,6 +26,7 @@ pub mod scene; pub use lyra_resource as assets; pub use lyra_ecs as ecs; pub use lyra_math as math; +pub use lyra_reflect as reflect; #[cfg(feature = "scripting")] pub use lyra_scripting as script; diff --git a/lyra-reflect/src/component.rs b/lyra-reflect/src/component.rs new file mode 100644 index 0000000..ca160a5 --- /dev/null +++ b/lyra-reflect/src/component.rs @@ -0,0 +1,70 @@ +use std::{any::TypeId, cell::{Ref, RefMut}}; + +use lyra_ecs::{Component, ComponentInfo, World, Entity, DynamicBundle}; + +use crate::{Reflect, FromType}; + +#[derive(Clone)] +pub struct ReflectedComponent { + pub type_id: TypeId, + pub info: ComponentInfo, + //value: Value, + //from_world: + + //from_world: for<'a> fn (world: &'a mut World) -> Box, + /// Inserts component into entity in the world + fn_insert: for<'a> fn (world: &'a mut World, entity: Entity, component: &dyn Reflect), + /// Inserts component into a bundle + fn_bundle_insert: for<'a> fn (dynamic_bundle: &'a mut DynamicBundle, component: &dyn Reflect), + fn_reflect: for<'a> fn (world: &'a World, entity: Entity) -> Option>, + fn_reflect_mut: for<'a> fn (world: &'a mut World, entity: Entity) -> Option>, +} + +impl ReflectedComponent { + /// Insert the reflected component into an entity. + pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { + (self.fn_insert)(world, entity, component); + } + + /// Insert this component into a DynamicBundle + pub fn bundle_insert(&self, dynamic_bundle: &mut DynamicBundle, component: &dyn Reflect) { + (self.fn_bundle_insert)(dynamic_bundle, component) + } + + /// Retrieves a reflected component from an entity. + pub fn reflect<'a>(&'a self, world: &'a World, entity: Entity) -> Option> { + (self.fn_reflect)(world, entity) + } + + /// Retrieves a reflected component from an entity. + pub fn reflect_mut<'a>(&'a mut self, world: &'a mut World, entity: Entity) -> Option> { + (self.fn_reflect_mut)(world, entity) + } +} + +impl FromType for ReflectedComponent { + fn from_type() -> Self { + ReflectedComponent { + type_id: TypeId::of::(), + info: ComponentInfo::new::(), + fn_insert: |world: &mut World, entity: Entity, component: &dyn Reflect| { + let mut c = C::default(); + c.apply(component); + world.insert(entity, (c,)); + }, + fn_bundle_insert: |bundle: &mut DynamicBundle, component: &dyn Reflect| { + let mut c = C::default(); + c.apply(component); + bundle.push(c); + }, + fn_reflect: |world: &World, entity: Entity| { + world.view_one::<&C>(entity) + .get().map(|c| c as Ref) + }, + fn_reflect_mut: |world: &mut World, entity: Entity| { + world.view_one::<&mut C>(entity) + .get().map(|c| c as RefMut) + }, + } + } +} \ No newline at end of file diff --git a/lyra-reflect/src/lib.rs b/lyra-reflect/src/lib.rs index 2b6bd24..0b8437f 100644 --- a/lyra-reflect/src/lib.rs +++ b/lyra-reflect/src/lib.rs @@ -36,6 +36,12 @@ pub use dynamic_tuple::*; pub mod reflected_field; pub use reflected_field::*; +pub mod component; +pub use component::*; + +pub mod resource; +pub use resource::*; + pub mod util; pub mod field; pub use field::*; @@ -237,67 +243,48 @@ pub trait FromType { fn from_type() -> Self; } -#[derive(Clone)] -pub struct ReflectedComponent { - pub type_id: TypeId, - pub info: ComponentInfo, - //value: Value, - //from_world: - - //from_world: for<'a> fn (world: &'a mut World) -> Box, - /// Inserts component into entity in the world - fn_insert: for<'a> fn (world: &'a mut World, entity: Entity, component: &dyn Reflect), - /// Inserts component into a bundle - fn_bundle_insert: for<'a> fn (dynamic_bundle: &'a mut DynamicBundle, component: &dyn Reflect), - fn_reflect: for<'a> fn (world: &'a World, entity: Entity) -> Option>, - fn_reflect_mut: for<'a> fn (world: &'a mut World, entity: Entity) -> Option>, +pub trait ReflectWorldExt { + /// Retrieves the type registry from the world. + fn get_type_registry(&self) -> Ref; + /// Retrieves the type registry mutably from the world. + fn get_type_registry_mut(&self) -> RefMut; + /// Get a registered type from the type registry. Returns `None` if the type is not registered + fn get_type(&self, type_id: TypeId) -> Option>; + /// Get a mutable registered type from the type registry in the world. returns `None` if the type is not registered. + fn get_type_mut(&self, type_id: TypeId) -> Option>; + /// Get a registered type, or register a new type and return it. + fn get_type_or_default(&self, type_id: TypeId) -> RefMut; } -impl ReflectedComponent { - /// Insert the reflected component into an entity. - pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { - (self.fn_insert)(world, entity, component); +impl ReflectWorldExt for World { + fn get_type_registry(&self) -> Ref { + self.get_resource::() } - - /// Insert this component into a DynamicBundle - pub fn bundle_insert(&self, dynamic_bundle: &mut DynamicBundle, component: &dyn Reflect) { - (self.fn_bundle_insert)(dynamic_bundle, component) + + fn get_type_registry_mut(&self) -> RefMut { + self.get_resource_mut::() } - - /// Retrieves a reflected component from an entity. - pub fn reflect<'a>(&'a self, world: &'a World, entity: Entity) -> Option> { - (self.fn_reflect)(world, entity) - } - - /// Retrieves a reflected component from an entity. - pub fn reflect_mut<'a>(&'a mut self, world: &'a mut World, entity: Entity) -> Option> { - (self.fn_reflect_mut)(world, entity) - } -} - -impl FromType for ReflectedComponent { - fn from_type() -> Self { - ReflectedComponent { - type_id: TypeId::of::(), - info: ComponentInfo::new::(), - fn_insert: |world: &mut World, entity: Entity, component: &dyn Reflect| { - let mut c = C::default(); - c.apply(component); - world.insert(entity, (c,)); - }, - fn_bundle_insert: |bundle: &mut DynamicBundle, component: &dyn Reflect| { - let mut c = C::default(); - c.apply(component); - bundle.push(c); - }, - fn_reflect: |world: &World, entity: Entity| { - world.view_one::<&C>(entity) - .get().map(|c| c as Ref) - }, - fn_reflect_mut: |world: &mut World, entity: Entity| { - world.view_one::<&mut C>(entity) - .get().map(|c| c as RefMut) - }, + + fn get_type(&self, type_id: TypeId) -> Option> { + let r = self.get_resource::(); + if r.has_type(type_id) { + Some(Ref::map(r, |tr| tr.get_type(type_id).unwrap())) + } else { + None } } + + fn get_type_mut(&self, type_id: TypeId) -> Option> { + let r = self.get_resource_mut::(); + if r.has_type(type_id) { + Some(RefMut::map(r, |tr| tr.get_type_mut(type_id).unwrap())) + } else { + None + } + } + + fn get_type_or_default(&self, type_id: TypeId) -> RefMut { + let r = self.get_resource_mut::(); + RefMut::map(r, |tr| tr.get_type_or_default(type_id)) + } } \ No newline at end of file diff --git a/lyra-reflect/src/resource.rs b/lyra-reflect/src/resource.rs new file mode 100644 index 0000000..aa95293 --- /dev/null +++ b/lyra-reflect/src/resource.rs @@ -0,0 +1,50 @@ +use std::{any::TypeId, cell::{Ref, RefMut}, ptr::NonNull}; + +use lyra_ecs::{World, ResourceObject}; + +use crate::{Reflect, FromType}; + +#[derive(Clone)] +pub struct ReflectedResource { + pub type_id: TypeId, + + fn_reflect: for<'a> fn (world: &'a World) -> Option>, + fn_reflect_mut: for<'a> fn (world: &'a mut World) -> Option>, + fn_reflect_ptr: fn (world: &mut World) -> Option>, +} + +impl ReflectedResource { + /// Retrieves the reflected resource from the world. + pub fn reflect<'a>(&self, world: &'a World) -> Option> { + (self.fn_reflect)(world) + } + + /// Retrieves a mutable reflected resource from the world. + pub fn reflect_mut<'a>(&self, world: &'a mut World) -> Option> { + (self.fn_reflect_mut)(world) + } + + pub fn reflect_ptr(&self, world: &mut World) -> Option> { + (self.fn_reflect_ptr)(world) + } +} + +impl FromType for ReflectedResource { + fn from_type() -> Self { + Self { + type_id: TypeId::of::(), + fn_reflect: |world: &World| { + world.try_get_resource::() + .map(|r| r as Ref) + }, + fn_reflect_mut: |world: &mut World| { + world.try_get_resource_mut::() + .map(|r| r as RefMut) + }, + fn_reflect_ptr: |world: &mut World| unsafe { + world.try_get_resource_ptr::() + .map(|ptr| ptr.cast::()) + }, + } + } +} \ No newline at end of file diff --git a/lyra-scripting/src/lib.rs b/lyra-scripting/src/lib.rs index 197e95e..640d227 100644 --- a/lyra-scripting/src/lib.rs +++ b/lyra-scripting/src/lib.rs @@ -2,7 +2,9 @@ pub mod lua; pub mod world; -use lyra_ecs::Component; +use std::any::TypeId; + +use lyra_ecs::{Component, ResourceObject}; pub use world::*; pub mod wrap; @@ -16,17 +18,19 @@ pub use script::*; use lyra_game::game::Game; +// required for some proc macros :( #[allow(unused_imports)] pub(crate) mod lyra_engine { pub use lyra_ecs as ecs; pub use lyra_reflect as reflect; } -use lyra_reflect::{ReflectedComponent, Reflect, FromType}; +use lyra_reflect::{ReflectedComponent, Reflect, FromType, ReflectedResource}; #[derive(Clone)] pub enum ReflectBranch { Component(ReflectedComponent), + Resource(ReflectedResource), } impl ReflectBranch { @@ -37,13 +41,38 @@ impl ReflectBranch { pub fn as_component_unchecked(&self) -> &ReflectedComponent { match self { ReflectBranch::Component(c) => c, - //_ => panic!("`self` is not an instance of `ReflectBranch::Component`") + _ => panic!("`self` is not an instance of `ReflectBranch::Component`") } } + /// Returns a boolean indicating if `self` is a reflection of a Component. pub fn is_component(&self) -> bool { matches!(self, ReflectBranch::Component(_)) } + + /// Gets self as a [`ReflectedResource`]. + /// + /// # Panics + /// If `self` is not a variant of [`ReflectBranch::Resource`]. + pub fn as_resource_unchecked(&self) -> &ReflectedResource { + match self { + ReflectBranch::Resource(v) => v, + _ => panic!("`self` is not an instance of `ReflectBranch::Component`") + } + } + + /// Returns a boolean indicating if `self` is a reflection of a Resource. + pub fn is_resource(&self) -> bool { + matches!(self, ReflectBranch::Resource(_)) + } + + /// Returns the type id of the reflected thing + pub fn reflect_type_id(&self) -> TypeId { + match self { + ReflectBranch::Component(c) => c.type_id, + ReflectBranch::Resource(r) => r.type_id, + } + } } pub struct ScriptBorrow { @@ -63,6 +92,7 @@ impl Clone for ScriptBorrow { } impl ScriptBorrow { + /// Creates a ScriptBorrow from a Component pub fn from_component(data: Option) -> Self where T: Reflect + Component + Default + 'static @@ -74,10 +104,24 @@ impl ScriptBorrow { data, } } + + /// Creates a ScriptBorrow from a Resource. + pub fn from_resource(data: Option) -> Self + where + T: Reflect + ResourceObject + Default + 'static + { + let data = data.map(|d| Box::new(d) as Box<(dyn Reflect + 'static)>); + + Self { + reflect_branch: ReflectBranch::Resource(>::from_type()), + data, + } + } } /// An extension trait that adds some helpful methods that makes it easier to do scripting things pub trait GameScriptExt { + /// A helper method for adding a ScriptApiProvider into the world. fn add_script_api_provider(&mut self, provider: P) where T: ScriptHost, diff --git a/lyra-scripting/src/lua/mod.rs b/lyra-scripting/src/lua/mod.rs index 5c92cb8..add893c 100644 --- a/lyra-scripting/src/lua/mod.rs +++ b/lyra-scripting/src/lua/mod.rs @@ -5,7 +5,7 @@ pub use dynamic_iter::*; pub mod world; use lyra_game::{game::GameStages, plugin::Plugin}; use lyra_resource::ResourceManager; -use tracing::{debug, error, trace, debug_span}; +use tracing::{debug, debug_span, error, trace}; pub use world::*; pub mod script; @@ -17,6 +17,9 @@ pub use loader::*; pub mod providers; pub mod wrappers; +pub mod proxy; +pub use proxy::*; + #[cfg(test)] mod test; @@ -43,24 +46,22 @@ use crate::{ use self::providers::{LyraEcsApiProvider, LyraMathApiProvider, UtilityApiProvider}; pub trait RegisterLuaType { - /// Register a lua type that **is not wrapped**. - fn register_lua_type<'a, T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData>( - &mut self, - ); + /// Register a type to lua that **is not wrapped**. + fn register_lua_type<'a, T>(&mut self) + where + T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData; + /// Registers a wrapped lua type. - /// You provide the wrapper as `W`, and the type that the wrapper wraps, as `T`. - fn register_lua_wrapper< - 'a, - W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData, - >( - &mut self, - ); + fn register_lua_wrapper<'a, W>(&mut self) + where + W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData; } impl RegisterLuaType for World { - fn register_lua_type<'a, T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData>( - &mut self, - ) { + fn register_lua_type<'a, T>(&mut self) + where + T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData + { let mut registry = self.get_resource_mut::(); let type_id = TypeId::of::(); @@ -70,12 +71,10 @@ impl RegisterLuaType for World { //reg_type.add_data(>::from_type()); } - fn register_lua_wrapper< - 'a, - W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData, - >( - &mut self, - ) { + fn register_lua_wrapper<'a, W>(&mut self) + where + W: Reflect + LuaProxy + LuaWrapper + Clone + mlua::FromLua<'a> + mlua::UserData + { let mut registry = self.get_resource_mut::(); let reg_type = registry.get_type_or_default(W::wrapped_type_id()); @@ -99,88 +98,6 @@ pub fn reflect_user_data(ud: &mlua::AnyUserData) -> ScriptBorrow { .expect("Type does not implement '__internal_reflect' properly") } -pub trait LuaWrapper { - /// The type id of the wrapped type. - fn wrapped_type_id() -> TypeId; -} - -pub trait LuaProxy { - fn as_lua_value<'lua>( - lua: &'lua mlua::Lua, - this: &dyn Reflect, - ) -> mlua::Result>; - fn apply( - lua: &mlua::Lua, - this: &mut dyn Reflect, - apply: &mlua::AnyUserData, - ) -> mlua::Result<()>; -} - -impl<'a, T: Reflect + Clone + mlua::FromLua<'a> + mlua::UserData> LuaProxy for T { - fn as_lua_value<'lua>( - lua: &'lua mlua::Lua, - this: &dyn Reflect, - ) -> mlua::Result> { - let this = this.as_any().downcast_ref::().unwrap(); - lua.create_userdata(this.clone()) - } - - fn apply( - _lua: &mlua::Lua, - this: &mut dyn Reflect, - apply: &mlua::AnyUserData, - ) -> mlua::Result<()> { - let this = this.as_any_mut().downcast_mut::().unwrap(); - let apply = apply.borrow::()?; - - *this = apply.clone(); - - Ok(()) - } -} - -#[derive(Clone)] -pub struct ReflectLuaProxy { - fn_as_uservalue: - for<'a> fn(lua: &'a Lua, this_ptr: NonNull) -> mlua::Result>, - fn_apply: for<'a> fn( - lua: &'a Lua, - this_ptr: NonNull, - apply: &'a mlua::AnyUserData<'a>, - ) -> mlua::Result<()>, -} - -impl<'a, T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData> FromType - for ReflectLuaProxy -{ - fn from_type() -> Self { - Self { - fn_as_uservalue: |lua, this| -> mlua::Result { - let this = unsafe { this.cast::().as_ref() }; - ::as_lua_value(lua, this) - }, - fn_apply: |lua, ptr, apply| { - let this = unsafe { ptr.cast::().as_mut() }; - ::apply(lua, this, apply) - }, - } - } -} - -impl<'lua> mlua::FromLua<'lua> for ScriptDynamicBundle { - fn from_lua(value: mlua::Value<'lua>, _lua: &'lua Lua) -> mlua::Result { - match value { - mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), - mlua::Value::Nil => Err(mlua::Error::FromLuaConversionError { - from: "Nil", - to: "DynamicBundle", - message: Some("Value was nil".to_string()), - }), - _ => panic!(), - } - } -} - impl mlua::UserData for ScriptDynamicBundle { fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_function("new", |_, ()| Ok(ScriptDynamicBundle(DynamicBundle::new()))); diff --git a/lyra-scripting/src/lua/providers/ecs.rs b/lyra-scripting/src/lua/providers/ecs.rs index 0e8ad5b..446688c 100644 --- a/lyra-scripting/src/lua/providers/ecs.rs +++ b/lyra-scripting/src/lua/providers/ecs.rs @@ -1,4 +1,4 @@ -use crate::{lua::LuaContext, ScriptApiProvider, ScriptWorldPtr, ScriptDynamicBundle, ScriptData}; +use crate::{lua::{LuaContext, wrappers::LuaDeltaTime, RegisterLuaType}, ScriptApiProvider, ScriptWorldPtr, ScriptDynamicBundle, ScriptData}; #[derive(Default)] pub struct LyraEcsApiProvider; @@ -6,6 +6,10 @@ pub struct LyraEcsApiProvider; impl ScriptApiProvider for LyraEcsApiProvider { type ScriptContext = LuaContext; + fn prepare_world(&mut self, world: &mut lyra_ecs::World) { + world.register_lua_wrapper::(); + } + fn expose_api(&mut self, data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> { let ctx = ctx.lock().unwrap(); @@ -13,6 +17,8 @@ impl ScriptApiProvider for LyraEcsApiProvider { globals.set("World", ctx.create_proxy::()?)?; globals.set("DynamicBundle", ctx.create_proxy::()?)?; + globals.set("DeltaTime", ctx.create_proxy::()?)?; + Ok(()) } diff --git a/lyra-scripting/src/lua/proxy.rs b/lyra-scripting/src/lua/proxy.rs new file mode 100644 index 0000000..e3a79de --- /dev/null +++ b/lyra-scripting/src/lua/proxy.rs @@ -0,0 +1,92 @@ +use std::{any::TypeId, ptr::NonNull}; + +use lyra_reflect::{Reflect, FromType}; + +use crate::ScriptDynamicBundle; + +pub trait LuaWrapper { + /// The type id of the wrapped type. + fn wrapped_type_id() -> TypeId; +} + +pub trait LuaProxy { + fn as_lua_value<'lua>( + lua: &'lua mlua::Lua, + this: &dyn Reflect, + ) -> mlua::Result>; + + fn apply( + lua: &mlua::Lua, + this: &mut dyn Reflect, + apply: &mlua::AnyUserData, + ) -> mlua::Result<()>; +} + +impl<'a, T> LuaProxy for T +where + T: Reflect + Clone + mlua::FromLua<'a> + mlua::UserData +{ + fn as_lua_value<'lua>( + lua: &'lua mlua::Lua, + this: &dyn Reflect, + ) -> mlua::Result> { + let this = this.as_any().downcast_ref::().unwrap(); + lua.create_userdata(this.clone()) + } + + fn apply( + _lua: &mlua::Lua, + this: &mut dyn Reflect, + apply: &mlua::AnyUserData, + ) -> mlua::Result<()> { + let this = this.as_any_mut().downcast_mut::().unwrap(); + let apply = apply.borrow::()?; + + *this = apply.clone(); + + Ok(()) + } +} + +#[derive(Clone)] +pub struct ReflectLuaProxy { + pub fn_as_uservalue: + for<'a> fn(lua: &'a mlua::Lua, this_ptr: NonNull) -> mlua::Result>, + pub fn_apply: for<'a> fn( + lua: &'a mlua::Lua, + this_ptr: NonNull, + apply: &'a mlua::AnyUserData<'a>, + ) -> mlua::Result<()>, +} + +impl<'a, T> FromType for ReflectLuaProxy +where + T: Reflect + LuaProxy + Clone + mlua::FromLua<'a> + mlua::UserData +{ + fn from_type() -> Self { + Self { + fn_as_uservalue: |lua, this| -> mlua::Result { + let this = unsafe { this.cast::().as_ref() }; + ::as_lua_value(lua, this) + }, + fn_apply: |lua, ptr, apply| { + let this = unsafe { ptr.cast::().as_mut() }; + ::apply(lua, this, apply) + }, + } + } +} + +impl<'lua> mlua::FromLua<'lua> for ScriptDynamicBundle { + fn from_lua(value: mlua::Value<'lua>, _lua: &'lua mlua::Lua) -> mlua::Result { + match value { + mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), + mlua::Value::Nil => Err(mlua::Error::FromLuaConversionError { + from: "Nil", + to: "DynamicBundle", + message: Some("Value was nil".to_string()), + }), + _ => panic!(), + } + } +} \ No newline at end of file diff --git a/lyra-scripting/src/lua/world.rs b/lyra-scripting/src/lua/world.rs index 6c1cfbb..95ec3e8 100644 --- a/lyra-scripting/src/lua/world.rs +++ b/lyra-scripting/src/lua/world.rs @@ -1,7 +1,7 @@ -use std::{sync::Arc, ptr::NonNull}; +use std::{sync::Arc, ptr::NonNull, any::Any, ops::Deref}; use lyra_ecs::query::dynamic::QueryDynamicType; -use lyra_reflect::TypeRegistry; +use lyra_reflect::{TypeRegistry, ReflectWorldExt, RegisteredType}; use mlua::{AnyUserDataExt, IntoLua, IntoLuaMulti}; use crate::{ScriptWorldPtr, ScriptEntity, ScriptDynamicBundle, ScriptBorrow}; @@ -159,5 +159,26 @@ impl mlua::UserData for ScriptWorldPtr { Ok(()) }); + + methods.add_method_mut("resource", |lua, this, (ty,): (mlua::AnyUserData,)| { + let reflect = ty + .call_function::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT_TYPE, ()) + .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()) { + //.expect("Failed to find resource pointer in world!"); + let reg_type = this.as_ref().get_type::(reflect.reflect_branch.reflect_type_id()) + .unwrap(); + let proxy = reg_type.get_data::() + .expect("Type does not have ReflectLuaProxy as a TypeData"); + + (proxy.fn_as_uservalue)(lua, res_ptr) + .and_then(|ud| ud.into_lua(lua)) + } else { + // if the resource is not found in the world, return nil + Ok(mlua::Value::Nil) + } + }); } } \ No newline at end of file diff --git a/lyra-scripting/src/lua/wrappers/delta_time.rs b/lyra-scripting/src/lua/wrappers/delta_time.rs new file mode 100644 index 0000000..a4fd4f6 --- /dev/null +++ b/lyra-scripting/src/lua/wrappers/delta_time.rs @@ -0,0 +1,52 @@ +use std::{ops::Deref, any::TypeId}; + +use lyra_game::DeltaTime; +use crate::{lyra_engine, lua::{FN_NAME_INTERNAL_REFLECT_TYPE, LuaWrapper}, ScriptBorrow}; + +#[derive(Clone, lyra_reflect::Reflect, Default)] +pub struct LuaDeltaTime(#[reflect(skip)] pub(crate) DeltaTime); + +impl std::ops::Deref for LuaDeltaTime { + type Target = DeltaTime; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::DerefMut for LuaDeltaTime { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl<'lua> mlua::FromLua<'lua> for LuaDeltaTime { + fn from_lua(value: mlua::prelude::LuaValue<'lua>, lua: &'lua mlua::prelude::Lua) -> mlua::prelude::LuaResult { + match value { + mlua::Value::UserData(ud) => Ok(ud.borrow::()?.clone()), + _ => unreachable!(), + } + } +} + +impl mlua::UserData for LuaDeltaTime { + fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("get", |_, this, ()| { + Ok(*this.0.deref()) + }); + + methods.add_meta_method(mlua::MetaMethod::ToString, |_, this, ()| { + Ok(format!("{}", this.0.deref())) + }); + + methods.add_function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| { + Ok(ScriptBorrow::from_resource::(None)) + }); + } +} + +impl LuaWrapper for LuaDeltaTime { + fn wrapped_type_id() -> std::any::TypeId { + TypeId::of::() + } +} \ No newline at end of file diff --git a/lyra-scripting/src/lua/wrappers/math.rs b/lyra-scripting/src/lua/wrappers/math.rs new file mode 100644 index 0000000..a439fa1 --- /dev/null +++ b/lyra-scripting/src/lua/wrappers/math.rs @@ -0,0 +1,605 @@ +use std::sync::Arc; + +use crate::lyra_engine; +use lyra_game::math; +use lyra_scripting_derive::wrap_math_vec_copy; + +use crate as lyra_scripting; + +// f32 types +wrap_math_vec_copy!( + math::Vec2, + derives(PartialEq), + fields(x, y), + metamethods( + Add(LuaVec2, f32), + Sub(LuaVec2, f32), + Div(LuaVec2, f32), + Mul(LuaVec2, f32), + Mod(LuaVec2, f32), + Eq, + Unm + ) +); +wrap_math_vec_copy!( + math::Vec3, + derives(PartialEq), + fields(x, y, z), + metamethods( + Add(LuaVec3), + Sub(LuaVec3, f32), + Div(LuaVec3, f32), + //Mul(LuaVec3, f32), + Mod(LuaVec3, f32), + Eq, Unm, ToString, + ), + custom_methods { + methods.add_meta_method(mlua::MetaMethod::Mul, |_, this, (v,): (mlua::Value,)| { + match v { + mlua::Value::Number(n) => { + Ok(Self(this.0 * (n as f32))) + }, + mlua::Value::UserData(ud) => { + if let Ok(other_this) = ud.borrow::() { + Ok(Self(this.0 * other_this.0)) + } else { + if let Ok(mt) = ud.get_metatable() { + if let Ok(name) = mt.get::("__name") { + return Err(mlua::Error::BadArgument { + to: Some("LuaVec3.__mul".to_string()), + pos: 2, + name: Some("rhs".to_string()), + cause: Arc::new(mlua::Error::RuntimeError( + format!("cannot multiply with unknown userdata named {}", name) + )) + }); + } + } + + Err(mlua::Error::BadArgument { + to: Some("LuaVec3.__mul".to_string()), + pos: 2, + name: Some("rhs".to_string()), + cause: Arc::new( + mlua::Error::runtime("cannot multiply with unknown userdata") + ) + }) + } + }, + _ => Err(mlua::Error::BadArgument { + to: Some("LuaVec3.__mul".to_string()), + pos: 2, + name: Some("rhs".to_string()), + cause: Arc::new( + mlua::Error::RuntimeError(format!("cannot multiply with {}", v.type_name())) + ) + }) + } + }); + } +); +/* wrap_math_vec_copy!( + math::Vec3A, + derives(PartialEq), + fields(x, y, z), + metamethods( + Add(LuaVec3A, f32), + Sub(LuaVec3A, f32), + Div(LuaVec3A, f32), + Mul(LuaVec3A, f32), + Mod(LuaVec3A, f32), + Eq, Unm + ) +); +wrap_math_vec_copy!( + math::Vec4, + derives(PartialEq), + fields(w, x, y, z), + metamethods( + Add(LuaVec4, f32), + Sub(LuaVec4, f32), + Div(LuaVec4, f32), + Mul(LuaVec4, f32), + Mod(LuaVec4, f32), + Eq, Unm + ) +); + +// f64 types +wrap_math_vec_copy!( + math::DVec2, + derives(PartialEq), + fields(x, y), + metamethods( + Add(LuaDVec2, f64), + Sub(LuaDVec2, f64), + Div(LuaDVec2, f64), + Mul(LuaDVec2, f64), + Mod(LuaDVec2, f64), + Eq, Unm + ) +); +wrap_math_vec_copy!( + math::DVec3, + derives(PartialEq), + fields(x, y, z), + metamethods( + Add(LuaDVec3, f64), + Sub(LuaDVec3, f64), + Div(LuaDVec3, f64), + Mul(LuaDVec3, f64), + Mod(LuaDVec3, f64), + Eq, Unm + ) +); +wrap_math_vec_copy!( + math::DVec4, + derives(PartialEq), + fields(w, x, y, z), + metamethods( + Add(LuaDVec4, f64), + Sub(LuaDVec4, f64), + Div(LuaDVec4, f64), + Mul(LuaDVec4, f64), + Mod(LuaDVec4, f64), + Eq, Unm + ) +); + +// i32 types +wrap_math_vec_copy!( + math::IVec2, + derives(PartialEq, Eq, Hash), + fields(x, y), + metamethods( + Add(LuaIVec2, i32), + Sub(LuaIVec2, i32), + Div(LuaIVec2, i32), + Mul(LuaIVec2, i32), + Mod(LuaIVec2, i32), + Shl(LuaIVec2, LuaUVec2, i32), + Shr(LuaIVec2, LuaUVec2, i32), + BAnd(LuaIVec2, i32), + BOr(LuaIVec2, i32), + BXor(LuaIVec2, i32), + Eq, Unm, BNot + ) +); +wrap_math_vec_copy!( + math::IVec3, + derives(PartialEq, Eq, Hash), + fields(x, y, z), + metamethods( + Add(LuaIVec3, i32), + Sub(LuaIVec3, i32), + Div(LuaIVec3, i32), + Mul(LuaIVec3, i32), + Mod(LuaIVec3, i32), + Shl(LuaIVec3, LuaUVec3, i32), + Shr(LuaIVec3, LuaUVec3, i32), + BAnd(LuaIVec3, i32), + BOr(LuaIVec3, i32), + BXor(LuaIVec3, i32), + Eq, Unm, BNot + ) +); +wrap_math_vec_copy!( + math::IVec4, + derives(PartialEq, Eq, Hash), + fields(w, x, y, z), + metamethods( + Add(LuaIVec4, i32), + Sub(LuaIVec4, i32), + Div(LuaIVec4, i32), + Mul(LuaIVec4, i32), + Mod(LuaIVec4, i32), + Shl(LuaIVec4, LuaUVec4, i32), + Shr(LuaIVec4, LuaUVec4, i32), + BAnd(LuaIVec4, i32), + BOr(LuaIVec4, i32), + BXor(LuaIVec4, i32), + Eq, Unm, BNot + ) +); + +// u32 types +wrap_math_vec_copy!( + math::UVec2, + derives(PartialEq, Eq, Hash), + fields(x, y), + metamethods( + Add(LuaUVec2, u32), + Sub(LuaUVec2, u32), + Div(LuaUVec2, u32), + Mul(LuaUVec2, u32), + Mod(LuaUVec2, u32), + Shl(LuaUVec2, LuaIVec2, i32), + Shr(LuaUVec2, LuaIVec2, i32), + BAnd(LuaUVec2, u32), + BOr(LuaUVec2, u32), + BXor(LuaUVec2, u32), + Eq, BNot + ) +); +wrap_math_vec_copy!( + math::UVec3, + derives(PartialEq, Eq, Hash), + fields(x, y, z), + metamethods( + Add(LuaUVec3, u32), + Sub(LuaUVec3, u32), + Div(LuaUVec3, u32), + Mul(LuaUVec3, u32), + Mod(LuaUVec3, u32), + Shl(LuaUVec3, LuaIVec3, i32), + Shr(LuaUVec3, LuaIVec3, i32), + BAnd(LuaUVec3, u32), + BOr(LuaUVec3, u32), + BXor(LuaUVec3, u32), + Eq, BNot + ) +); +wrap_math_vec_copy!( + math::UVec4, + derives(PartialEq, Eq, Hash), + fields(w, x, y, z), + metamethods( + Add(LuaUVec4, u32), + Sub(LuaUVec4, u32), + Div(LuaUVec4, u32), + Mul(LuaUVec4, u32), + Mod(LuaUVec4, u32), + Shl(LuaUVec4, LuaIVec4, i32), + Shr(LuaUVec4, LuaIVec4, i32), + BAnd(LuaUVec4, u32), + BOr(LuaUVec4, u32), + BXor(LuaUVec4, u32), + Eq, BNot + ) +); + +// i64 types +wrap_math_vec_copy!( + math::I64Vec2, + derives(PartialEq, Eq, Hash), + fields(x, y), + metamethods( + Add(LuaI64Vec2, i64), + Sub(LuaI64Vec2, i64), + Div(LuaI64Vec2, i64), + Mul(LuaI64Vec2, i64), + Mod(LuaI64Vec2, i64), + Shl(i64), + Shr(i64), + BAnd(LuaI64Vec2, i64), + BOr(LuaI64Vec2, i64), + BXor(LuaI64Vec2, i64), + Eq, BNot + ) +); +wrap_math_vec_copy!( + math::I64Vec3, + derives(PartialEq, Eq, Hash), + fields(x, y, z), + metamethods( + Add(LuaI64Vec3, i64), + Sub(LuaI64Vec3, i64), + Div(LuaI64Vec3, i64), + Mul(LuaI64Vec3, i64), + Mod(LuaI64Vec3, i64), + Shl(i64), + Shr(i64), + BAnd(LuaI64Vec3, i64), + BOr(LuaI64Vec3, i64), + BXor(LuaI64Vec3, i64), + Eq, BNot + ) +); +wrap_math_vec_copy!( + math::I64Vec4, + derives(PartialEq, Eq, Hash), + fields(w, x, y, z), + metamethods( + Add(LuaI64Vec4, i64), + Sub(LuaI64Vec4, i64), + Div(LuaI64Vec4, i64), + Mul(LuaI64Vec4, i64), + Mod(LuaI64Vec4, i64), + Shl(i64), + Shr(i64), + BAnd(LuaI64Vec4, i64), + BOr(LuaI64Vec4, i64), + BXor(LuaI64Vec4, i64), + Eq, BNot + ) +); + +// u64 types +wrap_math_vec_copy!( + math::U64Vec2, + derives(PartialEq, Eq, Hash), + fields(x, y), + metamethods( + Add(LuaU64Vec2, u64), + Sub(LuaU64Vec2, u64), + Div(LuaU64Vec2, u64), + Mul(LuaU64Vec2, u64), + Mod(LuaU64Vec2, u64), + Shl(i64), + Shr(i64), + BAnd(LuaU64Vec2, u64), + BOr(LuaU64Vec2, u64), + BXor(LuaU64Vec2, u64), + Eq, BNot + ) +); +wrap_math_vec_copy!( + math::U64Vec3, + derives(PartialEq, Eq, Hash), + fields(x, y, z), + metamethods( + Add(LuaU64Vec3, u64), + Sub(LuaU64Vec3, u64), + Div(LuaU64Vec3, u64), + Mul(LuaU64Vec3, u64), + Mod(LuaU64Vec3, u64), + Shl(i64), + Shr(i64), + BAnd(LuaU64Vec3, u64), + BOr(LuaU64Vec3, u64), + BXor(LuaU64Vec3, u64), + Eq, BNot + ) +); +wrap_math_vec_copy!( + math::U64Vec4, + derives(PartialEq, Eq, Hash), + fields(w, x, y, z), + metamethods( + Add(LuaU64Vec4, u64), + Sub(LuaU64Vec4, u64), + Div(LuaU64Vec4, u64), + Mul(LuaU64Vec4, u64), + Mod(LuaU64Vec4, u64), + Shl(i64), + Shr(i64), + BAnd(LuaU64Vec4, u64), + BOr(LuaU64Vec4, u64), + BXor(LuaU64Vec4, u64), + Eq, BNot + ) +); + +// bool types +wrap_math_vec_copy!( + math::BVec2, + derives(PartialEq, Eq, Hash), + fields(x, y), + metamethods(Eq, BAnd, BOr, BXor, BNot) +); +wrap_math_vec_copy!( + math::BVec3, + derives(PartialEq, Eq, Hash), + fields(x, y, z), + metamethods(Eq, BAnd, BOr, BXor, BNot) +); +wrap_math_vec_copy!( + math::BVec4, + derives(PartialEq, Eq, Hash), + fields(w, x, y, z), + metamethods(Eq, BAnd, BOr, BXor, BNot) +); + +// mat2 +wrap_math_vec_copy!( + math::Mat2, + derives(PartialEq), + no_new, + matrix { + col_type = LuaVec2 + }, + metamethods( + Eq, + Add, + Sub, + Mul(LuaMat2, f32), + Unm + ) +); */ + +/* wrap_math_vec_copy!( + math::Mat4, + derives(PartialEq), + no_new, + matrix { + col_type = LuaVec4 + }, + metamethods( + Eq, + Add, + Sub, + Mul(LuaMat4, f32), + Unm + ) +); */ + +wrap_math_vec_copy!( + math::Quat, + derives(PartialEq), + no_new, + metamethods( + Eq, + // __mul for LuaVec3 is manually implemented below since it doesn't return Self + Mul(LuaQuat, f32), + Add, + Sub, + Div(f32), + ), + custom_methods { + methods.add_function("new", |_, (x, y, z, w)| { + Ok(Self(math::Quat::from_xyzw(x, y, z, w))) + }); + + methods.add_function("from_rotation_x", |_, (rad,)| { + let q = math::Quat::from_rotation_x(rad); + Ok(Self(q)) + }); + + methods.add_function("from_rotation_y", |_, (rad,)| { + let q = math::Quat::from_rotation_y(rad); + Ok(Self(q)) + }); + + methods.add_function("from_rotation_z", |_, (rad,)| { + let q = math::Quat::from_rotation_z(rad); + Ok(Self(q)) + }); + + methods.add_method("dot", |_, this, (rhs,): (Self,)| { + Ok(this.dot(rhs.0)) + }); + + methods.add_method("length", |_, this, ()| { + Ok(this.length()) + }); + + methods.add_method("length_squared", |_, this, ()| { + Ok(this.length_squared()) + }); + + methods.add_method("normalize", |_, this, ()| { + Ok(Self(this.normalize())) + }); + + methods.add_method("mult_quat", |_, this, (rhs,): (Self,)| { + Ok(Self(this.0 * rhs.0)) + }); + + methods.add_method("mult_vec3", |_, this, (rhs,): (LuaVec3,)| { + Ok(LuaVec3(this.0 * rhs.0)) + }); + + // manually implemented here since it doesn't return `Self` + methods.add_meta_method(mlua::MetaMethod::Mul, |_, this, (rhs,): (LuaVec3,)| { + Ok(LuaVec3(this.0 * rhs.0)) + }); + + methods.add_method("lerp", |_, this, (rhs, alpha): (Self, f32)| { + Ok(Self(this.lerp(*rhs, alpha))) + }); + } +); + +wrap_math_vec_copy!( + math::Transform, + //derives(PartialEq), + no_new, + metamethods(ToString, Eq), + custom_fields { + fields.add_field_method_get("translation", |_, this| { + Ok(LuaVec3(this.translation)) + }); + fields.add_field_method_set("translation", |_, this, v: LuaVec3| { + this.translation = *v; + Ok(()) + }); + + fields.add_field_method_get("rotation", |_, this| { + Ok(LuaQuat(this.rotation)) + }); + fields.add_field_method_set("rotation", |_, this, v: LuaQuat| { + this.rotation = *v; + Ok(()) + }); + + fields.add_field_method_get("scale", |_, this| { + Ok(LuaVec3(this.scale)) + }); + fields.add_field_method_set("scale", |_, this, v: LuaVec3| { + this.scale = *v; + Ok(()) + }); + }, + custom_methods { + methods.add_function("default", |_, ()| { + Ok(Self(math::Transform::default())) + }); + + methods.add_function("new", |_, (pos, rot, scale): (LuaVec3, LuaQuat, LuaVec3)| { + Ok(Self(math::Transform::new(*pos, *rot, *scale))) + }); + + methods.add_function("from_translation", |_, (pos,): (LuaVec3,)| { + Ok(Self(math::Transform::from_translation(*pos))) + }); + + methods.add_function("from_xyz", |_, (x, y, z)| { + Ok(Self(math::Transform::from_xyz(x, y, z))) + }); + + methods.add_method("forward", |_, this, ()| { + Ok(LuaVec3(this.forward())) + }); + + methods.add_method("left", |_, this, ()| { + Ok(LuaVec3(this.left())) + }); + + methods.add_method("up", |_, this, ()| { + Ok(LuaVec3(this.up())) + }); + + methods.add_method_mut("rotate", |_, this, (quat,): (LuaQuat,)| { + this.rotate(*quat); + Ok(()) + }); + + methods.add_method_mut("rotate_x", |_, this, (deg,): (f32,)| { + this.rotate_x(math::Angle::Degrees(deg)); + Ok(()) + }); + + methods.add_method_mut("rotate_y", |_, this, (deg,): (f32,)| { + this.rotate_y(math::Angle::Degrees(deg)); + Ok(()) + }); + + methods.add_method_mut("rotate_z", |_, this, (deg,): (f32,)| { + this.rotate_z(math::Angle::Degrees(deg)); + Ok(()) + }); + + methods.add_method_mut("rotate_x_rad", |_, this, (rad,): (f32,)| { + this.rotate_x(math::Angle::Radians(rad)); + Ok(()) + }); + + methods.add_method_mut("rotate_y_rad", |_, this, (rad,): (f32,)| { + this.rotate_y(math::Angle::Radians(rad)); + Ok(()) + }); + + methods.add_method_mut("rotate_z_rad", |_, this, (rad,): (f32,)| { + this.rotate_z(math::Angle::Radians(rad)); + Ok(()) + }); + + methods.add_method("lerp", |_, this, (rhs, alpha): (Self, f32)| { + Ok(Self(this.lerp(*rhs, alpha))) + }); + + // rotate a transform + methods.add_meta_method(mlua::MetaMethod::Mul, |_, this, (quat,): (LuaQuat,)| { + let mut t = *this; + t.rotation *= *quat; + Ok(t) + }); + + // move a transform + methods.add_meta_method(mlua::MetaMethod::Add, |_, this, (pos,): (LuaVec3,)| { + let mut t = *this; + t.translation += *pos; + Ok(t) + }); + } +); diff --git a/lyra-scripting/src/lua/wrappers/mod.rs b/lyra-scripting/src/lua/wrappers/mod.rs index 22a2317..1fd0c6b 100644 --- a/lyra-scripting/src/lua/wrappers/mod.rs +++ b/lyra-scripting/src/lua/wrappers/mod.rs @@ -1,566 +1,5 @@ -use lyra_game::math; -use lyra_scripting_derive::wrap_math_vec_copy; -use crate::lyra_engine; +pub mod math; +pub use math::*; -use crate as lyra_scripting; - -// f32 types -wrap_math_vec_copy!( - math::Vec2, - derives(PartialEq), - fields(x, y), - metamethods( - Add(LuaVec2, f32), - Sub(LuaVec2, f32), - Div(LuaVec2, f32), - Mul(LuaVec2, f32), - Mod(LuaVec2, f32), - Eq, Unm - ) -); -wrap_math_vec_copy!( - math::Vec3, - derives(PartialEq), - fields(x, y, z), - metamethods( - Add(LuaVec3), - Sub(LuaVec3, f32), - Div(LuaVec3, f32), - Mul(LuaVec3, f32), - Mod(LuaVec3, f32), - Eq, Unm, ToString, - ), - custom_methods { - /* methods.add_meta_method(mlua::MetaMethod::Add, |_, this, (trans,): (LuaTransform,)| { - println!("Adding"); - let mut t = *trans; - t.translation += **this; - Ok(LuaTransform(t)) - }); */ - } -); -/* wrap_math_vec_copy!( - math::Vec3A, - derives(PartialEq), - fields(x, y, z), - metamethods( - Add(LuaVec3A, f32), - Sub(LuaVec3A, f32), - Div(LuaVec3A, f32), - Mul(LuaVec3A, f32), - Mod(LuaVec3A, f32), - Eq, Unm - ) -); -wrap_math_vec_copy!( - math::Vec4, - derives(PartialEq), - fields(w, x, y, z), - metamethods( - Add(LuaVec4, f32), - Sub(LuaVec4, f32), - Div(LuaVec4, f32), - Mul(LuaVec4, f32), - Mod(LuaVec4, f32), - Eq, Unm - ) -); - -// f64 types -wrap_math_vec_copy!( - math::DVec2, - derives(PartialEq), - fields(x, y), - metamethods( - Add(LuaDVec2, f64), - Sub(LuaDVec2, f64), - Div(LuaDVec2, f64), - Mul(LuaDVec2, f64), - Mod(LuaDVec2, f64), - Eq, Unm - ) -); -wrap_math_vec_copy!( - math::DVec3, - derives(PartialEq), - fields(x, y, z), - metamethods( - Add(LuaDVec3, f64), - Sub(LuaDVec3, f64), - Div(LuaDVec3, f64), - Mul(LuaDVec3, f64), - Mod(LuaDVec3, f64), - Eq, Unm - ) -); -wrap_math_vec_copy!( - math::DVec4, - derives(PartialEq), - fields(w, x, y, z), - metamethods( - Add(LuaDVec4, f64), - Sub(LuaDVec4, f64), - Div(LuaDVec4, f64), - Mul(LuaDVec4, f64), - Mod(LuaDVec4, f64), - Eq, Unm - ) -); - -// i32 types -wrap_math_vec_copy!( - math::IVec2, - derives(PartialEq, Eq, Hash), - fields(x, y), - metamethods( - Add(LuaIVec2, i32), - Sub(LuaIVec2, i32), - Div(LuaIVec2, i32), - Mul(LuaIVec2, i32), - Mod(LuaIVec2, i32), - Shl(LuaIVec2, LuaUVec2, i32), - Shr(LuaIVec2, LuaUVec2, i32), - BAnd(LuaIVec2, i32), - BOr(LuaIVec2, i32), - BXor(LuaIVec2, i32), - Eq, Unm, BNot - ) -); -wrap_math_vec_copy!( - math::IVec3, - derives(PartialEq, Eq, Hash), - fields(x, y, z), - metamethods( - Add(LuaIVec3, i32), - Sub(LuaIVec3, i32), - Div(LuaIVec3, i32), - Mul(LuaIVec3, i32), - Mod(LuaIVec3, i32), - Shl(LuaIVec3, LuaUVec3, i32), - Shr(LuaIVec3, LuaUVec3, i32), - BAnd(LuaIVec3, i32), - BOr(LuaIVec3, i32), - BXor(LuaIVec3, i32), - Eq, Unm, BNot - ) -); -wrap_math_vec_copy!( - math::IVec4, - derives(PartialEq, Eq, Hash), - fields(w, x, y, z), - metamethods( - Add(LuaIVec4, i32), - Sub(LuaIVec4, i32), - Div(LuaIVec4, i32), - Mul(LuaIVec4, i32), - Mod(LuaIVec4, i32), - Shl(LuaIVec4, LuaUVec4, i32), - Shr(LuaIVec4, LuaUVec4, i32), - BAnd(LuaIVec4, i32), - BOr(LuaIVec4, i32), - BXor(LuaIVec4, i32), - Eq, Unm, BNot - ) -); - -// u32 types -wrap_math_vec_copy!( - math::UVec2, - derives(PartialEq, Eq, Hash), - fields(x, y), - metamethods( - Add(LuaUVec2, u32), - Sub(LuaUVec2, u32), - Div(LuaUVec2, u32), - Mul(LuaUVec2, u32), - Mod(LuaUVec2, u32), - Shl(LuaUVec2, LuaIVec2, i32), - Shr(LuaUVec2, LuaIVec2, i32), - BAnd(LuaUVec2, u32), - BOr(LuaUVec2, u32), - BXor(LuaUVec2, u32), - Eq, BNot - ) -); -wrap_math_vec_copy!( - math::UVec3, - derives(PartialEq, Eq, Hash), - fields(x, y, z), - metamethods( - Add(LuaUVec3, u32), - Sub(LuaUVec3, u32), - Div(LuaUVec3, u32), - Mul(LuaUVec3, u32), - Mod(LuaUVec3, u32), - Shl(LuaUVec3, LuaIVec3, i32), - Shr(LuaUVec3, LuaIVec3, i32), - BAnd(LuaUVec3, u32), - BOr(LuaUVec3, u32), - BXor(LuaUVec3, u32), - Eq, BNot - ) -); -wrap_math_vec_copy!( - math::UVec4, - derives(PartialEq, Eq, Hash), - fields(w, x, y, z), - metamethods( - Add(LuaUVec4, u32), - Sub(LuaUVec4, u32), - Div(LuaUVec4, u32), - Mul(LuaUVec4, u32), - Mod(LuaUVec4, u32), - Shl(LuaUVec4, LuaIVec4, i32), - Shr(LuaUVec4, LuaIVec4, i32), - BAnd(LuaUVec4, u32), - BOr(LuaUVec4, u32), - BXor(LuaUVec4, u32), - Eq, BNot - ) -); - -// i64 types -wrap_math_vec_copy!( - math::I64Vec2, - derives(PartialEq, Eq, Hash), - fields(x, y), - metamethods( - Add(LuaI64Vec2, i64), - Sub(LuaI64Vec2, i64), - Div(LuaI64Vec2, i64), - Mul(LuaI64Vec2, i64), - Mod(LuaI64Vec2, i64), - Shl(i64), - Shr(i64), - BAnd(LuaI64Vec2, i64), - BOr(LuaI64Vec2, i64), - BXor(LuaI64Vec2, i64), - Eq, BNot - ) -); -wrap_math_vec_copy!( - math::I64Vec3, - derives(PartialEq, Eq, Hash), - fields(x, y, z), - metamethods( - Add(LuaI64Vec3, i64), - Sub(LuaI64Vec3, i64), - Div(LuaI64Vec3, i64), - Mul(LuaI64Vec3, i64), - Mod(LuaI64Vec3, i64), - Shl(i64), - Shr(i64), - BAnd(LuaI64Vec3, i64), - BOr(LuaI64Vec3, i64), - BXor(LuaI64Vec3, i64), - Eq, BNot - ) -); -wrap_math_vec_copy!( - math::I64Vec4, - derives(PartialEq, Eq, Hash), - fields(w, x, y, z), - metamethods( - Add(LuaI64Vec4, i64), - Sub(LuaI64Vec4, i64), - Div(LuaI64Vec4, i64), - Mul(LuaI64Vec4, i64), - Mod(LuaI64Vec4, i64), - Shl(i64), - Shr(i64), - BAnd(LuaI64Vec4, i64), - BOr(LuaI64Vec4, i64), - BXor(LuaI64Vec4, i64), - Eq, BNot - ) -); - -// u64 types -wrap_math_vec_copy!( - math::U64Vec2, - derives(PartialEq, Eq, Hash), - fields(x, y), - metamethods( - Add(LuaU64Vec2, u64), - Sub(LuaU64Vec2, u64), - Div(LuaU64Vec2, u64), - Mul(LuaU64Vec2, u64), - Mod(LuaU64Vec2, u64), - Shl(i64), - Shr(i64), - BAnd(LuaU64Vec2, u64), - BOr(LuaU64Vec2, u64), - BXor(LuaU64Vec2, u64), - Eq, BNot - ) -); -wrap_math_vec_copy!( - math::U64Vec3, - derives(PartialEq, Eq, Hash), - fields(x, y, z), - metamethods( - Add(LuaU64Vec3, u64), - Sub(LuaU64Vec3, u64), - Div(LuaU64Vec3, u64), - Mul(LuaU64Vec3, u64), - Mod(LuaU64Vec3, u64), - Shl(i64), - Shr(i64), - BAnd(LuaU64Vec3, u64), - BOr(LuaU64Vec3, u64), - BXor(LuaU64Vec3, u64), - Eq, BNot - ) -); -wrap_math_vec_copy!( - math::U64Vec4, - derives(PartialEq, Eq, Hash), - fields(w, x, y, z), - metamethods( - Add(LuaU64Vec4, u64), - Sub(LuaU64Vec4, u64), - Div(LuaU64Vec4, u64), - Mul(LuaU64Vec4, u64), - Mod(LuaU64Vec4, u64), - Shl(i64), - Shr(i64), - BAnd(LuaU64Vec4, u64), - BOr(LuaU64Vec4, u64), - BXor(LuaU64Vec4, u64), - Eq, BNot - ) -); - -// bool types -wrap_math_vec_copy!( - math::BVec2, - derives(PartialEq, Eq, Hash), - fields(x, y), - metamethods(Eq, BAnd, BOr, BXor, BNot) -); -wrap_math_vec_copy!( - math::BVec3, - derives(PartialEq, Eq, Hash), - fields(x, y, z), - metamethods(Eq, BAnd, BOr, BXor, BNot) -); -wrap_math_vec_copy!( - math::BVec4, - derives(PartialEq, Eq, Hash), - fields(w, x, y, z), - metamethods(Eq, BAnd, BOr, BXor, BNot) -); - -// mat2 -wrap_math_vec_copy!( - math::Mat2, - derives(PartialEq), - no_new, - matrix { - col_type = LuaVec2 - }, - metamethods( - Eq, - Add, - Sub, - Mul(LuaMat2, f32), - Unm - ) -); */ - -/* wrap_math_vec_copy!( - math::Mat4, - derives(PartialEq), - no_new, - matrix { - col_type = LuaVec4 - }, - metamethods( - Eq, - Add, - Sub, - Mul(LuaMat4, f32), - Unm - ) -); */ - -wrap_math_vec_copy!( - math::Quat, - derives(PartialEq), - no_new, - metamethods( - Eq, - // __mul for LuaVec3 is manually implemented below since it doesn't return Self - Mul(LuaQuat, f32), - Add, - Sub, - Div(f32), - ), - custom_methods { - methods.add_function("new", |_, (x, y, z, w)| { - Ok(Self(math::Quat::from_xyzw(x, y, z, w))) - }); - - methods.add_function("from_rotation_x", |_, (rad,)| { - let q = math::Quat::from_rotation_x(rad); - Ok(Self(q)) - }); - - methods.add_function("from_rotation_y", |_, (rad,)| { - let q = math::Quat::from_rotation_y(rad); - Ok(Self(q)) - }); - - methods.add_function("from_rotation_z", |_, (rad,)| { - let q = math::Quat::from_rotation_z(rad); - Ok(Self(q)) - }); - - methods.add_method("dot", |_, this, (rhs,): (Self,)| { - Ok(this.dot(rhs.0)) - }); - - methods.add_method("length", |_, this, ()| { - Ok(this.length()) - }); - - methods.add_method("length_squared", |_, this, ()| { - Ok(this.length_squared()) - }); - - methods.add_method("normalize", |_, this, ()| { - Ok(Self(this.normalize())) - }); - - methods.add_method("mult_quat", |_, this, (rhs,): (Self,)| { - Ok(Self(this.0 * rhs.0)) - }); - - methods.add_method("mult_vec3", |_, this, (rhs,): (LuaVec3,)| { - Ok(LuaVec3(this.0 * rhs.0)) - }); - - // manually implemented here since it doesn't return `Self` - methods.add_meta_method(mlua::MetaMethod::Mul, |_, this, (rhs,): (LuaVec3,)| { - Ok(LuaVec3(this.0 * rhs.0)) - }); - - methods.add_method("lerp", |_, this, (rhs, alpha): (Self, f32)| { - Ok(Self(this.lerp(*rhs, alpha))) - }); - } -); - -wrap_math_vec_copy!( - math::Transform, - //derives(PartialEq), - no_new, - metamethods(ToString, Eq), - custom_fields { - fields.add_field_method_get("translation", |_, this| { - Ok(LuaVec3(this.translation)) - }); - fields.add_field_method_set("translation", |_, this, v: LuaVec3| { - this.translation = *v; - Ok(()) - }); - - fields.add_field_method_get("rotation", |_, this| { - Ok(LuaQuat(this.rotation)) - }); - fields.add_field_method_set("rotation", |_, this, v: LuaQuat| { - this.rotation = *v; - Ok(()) - }); - - fields.add_field_method_get("scale", |_, this| { - Ok(LuaVec3(this.scale)) - }); - fields.add_field_method_set("scale", |_, this, v: LuaVec3| { - this.scale = *v; - Ok(()) - }); - }, - custom_methods { - methods.add_function("default", |_, ()| { - Ok(Self(math::Transform::default())) - }); - - methods.add_function("new", |_, (pos, rot, scale): (LuaVec3, LuaQuat, LuaVec3)| { - Ok(Self(math::Transform::new(*pos, *rot, *scale))) - }); - - methods.add_function("from_translation", |_, (pos,): (LuaVec3,)| { - Ok(Self(math::Transform::from_translation(*pos))) - }); - - methods.add_function("from_xyz", |_, (x, y, z)| { - Ok(Self(math::Transform::from_xyz(x, y, z))) - }); - - methods.add_method("forward", |_, this, ()| { - Ok(LuaVec3(this.forward())) - }); - - methods.add_method("left", |_, this, ()| { - Ok(LuaVec3(this.left())) - }); - - methods.add_method("up", |_, this, ()| { - Ok(LuaVec3(this.up())) - }); - - methods.add_method_mut("rotate", |_, this, (quat,): (LuaQuat,)| { - this.rotate(*quat); - Ok(()) - }); - - methods.add_method_mut("rotate_x", |_, this, (deg,): (f32,)| { - this.rotate_x(math::Angle::Degrees(deg)); - Ok(()) - }); - - methods.add_method_mut("rotate_y", |_, this, (deg,): (f32,)| { - this.rotate_y(math::Angle::Degrees(deg)); - Ok(()) - }); - - methods.add_method_mut("rotate_z", |_, this, (deg,): (f32,)| { - this.rotate_z(math::Angle::Degrees(deg)); - Ok(()) - }); - - methods.add_method_mut("rotate_x_rad", |_, this, (rad,): (f32,)| { - this.rotate_x(math::Angle::Radians(rad)); - Ok(()) - }); - - methods.add_method_mut("rotate_y_rad", |_, this, (rad,): (f32,)| { - this.rotate_y(math::Angle::Radians(rad)); - Ok(()) - }); - - methods.add_method_mut("rotate_z_rad", |_, this, (rad,): (f32,)| { - this.rotate_z(math::Angle::Radians(rad)); - Ok(()) - }); - - methods.add_method("lerp", |_, this, (rhs, alpha): (Self, f32)| { - Ok(Self(this.lerp(*rhs, alpha))) - }); - - // rotate a transform - methods.add_meta_method(mlua::MetaMethod::Mul, |_, this, (quat,): (LuaQuat,)| { - let mut t = *this; - t.rotation *= *quat; - Ok(t) - }); - - // move a transform - methods.add_meta_method(mlua::MetaMethod::Add, |_, this, (pos,): (LuaVec3,)| { - let mut t = *this; - t.translation += *pos; - Ok(t) - }); - } -); \ No newline at end of file +pub mod delta_time; +pub use delta_time::*; \ No newline at end of file