scripting: Implement LuaVec3:move_by, and add more methods for Lua on math types

This commit is contained in:
SeanOMik 2024-02-19 23:14:38 -05:00
parent e6b4e83dee
commit e354528942
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
5 changed files with 170 additions and 78 deletions

View File

@ -14,6 +14,11 @@ function on_update()
---@type number ---@type number
local dt = world:resource(DeltaTime) local dt = world:resource(DeltaTime)
local v = Vec3.new(10, 10, 10)
v:move_by(50, 50, 50)
v:move_by(Vec3.new(50, 50, 50))
print("v = " .. tostring(v))
world:view(function (t) world:view(function (t)
t:translate(0, 0.5 * dt, 0) t:translate(0, 0.5 * dt, 0)

@ -1 +1 @@
Subproject commit d32c138e996ec2fe17b7a5f7c0d3ff1562e446f0 Subproject commit 22b6d218bdb6a5aafc0efd4fb80a67d2c796d0e7

View File

@ -38,6 +38,22 @@ impl MetaMethod {
s.starts_with("Lua") s.starts_with("Lua")
} }
/// Returns a boolean indiciating if the metamethod has takes in any arguments
fn does_metamethod_have_arg(metamethod: &Ident) -> bool {
let mm_str = metamethod.to_string();
let mm_str = mm_str.as_str();
match mm_str {
"Add" | "Sub" | "Div" | "Mul" | "Mod" | "Eq" | "Shl" | "Shr" | "BAnd" | "BOr"
| "BXor" => {
true
},
"Unm" | "BNot" | "ToString" => {
false
},
_ => todo!(),
}
}
/// returns the tokens of the body of the metamethod /// returns the tokens of the body of the metamethod
/// ///
/// Parameters /// Parameters
@ -139,11 +155,20 @@ impl MetaMethod {
}; };
let body = Self::get_method_body(&self.ident, other); let body = Self::get_method_body(&self.ident, other);
quote! { if Self::does_metamethod_have_arg(&self.ident) {
builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (#wrapper_ident,)| { quote! {
#body builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, (v,): (#wrapper_ident,)| {
}); #body
});
}
} else {
quote! {
builder.meta_method(elua::MetaMethod::#mt_ident, |_, this, ()| {
#body
});
}
} }
} else if self.mods.len() == 1 { } else if self.mods.len() == 1 {
let first = self.mods.iter().next().unwrap(); let first = self.mods.iter().next().unwrap();
let body = Self::get_body_for_arg(&self.ident, first, quote!(v)); let body = Self::get_body_for_arg(&self.ident, first, quote!(v));

View File

@ -9,9 +9,9 @@ pub(crate) struct MatWrapper {
impl MatWrapper { impl MatWrapper {
pub fn to_field_tokens(&self, wrapped_path: &Path, wrapper_ident: &Ident) -> proc_macro2::TokenStream { pub fn to_field_tokens(&self, wrapped_path: &Path, wrapper_ident: &Ident) -> proc_macro2::TokenStream {
quote! { quote! {
fields.add_field("ZERO", #wrapper_ident(#wrapped_path::ZERO)); builder.field("ZERO", #wrapper_ident(#wrapped_path::ZERO));
fields.add_field("IDENTITY", #wrapper_ident(#wrapped_path::IDENTITY)); builder.field("IDENTITY", #wrapper_ident(#wrapped_path::IDENTITY));
fields.add_field("NAN", #wrapper_ident(#wrapped_path::NAN)); builder.field("NAN", #wrapper_ident(#wrapped_path::NAN));
} }
} }
@ -28,37 +28,37 @@ impl MatWrapper {
let element_ty = quote!(f32); let element_ty = quote!(f32);
quote! { quote! {
methods.add_function("from_cols", builder.function("from_cols",
|_, (x_axis, y_axis): (#column_type, #column_type)| { |_, (x_axis, y_axis): (#column_type, #column_type)| {
Ok(#wrapper_ident(#wrapped_path::from_cols(x_axis.0, y_axis.0))) Ok(#wrapper_ident(#wrapped_path::from_cols(x_axis.0, y_axis.0)))
}); });
methods.add_function("from_cols_array", builder.function("from_cols_array",
|_, (arr,): ([#element_ty; #column_size_xtwo],)| { |_, (arr,): ([#element_ty; #column_size_xtwo],)| {
Ok(#wrapper_ident(#wrapped_path::from_cols_array(&arr))) Ok(#wrapper_ident(#wrapped_path::from_cols_array(&arr)))
}); });
methods.add_function("from_cols_array_2d", builder.function("from_cols_array_2d",
|_, (arr,): ([[#element_ty; #column_size]; #column_size],)| { |_, (arr,): ([[#element_ty; #column_size]; #column_size],)| {
Ok(#wrapper_ident(#wrapped_path::from_cols_array_2d(&arr))) Ok(#wrapper_ident(#wrapped_path::from_cols_array_2d(&arr)))
}); });
methods.add_function("from_diagonal", builder.function("from_diagonal",
|_, (diag,): (#column_type,)| { |_, (diag,): (#column_type,)| {
Ok(#wrapper_ident(#wrapped_path::from_diagonal(diag.0))) Ok(#wrapper_ident(#wrapped_path::from_diagonal(diag.0)))
}); });
methods.add_method("col", builder.method("col",
|_, this, (idx,): (usize,)| { |_, this, (idx,): (usize,)| {
Ok(#column_type(this.col(idx))) Ok(#column_type(this.col(idx)))
}); });
methods.add_method("row", builder.method("row",
|_, this, (idx,): (usize,)| { |_, this, (idx,): (usize,)| {
Ok(#column_type(this.row(idx))) Ok(#column_type(this.row(idx)))
}); });
methods.add_method_mut("set_col", builder.method_mut("set_col",
|_, this, (idx, newc): (usize, #column_type)| { |_, this, (idx, newc): (usize, #column_type)| {
let col = this.col_mut(idx); let col = this.col_mut(idx);
*col = newc.0; *col = newc.0;
@ -66,38 +66,38 @@ impl MatWrapper {
Ok(()) Ok(())
}); });
methods.add_method("is_finite", builder.method("is_finite",
|_, this, (): ()| { |_, this, (): ()| {
Ok(this.is_finite()) Ok(this.is_finite())
}); });
methods.add_method("is_nan", builder.method("is_nan",
|_, this, (): ()| { |_, this, (): ()| {
Ok(this.is_nan()) Ok(this.is_nan())
}); });
methods.add_method("transpose", builder.method("transpose",
|_, this, (): ()| { |_, this, (): ()| {
Ok(#wrapper_ident(this.0.transpose())) Ok(#wrapper_ident(this.0.transpose()))
}); });
methods.add_method("determinant", builder.method("determinant",
|_, this, (): ()| { |_, this, (): ()| {
Ok(this.determinant()) Ok(this.determinant())
}); });
methods.add_method("inverse", builder.method("inverse",
|_, this, (): ()| { |_, this, (): ()| {
Ok(#wrapper_ident(this.inverse())) Ok(#wrapper_ident(this.inverse()))
}); });
methods.add_method("abs_diff_eq", builder.method("abs_diff_eq",
|_, this, (rhs, max_abs_diff): (#wrapper_ident, f32)| { |_, this, (rhs, max_abs_diff): (#wrapper_ident, f32)| {
Ok(this.abs_diff_eq(rhs.0, max_abs_diff)) Ok(this.abs_diff_eq(rhs.0, max_abs_diff))
}); });
// TODO: After all DMat's are implemented // TODO: After all DMat's are implemented
/* methods.add_method("as_dmat", /* builder.method("as_dmat",
|_, this, (rhs, max_abs_diff): (#wrapper_ident, f32)| { |_, this, (rhs, max_abs_diff): (#wrapper_ident, f32)| {
Ok(D#wrapper_ident(this.as_dmat)) Ok(D#wrapper_ident(this.as_dmat))
}); */ }); */

View File

@ -7,7 +7,7 @@ use lyra_scripting_derive::wrap_math_vec_copy;
use crate as lyra_scripting; use crate as lyra_scripting;
// f32 types // f32 types
/* wrap_math_vec_copy!( wrap_math_vec_copy!(
math::Vec2, math::Vec2,
derives(PartialEq), derives(PartialEq),
fields(x, y), fields(x, y),
@ -18,8 +18,21 @@ use crate as lyra_scripting;
Mul(LuaVec2, f32), Mul(LuaVec2, f32),
Mod(LuaVec2, f32), Mod(LuaVec2, f32),
Eq, Unm, ToString Eq, Unm, ToString
) ),
); */ custom_methods {
builder.method_mut("move_by", |lua, this, vals: elua::ValueVec| {
let vals_clone = vals.clone();
if let Some((x, y)) = vals.try_into_vals::<(f32, f32)>(lua)? {
this.x += x;
this.y += y;
} else if let Some(v) = vals_clone.try_into_vals::<Self>(lua)? {
this.0 += v.0;
}
Ok(())
});
}
);
wrap_math_vec_copy!( wrap_math_vec_copy!(
math::Vec3, math::Vec3,
derives(PartialEq), derives(PartialEq),
@ -31,9 +44,36 @@ wrap_math_vec_copy!(
Mul(LuaVec3, f32), Mul(LuaVec3, f32),
Mod(LuaVec3, f32), Mod(LuaVec3, f32),
Eq, Unm, ToString Eq, Unm, ToString
) ),
custom_methods {
builder.method_mut("move_by", |lua, this, vals: elua::ValueVec| {
let vals_clone = vals.clone();
if let Some((x, y, z)) = vals.try_into_vals::<(f32, f32, f32)>(lua)? {
this.x += x;
this.y += y;
this.z += z;
} else if let Some(v) = vals_clone.try_into_vals::<Self>(lua)? {
this.0 += v.0;
}
Ok(())
});
}
); );
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
)
);
// ================================================= // =================================================
@ -51,19 +91,7 @@ wrap_math_vec_copy!(
Eq, Unm 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 // f64 types
wrap_math_vec_copy!( wrap_math_vec_copy!(
@ -328,30 +356,30 @@ wrap_math_vec_copy!(
BXor(LuaU64Vec4, u64), BXor(LuaU64Vec4, u64),
Eq, BNot Eq, BNot
) )
); );*/
// bool types // bool types
wrap_math_vec_copy!( /* wrap_math_vec_copy!(
math::BVec2, math::BVec2,
derives(PartialEq, Eq, Hash), derives(PartialEq, Eq, Hash),
fields(x, y), fields(x, y),
metamethods(Eq, BAnd, BOr, BXor, BNot) metamethods(Eq, BAnd, BOr, BXOr, BNot)
); );
wrap_math_vec_copy!( wrap_math_vec_copy!(
math::BVec3, math::BVec3,
derives(PartialEq, Eq, Hash), derives(PartialEq, Eq, Hash),
fields(x, y, z), fields(x, y, z),
metamethods(Eq, BAnd, BOr, BXor, BNot) metamethods(Eq, BAnd, BOr, BXOr, BNot)
); );
wrap_math_vec_copy!( wrap_math_vec_copy!(
math::BVec4, math::BVec4,
derives(PartialEq, Eq, Hash), derives(PartialEq, Eq, Hash),
fields(w, x, y, z), fields(w, x, y, z),
metamethods(Eq, BAnd, BOr, BXor, BNot) metamethods(Eq, BAnd, BOr, BXOr, BNot)
); ); */
// mat2 // mat2
wrap_math_vec_copy!( /* wrap_math_vec_copy!(
math::Mat2, math::Mat2,
derives(PartialEq), derives(PartialEq),
no_new, no_new,
@ -367,6 +395,7 @@ wrap_math_vec_copy!(
) )
); */ ); */
// TODO
/* wrap_math_vec_copy!( /* wrap_math_vec_copy!(
math::Mat4, math::Mat4,
derives(PartialEq), derives(PartialEq),
@ -392,8 +421,31 @@ wrap_math_vec_copy!(
/// A macro that generates field getters and setters for lua wrapped types.
macro_rules! wrapped_field_getsetters {
($builder: ident, $name: literal, $field: ident, $type: ident) => {
$builder.field_getter($name, |_, this| {
Ok($type(this.$field))
});
$builder.field_setter($name, |_, this, v: $type| {
this.$field = *v;
Ok(())
});
};
}
/// A macro that generates field getters and setters for types that already implement As/FromLua.
macro_rules! field_getsetters {
($builder: ident, $name: literal, $field: ident, $type: ty) => {
$builder.field_getter($name, |_, this| {
Ok(this.$field)
});
$builder.field_setter($name, |_, this, v: $type| {
this.$field = v;
Ok(())
});
};
}
wrap_math_vec_copy!( wrap_math_vec_copy!(
@ -403,12 +455,19 @@ wrap_math_vec_copy!(
metamethods( metamethods(
Eq, Eq,
// __mul for LuaVec3 is manually implemented below since it doesn't return Self // __mul for LuaVec3 is manually implemented below since it doesn't return Self
Mul(LuaQuat, f32), //Mul(LuaQuat, f32),
Add, Add,
Sub, Sub,
Div(f32), Div(f32),
), ),
custom_fields {
field_getsetters!(builder, "x", x, f32);
field_getsetters!(builder, "y", y, f32);
field_getsetters!(builder, "z", z, f32);
field_getsetters!(builder, "w", w, f32);
},
custom_methods { custom_methods {
// manually implemented since Quat doesn't have a `new` function
builder.function("new", |_, (x, y, z, w)| { builder.function("new", |_, (x, y, z, w)| {
Ok(Self(math::Quat::from_xyzw(x, y, z, w))) Ok(Self(math::Quat::from_xyzw(x, y, z, w)))
}); });
@ -440,21 +499,44 @@ wrap_math_vec_copy!(
Ok(this.length_squared()) Ok(this.length_squared())
}); });
builder.method("normalize", |_, this, ()| { builder.method_mut("normalize", |_, this, ()| {
Ok(Self(this.normalize())) this.0 = this.normalize();
Ok(())
}); });
builder.method("mult_quat", |_, this, (rhs,): (Self,)| { builder.method_mut("mult_quat", |_, this, (rhs,): (Self,)| {
Ok(Self(this.0 * rhs.0)) this.0 *= rhs.0;
Ok(())
}); });
builder.method("mult_vec3", |_, this, (rhs,): (LuaVec3,)| { builder.method("mult_vec3", |_, this, (rhs,): (LuaVec3,)| {
Ok(LuaVec3(this.0 * rhs.0)) Ok(LuaVec3(this.0 * rhs.0))
}); });
// manually implemented here since it doesn't return `Self` // manually implemented here since multiplying may not return `Self`.
builder.meta_method(elua::MetaMethod::Mul, |_, this, (rhs,): (LuaVec3,)| { builder.meta_method(elua::MetaMethod::Mul, |lua, this, (val,): (elua::Value,)| {
Ok(LuaVec3(this.0 * rhs.0)) use elua::AsLua;
match val {
elua::Value::Userdata(ud) => {
if ud.is::<LuaVec3>()? {
let v3 = ud.as_ref::<LuaVec3>()?;
LuaVec3(this.0 * v3.0)
.as_lua(lua)
} else {
let quat = ud.as_ref::<LuaQuat>()?;
LuaQuat(this.0 * quat.0)
.as_lua(lua)
}
},
elua::Value::Number(n) => {
LuaQuat(this.0 * (n as f32))
.as_lua(lua)
},
_ => {
todo!()
}
}
}); });
builder.method("lerp", |_, this, (rhs, alpha): (Self, f32)| { builder.method("lerp", |_, this, (rhs, alpha): (Self, f32)| {
@ -469,29 +551,9 @@ wrap_math_vec_copy!(
no_new, no_new,
metamethods(ToString, Eq), metamethods(ToString, Eq),
custom_fields { custom_fields {
builder.field_getter("translation", |_, this| { wrapped_field_getsetters!(builder, "translation", translation, LuaVec3);
Ok(LuaVec3(this.translation)) wrapped_field_getsetters!(builder, "rotation", rotation, LuaQuat);
}); wrapped_field_getsetters!(builder, "scale", scale, LuaVec3);
builder.field_setter("translation", |_, this, v: LuaVec3| {
this.translation = *v;
Ok(())
});
builder.field_getter("rotation", |_, this| {
Ok(LuaQuat(this.rotation))
});
builder.field_setter("rotation", |_, this, v: LuaQuat| {
this.rotation = *v;
Ok(())
});
builder.field_getter("scale", |_, this| {
Ok(LuaVec3(this.scale))
});
builder.field_setter("scale", |_, this, v: LuaVec3| {
this.scale = *v;
Ok(())
});
}, },
custom_methods { custom_methods {
builder.function("default", |_, ()| { builder.function("default", |_, ()| {