Create an early scripting engine #2
|
@ -3,9 +3,8 @@ function on_init()
|
|||
print("Loaded textured cube")
|
||||
|
||||
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))
|
||||
end
|
||||
|
||||
|
|
|
@ -26,13 +26,52 @@ use lyra_ecs::{
|
|||
Component, ComponentInfo, World
|
||||
};
|
||||
use lyra_reflect::{Reflect, TypeRegistry};
|
||||
use crate::ScriptBorrow;
|
||||
|
||||
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";
|
||||
|
||||
/// 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";
|
||||
|
||||
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.
|
||||
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 {
|
||||
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 super::{
|
||||
reflect_user_data, wrappers::LuaResHandle, DynamicViewIter, LuaTableProxyLookup,
|
||||
ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE,
|
||||
reflect_user_data, wrappers::LuaResHandle, DynamicViewIter, LuaTableProxyLookup, ReflectLuaProxy, ReflectedIterator, FN_NAME_INTERNAL_AS_COMPONENT, FN_NAME_INTERNAL_REFLECT, FN_NAME_INTERNAL_REFLECT_TYPE
|
||||
};
|
||||
|
||||
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")),
|
||||
))?;
|
||||
|
||||
let script_brw = ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?;
|
||||
let reflect = script_brw.reflect_branch.as_component_unchecked();
|
||||
let comp_borrow = {
|
||||
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();
|
||||
//let refl_data = refl_data.as_ref();
|
||||
ud.execute_method::<_, ScriptBorrow>(FN_NAME_INTERNAL_REFLECT, ())?
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,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<Self> {
|
||||
fn from_lua(_: &'lua elua::State, _: elua::Value<'lua>) -> elua::Result<Self> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::any::TypeId;
|
||||
use std::{cell::Ref, sync::Arc};
|
||||
|
||||
use elua::{AsLua, FromLua};
|
||||
use elua::FromLua;
|
||||
use lyra_game::scene::ModelComponent;
|
||||
use lyra_reflect::Reflect;
|
||||
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;
|
||||
|
||||
#[derive(Clone, Reflect)]
|
||||
pub struct LuaModelComponent(ModelComponent);
|
||||
pub struct LuaModelComponent(pub ModelComponent);
|
||||
|
||||
impl elua::Userdata for LuaModelComponent {
|
||||
fn name() -> String {
|
||||
|
@ -44,7 +44,8 @@ impl elua::Userdata for LuaModelComponent {
|
|||
})
|
||||
.function(FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
|
||||
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())))
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use elua::FromLua;
|
||||
use lyra_resource::ResourceStorage;
|
||||
use elua::{AsLua, FromLua};
|
||||
use lyra_game::scene::ModelComponent;
|
||||
use lyra_resource::{Model, ResHandle, ResourceStorage};
|
||||
|
||||
use crate::lua::FN_NAME_INTERNAL_AS_COMPONENT;
|
||||
|
||||
use super::LuaModelComponent;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LuaResHandle(pub Arc<dyn ResourceStorage>);
|
||||
|
@ -46,6 +51,18 @@ impl elua::Userdata for LuaResHandle {
|
|||
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(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue