Implement int vector roblox types

This commit is contained in:
Filip Tibell 2023-03-11 10:20:22 +01:00
parent d23366fc98
commit fd369f707f
No known key found for this signature in database
3 changed files with 309 additions and 6 deletions

View file

@ -5,11 +5,15 @@ pub(crate) use rbx_dom_weak::types::{Variant as RbxVariant, VariantType as RbxVa
// NOTE: We create a new inner module scope here to make imports of datatypes more ergonomic
mod vector2;
mod vector2int16;
mod vector3;
mod vector3int16;
pub mod types {
pub use super::vector2::Vector2;
pub use super::vector2int16::Vector2int16;
pub use super::vector3::Vector3;
pub use super::vector3int16::Vector3int16;
}
// Trait definitions for conversion between rbx_dom_weak variant <-> our custom datatypes
@ -142,12 +146,12 @@ impl RbxVariantDisplayName for RbxVariant {
// Generic impls for converting from lua values <-> rbx_dom_weak variants
// We use a separate trait here since creating lua stuff needs the lua context
pub(crate) trait FromRbxVariantLua<'lua>: Sized {
fn from_rbx_variant_lua(variant: &RbxVariant, lua: &'lua Lua) -> RbxConversionResult<Self>;
pub(crate) trait RbxVariantToLua<'lua>: Sized {
fn rbx_variant_to_lua(variant: &RbxVariant, lua: &'lua Lua) -> RbxConversionResult<Self>;
}
impl<'lua> FromRbxVariantLua<'lua> for LuaValue<'lua> {
fn from_rbx_variant_lua(variant: &RbxVariant, lua: &'lua Lua) -> RbxConversionResult<Self> {
impl<'lua> RbxVariantToLua<'lua> for LuaValue<'lua> {
fn rbx_variant_to_lua(variant: &RbxVariant, lua: &'lua Lua) -> RbxConversionResult<Self> {
use self::types::*;
use base64::engine::general_purpose::STANDARD_NO_PAD;
use base64::engine::Engine as _;
@ -179,9 +183,15 @@ impl<'lua> FromRbxVariantLua<'lua> for LuaValue<'lua> {
Rbx::Vector2(_) => Vector2::from_rbx_variant(variant)?
.to_lua(lua)
.map_err(RbxConversionError::external),
Rbx::Vector2int16(_) => Vector2int16::from_rbx_variant(variant)?
.to_lua(lua)
.map_err(RbxConversionError::external),
Rbx::Vector3(_) => Vector3::from_rbx_variant(variant)?
.to_lua(lua)
.map_err(RbxConversionError::external),
Rbx::Vector3int16(_) => Vector3int16::from_rbx_variant(variant)?
.to_lua(lua)
.map_err(RbxConversionError::external),
// Not yet implemented datatypes
Rbx::Axes(_) => todo!(),
Rbx::BrickColor(_) => todo!(),
@ -201,8 +211,6 @@ impl<'lua> FromRbxVariantLua<'lua> for LuaValue<'lua> {
Rbx::Region3int16(_) => todo!(),
Rbx::UDim(_) => todo!(),
Rbx::UDim2(_) => todo!(),
Rbx::Vector2int16(_) => todo!(),
Rbx::Vector3int16(_) => todo!(),
v => Err(RbxConversionError::FromRbxVariant {
from: v.display_name(),
to: "LuaValue",
@ -256,8 +264,12 @@ impl<'lua> ToRbxVariant for LuaValue<'lua> {
(LuaValue::UserData(u), d) => {
if let Ok(v2) = u.borrow::<Vector2>() {
v2.to_rbx_variant(Some(d))
} else if let Ok(v2i) = u.borrow::<Vector2int16>() {
v2i.to_rbx_variant(Some(d))
} else if let Ok(v3) = u.borrow::<Vector3>() {
v3.to_rbx_variant(Some(d))
} else if let Ok(v3i) = u.borrow::<Vector3int16>() {
v3i.to_rbx_variant(Some(d))
} else {
Err(RbxConversionError::ToRbxVariant {
to: d.display_name(),
@ -289,8 +301,12 @@ impl<'lua> ToRbxVariant for LuaValue<'lua> {
LuaValue::UserData(u) => {
if let Ok(v2) = u.borrow::<Vector2>() {
v2.to_rbx_variant(None)
} else if let Ok(v2i) = u.borrow::<Vector2int16>() {
v2i.to_rbx_variant(None)
} else if let Ok(v3) = u.borrow::<Vector3>() {
v3.to_rbx_variant(None)
} else if let Ok(v3i) = u.borrow::<Vector3int16>() {
v3i.to_rbx_variant(None)
} else {
Err(RbxConversionError::ToRbxVariant {
to: "Variant",

View file

@ -0,0 +1,142 @@
use core::fmt;
use glam::IVec2;
use mlua::prelude::*;
use rbx_dom_weak::types::Vector2int16 as RbxVector2int16;
use super::*;
/**
An implementation of the [Vector2int16](https://create.roblox.com/docs/reference/engine/datatypes/Vector2int16)
Roblox datatype, backed by [`glam::IVec2`].
This implements all documented properties, methods &
constructors of the Vector2int16 class as of March 2023.
*/
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Vector2int16(pub IVec2);
impl fmt::Display for Vector2int16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}, {}", self.0.x, self.0.y)
}
}
impl LuaUserData for Vector2int16 {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("X", |_, this| Ok(this.0.x));
fields.add_field_method_get("Y", |_, this| Ok(this.0.y));
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector2int16(-this.0)));
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector2int16| {
Ok(Vector2int16(this.0 + rhs.0))
});
methods.add_meta_method(LuaMetaMethod::Sub, |_, this, rhs: Vector2int16| {
Ok(Vector2int16(this.0 - rhs.0))
});
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::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::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()
)),
})
});
}
}
impl DatatypeTable for Vector2int16 {
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
datatype_table.set(
"new",
lua.create_function(|_, (x, y): (Option<i16>, Option<i16>)| {
Ok(Vector2int16(IVec2 {
x: x.unwrap_or_default() as i32,
y: y.unwrap_or_default() as i32,
}))
})?,
)
}
}
impl From<&RbxVector2int16> for Vector2int16 {
fn from(v: &RbxVector2int16) -> Self {
Vector2int16(IVec2 {
x: v.x.clamp(i16::MIN, i16::MAX) as i32,
y: v.y.clamp(i16::MIN, i16::MAX) as i32,
})
}
}
impl From<&Vector2int16> for RbxVector2int16 {
fn from(v: &Vector2int16) -> Self {
RbxVector2int16 {
x: v.0.x.clamp(i16::MIN as i32, i16::MAX as i32) as i16,
y: v.0.y.clamp(i16::MIN as i32, i16::MAX as i32) as i16,
}
}
}
impl FromRbxVariant for Vector2int16 {
fn from_rbx_variant(variant: &RbxVariant) -> RbxConversionResult<Self> {
if let RbxVariant::Vector2int16(v) = variant {
Ok(v.into())
} else {
Err(RbxConversionError::FromRbxVariant {
from: variant.display_name(),
to: "Vector2int16",
detail: None,
})
}
}
}
impl ToRbxVariant for Vector2int16 {
fn to_rbx_variant(
&self,
desired_type: Option<RbxVariantType>,
) -> RbxConversionResult<RbxVariant> {
if matches!(desired_type, None | Some(RbxVariantType::Vector2int16)) {
Ok(RbxVariant::Vector2int16(self.into()))
} else {
Err(RbxConversionError::DesiredTypeMismatch {
can_convert_to: Some(RbxVariantType::Vector2int16.display_name()),
detail: None,
})
}
}
}

View file

@ -0,0 +1,145 @@
use core::fmt;
use glam::IVec3;
use mlua::prelude::*;
use rbx_dom_weak::types::Vector3int16 as RbxVector3int16;
use super::*;
/**
An implementation of the [Vector3int16](https://create.roblox.com/docs/reference/engine/datatypes/Vector3int16)
Roblox datatype, backed by [`glam::IVec3`].
This implements all documented properties, methods &
constructors of the Vector3int16 class as of March 2023.
*/
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Vector3int16(pub IVec3);
impl fmt::Display for Vector3int16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}, {}", self.0.x, self.0.y)
}
}
impl LuaUserData for Vector3int16 {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("X", |_, this| Ok(this.0.x));
fields.add_field_method_get("Y", |_, this| Ok(this.0.y));
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(LuaMetaMethod::Eq, datatype_impl_eq);
methods.add_meta_method(LuaMetaMethod::ToString, datatype_impl_to_string);
methods.add_meta_method(LuaMetaMethod::Unm, |_, this, ()| Ok(Vector3int16(-this.0)));
methods.add_meta_method(LuaMetaMethod::Add, |_, this, rhs: Vector3int16| {
Ok(Vector3int16(this.0 + rhs.0))
});
methods.add_meta_method(LuaMetaMethod::Sub, |_, this, rhs: Vector3int16| {
Ok(Vector3int16(this.0 - rhs.0))
});
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::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::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()
)),
})
});
}
}
impl DatatypeTable for Vector3int16 {
fn make_dt_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
datatype_table.set(
"new",
lua.create_function(|_, (x, y, z): (Option<i16>, Option<i16>, Option<i16>)| {
Ok(Vector3int16(IVec3 {
x: x.unwrap_or_default() as i32,
y: y.unwrap_or_default() as i32,
z: z.unwrap_or_default() as i32,
}))
})?,
)
}
}
impl From<&RbxVector3int16> for Vector3int16 {
fn from(v: &RbxVector3int16) -> Self {
Vector3int16(IVec3 {
x: v.x.clamp(i16::MIN, i16::MAX) as i32,
y: v.y.clamp(i16::MIN, i16::MAX) as i32,
z: v.z.clamp(i16::MIN, i16::MAX) as i32,
})
}
}
impl From<&Vector3int16> for RbxVector3int16 {
fn from(v: &Vector3int16) -> Self {
RbxVector3int16 {
x: v.0.x.clamp(i16::MIN as i32, i16::MAX as i32) as i16,
y: v.0.y.clamp(i16::MIN as i32, i16::MAX as i32) as i16,
z: v.0.z.clamp(i16::MIN as i32, i16::MAX as i32) as i16,
}
}
}
impl FromRbxVariant for Vector3int16 {
fn from_rbx_variant(variant: &RbxVariant) -> RbxConversionResult<Self> {
if let RbxVariant::Vector3int16(v) = variant {
Ok(v.into())
} else {
Err(RbxConversionError::FromRbxVariant {
from: variant.display_name(),
to: "Vector3int16",
detail: None,
})
}
}
}
impl ToRbxVariant for Vector3int16 {
fn to_rbx_variant(
&self,
desired_type: Option<RbxVariantType>,
) -> RbxConversionResult<RbxVariant> {
if matches!(desired_type, None | Some(RbxVariantType::Vector3int16)) {
Ok(RbxVariant::Vector3int16(self.into()))
} else {
Err(RbxConversionError::DesiredTypeMismatch {
can_convert_to: Some(RbxVariantType::Vector3int16.display_name()),
detail: None,
})
}
}
}