mirror of
https://github.com/lune-org/lune.git
synced 2025-01-05 19:09:10 +00:00
Implement Axes roblox datatype
This commit is contained in:
parent
7aef25c316
commit
cfc9299165
5 changed files with 188 additions and 4 deletions
|
@ -116,11 +116,12 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
use RbxVariant as Rbx;
|
use RbxVariant as Rbx;
|
||||||
|
|
||||||
|
// NOTE: Enum is intentionally left out here, it has a custom
|
||||||
|
// conversion going from instance property > datatype instead,
|
||||||
|
// check `EnumItem::from_instance_property` for specifics
|
||||||
Ok(match variant.clone() {
|
Ok(match variant.clone() {
|
||||||
// Not yet implemented datatypes
|
// Not yet implemented datatypes
|
||||||
// Rbx::Axes(_) => todo!(),
|
|
||||||
// Rbx::CFrame(_) => todo!(),
|
// Rbx::CFrame(_) => todo!(),
|
||||||
// Rbx::Enum(_) => todo!(),
|
|
||||||
// Rbx::Faces(_) => todo!(),
|
// Rbx::Faces(_) => todo!(),
|
||||||
// Rbx::NumberRange(_) => todo!(),
|
// Rbx::NumberRange(_) => todo!(),
|
||||||
// Rbx::NumberSequence(_) => todo!(),
|
// Rbx::NumberSequence(_) => todo!(),
|
||||||
|
@ -131,8 +132,9 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
// Rbx::Region3(_) => todo!(),
|
// Rbx::Region3(_) => todo!(),
|
||||||
// Rbx::Region3int16(_) => todo!(),
|
// Rbx::Region3int16(_) => todo!(),
|
||||||
|
|
||||||
Rbx::BrickColor(value) => lua.create_userdata(BrickColor::from(value))?,
|
Rbx::Axes(value) => lua.create_userdata(Axes::from(value))?,
|
||||||
|
|
||||||
|
Rbx::BrickColor(value) => lua.create_userdata(BrickColor::from(value))?,
|
||||||
Rbx::Color3(value) => lua.create_userdata(Color3::from(value))?,
|
Rbx::Color3(value) => lua.create_userdata(Color3::from(value))?,
|
||||||
Rbx::Color3uint8(value) => lua.create_userdata(Color3::from(value))?,
|
Rbx::Color3uint8(value) => lua.create_userdata(Color3::from(value))?,
|
||||||
Rbx::ColorSequence(value) => lua.create_userdata(ColorSequence::from(value))?,
|
Rbx::ColorSequence(value) => lua.create_userdata(ColorSequence::from(value))?,
|
||||||
|
@ -167,8 +169,9 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
||||||
use rbx_dom_weak::types as rbx;
|
use rbx_dom_weak::types as rbx;
|
||||||
|
|
||||||
let f = match variant_type {
|
let f = match variant_type {
|
||||||
RbxVariantType::BrickColor => convert::<BrickColor, rbx::BrickColor>,
|
RbxVariantType::Axes => convert::<Axes, rbx::Axes>,
|
||||||
|
|
||||||
|
RbxVariantType::BrickColor => convert::<BrickColor, rbx::BrickColor>,
|
||||||
RbxVariantType::Color3 => convert::<Color3, rbx::Color3>,
|
RbxVariantType::Color3 => convert::<Color3, rbx::Color3>,
|
||||||
RbxVariantType::Color3uint8 => convert::<Color3, rbx::Color3uint8>,
|
RbxVariantType::Color3uint8 => convert::<Color3, rbx::Color3uint8>,
|
||||||
RbxVariantType::ColorSequence => convert::<ColorSequence, rbx::ColorSequence>,
|
RbxVariantType::ColorSequence => convert::<ColorSequence, rbx::ColorSequence>,
|
||||||
|
|
133
packages/lib-roblox/src/datatypes/types/axes.rs
Normal file
133
packages/lib-roblox/src/datatypes/types/axes.rs
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use rbx_dom_weak::types::Axes as RbxAxes;
|
||||||
|
|
||||||
|
use super::{super::*, EnumItem};
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the [Axes](https://create.roblox.com/docs/reference/engine/datatypes/Axes) Roblox datatype.
|
||||||
|
|
||||||
|
This implements all documented properties, methods & constructors of the Axes class as of March 2023.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub struct Axes {
|
||||||
|
pub(crate) x: bool,
|
||||||
|
pub(crate) y: bool,
|
||||||
|
pub(crate) z: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Axes {
|
||||||
|
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||||
|
datatype_table.set(
|
||||||
|
"new",
|
||||||
|
lua.create_function(|_, args: LuaMultiValue| {
|
||||||
|
let mut x = false;
|
||||||
|
let mut y = false;
|
||||||
|
let mut z = false;
|
||||||
|
let mut check = |e: &EnumItem| {
|
||||||
|
if e.parent.desc.name == "Axis" {
|
||||||
|
match &e.name {
|
||||||
|
name if name == "X" => x = true,
|
||||||
|
name if name == "Y" => y = true,
|
||||||
|
name if name == "Z" => z = true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
} else if e.parent.desc.name == "NormalId" {
|
||||||
|
match &e.name {
|
||||||
|
name if name == "Left" || name == "Right" => x = true,
|
||||||
|
name if name == "Top" || name == "Bottom" => y = true,
|
||||||
|
name if name == "Front" || name == "Back" => z = true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (index, arg) in args.into_iter().enumerate() {
|
||||||
|
if let LuaValue::UserData(u) = arg {
|
||||||
|
if let Ok(e) = u.borrow::<EnumItem>() {
|
||||||
|
check(&e);
|
||||||
|
} else {
|
||||||
|
return Err(LuaError::RuntimeError(format!(
|
||||||
|
"Expected argument #{} to be an EnumItem, got userdata",
|
||||||
|
index
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(LuaError::RuntimeError(format!(
|
||||||
|
"Expected argument #{} to be an EnumItem, got {}",
|
||||||
|
index,
|
||||||
|
arg.type_name()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Axes { x, y, z })
|
||||||
|
})?,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for Axes {
|
||||||
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("X", |_, this| Ok(this.x));
|
||||||
|
fields.add_field_method_get("Y", |_, this| Ok(this.y));
|
||||||
|
fields.add_field_method_get("Z", |_, this| Ok(this.z));
|
||||||
|
fields.add_field_method_get("Left", |_, this| Ok(this.x));
|
||||||
|
fields.add_field_method_get("Right", |_, this| Ok(this.x));
|
||||||
|
fields.add_field_method_get("Top", |_, this| Ok(this.y));
|
||||||
|
fields.add_field_method_get("Bottom", |_, this| Ok(this.y));
|
||||||
|
fields.add_field_method_get("Front", |_, this| Ok(this.z));
|
||||||
|
fields.add_field_method_get("Back", |_, this| Ok(this.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||||
|
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Axes {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let mut got_value = false;
|
||||||
|
if self.x {
|
||||||
|
write!(f, "X")?;
|
||||||
|
got_value = true;
|
||||||
|
}
|
||||||
|
if self.y {
|
||||||
|
if got_value {
|
||||||
|
write!(f, ", Y")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "Y")?;
|
||||||
|
got_value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.z {
|
||||||
|
if got_value {
|
||||||
|
write!(f, ", Z")?;
|
||||||
|
} else {
|
||||||
|
write!(f, "Z")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RbxAxes> for Axes {
|
||||||
|
fn from(v: RbxAxes) -> Self {
|
||||||
|
let bits = v.bits();
|
||||||
|
let x = (bits & 1) == 1;
|
||||||
|
let y = ((bits >> 1) & 1) == 1;
|
||||||
|
let z = ((bits >> 2) & 1) == 1;
|
||||||
|
Self { x, y, z }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Axes> for RbxAxes {
|
||||||
|
fn from(v: Axes) -> Self {
|
||||||
|
let mut bits = 0;
|
||||||
|
bits += v.x as u8;
|
||||||
|
bits += (v.y as u8) << 1;
|
||||||
|
bits += (v.z as u8) << 2;
|
||||||
|
RbxAxes::from_bits(bits).expect("Invalid bits")
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod axes;
|
||||||
mod brick_color;
|
mod brick_color;
|
||||||
mod color3;
|
mod color3;
|
||||||
mod color_sequence;
|
mod color_sequence;
|
||||||
|
@ -12,6 +13,7 @@ mod vector2int16;
|
||||||
mod vector3;
|
mod vector3;
|
||||||
mod vector3int16;
|
mod vector3int16;
|
||||||
|
|
||||||
|
pub use axes::Axes;
|
||||||
pub use brick_color::BrickColor;
|
pub use brick_color::BrickColor;
|
||||||
pub use color3::Color3;
|
pub use color3::Color3;
|
||||||
pub use color_sequence::ColorSequence;
|
pub use color_sequence::ColorSequence;
|
||||||
|
@ -68,6 +70,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
create_tests! {
|
create_tests! {
|
||||||
|
axes: "datatypes/Axes",
|
||||||
brick_color: "datatypes/BrickColor",
|
brick_color: "datatypes/BrickColor",
|
||||||
color3: "datatypes/Color3",
|
color3: "datatypes/Color3",
|
||||||
color_sequence: "datatypes/ColorSequence",
|
color_sequence: "datatypes/ColorSequence",
|
||||||
|
|
|
@ -19,6 +19,7 @@ fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
||||||
use datatypes::types::*;
|
use datatypes::types::*;
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
// Classes
|
// Classes
|
||||||
|
("Axes", make_dt(lua, Axes::make_table)?),
|
||||||
("BrickColor", make_dt(lua, BrickColor::make_table)?),
|
("BrickColor", make_dt(lua, BrickColor::make_table)?),
|
||||||
("Color3", make_dt(lua, Color3::make_table)?),
|
("Color3", make_dt(lua, Color3::make_table)?),
|
||||||
("ColorSequence", make_dt(lua, ColorSequence::make_table)?),
|
("ColorSequence", make_dt(lua, ColorSequence::make_table)?),
|
||||||
|
|
44
tests/roblox/datatypes/Axes.luau
Normal file
44
tests/roblox/datatypes/Axes.luau
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
-- HACK: Make luau happy, with the mlua rust
|
||||||
|
-- crate all globals are also present in _G
|
||||||
|
local Axes = _G.Axes
|
||||||
|
local Enum = _G.Enum
|
||||||
|
|
||||||
|
-- Constructors & properties
|
||||||
|
|
||||||
|
Axes.new()
|
||||||
|
Axes.new(Enum.Axis.X)
|
||||||
|
Axes.new(Enum.Axis.X, Enum.NormalId.Top)
|
||||||
|
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Axes.new(false)
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Axes.new({})
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Axes.new(newproxy(true))
|
||||||
|
end))
|
||||||
|
|
||||||
|
assert(Axes.new().X == false)
|
||||||
|
assert(Axes.new().Y == false)
|
||||||
|
assert(Axes.new().Z == false)
|
||||||
|
|
||||||
|
assert(Axes.new(Enum.Axis.X, Enum.NormalId.Top).X == true)
|
||||||
|
assert(Axes.new(Enum.Axis.X, Enum.NormalId.Top).Y == true)
|
||||||
|
assert(Axes.new(Enum.Axis.X, Enum.NormalId.Top).Z == false)
|
||||||
|
|
||||||
|
assert(Axes.new(Enum.Axis.X, Enum.NormalId.Left).X == true)
|
||||||
|
assert(Axes.new(Enum.Axis.X, Enum.NormalId.Right).X == true)
|
||||||
|
|
||||||
|
assert(Axes.new(Enum.NormalId.Front, Enum.NormalId.Back).X == false)
|
||||||
|
assert(Axes.new(Enum.NormalId.Front, Enum.NormalId.Back).Y == false)
|
||||||
|
assert(Axes.new(Enum.NormalId.Front, Enum.NormalId.Back).Z == true)
|
||||||
|
|
||||||
|
-- Ops
|
||||||
|
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Axes.new() + Axes.new()
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Axes.new() / Axes.new()
|
||||||
|
end))
|
Loading…
Reference in a new issue