lua: expose WorldTransform
CI / build (pull_request) Failing after 3m20s Details

This commit is contained in:
SeanOMik 2024-10-17 17:11:46 -04:00
parent d0e6fc6ecd
commit d001e136d0
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
9 changed files with 131 additions and 29 deletions

View File

@ -93,13 +93,15 @@ function on_update()
---@type number
local dt = world:resource(DeltaTime)
--[[ world:view(
world:view(
---@param t Transform
function (t)
---@param wt WorldTransform
function (t, wt)
print("Entity is at: " .. tostring(wt))
t:translate(0, 0.15 * dt, 0)
return t
end, Transform
) ]]
end, Transform, WorldTransform
)
--[[ world:view(
---@param c Camera

View File

@ -1,18 +1,10 @@
use lyra_engine::{
assets::{gltf::Gltf, ResourceManager},
game::App,
input::{
assets::{gltf::Gltf, ResourceManager}, game::App, input::{
Action, ActionHandler, ActionKind, ActionMapping, ActionMappingId, ActionSource,
InputActionPlugin, KeyCode, LayoutId, MouseAxis, MouseInput,
},
script::{lua::{LuaScript, LuaScriptingPlugin}, Script, ScriptList},
math::{self, Transform, Vec3},
render::light::directional::DirectionalLight,
scene::{
CameraComponent, FreeFlyCamera, FreeFlyCameraPlugin, WorldTransform,
ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN,
ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN,
},
}, math::{self, Transform, Vec3}, render::light::directional::DirectionalLight, scene::{
self, CameraComponent, FreeFlyCamera, FreeFlyCameraPlugin, WorldTransform, ACTLBL_LOOK_LEFT_RIGHT, ACTLBL_LOOK_ROLL, ACTLBL_LOOK_UP_DOWN, ACTLBL_MOVE_FORWARD_BACKWARD, ACTLBL_MOVE_LEFT_RIGHT, ACTLBL_MOVE_UP_DOWN
}, script::{lua::{LuaScript, LuaScriptingPlugin}, Script, ScriptList}
};
#[async_std::main]
@ -91,6 +83,11 @@ async fn main() {
app.with_plugin(setup_scene_plugin);
app.with_plugin(action_handler_plugin);
app.with_plugin(setup_script_plugin);
app.with_system(
"update_world_transforms",
scene::system_update_world_transforms,
&[],
);
//app.with_plugin(camera_debug_plugin);
app.with_plugin(FreeFlyCameraPlugin);
app.run();

View File

@ -2,6 +2,7 @@ use std::ops::Deref;
use lyra_ecs::{query::{filter::{Has, Not}, Entities, View}, relation::{ChildOf, RelationOriginComponent}, Component, Entity, World};
use lyra_math::Transform;
use lyra_reflect::Reflect;
use crate::lyra_engine;
/// The world transform of an entity.
@ -11,7 +12,7 @@ use crate::lyra_engine;
/// you should use its [`Transform`]. You cannot mutate [`WorldTransform`] as its managed completey
/// by the [`system_update_world_transforms`] system. For the WorldTransform to work properly, you
/// must have both a [`Transform`] and [`WorldTransform`] on the entities in the scene.
#[derive(Debug, Copy, Clone, PartialEq, Default, Component)]
#[derive(Debug, Copy, Clone, PartialEq, Default, Component, Reflect)]
pub struct WorldTransform(pub(crate) Transform);
impl Deref for WorldTransform {

View File

@ -47,7 +47,7 @@ fn field_table_getter(field: &Field) -> proc_macro2::TokenStream {
}
}
fn wrapper_creation(wrapper: &syn::Ident, type_path: &syn::Path, create: Option<&syn::Block>, fields: &Vec<Field>) -> proc_macro2::TokenStream {
fn wrapper_creation(wrapper: &syn::Ident, type_path: &syn::Path, struct_type: StructType, create: Option<&syn::Block>, fields: &Vec<Field>) -> proc_macro2::TokenStream {
match create {
Some(b) => quote!(#b),
@ -59,19 +59,28 @@ fn wrapper_creation(wrapper: &syn::Ident, type_path: &syn::Path, create: Option<
}); */
let field_iter = fields.iter().map(|f| {
let ident = &f.field;
if f.field_ty.is_wrapped() {
if f.field_ty.is_wrapped() && struct_type == StructType::Fields {
quote!(#ident: (*#ident).clone())
} else {
quote!(#ident)
}
});
quote! {
#wrapper(#type_path {
#(
#field_iter
),*
})
match struct_type {
StructType::Fields => {
quote! {
#wrapper(#type_path {
#(
#field_iter
),*
})
}
},
StructType::Tuple => {
quote! {
#wrapper(#type_path( #(#field_iter),* ))
}
},
}
}
}
@ -104,8 +113,17 @@ enum ReflectType {
Resource,
}
/// The type of the wrapping struct
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
enum StructType {
#[default]
Fields,
Tuple,
}
struct IntoLuaUsage {
type_path: syn::Path,
struct_type: StructType,
override_name: Option<syn::Ident>,
table_name: String,
derives: Vec<syn::Ident>,
@ -126,6 +144,7 @@ impl syn::parse::Parse for IntoLuaUsage {
let mut s = Self {
type_path,
struct_type: StructType::Fields,
override_name: None,
table_name: lua_name,
derives: vec![],
@ -149,6 +168,23 @@ impl syn::parse::Parse for IntoLuaUsage {
let name: syn::Ident = input.parse()?;
s.override_name = Some(name);
},
"struct_type" => {
let _eq: Token![=] = input.parse()?;
let st_token = input.parse::<syn::LitStr>()?;
let st_str = st_token.value().to_lowercase();
let st_str = st_str.as_str();
let st = match st_str {
"fields" => StructType::Fields,
"tuple" => StructType::Tuple,
_ => return Err(syn::Error::new_spanned(
st_token,
format!("unknown struct type: '{}', expected 'fields', or `tuple`", st_str),
)),
};
s.struct_type = st;
},
"lua_name" => {
let _eq: Token![=] = input.parse()?;
s.table_name = input.parse::<syn::LitStr>()?.value();
@ -242,7 +278,7 @@ pub fn to_lua_struct_impl(input: proc_macro::TokenStream) -> proc_macro::TokenSt
let lua_name = &input.table_name;
let field_getters_iter = input.fields.iter().map(|f| field_table_getter(f));
let field_setters_iter = input.fields.iter().map(|f| field_table_setter(f));
let struct_creator = wrapper_creation(&wrapper, type_path, input.create.as_ref(), &input.fields);
let struct_creator = wrapper_creation(&wrapper, type_path, input.struct_type, input.create.as_ref(), &input.fields);
let reflect_fn = get_reflect_lua_functions(reflect_type, &input.type_path, true);
let reflect_type_fn = get_reflect_lua_functions(reflect_type, &input.type_path, false);

View File

@ -1,3 +1,5 @@
---@meta
---@class Window: userdata
Window = {
---Gets or sets the window's focus.

View File

@ -0,0 +1,9 @@
---@meta
--- A Transform represents the relative position of the entity to its parent entity, while
--- a world transform is the position relative to the World. When wanting to move an entity,
--- you should use its [`Transform`]. You cannot mutate [`WorldTransform`] as its managed completey
--- by the [`system_update_world_transforms`] system. For the WorldTransform to work properly, you
--- must have both a [`Transform`] and [`WorldTransform`] on the entities in the scene.
---@alias WorldTransform Transform The world transform of an entity.
WorldTransform = {}

View File

@ -19,6 +19,7 @@ impl ScriptApiProvider for LyraEcsApiProvider {
world.register_lua_convert_component::<LuaCamera>("Camera");
world.register_lua_convert_component::<LuaFreeFlyCamera>("FreeFlyCamera");
world.register_lua_convert_component::<LuaWorldTransform>("WorldTransform");
world.register_lua_wrapper::<LuaDeviceId>();
world.register_lua_convert::<LuaDeviceEventRaw>();
@ -44,6 +45,7 @@ impl ScriptApiProvider for LyraEcsApiProvider {
expose_comp_table_wrapper::<LuaCamera>(&ctx, &globals, "Camera")?;
expose_comp_table_wrapper::<LuaFreeFlyCamera>(&ctx, &globals, "FreeFlyCamera")?;
expose_comp_table_wrapper::<LuaWorldTransform>(&ctx, &globals, "WorldTransform")?;
expose_table_wrapper::<LuaDeviceEvent>(&ctx, &globals, "DeviceEvent")?;
let dt_table = create_reflect_table::<lyra_game::DeltaTime>(&ctx)?;
@ -86,11 +88,12 @@ where
table.set(mlua::MetaMethod::Type.name(), name)?;
Ok(table)
}
/// Expose a wrapper that converts to/from a lua type.
/// Expose a wrapper of a component that converts to/from a lua type.
///
/// This type of wrapper could convert to/from a Lua table, or number, string, etc., any Lua type.
///
/// This creates the reflection functions on a table specified in globals.
/// The table name is set to `name`, which is also how the script will use the table.

View File

@ -20,4 +20,7 @@ mod free_fly_camera;
pub use free_fly_camera::*;
mod events;
pub use events::*;
pub use events::*;
mod world_transform;
pub use world_transform::*;

View File

@ -0,0 +1,49 @@
use crate::lua::{wrappers::LuaTransform, LuaWrapper};
use crate::lyra_engine;
use lyra_game::scene::WorldTransform;
use lyra_reflect::Reflect;
#[derive(Clone, Default, Reflect)]
pub struct LuaWorldTransform(pub(crate) WorldTransform);
impl std::ops::Deref for LuaWorldTransform {
type Target = WorldTransform;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for LuaWorldTransform {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl mlua::FromLua for LuaWorldTransform {
fn from_lua(v: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Self> {
let t = LuaTransform::from_lua(v, lua)?;
Ok(Self(WorldTransform::from(*t)))
}
}
impl mlua::IntoLua for LuaWorldTransform {
fn into_lua(self, lua: &mlua::Lua) -> mlua::Result<mlua::Value> {
let t = LuaTransform(*self.0);
t.into_lua(lua)
}
}
impl LuaWrapper for LuaWorldTransform {
type Wrap = WorldTransform;
#[inline(always)]
fn into_wrapped(self) -> Self::Wrap {
self.0
}
#[inline(always)]
fn from_wrapped(wrap: Self::Wrap) -> Option<Self> {
Some(Self(wrap))
}
}