scripting: create `FN_NAME_INTERNAL_AS_COMPONENT` for implicitly converting some types as components
This commit is contained in:
parent
6731fcd7f2
commit
388f686917
|
@ -3,9 +3,8 @@ function on_init()
|
||||||
print("Loaded textured cube")
|
print("Loaded textured cube")
|
||||||
|
|
||||||
local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
|
local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
|
||||||
local cube_comp = ModelComponent.new(cube)
|
|
||||||
|
|
||||||
local e = world:spawn(pos, cube_comp)
|
local e = world:spawn(pos, cube)
|
||||||
print("spawned entity " .. tostring(e))
|
print("spawned entity " .. tostring(e))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,52 @@ use lyra_ecs::{
|
||||||
Component, ComponentInfo, World
|
Component, ComponentInfo, World
|
||||||
};
|
};
|
||||||
use lyra_reflect::{Reflect, TypeRegistry};
|
use lyra_reflect::{Reflect, TypeRegistry};
|
||||||
|
use crate::ScriptBorrow;
|
||||||
|
|
||||||
pub type LuaContext = Mutex<elua::State>;
|
pub type LuaContext = Mutex<elua::State>;
|
||||||
|
|
||||||
|
/// Name of a Lua function that is used to Reflect the Userdata, but without a value.
|
||||||
|
///
|
||||||
|
/// This is used for reflecting the userdata as an ECS Component or Resource. This **function**
|
||||||
|
/// returns a [`ScriptBorrow`] with data as `None`.
|
||||||
pub const FN_NAME_INTERNAL_REFLECT_TYPE: &str = "__lyra_internal_reflect_type";
|
pub const FN_NAME_INTERNAL_REFLECT_TYPE: &str = "__lyra_internal_reflect_type";
|
||||||
|
|
||||||
|
/// Name of a Lua function that is used to Reflect the Userdata.
|
||||||
|
///
|
||||||
|
/// This is used for reflecting the userdata as an ECS Component or Resource. This **method**
|
||||||
|
/// returns a [`ScriptBorrow`] with data as `Some`. **Anything that calls this expects the
|
||||||
|
/// method to return data**.
|
||||||
pub const FN_NAME_INTERNAL_REFLECT: &str = "__lyra_internal_reflect";
|
pub const FN_NAME_INTERNAL_REFLECT: &str = "__lyra_internal_reflect";
|
||||||
|
|
||||||
use crate::ScriptBorrow;
|
/// Name of a Lua function implemented for Userdata types that can be made into components.
|
||||||
|
///
|
||||||
|
/// This is used for types that can be converted into components. When implementing this function,
|
||||||
|
/// you must return a [`ScriptBorrow`] that contains the component for this userdata.
|
||||||
|
/// You can return [`elua::Value::Nil`] if for some reason the type could not be converted
|
||||||
|
/// into a component.
|
||||||
|
///
|
||||||
|
/// A good example of this is `LuaResHandle`. The resource handle is requested from the
|
||||||
|
/// world, and could be a 3d model. The 3d model could then be manually wrapped as
|
||||||
|
/// [`LuaModelComponent`] with its `new` function. But for quality of life, this internal
|
||||||
|
/// function was created so that the userdata can be converted into its component
|
||||||
|
/// type without having to wrap it.
|
||||||
|
///
|
||||||
|
/// Without implementing this function:
|
||||||
|
/// ```lua
|
||||||
|
/// local cube = world:request_res("assets/cube-texture-embedded.gltf")
|
||||||
|
/// local cube_comp = ModelComponent.new(cube) -- annoying to write
|
||||||
|
///
|
||||||
|
/// local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
|
||||||
|
/// local e = world:spawn(pos, cube_comp)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// With this function:
|
||||||
|
/// /// ```lua
|
||||||
|
/// local cube = world:request_res("assets/cube-texture-embedded.gltf")
|
||||||
|
/// local pos = Transform.from_translation(Vec3.new(0, 0, -8.0))
|
||||||
|
/// local e = world:spawn(pos, cube)
|
||||||
|
/// ```
|
||||||
|
pub const FN_NAME_INTERNAL_AS_COMPONENT: &str = "__lyra_internal_refl_as_component";
|
||||||
|
|
||||||
/// A trait used for registering a Lua type with the world.
|
/// A trait used for registering a Lua type with the world.
|
||||||
pub trait RegisterLuaType {
|
pub trait RegisterLuaType {
|
||||||
|
@ -140,7 +179,8 @@ impl elua::Userdata for ScriptBorrow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function used for reflecting userdata as a ScriptBorrow
|
||||||
pub fn reflect_user_data(ud: &elua::AnyUserdata) -> ScriptBorrow {
|
pub fn reflect_user_data(ud: &elua::AnyUserdata) -> ScriptBorrow {
|
||||||
ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
|
ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())
|
||||||
.expect("Type does not implement '__internal_reflect' properly")
|
.expect("Type does not implement internal reflect method properly")
|
||||||
}
|
}
|
|
@ -7,8 +7,7 @@ use lyra_reflect::{ReflectWorldExt, RegisteredType, TypeRegistry};
|
||||||
use lyra_resource::ResourceManager;
|
use lyra_resource::ResourceManager;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
reflect_user_data, wrappers::LuaResHandle, DynamicViewIter, LuaTableProxyLookup,
|
reflect_user_data, wrappers::LuaResHandle, DynamicViewIter, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE
|
||||||
ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'lua> elua::FromLua<'lua> for ScriptEntity {
|
impl<'lua> elua::FromLua<'lua> for ScriptEntity {
|
||||||
|
@ -79,11 +78,22 @@ impl elua::Userdata for ScriptWorldPtr {
|
||||||
Arc::new(elua::Error::runtime("provided component is not userdata")),
|
Arc::new(elua::Error::runtime("provided component is not userdata")),
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
let script_brw = ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
|
let comp_borrow = {
|
||||||
let reflect = script_brw.reflect_branch.as_component_unchecked();
|
if let Ok(as_comp) = ud.get::<_, elua::Function>(FN_NAME_INTERNAL_AS_COMPONENT) {
|
||||||
|
let ud = match as_comp.exec(ud.clone())? {
|
||||||
|
elua::Value::Userdata(ud) => ud,
|
||||||
|
elua::Value::Nil => ud.clone(),
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
let refl_data = script_brw.data.unwrap();
|
ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?
|
||||||
//let refl_data = refl_data.as_ref();
|
} else {
|
||||||
|
ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let reflect = comp_borrow.reflect_branch.as_component_unchecked();
|
||||||
|
let refl_data = comp_borrow.data.unwrap();
|
||||||
reflect.bundle_insert(&mut bundle, refl_data);
|
reflect.bundle_insert(&mut bundle, refl_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,13 @@ impl std::ops::DerefMut for LuaDeltaTime {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> elua::FromLua<'lua> for LuaDeltaTime {
|
impl<'lua> elua::FromLua<'lua> for LuaDeltaTime {
|
||||||
fn from_lua(lua: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result<Self> {
|
fn from_lua(_: &'lua elua::State, _: elua::Value<'lua>) -> elua::Result<Self> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> elua::AsLua<'lua> for LuaDeltaTime {
|
impl<'lua> elua::AsLua<'lua> for LuaDeltaTime {
|
||||||
fn as_lua(self, lua: &'lua elua::State) -> elua::Result<elua::Value<'lua>> {
|
fn as_lua(self, _: &'lua elua::State) -> elua::Result<elua::Value<'lua>> {
|
||||||
Ok(elua::Value::Number(*self.0 as f64))
|
Ok(elua::Value::Number(*self.0 as f64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
use std::{cell::Ref, sync::Arc};
|
use std::{cell::Ref, sync::Arc};
|
||||||
|
|
||||||
use elua::{AsLua, FromLua};
|
use elua::FromLua;
|
||||||
use lyra_game::scene::ModelComponent;
|
use lyra_game::scene::ModelComponent;
|
||||||
use lyra_reflect::Reflect;
|
use lyra_reflect::Reflect;
|
||||||
use lyra_resource::{Model, ResHandle};
|
use lyra_resource::{Model, ResHandle};
|
||||||
|
@ -13,7 +13,7 @@ use crate::{lua::{FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE}, Scri
|
||||||
use super::LuaResHandle;
|
use super::LuaResHandle;
|
||||||
|
|
||||||
#[derive(Clone, Reflect)]
|
#[derive(Clone, Reflect)]
|
||||||
pub struct LuaModelComponent(ModelComponent);
|
pub struct LuaModelComponent(pub ModelComponent);
|
||||||
|
|
||||||
impl elua::Userdata for LuaModelComponent {
|
impl elua::Userdata for LuaModelComponent {
|
||||||
fn name() -> String {
|
fn name() -> String {
|
||||||
|
@ -44,7 +44,8 @@ impl elua::Userdata for LuaModelComponent {
|
||||||
})
|
})
|
||||||
.function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
.function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
||||||
Ok(ScriptBorrow::from_component::<ModelComponent>(None))
|
Ok(ScriptBorrow::from_component::<ModelComponent>(None))
|
||||||
}).method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
|
})
|
||||||
|
.method(FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
|
||||||
Ok(ScriptBorrow::from_component(Some(this.0.clone())))
|
Ok(ScriptBorrow::from_component(Some(this.0.clone())))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
use std::{ops::Deref, sync::Arc};
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
use elua::FromLua;
|
use elua::{AsLua, FromLua};
|
||||||
use lyra_resource::ResourceStorage;
|
use lyra_game::scene::ModelComponent;
|
||||||
|
use lyra_resource::{Model, ResHandle, ResourceStorage};
|
||||||
|
|
||||||
|
use crate::lua::FN_NAME_INTERNAL_AS_COMPONENT;
|
||||||
|
|
||||||
|
use super::LuaModelComponent;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LuaResHandle(pub Arc<dyn ResourceStorage>);
|
pub struct LuaResHandle(pub Arc<dyn ResourceStorage>);
|
||||||
|
@ -46,6 +51,18 @@ impl elua::Userdata for LuaResHandle {
|
||||||
Ok(this.is_loaded())
|
Ok(this.is_loaded())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.method(FN_NAME_INTERNAL_AS_COMPONENT, |lua, this, ()| {
|
||||||
|
let any = this.0.as_any();
|
||||||
|
match any.downcast_ref::<ResHandle<Model>>() {
|
||||||
|
Some(model) => {
|
||||||
|
LuaModelComponent(ModelComponent(model.clone())).as_lua(lua)
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
Ok(elua::Value::Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue