Make implementation of math ops generic, implement math ops on Color3

This commit is contained in:
Filip Tibell 2023-03-15 14:27:06 +01:00
parent 2a6b88e6a7
commit e9b79ea28f
No known key found for this signature in database
6 changed files with 307 additions and 161 deletions

View file

@ -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<D>(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult<D>
where
D: LuaUserData + ops::Mul<D, Output = D> + ops::Mul<f32, Output = D> + 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::<D>() {
return Ok(*datatype * *vec);
}
}
_ => {}
};
Err(LuaError::FromLuaConversionError {
from: rhs.type_name(),
to: type_name::<D>(),
message: Some(format!(
"Expected {} or number, got {}",
type_name::<D>(),
rhs.type_name()
)),
})
}
pub(super) fn userdata_impl_mul_i32<D>(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult<D>
where
D: LuaUserData + ops::Mul<D, Output = D> + ops::Mul<i32, Output = D> + 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::<D>() {
return Ok(*datatype * *vec);
}
}
_ => {}
};
Err(LuaError::FromLuaConversionError {
from: rhs.type_name(),
to: type_name::<D>(),
message: Some(format!(
"Expected {} or number, got {}",
type_name::<D>(),
rhs.type_name()
)),
})
}
pub(super) fn userdata_impl_div_f32<D>(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult<D>
where
D: LuaUserData + ops::Div<D, Output = D> + ops::Div<f32, Output = D> + 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::<D>() {
return Ok(*datatype / *vec);
}
}
_ => {}
};
Err(LuaError::FromLuaConversionError {
from: rhs.type_name(),
to: type_name::<D>(),
message: Some(format!(
"Expected {} or number, got {}",
type_name::<D>(),
rhs.type_name()
)),
})
}
pub(super) fn userdata_impl_div_i32<D>(_: &Lua, datatype: &D, rhs: LuaValue) -> LuaResult<D>
where
D: LuaUserData + ops::Div<D, Output = D> + ops::Div<i32, Output = D> + 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::<D>() {
return Ok(*datatype / *vec);
}
}
_ => {}
};
Err(LuaError::FromLuaConversionError {
from: rhs.type_name(),
to: type_name::<D>(),
message: Some(format!(
"Expected {} or number, got {}",
type_name::<D>(),
rhs.type_name()
)),
})
}

View file

@ -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<f32> 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<f32> 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<RbxColor3> for Color3 {
fn from(v: RbxColor3) -> Self {
Self {

View file

@ -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::<Vector2>() {
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::<Vector2>() {
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<f32> 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<f32> for Vector2 {
type Output = Vector2;
fn div(self, rhs: f32) -> Self::Output {
Self(self.0 / rhs)
}
}
impl From<RbxVector2> for Vector2 {
fn from(v: RbxVector2) -> Self {
Vector2(Vec2 { x: v.x, y: v.y })

View file

@ -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::<Vector2int16>() {
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::<Vector2int16>() {
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<i32> 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<i32> for Vector2int16 {
type Output = Vector2int16;
fn div(self, rhs: i32) -> Self::Output {
Self(self.0 / rhs)
}
}
impl From<RbxVector2int16> for Vector2int16 {
fn from(v: RbxVector2int16) -> Self {
Vector2int16(IVec2 {

View file

@ -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::<Vector3>() {
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::<Vector3>() {
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<f32> 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<f32> for Vector3 {
type Output = Vector3;
fn div(self, rhs: f32) -> Self::Output {
Self(self.0 / rhs)
}
}
impl From<RbxVector3> for Vector3 {
fn from(v: RbxVector3) -> Self {
Vector3(Vec3 {

View file

@ -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::<Vector3int16>() {
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::<Vector3int16>() {
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<i32> 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<i32> for Vector3int16 {
type Output = Vector3int16;
fn div(self, rhs: i32) -> Self::Output {
Self(self.0 / rhs)
}
}
impl From<RbxVector3int16> for Vector3int16 {
fn from(v: RbxVector3int16) -> Self {
Vector3int16(IVec3 {