scripting: fix math type wrapper macro for lua. Expose math types as userdata through LuaProxy trait

This commit is contained in:
SeanOMik 2024-02-19 17:57:48 -05:00
parent ea958f9f18
commit e6b4e83dee
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
10 changed files with 145 additions and 291 deletions

View File

@ -1,5 +1,3 @@
print("Hello World")
--[[ function on_init()
print("Lua script was initialized!")
end
@ -13,27 +11,11 @@ function on_pre_update()
end ]]
function on_update()
--print("Lua's update function was called")
--[[ world:view(
---@param t Transform
function (t)
print("Found entity at a really cool place: " .. tostring(t))
t.translation:move_by(0, 0.001, 0)
return t
end,
Transform
) ]]
---@type number
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.5, 0) * dt:get())
t.translation:move_by(0, 0.5 * dt, 0)
t:translate(0, 0.5 * dt, 0)
return t
end, Transform)

View File

@ -342,7 +342,7 @@ impl Game {
.with(fmt::layer().with_writer(stdout_layer))
.with(filter::Targets::new()
// done by prefix, so it includes all lyra subpackages
.with_target("lyra", Level::TRACE)
.with_target("lyra", Level::DEBUG)
.with_target("wgpu", Level::WARN)
.with_default(Level::INFO))
.init();

View File

@ -85,6 +85,13 @@ impl Transform {
pub fn rotate_z(&mut self, angle: Angle) {
self.rotate(Quat::from_rotation_z(angle.to_radians()))
}
pub fn translate(&mut self, x: f32, y: f32, z: f32) {
let trans = &mut self.translation;
trans.x += x;
trans.y += y;
trans.z += z;
}
/// Performs a linear interpolation between `self` and `rhs` based on the value `alpha`.
///

@ -1 +1 @@
Subproject commit 9b542fb523a3dc5d2eb77b246136111ad8bc4dd2
Subproject commit d32c138e996ec2fe17b7a5f7c0d3ff1562e446f0

View File

@ -140,7 +140,7 @@ impl MetaMethod {
let body = Self::get_method_body(&self.ident, other);
quote! {
methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (#wrapper_ident,)| {
builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (#wrapper_ident,)| {
#body
});
}
@ -149,12 +149,12 @@ impl MetaMethod {
let body = Self::get_body_for_arg(&self.ident, first, quote!(v));
quote! {
methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (#first,)| {
builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (#first,)| {
#body
});
}
} else {
// an optional match arm that matches mlua::Value:Number
// an optional match arm that matches elua::Value:Number
let number_arm = {
let num_ident = self.mods.iter().find(|i| {
let is = i.to_string();
@ -171,7 +171,7 @@ impl MetaMethod {
let body = Self::get_body_for_arg(&self.ident, num_ident, quote!(n as #num_ident));
quote! {
mlua::Value::Number(n) => {
elua::Value::Number(n) => {
#body
},
}
@ -187,7 +187,7 @@ impl MetaMethod {
let body = Self::get_method_body(&self.ident, quote!(other.0));
quote! {
if let Ok(other) = ud.borrow::<#i>() {
if let Ok(other) = ud.as_ref::<#i>() {
#body
}
}
@ -195,30 +195,30 @@ impl MetaMethod {
});
quote! {
mlua::Value::UserData(ud) => {
elua::Value::Userdata(ud) => {
#(#if_statements else)*
// this is the body of the else statement
{
// try to get the name of the userdata for the error message
if let Ok(mt) = ud.get_metatable() {
if let Ok(name) = mt.get::<String>("__name") {
return Err(mlua::Error::BadArgument {
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
pos: 2,
name: Some("rhs".to_string()),
cause: Arc::new(mlua::Error::RuntimeError(
if let Ok(name) = mt.get::<_, String>("__name") {
return Err(elua::Error::BadArgument {
func: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
arg_index: 2,
arg_name: Some("rhs".to_string()),
error: Arc::new(elua::Error::Runtime(
format!("cannot multiply with unknown userdata named {}", name)
))
});
}
}
Err(mlua::Error::BadArgument {
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
pos: 2,
name: Some("rhs".to_string()),
cause: Arc::new(
mlua::Error::runtime("cannot multiply with unknown userdata")
Err(elua::Error::BadArgument {
func: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
arg_index: 2,
arg_name: Some("rhs".to_string()),
error: Arc::new(
elua::Error::runtime("cannot multiply with unknown userdata")
)
})
}
@ -227,16 +227,16 @@ impl MetaMethod {
};
quote! {
methods.add_meta_method(mlua::MetaMethod::#mt_ident, |_, this, (v,): (mlua::Value,)| {
builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (elua::Value,)| {
match v {
#number_arm
#userdata_arm
_ => Err(mlua::Error::BadArgument {
to: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
pos: 2,
name: Some("rhs".to_string()),
cause: Arc::new(
mlua::Error::RuntimeError(format!("cannot multiply with {}", v.type_name()))
_ => Err(elua::Error::BadArgument {
func: Some(format!("{}.__{}", #wrapped_str, #mt_lua_name)),
arg_index: 2,
arg_name: Some("rhs".to_string()),
error: Arc::new(
elua::Error::Runtime(format!("cannot multiply with {}", v.type_name()))
)
})
}
@ -293,8 +293,8 @@ impl VecWrapper {
if axis_type_name.contains("b") {
return quote! {
fields.add_field("FALSE", #wrapper_ident(#wrapped_path::FALSE));
fields.add_field("TRUE", #wrapper_ident(#wrapped_path::TRUE));
builder.field("FALSE", #wrapper_ident(#wrapped_path::FALSE));
builder.field("TRUE", #wrapper_ident(#wrapped_path::TRUE));
};
}
@ -331,7 +331,7 @@ impl VecWrapper {
let const_name = cnst.to_string();
quote! {
fields.add_field(#const_name, #wrapper_ident(#wrapped_path::#cnst));
builder.field(#const_name, #wrapper_ident(#wrapped_path::#cnst));
}
});
@ -356,17 +356,17 @@ impl VecWrapper {
optional_methods.push(
quote! {
methods.add_method("clamp_length",
builder.method("clamp_length",
|_, this, (min, max): (#type_id, #type_id)| {
Ok(#wrapper_ident(this.clamp_length(min, max)))
});
methods.add_method("abs_diff_eq",
builder.method("abs_diff_eq",
|_, this, (rhs, max_abs_diff): (#wrapper_ident, #type_id)| {
Ok(this.abs_diff_eq(rhs.0, max_abs_diff))
});
methods.add_method("ceil",
builder.method("ceil",
|_, this, (): ()| {
Ok(#wrapper_ident(this.ceil()))
});
@ -376,7 +376,7 @@ impl VecWrapper {
if vec_size != 4 {
optional_methods.push(
quote! {
methods.add_method("angle_between",
builder.method("angle_between",
|_, this, (rhs,): (#wrapper_ident,)| {
Ok(this.angle_between(rhs.0))
});
@ -388,7 +388,7 @@ impl VecWrapper {
if !axis_type_name.contains("u") {
optional_methods.push(
quote! {
methods.add_method("abs",
builder.method("abs",
|_, this, (): ()| {
Ok(#wrapper_ident(this.abs()))
});
@ -400,19 +400,19 @@ impl VecWrapper {
quote! {
methods.add_method("clamp",
builder.method("clamp",
|_, this, (min, max): (#wrapper_ident, #wrapper_ident)| {
Ok(#wrapper_ident(this.clamp(min.0, max.0)))
});
// TODO: Not all Vecs have this
/* methods.add_method("clamp_length",
/* builder.method("clamp_length",
|_, this, (min, max): (f32, f32)| {
Ok(#wrapper_ident(this.clamp_length(min, max)))
}); */
methods.add_method("to_array",
builder.method("to_array",
|_, this, (): ()| {
Ok(this.to_array())
});
@ -570,10 +570,10 @@ pub fn wrap_math_vec_copy(input: proc_macro::TokenStream) -> proc_macro::TokenSt
let field_get_set_pairs = input.field_idents.iter().map(|i| {
let is = i.to_string();
quote! {
fields.add_field_method_get(#is, |_, this| {
builder.field_getter(#is, |_, this| {
Ok(this.#i)
});
fields.add_field_method_set(#is, |_, this, #i| {
builder.field_setter(#is, |_, this, #i| {
this.#i = #i;
Ok(())
});
@ -591,7 +591,7 @@ pub fn wrap_math_vec_copy(input: proc_macro::TokenStream) -> proc_macro::TokenSt
if !input.skip_new_fn {
quote! {
methods.add_function("new", |_, ( #(#idents_c),* )| {
builder.function("new", |_, ( #(#idents_c),* )| {
Ok(#wrapper_typename(#path::new( #(#idents),* )))
});
}
@ -631,33 +631,35 @@ pub fn wrap_math_vec_copy(input: proc_macro::TokenStream) -> proc_macro::TokenSt
}
}
impl<'lua> mlua::FromLua<'lua> for #wrapper_typename {
fn from_lua(value: mlua::Value<'lua>, _lua: &'lua mlua::Lua) -> mlua::Result<Self> {
impl<'lua> elua::FromLua<'lua> for #wrapper_typename {
fn from_lua(_lua: &'lua elua::State, value: elua::Value<'lua>) -> elua::Result<Self> {
match value {
mlua::Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
elua::Value::Userdata(ud) => Ok(*ud.as_ref::<Self>()?),
_ => panic!("Attempt to get {} from a {} value", stringify!(#wrapper_typename), value.type_name()),
}
}
}
impl mlua::UserData for #wrapper_typename {
fn add_fields<'lua, F: mlua::prelude::LuaUserDataFields<'lua, Self>>(fields: &mut F) {
impl elua::Userdata for #wrapper_typename {
fn name() -> String {
stringify!(#type_name).to_string()
}
fn build<'a>(_: &elua::State, builder: &mut elua::UserdataBuilder<'a, Self>) -> elua::Result<()> {
#(#field_get_set_pairs)*
#matrix_wrapper_fields
#vec_wrapper_fields
#custom_fields
}
fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
#new_fn_idents
methods.add_method(#FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
builder.method(#FN_NAME_INTERNAL_REFLECT, |_, this, ()| {
Ok(crate::ScriptBorrow::from_component::<#path>(Some(this.0.clone())))
});
methods.add_function(#FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
builder.function(#FN_NAME_INTERNAL_REFLECT_TYPE, |_, ()| {
Ok(crate::ScriptBorrow::from_component::<#path>(None))
});
@ -667,6 +669,8 @@ pub fn wrap_math_vec_copy(input: proc_macro::TokenStream) -> proc_macro::TokenSt
#vec_wrapper_methods
#custom_methods
Ok(())
}
}
@ -677,5 +681,20 @@ pub fn wrap_math_vec_copy(input: proc_macro::TokenStream) -> proc_macro::TokenSt
t
}
}
impl<'a> elua::FromLuaVec<'a> for #wrapper_typename {
fn from_lua_value_vec(state: &'a elua::State, mut values: elua::ValueVec<'a>) -> elua::Result<Self> {
use elua::FromLua;
if let Some(val) = values.pop_front() {
#wrapper_typename::from_lua(state, val)
} else {
Err(elua::Error::IncorrectArgCount {
arg_expected: 1,
arg_count: values.len() as i32,
})
}
}
}
})
}

View File

@ -1,6 +1,5 @@
use elua::TableProxy;
use lyra_ecs::World;
use lyra_game::math::{Quat, Transform, Vec3};
use crate::lua::wrappers::{LuaQuat, LuaTransform, LuaVec3};
use crate::ScriptData;
use crate::lua::RegisterLuaType;
@ -13,31 +12,21 @@ impl ScriptApiProvider for LyraMathApiProvider {
type ScriptContext = LuaContext;
fn prepare_world(&mut self, world: &mut World) {
// TODO
/* world.register_lua_wrapper::<LuaVec3>();
world.register_lua_wrapper::<LuaTransform>(); */
world.register_lua_table_proxy::<LuaVec3, Vec3>();
world.register_lua_table_proxy::<LuaQuat, Quat>();
world.register_lua_table_proxy::<LuaTransform, Transform>();
world.register_lua_wrapper::<LuaVec3>();
world.register_lua_wrapper::<LuaQuat>();
world.register_lua_wrapper::<LuaTransform>();
}
fn expose_api(&mut self, _data: &ScriptData, ctx: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
let ctx = ctx.lock().unwrap();
let bytes = include_bytes!("../../../scripts/lua/math/vec3.lua");
ctx.load("lyra/math/vec2.lua", bytes.as_slice())?.execute(())?;
/* let bytes = include_bytes!("../../../scripts/lua/math/transform.lua");
ctx.load("lyra/math/transform.lua", bytes.as_slice())?.execute(())?; */
let bytes = include_bytes!("../../../scripts/lua/math/quat.lua");
ctx.load("lyra/math/quat.lua", bytes.as_slice())?.execute(())?;
let bytes = include_bytes!("../../../scripts/lua/math/transform.lua");
ctx.load("lyra/math/transform.lua", bytes.as_slice())?.execute(())?;
// TODO
//let globals = ctx.globals()?;
//globals.set("Vec3", elua::Proxy::<LuaVec3>::from(LuaVec3(Vec3::ZERO)))?;
//globals.set("Vec3", ctx.create_proxy::<LuaVec3>()?)?;
//globals.set("Transform", ctx.create_proxy::<LuaTransform>()?)?;
let globals = ctx.globals()?;
globals.set("Vec3", ctx.create_proxy::<LuaVec3>()?)?;
globals.set("Quat", ctx.create_proxy::<LuaQuat>()?)?;
globals.set("Transform", ctx.create_proxy::<LuaTransform>()?)?;
Ok(())
}
@ -49,156 +38,4 @@ impl ScriptApiProvider for LyraMathApiProvider {
fn update_script_environment(&mut self, _: crate::ScriptWorldPtr, _: &crate::ScriptData, _: &mut Self::ScriptContext) -> Result<(), crate::ScriptError> {
Ok(())
}
}
#[derive(Clone, Copy)]
struct LuaVec3(Vec3);
impl TableProxy for LuaVec3 {
fn from_table<'a>(_: &'a elua::State, table: elua::Table<'a>) -> elua::Result<Self> {
let x: f32 = table.get("x")?;
let y: f32 = table.get("y")?;
let z: f32 = table.get("z")?;
Ok(LuaVec3(Vec3 {
x,
y,
z,
}))
}
fn as_table<'a>(&self, state: &'a elua::State) -> elua::Result<elua::Table<'a>> {
let globals = state.globals()?;
let vec3: elua::Table = globals.get("Vec3")?;
let new_fn: elua::Function = vec3.get("new")?;
new_fn.exec((vec3, self.0.x, self.0.y, self.0.z))
}
fn table_name() -> String {
"Vec3".to_string()
}
}
#[derive(Clone, Copy)]
struct LuaQuat(Quat);
impl TableProxy for LuaQuat {
fn from_table<'a>(_: &'a elua::State, table: elua::Table<'a>) -> elua::Result<Self> {
let x: f32 = table.get("x")?;
let y: f32 = table.get("y")?;
let z: f32 = table.get("z")?;
let w: f32 = table.get("w")?;
Ok(LuaQuat(Quat::from_xyzw(x, y, z, w)))
}
fn as_table<'a>(&self, state: &'a elua::State) -> elua::Result<elua::Table<'a>> {
let globals = state.globals()?;
let quat: elua::Table = globals.get("Quat")?;
let new_fn: elua::Function = quat.get("new")?;
new_fn.exec((quat, self.0.x, self.0.y, self.0.z, self.0.w))
}
fn table_name() -> String {
"Quat".to_string()
}
}
#[derive(Clone, Copy)]
struct LuaTransform(Transform);
impl TableProxy for LuaTransform {
fn from_table<'a>(lua: &'a elua::State, table: elua::Table<'a>) -> elua::Result<Self> {
let translation: elua::Table = table.get("translation")?;
let rotation: elua::Table = table.get("rotation")?;
let scale: elua::Table = table.get("scale")?;
let translation = LuaVec3::from_table(lua, translation)?;
let rotation = LuaQuat::from_table(lua, rotation)?;
let scale = LuaVec3::from_table(lua, scale)?;
Ok(LuaTransform(Transform::new(translation.0, rotation.0, scale.0)))
}
fn as_table<'a>(&self, state: &'a elua::State) -> elua::Result<elua::Table<'a>> {
let globals = state.globals()?;
let transform: elua::Table = globals.get("Transform")?;
let new_fn: elua::Function = transform.get("new")?;
let translation = LuaVec3(self.0.translation).as_table(state)?;
let rotation = LuaQuat(self.0.rotation).as_table(state)?;
let scale = LuaVec3(self.0.scale).as_table(state)?;
new_fn.exec((transform, translation, rotation, scale))
}
fn table_name() -> String {
"Transform".to_string()
}
}
/* #[derive(Clone, Copy, PartialEq, Debug, lyra_reflect::Reflect)]
pub struct LuaVec3(#[reflect(skip)] math::Vec3);
impl From<math::Vec3> for LuaVec3 {
fn from(value: math::Vec3) -> Self {
Self(value)
}
}
impl<'lua> mlua::IntoLua<'lua> for LuaVec3 {
fn into_lua(self, lua: &'lua mlua::prelude::Lua) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue<'lua>> {
let globals = lua.globals();
let v3 = globals.get::<_, mlua::Table>("Vec3")?;
let v3_new = v3.get::<_, mlua::Function>("new")?;
v3_new.call::<_, mlua::Table>((v3, self.0.x, self.0.y, self.0.z))
.and_then(|t| t.into_lua(lua))
}
}
#[derive(Clone, Copy, PartialEq, Debug, lyra_reflect::Reflect)]
pub struct LuaQuat(#[reflect(skip)] math::Quat);
impl From<math::Quat> for LuaQuat {
fn from(value: math::Quat) -> Self {
Self(value)
}
}
impl<'lua> mlua::IntoLua<'lua> for LuaQuat {
fn into_lua(self, lua: &'lua mlua::prelude::Lua) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue<'lua>> {
let globals = lua.globals();
let q = globals.get::<_, mlua::Table>("Quat")?;
let q_new = q.get::<_, mlua::Function>("new")?;
q_new.call::<_, mlua::Table>((q, self.0.x, self.0.y, self.0.z, self.0.w))
.and_then(|t| t.into_lua(lua))
}
}
#[derive(Clone, Copy, Debug, lyra_reflect::Reflect)]
pub struct LuaTransform(#[reflect(skip)] math::Transform);
impl From<math::Transform> for LuaTransform {
fn from(value: math::Transform) -> Self {
Self(value)
}
}
impl<'lua> mlua::IntoLua<'lua> for LuaTransform {
fn into_lua(self, lua: &'lua mlua::prelude::Lua) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue<'lua>> {
let globals = lua.globals();
let translation = LuaVec3(self.0.translation).into_lua(lua)?;
let rot = LuaQuat(self.0.rotation).into_lua(lua)?;
let scale = LuaVec3(self.0.scale).into_lua(lua)?;
let transf = globals.get::<_, mlua::Table>("Transform")?;
let transf_new = transf.get::<_, mlua::Function>("new")?;
transf_new.call::<_, mlua::Table>((transf, translation, rot, scale))
.and_then(|t| t.into_lua(lua))
}
} */
}

View File

@ -1,6 +1,6 @@
use std::sync::Mutex;
use elua::{AsLua, StdLibrary};
use elua::{AsLua, StdLibraries};
use crate::{ScriptHost, ScriptError, ScriptWorldPtr, ScriptEntity};
@ -25,12 +25,10 @@ impl ScriptHost for LuaHost {
fn load_script(&mut self, script: &[u8], script_data: &crate::ScriptData, providers: &mut crate::ScriptApiProviders<Self>) -> Result<Self::ScriptContext, crate::ScriptError> {
let mut ctx = Mutex::new({
let s = elua::State::new();
s.expose_libraries(&[StdLibrary::Debug, StdLibrary::Package]);
s.expose_libraries(StdLibraries::all());
s
});
//Mutex::new(elua::State::new_with_libraries(StdLibraries::all()));
for provider in providers.apis.iter_mut() {
provider.expose_api(script_data, &mut ctx)?;
}

View File

@ -75,7 +75,8 @@ impl elua::Userdata for ScriptWorldPtr {
elua::Value::Table(t) => {
let name: String = t.get(elua::MetaMethod::Name)?;
let lookup = world.get_resource::<LuaTableProxyLookup>();
let lookup = world.try_get_resource::<LuaTableProxyLookup>()
.ok_or(elua::Error::runtime("Unable to lookup table proxy, none were ever registered!"))?;
let info = lookup.comp_info_from_name.get(&name)
.ok_or_else(||
elua::Error::BadArgument {

View File

@ -19,7 +19,7 @@ use crate as lyra_scripting;
Mod(LuaVec2, f32),
Eq, Unm, ToString
)
);
); */
wrap_math_vec_copy!(
math::Vec3,
derives(PartialEq),
@ -32,7 +32,7 @@ wrap_math_vec_copy!(
Mod(LuaVec3, f32),
Eq, Unm, ToString
)
); */
);
// =================================================
@ -396,7 +396,7 @@ wrap_math_vec_copy!(
/* wrap_math_vec_copy!(
wrap_math_vec_copy!(
math::Quat,
derives(PartialEq),
no_new,
@ -409,55 +409,55 @@ wrap_math_vec_copy!(
Div(f32),
),
custom_methods {
methods.add_function("new", |_, (x, y, z, w)| {
builder.function("new", |_, (x, y, z, w)| {
Ok(Self(math::Quat::from_xyzw(x, y, z, w)))
});
methods.add_function("from_rotation_x", |_, (rad,)| {
builder.function("from_rotation_x", |_, (rad,)| {
let q = math::Quat::from_rotation_x(rad);
Ok(Self(q))
});
methods.add_function("from_rotation_y", |_, (rad,)| {
builder.function("from_rotation_y", |_, (rad,)| {
let q = math::Quat::from_rotation_y(rad);
Ok(Self(q))
});
methods.add_function("from_rotation_z", |_, (rad,)| {
builder.function("from_rotation_z", |_, (rad,)| {
let q = math::Quat::from_rotation_z(rad);
Ok(Self(q))
});
methods.add_method("dot", |_, this, (rhs,): (Self,)| {
builder.method("dot", |_, this, (rhs,): (Self,)| {
Ok(this.dot(rhs.0))
});
methods.add_method("length", |_, this, ()| {
builder.method("length", |_, this, ()| {
Ok(this.length())
});
methods.add_method("length_squared", |_, this, ()| {
builder.method("length_squared", |_, this, ()| {
Ok(this.length_squared())
});
methods.add_method("normalize", |_, this, ()| {
builder.method("normalize", |_, this, ()| {
Ok(Self(this.normalize()))
});
methods.add_method("mult_quat", |_, this, (rhs,): (Self,)| {
builder.method("mult_quat", |_, this, (rhs,): (Self,)| {
Ok(Self(this.0 * rhs.0))
});
methods.add_method("mult_vec3", |_, this, (rhs,): (LuaVec3,)| {
builder.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,)| {
builder.meta_method(elua::MetaMethod::Mul, |_, this, (rhs,): (LuaVec3,)| {
Ok(LuaVec3(this.0 * rhs.0))
});
methods.add_method("lerp", |_, this, (rhs, alpha): (Self, f32)| {
builder.method("lerp", |_, this, (rhs, alpha): (Self, f32)| {
Ok(Self(this.lerp(*rhs, alpha)))
});
}
@ -469,111 +469,119 @@ wrap_math_vec_copy!(
no_new,
metamethods(ToString, Eq),
custom_fields {
fields.add_field_method_get("translation", |_, this| {
builder.field_getter("translation", |_, this| {
Ok(LuaVec3(this.translation))
});
fields.add_field_method_set("translation", |_, this, v: LuaVec3| {
builder.field_setter("translation", |_, this, v: LuaVec3| {
this.translation = *v;
Ok(())
});
fields.add_field_method_get("rotation", |_, this| {
builder.field_getter("rotation", |_, this| {
Ok(LuaQuat(this.rotation))
});
fields.add_field_method_set("rotation", |_, this, v: LuaQuat| {
builder.field_setter("rotation", |_, this, v: LuaQuat| {
this.rotation = *v;
Ok(())
});
fields.add_field_method_get("scale", |_, this| {
builder.field_getter("scale", |_, this| {
Ok(LuaVec3(this.scale))
});
fields.add_field_method_set("scale", |_, this, v: LuaVec3| {
builder.field_setter("scale", |_, this, v: LuaVec3| {
this.scale = *v;
Ok(())
});
},
custom_methods {
methods.add_function("default", |_, ()| {
builder.function("default", |_, ()| {
Ok(Self(math::Transform::default()))
});
methods.add_function("new", |_, (pos, rot, scale): (LuaVec3, LuaQuat, LuaVec3)| {
builder.function("new", |_, (pos, rot, scale): (LuaVec3, LuaQuat, LuaVec3)| {
Ok(Self(math::Transform::new(*pos, *rot, *scale)))
});
methods.add_function("from_translation", |_, (pos,): (LuaVec3,)| {
builder.function("from_translation", |_, (pos,): (LuaVec3,)| {
Ok(Self(math::Transform::from_translation(*pos)))
});
methods.add_function("from_xyz", |_, (x, y, z)| {
builder.function("from_xyz", |_, (x, y, z)| {
Ok(Self(math::Transform::from_xyz(x, y, z)))
});
methods.add_method("forward", |_, this, ()| {
builder.method("clone", |_, this, ()| {
Ok(this.clone())
});
builder.method("forward", |_, this, ()| {
Ok(LuaVec3(this.forward()))
});
methods.add_method("left", |_, this, ()| {
builder.method("left", |_, this, ()| {
Ok(LuaVec3(this.left()))
});
methods.add_method("up", |_, this, ()| {
builder.method("up", |_, this, ()| {
Ok(LuaVec3(this.up()))
});
methods.add_method_mut("rotate", |_, this, (quat,): (LuaQuat,)| {
builder.method_mut("rotate", |_, this, (quat,): (LuaQuat,)| {
this.rotate(*quat);
Ok(())
});
methods.add_method_mut("rotate_x", |_, this, (deg,): (f32,)| {
builder.method_mut("rotate_x", |_, this, (deg,): (f32,)| {
this.rotate_x(math::Angle::Degrees(deg));
Ok(())
});
methods.add_method_mut("rotate_y", |_, this, (deg,): (f32,)| {
builder.method_mut("rotate_y", |_, this, (deg,): (f32,)| {
this.rotate_y(math::Angle::Degrees(deg));
Ok(())
});
methods.add_method_mut("rotate_z", |_, this, (deg,): (f32,)| {
builder.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,)| {
builder.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,)| {
builder.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,)| {
builder.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)| {
builder.method_mut("translate", |_, this, (x, y, z): (f32, f32, f32)| {
this.translate(x, y, z);
Ok(())
});
builder.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,)| {
builder.meta_method(elua::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,)| {
builder.meta_method(elua::MetaMethod::Add, |_, this, (pos,): (LuaVec3,)| {
let mut t = *this;
t.translation += *pos;
Ok(t)
});
}
);
*/

View File

@ -12,9 +12,11 @@ mkShell rec {
heaptrack
mold
udev
lua5_4_compat
];
buildInputs = [
udev alsa-lib vulkan-loader
udev alsa-lib libGL gcc
vulkan-loader vulkan-headers vulkan-tools
xorg.libX11 xorg.libXcursor xorg.libXi xorg.libXrandr # To use the x11 feature
libxkbcommon wayland # To use the wayland feature
];