From e9b79ea28f11a8338759ecb29aab36bc7c8d9dfa Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Wed, 15 Mar 2023 14:27:06 +0100 Subject: [PATCH] Make implementation of math ops generic, implement math ops on Color3 --- packages/lib-roblox/src/datatypes/shared.rs | 102 +++++++++++++++++- .../lib-roblox/src/datatypes/types/color3.rs | 86 +++++++++++++++ .../lib-roblox/src/datatypes/types/vector2.rs | 70 ++++++------ .../src/datatypes/types/vector2int16.rs | 70 ++++++------ .../lib-roblox/src/datatypes/types/vector3.rs | 70 ++++++------ .../src/datatypes/types/vector3int16.rs | 70 ++++++------ 6 files changed, 307 insertions(+), 161 deletions(-) diff --git a/packages/lib-roblox/src/datatypes/shared.rs b/packages/lib-roblox/src/datatypes/shared.rs index 10b5070..5ec63b7 100644 --- a/packages/lib-roblox/src/datatypes/shared.rs +++ b/packages/lib-roblox/src/datatypes/shared.rs @@ -1,4 +1,4 @@ -use std::ops; +use std::{any::type_name, ops}; use mlua::prelude::*; @@ -44,3 +44,103 @@ where { Ok(*datatype - value) } + +pub(super) fn userdata_impl_mul_f32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult +where + D: LuaUserData + ops::Mul + ops::Mul + Copy + 'static, +{ + match &rhs { + LuaValue::Number(n) => return Ok(*datatype * *n as f32), + LuaValue::Integer(i) => return Ok(*datatype * *i as f32), + LuaValue::UserData(ud) => { + if let Ok(vec) = ud.borrow::() { + return Ok(*datatype * *vec); + } + } + _ => {} + }; + Err(LuaError::FromLuaConversionError { + from: rhs.type_name(), + to: type_name::(), + message: Some(format!( + "Expected {} or number, got {}", + type_name::(), + rhs.type_name() + )), + }) +} + +pub(super) fn userdata_impl_mul_i32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult +where + D: LuaUserData + ops::Mul + ops::Mul + Copy + 'static, +{ + match &rhs { + LuaValue::Number(n) => return Ok(*datatype * *n as i32), + LuaValue::Integer(i) => return Ok(*datatype * *i), + LuaValue::UserData(ud) => { + if let Ok(vec) = ud.borrow::() { + return Ok(*datatype * *vec); + } + } + _ => {} + }; + Err(LuaError::FromLuaConversionError { + from: rhs.type_name(), + to: type_name::(), + message: Some(format!( + "Expected {} or number, got {}", + type_name::(), + rhs.type_name() + )), + }) +} + +pub(super) fn userdata_impl_div_f32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult +where + D: LuaUserData + ops::Div + ops::Div + Copy + 'static, +{ + match &rhs { + LuaValue::Number(n) => return Ok(*datatype / *n as f32), + LuaValue::Integer(i) => return Ok(*datatype / *i as f32), + LuaValue::UserData(ud) => { + if let Ok(vec) = ud.borrow::() { + return Ok(*datatype / *vec); + } + } + _ => {} + }; + Err(LuaError::FromLuaConversionError { + from: rhs.type_name(), + to: type_name::(), + message: Some(format!( + "Expected {} or number, got {}", + type_name::(), + rhs.type_name() + )), + }) +} + +pub(super) fn userdata_impl_div_i32(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult +where + D: LuaUserData + ops::Div + ops::Div + Copy + 'static, +{ + match &rhs { + LuaValue::Number(n) => return Ok(*datatype / *n as i32), + LuaValue::Integer(i) => return Ok(*datatype / *i), + LuaValue::UserData(ud) => { + if let Ok(vec) = ud.borrow::() { + return Ok(*datatype / *vec); + } + } + _ => {} + }; + Err(LuaError::FromLuaConversionError { + from: rhs.type_name(), + to: type_name::(), + message: Some(format!( + "Expected {} or number, got {}", + type_name::(), + rhs.type_name() + )), + }) +} diff --git a/packages/lib-roblox/src/datatypes/types/color3.rs b/packages/lib-roblox/src/datatypes/types/color3.rs index 38093cd..00731d4 100644 --- a/packages/lib-roblox/src/datatypes/types/color3.rs +++ b/packages/lib-roblox/src/datatypes/types/color3.rs @@ -1,4 +1,5 @@ use core::fmt; +use std::ops; use glam::Vec3; use mlua::prelude::*; @@ -10,6 +11,9 @@ use super::super::*; An implementation of the [Color3](https://create.roblox.com/docs/reference/engine/datatypes/Color3) Roblox datatype. This implements all documented properties, methods & constructors of the Color3 class as of March 2023. + + It also implements math operations for addition, subtraction, multiplication, and division, + all of which are suspiciously missing from the Roblox implementation of the Color3 datatype. */ #[derive(Debug, Clone, Copy, PartialEq)] pub struct Color3 { @@ -151,6 +155,11 @@ impl LuaUserData for Color3 { // Metamethods methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq); methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string); + methods.add_meta_method(LuaMetaMethod::Unm, userdata_impl_unm); + methods.add_meta_method(LuaMetaMethod::Add, userdata_impl_add); + methods.add_meta_method(LuaMetaMethod::Sub, userdata_impl_sub); + methods.add_meta_method(LuaMetaMethod::Mul, userdata_impl_mul_f32); + methods.add_meta_method(LuaMetaMethod::Div, userdata_impl_div_f32); } } @@ -170,6 +179,83 @@ impl fmt::Display for Color3 { } } +impl ops::Neg for Color3 { + type Output = Self; + fn neg(self) -> Self::Output { + Color3 { + r: -self.r, + g: -self.g, + b: -self.b, + } + } +} + +impl ops::Add for Color3 { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + Color3 { + r: self.r + rhs.r, + g: self.g + rhs.g, + b: self.b + rhs.b, + } + } +} + +impl ops::Sub for Color3 { + type Output = Self; + fn sub(self, rhs: Self) -> Self::Output { + Color3 { + r: self.r - rhs.r, + g: self.g - rhs.g, + b: self.b - rhs.b, + } + } +} + +impl ops::Mul for Color3 { + type Output = Color3; + fn mul(self, rhs: Self) -> Self::Output { + Color3 { + r: self.r * rhs.r, + g: self.g * rhs.g, + b: self.b * rhs.b, + } + } +} + +impl ops::Mul for Color3 { + type Output = Color3; + fn mul(self, rhs: f32) -> Self::Output { + Color3 { + r: self.r * rhs, + g: self.g * rhs, + b: self.b * rhs, + } + } +} + +impl ops::Div for Color3 { + type Output = Color3; + fn div(self, rhs: Self) -> Self::Output { + Color3 { + r: self.r / rhs.r, + g: self.g / rhs.g, + b: self.b / rhs.b, + } + } +} + +impl ops::Div for Color3 { + type Output = Color3; + fn div(self, rhs: f32) -> Self::Output { + Color3 { + r: self.r / rhs, + g: self.g / rhs, + b: self.b / rhs, + } + } +} + impl From for Color3 { fn from(v: RbxColor3) -> Self { Self { diff --git a/packages/lib-roblox/src/datatypes/types/vector2.rs b/packages/lib-roblox/src/datatypes/types/vector2.rs index 1e1d8e1..39f588d 100644 --- a/packages/lib-roblox/src/datatypes/types/vector2.rs +++ b/packages/lib-roblox/src/datatypes/types/vector2.rs @@ -68,46 +68,8 @@ impl LuaUserData for Vector2 { methods.add_meta_method(LuaMetaMethod::Unm, userdata_impl_unm); methods.add_meta_method(LuaMetaMethod::Add, userdata_impl_add); methods.add_meta_method(LuaMetaMethod::Sub, userdata_impl_sub); - methods.add_meta_method(LuaMetaMethod::Mul, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector2(this.0 * Vec2::splat(*n as f32))), - LuaValue::Integer(i) => return Ok(Vector2(this.0 * Vec2::splat(*i as f32))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector2(this.0 * vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector2", - message: Some(format!( - "Expected Vector2 or number, got {}", - rhs.type_name() - )), - }) - }); - methods.add_meta_method(LuaMetaMethod::Div, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector2(this.0 / Vec2::splat(*n as f32))), - LuaValue::Integer(i) => return Ok(Vector2(this.0 / Vec2::splat(*i as f32))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector2(this.0 / vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector2", - message: Some(format!( - "Expected Vector2 or number, got {}", - rhs.type_name() - )), - }) - }); + methods.add_meta_method(LuaMetaMethod::Mul, userdata_impl_mul_f32); + methods.add_meta_method(LuaMetaMethod::Div, userdata_impl_div_f32); } } @@ -138,6 +100,34 @@ impl ops::Sub for Vector2 { } } +impl ops::Mul for Vector2 { + type Output = Vector2; + fn mul(self, rhs: Self) -> Self::Output { + Self(self.0 * rhs.0) + } +} + +impl ops::Mul for Vector2 { + type Output = Vector2; + fn mul(self, rhs: f32) -> Self::Output { + Self(self.0 * rhs) + } +} + +impl ops::Div for Vector2 { + type Output = Vector2; + fn div(self, rhs: Self) -> Self::Output { + Self(self.0 / rhs.0) + } +} + +impl ops::Div for Vector2 { + type Output = Vector2; + fn div(self, rhs: f32) -> Self::Output { + Self(self.0 / rhs) + } +} + impl From for Vector2 { fn from(v: RbxVector2) -> Self { Vector2(Vec2 { x: v.x, y: v.y }) diff --git a/packages/lib-roblox/src/datatypes/types/vector2int16.rs b/packages/lib-roblox/src/datatypes/types/vector2int16.rs index 08aa5c3..73f9536 100644 --- a/packages/lib-roblox/src/datatypes/types/vector2int16.rs +++ b/packages/lib-roblox/src/datatypes/types/vector2int16.rs @@ -43,46 +43,8 @@ impl LuaUserData for Vector2int16 { methods.add_meta_method(LuaMetaMethod::Unm, userdata_impl_unm); methods.add_meta_method(LuaMetaMethod::Add, userdata_impl_add); methods.add_meta_method(LuaMetaMethod::Sub, userdata_impl_sub); - methods.add_meta_method(LuaMetaMethod::Mul, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector2int16(this.0 * IVec2::splat(*n as i32))), - LuaValue::Integer(i) => return Ok(Vector2int16(this.0 * IVec2::splat(*i))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector2int16(this.0 * vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector2int16", - message: Some(format!( - "Expected Vector2int16 or number, got {}", - rhs.type_name() - )), - }) - }); - methods.add_meta_method(LuaMetaMethod::Div, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector2int16(this.0 / IVec2::splat(*n as i32))), - LuaValue::Integer(i) => return Ok(Vector2int16(this.0 / IVec2::splat(*i))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector2int16(this.0 / vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector2int16", - message: Some(format!( - "Expected Vector2int16 or number, got {}", - rhs.type_name() - )), - }) - }); + methods.add_meta_method(LuaMetaMethod::Mul, userdata_impl_mul_i32); + methods.add_meta_method(LuaMetaMethod::Div, userdata_impl_div_i32); } } @@ -113,6 +75,34 @@ impl ops::Sub for Vector2int16 { } } +impl ops::Mul for Vector2int16 { + type Output = Vector2int16; + fn mul(self, rhs: Self) -> Self::Output { + Self(self.0 * rhs.0) + } +} + +impl ops::Mul for Vector2int16 { + type Output = Vector2int16; + fn mul(self, rhs: i32) -> Self::Output { + Self(self.0 * rhs) + } +} + +impl ops::Div for Vector2int16 { + type Output = Vector2int16; + fn div(self, rhs: Self) -> Self::Output { + Self(self.0 / rhs.0) + } +} + +impl ops::Div for Vector2int16 { + type Output = Vector2int16; + fn div(self, rhs: i32) -> Self::Output { + Self(self.0 / rhs) + } +} + impl From for Vector2int16 { fn from(v: RbxVector2int16) -> Self { Vector2int16(IVec2 { diff --git a/packages/lib-roblox/src/datatypes/types/vector3.rs b/packages/lib-roblox/src/datatypes/types/vector3.rs index 1d90f88..8f7a7a5 100644 --- a/packages/lib-roblox/src/datatypes/types/vector3.rs +++ b/packages/lib-roblox/src/datatypes/types/vector3.rs @@ -82,46 +82,8 @@ impl LuaUserData for Vector3 { methods.add_meta_method(LuaMetaMethod::Unm, userdata_impl_unm); methods.add_meta_method(LuaMetaMethod::Add, userdata_impl_add); methods.add_meta_method(LuaMetaMethod::Sub, userdata_impl_sub); - methods.add_meta_method(LuaMetaMethod::Mul, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector3(this.0 * Vec3::splat(*n as f32))), - LuaValue::Integer(i) => return Ok(Vector3(this.0 * Vec3::splat(*i as f32))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector3(this.0 * vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector3", - message: Some(format!( - "Expected Vector3 or number, got {}", - rhs.type_name() - )), - }) - }); - methods.add_meta_method(LuaMetaMethod::Div, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector3(this.0 / Vec3::splat(*n as f32))), - LuaValue::Integer(i) => return Ok(Vector3(this.0 / Vec3::splat(*i as f32))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector3(this.0 / vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector3", - message: Some(format!( - "Expected Vector3 or number, got {}", - rhs.type_name() - )), - }) - }); + methods.add_meta_method(LuaMetaMethod::Mul, userdata_impl_mul_f32); + methods.add_meta_method(LuaMetaMethod::Div, userdata_impl_div_f32); } } @@ -152,6 +114,34 @@ impl ops::Sub for Vector3 { } } +impl ops::Mul for Vector3 { + type Output = Vector3; + fn mul(self, rhs: Self) -> Self::Output { + Self(self.0 * rhs.0) + } +} + +impl ops::Mul for Vector3 { + type Output = Vector3; + fn mul(self, rhs: f32) -> Self::Output { + Self(self.0 * rhs) + } +} + +impl ops::Div for Vector3 { + type Output = Vector3; + fn div(self, rhs: Self) -> Self::Output { + Self(self.0 / rhs.0) + } +} + +impl ops::Div for Vector3 { + type Output = Vector3; + fn div(self, rhs: f32) -> Self::Output { + Self(self.0 / rhs) + } +} + impl From for Vector3 { fn from(v: RbxVector3) -> Self { Vector3(Vec3 { diff --git a/packages/lib-roblox/src/datatypes/types/vector3int16.rs b/packages/lib-roblox/src/datatypes/types/vector3int16.rs index 3e70164..93111c0 100644 --- a/packages/lib-roblox/src/datatypes/types/vector3int16.rs +++ b/packages/lib-roblox/src/datatypes/types/vector3int16.rs @@ -45,46 +45,8 @@ impl LuaUserData for Vector3int16 { methods.add_meta_method(LuaMetaMethod::Unm, userdata_impl_unm); methods.add_meta_method(LuaMetaMethod::Add, userdata_impl_add); methods.add_meta_method(LuaMetaMethod::Sub, userdata_impl_sub); - methods.add_meta_method(LuaMetaMethod::Mul, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector3int16(this.0 * IVec3::splat(*n as i32))), - LuaValue::Integer(i) => return Ok(Vector3int16(this.0 * IVec3::splat(*i))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector3int16(this.0 * vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector3int16", - message: Some(format!( - "Expected Vector3int16 or number, got {}", - rhs.type_name() - )), - }) - }); - methods.add_meta_method(LuaMetaMethod::Div, |_, this, rhs: LuaValue| { - match &rhs { - LuaValue::Number(n) => return Ok(Vector3int16(this.0 / IVec3::splat(*n as i32))), - LuaValue::Integer(i) => return Ok(Vector3int16(this.0 / IVec3::splat(*i))), - LuaValue::UserData(ud) => { - if let Ok(vec) = ud.borrow::() { - return Ok(Vector3int16(this.0 / vec.0)); - } - } - _ => {} - }; - Err(LuaError::FromLuaConversionError { - from: rhs.type_name(), - to: "Vector3int16", - message: Some(format!( - "Expected Vector3int16 or number, got {}", - rhs.type_name() - )), - }) - }); + methods.add_meta_method(LuaMetaMethod::Mul, userdata_impl_mul_i32); + methods.add_meta_method(LuaMetaMethod::Div, userdata_impl_div_i32); } } @@ -115,6 +77,34 @@ impl ops::Sub for Vector3int16 { } } +impl ops::Mul for Vector3int16 { + type Output = Vector3int16; + fn mul(self, rhs: Self) -> Self::Output { + Self(self.0 * rhs.0) + } +} + +impl ops::Mul for Vector3int16 { + type Output = Vector3int16; + fn mul(self, rhs: i32) -> Self::Output { + Self(self.0 * rhs) + } +} + +impl ops::Div for Vector3int16 { + type Output = Vector3int16; + fn div(self, rhs: Self) -> Self::Output { + Self(self.0 / rhs.0) + } +} + +impl ops::Div for Vector3int16 { + type Output = Vector3int16; + fn div(self, rhs: i32) -> Self::Output { + Self(self.0 / rhs) + } +} + impl From for Vector3int16 { fn from(v: RbxVector3int16) -> Self { Vector3int16(IVec3 {