mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
Implement number range/sequence roblox datatypes
This commit is contained in:
parent
da8e86d743
commit
e3bcf79f09
11 changed files with 404 additions and 33 deletions
|
@ -121,8 +121,6 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
|||
// check `EnumItem::from_instance_property` for specifics
|
||||
Ok(match variant.clone() {
|
||||
// Not yet implemented datatypes
|
||||
// Rbx::NumberRange(_) => todo!(),
|
||||
// Rbx::NumberSequence(_) => todo!(),
|
||||
// Rbx::OptionalCFrame(_) => todo!(),
|
||||
// Rbx::PhysicalProperties(_) => todo!(),
|
||||
// Rbx::Ray(_) => todo!(),
|
||||
|
@ -139,6 +137,9 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
|||
Rbx::Color3uint8(value) => lua.create_userdata(Color3::from(value))?,
|
||||
Rbx::ColorSequence(value) => lua.create_userdata(ColorSequence::from(value))?,
|
||||
|
||||
Rbx::NumberRange(value) => lua.create_userdata(NumberRange::from(value))?,
|
||||
Rbx::NumberSequence(value) => lua.create_userdata(NumberSequence::from(value))?,
|
||||
|
||||
Rbx::Rect(value) => lua.create_userdata(Rect::from(value))?,
|
||||
Rbx::UDim(value) => lua.create_userdata(UDim::from(value))?,
|
||||
Rbx::UDim2(value) => lua.create_userdata(UDim2::from(value))?,
|
||||
|
@ -186,6 +187,9 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
|||
RbxVariantType::UDim => convert::<UDim, rbx::UDim>,
|
||||
RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>,
|
||||
|
||||
RbxVariantType::NumberRange => convert::<NumberRange, rbx::NumberRange>,
|
||||
RbxVariantType::NumberSequence => convert::<NumberSequence, rbx::NumberSequence>,
|
||||
|
||||
RbxVariantType::Vector2 => convert::<Vector2, rbx::Vector2>,
|
||||
RbxVariantType::Vector2int16 => convert::<Vector2int16, rbx::Vector2int16>,
|
||||
RbxVariantType::Vector3 => convert::<Vector3, rbx::Vector3>,
|
||||
|
|
|
@ -8,6 +8,9 @@ mod r#enum;
|
|||
mod r#enum_item;
|
||||
mod r#enums;
|
||||
mod faces;
|
||||
mod number_range;
|
||||
mod number_sequence;
|
||||
mod number_sequence_keypoint;
|
||||
mod rect;
|
||||
mod udim;
|
||||
mod udim2;
|
||||
|
@ -23,6 +26,9 @@ pub use color3::Color3;
|
|||
pub use color_sequence::ColorSequence;
|
||||
pub use color_sequence_keypoint::ColorSequenceKeypoint;
|
||||
pub use faces::Faces;
|
||||
pub use number_range::NumberRange;
|
||||
pub use number_sequence::NumberSequence;
|
||||
pub use number_sequence_keypoint::NumberSequenceKeypoint;
|
||||
pub use r#enum::Enum;
|
||||
pub use r#enum_item::EnumItem;
|
||||
pub use r#enums::Enums;
|
||||
|
@ -84,6 +90,9 @@ mod tests {
|
|||
color_sequence_keypoint: "datatypes/ColorSequenceKeypoint",
|
||||
r#enum: "datatypes/Enum",
|
||||
faces: "datatypes/Faces",
|
||||
number_range: "datatypes/NumberRange",
|
||||
number_sequence: "datatypes/NumberSequence",
|
||||
number_sequence_keypoint: "datatypes/NumberSequenceKeypoint",
|
||||
rect: "datatypes/Rect",
|
||||
udim: "datatypes/UDim",
|
||||
udim2: "datatypes/UDim2",
|
||||
|
|
70
packages/lib-roblox/src/datatypes/types/number_range.rs
Normal file
70
packages/lib-roblox/src/datatypes/types/number_range.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use core::fmt;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::NumberRange as RbxNumberRange;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
/**
|
||||
An implementation of the [NumberRange](https://create.roblox.com/docs/reference/engine/datatypes/NumberRange) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the NumberRange class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct NumberRange {
|
||||
pub(crate) min: f32,
|
||||
pub(crate) max: f32,
|
||||
}
|
||||
|
||||
impl NumberRange {
|
||||
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||
datatype_table.set(
|
||||
"new",
|
||||
lua.create_function(|_, (min, max): (f32, Option<f32>)| {
|
||||
Ok(match max {
|
||||
Some(max) => NumberRange {
|
||||
min: min.min(max),
|
||||
max: min.max(max),
|
||||
},
|
||||
None => NumberRange { min, max: min },
|
||||
})
|
||||
})?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for NumberRange {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("Min", |_, this| Ok(this.min));
|
||||
fields.add_field_method_get("Max", |_, this| Ok(this.max));
|
||||
}
|
||||
|
||||
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 NumberRange {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}, {}", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RbxNumberRange> for NumberRange {
|
||||
fn from(v: RbxNumberRange) -> Self {
|
||||
Self {
|
||||
min: v.min,
|
||||
max: v.max,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NumberRange> for RbxNumberRange {
|
||||
fn from(v: NumberRange) -> Self {
|
||||
Self {
|
||||
min: v.min,
|
||||
max: v.max,
|
||||
}
|
||||
}
|
||||
}
|
119
packages/lib-roblox/src/datatypes/types/number_sequence.rs
Normal file
119
packages/lib-roblox/src/datatypes/types/number_sequence.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
use core::fmt;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::{
|
||||
NumberSequence as RbxNumberSequence, NumberSequenceKeypoint as RbxNumberSequenceKeypoint,
|
||||
};
|
||||
|
||||
use super::{super::*, NumberSequenceKeypoint};
|
||||
|
||||
/**
|
||||
An implementation of the [NumberSequence](https://create.roblox.com/docs/reference/engine/datatypes/NumberSequence) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the NumberSequence class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct NumberSequence {
|
||||
pub(crate) keypoints: Vec<NumberSequenceKeypoint>,
|
||||
}
|
||||
|
||||
impl NumberSequence {
|
||||
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||
type ArgsColor = f32;
|
||||
type ArgsColors = (f32, f32);
|
||||
type ArgsKeypoints = Vec<NumberSequenceKeypoint>;
|
||||
datatype_table.set(
|
||||
"new",
|
||||
lua.create_function(|lua, args: LuaMultiValue| {
|
||||
if let Ok(value) = ArgsColor::from_lua_multi(args.clone(), lua) {
|
||||
Ok(NumberSequence {
|
||||
keypoints: vec![
|
||||
NumberSequenceKeypoint {
|
||||
time: 0.0,
|
||||
value,
|
||||
envelope: 0.0,
|
||||
},
|
||||
NumberSequenceKeypoint {
|
||||
time: 1.0,
|
||||
value,
|
||||
envelope: 0.0,
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if let Ok((v0, v1)) = ArgsColors::from_lua_multi(args.clone(), lua) {
|
||||
Ok(NumberSequence {
|
||||
keypoints: vec![
|
||||
NumberSequenceKeypoint {
|
||||
time: 0.0,
|
||||
value: v0,
|
||||
envelope: 0.0,
|
||||
},
|
||||
NumberSequenceKeypoint {
|
||||
time: 1.0,
|
||||
value: v1,
|
||||
envelope: 0.0,
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if let Ok(keypoints) = ArgsKeypoints::from_lua_multi(args, lua) {
|
||||
Ok(NumberSequence { keypoints })
|
||||
} else {
|
||||
// FUTURE: Better error message here using given arg types
|
||||
Err(LuaError::RuntimeError(
|
||||
"Invalid arguments to constructor".to_string(),
|
||||
))
|
||||
}
|
||||
})?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for NumberSequence {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("Keypoints", |_, this| Ok(this.keypoints.clone()));
|
||||
}
|
||||
|
||||
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 NumberSequence {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for (index, keypoint) in self.keypoints.iter().enumerate() {
|
||||
if index < self.keypoints.len() - 1 {
|
||||
write!(f, "{}, ", keypoint)?;
|
||||
} else {
|
||||
write!(f, "{}", keypoint)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RbxNumberSequence> for NumberSequence {
|
||||
fn from(v: RbxNumberSequence) -> Self {
|
||||
Self {
|
||||
keypoints: v
|
||||
.keypoints
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(NumberSequenceKeypoint::from)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NumberSequence> for RbxNumberSequence {
|
||||
fn from(v: NumberSequence) -> Self {
|
||||
Self {
|
||||
keypoints: v
|
||||
.keypoints
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(RbxNumberSequenceKeypoint::from)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
use core::fmt;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use rbx_dom_weak::types::NumberSequenceKeypoint as RbxNumberSequenceKeypoint;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
/**
|
||||
An implementation of the [NumberSequenceKeypoint](https://create.roblox.com/docs/reference/engine/datatypes/NumberSequenceKeypoint) Roblox datatype.
|
||||
|
||||
This implements all documented properties, methods & constructors of the NumberSequenceKeypoint class as of March 2023.
|
||||
*/
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct NumberSequenceKeypoint {
|
||||
pub(crate) time: f32,
|
||||
pub(crate) value: f32,
|
||||
pub(crate) envelope: f32,
|
||||
}
|
||||
|
||||
impl NumberSequenceKeypoint {
|
||||
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||
datatype_table.set(
|
||||
"new",
|
||||
lua.create_function(|_, (time, value, envelope): (f32, f32, Option<f32>)| {
|
||||
Ok(NumberSequenceKeypoint {
|
||||
time,
|
||||
value,
|
||||
envelope: envelope.unwrap_or_default(),
|
||||
})
|
||||
})?,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for NumberSequenceKeypoint {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("Time", |_, this| Ok(this.time));
|
||||
fields.add_field_method_get("Value", |_, this| Ok(this.value));
|
||||
fields.add_field_method_get("Envelope", |_, this| Ok(this.envelope));
|
||||
}
|
||||
|
||||
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 NumberSequenceKeypoint {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{} > {}", self.time, self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RbxNumberSequenceKeypoint> for NumberSequenceKeypoint {
|
||||
fn from(v: RbxNumberSequenceKeypoint) -> Self {
|
||||
Self {
|
||||
time: v.time,
|
||||
value: v.value,
|
||||
envelope: v.envelope,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NumberSequenceKeypoint> for RbxNumberSequenceKeypoint {
|
||||
fn from(v: NumberSequenceKeypoint) -> Self {
|
||||
Self {
|
||||
time: v.time,
|
||||
value: v.value,
|
||||
envelope: v.envelope,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -76,7 +76,7 @@ impl LuaUserData for UDim2 {
|
|||
// Methods
|
||||
methods.add_method("Lerp", |_, this, (goal, alpha): (UDim2, f32)| {
|
||||
let this_x = Vec2::new(this.x.scale, this.x.offset as f32);
|
||||
let goal_x = Vec2::new(goal.x.scale, this.x.offset as f32);
|
||||
let goal_x = Vec2::new(goal.x.scale, goal.x.offset as f32);
|
||||
|
||||
let this_y = Vec2::new(this.y.scale, this.y.offset as f32);
|
||||
let goal_y = Vec2::new(goal.y.scale, goal.y.offset as f32);
|
||||
|
|
|
@ -26,6 +26,9 @@ fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
|||
("ColorSequence", make_dt(lua, ColorSequence::make_table)?),
|
||||
("ColorSequenceKeypoint", make_dt(lua, ColorSequenceKeypoint::make_table)?),
|
||||
("Faces", make_dt(lua, Faces::make_table)?),
|
||||
("NumberRange", make_dt(lua, NumberRange::make_table)?),
|
||||
("NumberSequence", make_dt(lua, NumberSequence::make_table)?),
|
||||
("NumberSequenceKeypoint", make_dt(lua, NumberSequenceKeypoint::make_table)?),
|
||||
("Rect", make_dt(lua, Rect::make_table)?),
|
||||
("UDim", make_dt(lua, UDim::make_table)?),
|
||||
("UDim2", make_dt(lua, UDim2::make_table)?),
|
||||
|
|
32
tests/roblox/datatypes/NumberRange.luau
Normal file
32
tests/roblox/datatypes/NumberRange.luau
Normal file
|
@ -0,0 +1,32 @@
|
|||
-- HACK: Make luau happy, with the mlua rust
|
||||
-- crate all globals are also present in _G
|
||||
local NumberRange = _G.NumberRange
|
||||
|
||||
-- Constructors & properties
|
||||
|
||||
NumberRange.new(0)
|
||||
NumberRange.new(0, 0)
|
||||
|
||||
assert(not pcall(function()
|
||||
return NumberRange.new()
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberRange.new(false)
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberRange.new("", "")
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberRange.new(newproxy(true))
|
||||
end))
|
||||
|
||||
assert(NumberRange.new(0, 1).Min == 0)
|
||||
assert(NumberRange.new(1, 1).Min == 1)
|
||||
|
||||
assert(NumberRange.new(0, 0).Max == 0)
|
||||
assert(NumberRange.new(0, 1).Max == 1)
|
||||
|
||||
-- Swapped args should still set proper min/max
|
||||
|
||||
assert(NumberRange.new(1, 0).Min == 0)
|
||||
assert(NumberRange.new(1, 0).Max == 1)
|
32
tests/roblox/datatypes/NumberSequence.luau
Normal file
32
tests/roblox/datatypes/NumberSequence.luau
Normal file
|
@ -0,0 +1,32 @@
|
|||
-- HACK: Make luau happy, with the mlua rust
|
||||
-- crate all globals are also present in _G
|
||||
local NumberSequence = _G.NumberSequence
|
||||
local NumberSequenceKeypoint = _G.NumberSequenceKeypoint
|
||||
|
||||
-- Constructors & properties
|
||||
|
||||
NumberSequence.new(0)
|
||||
NumberSequence.new(0, 0)
|
||||
local sequence = NumberSequence.new({
|
||||
NumberSequenceKeypoint.new(0, 1),
|
||||
NumberSequenceKeypoint.new(0.5, 0.5),
|
||||
NumberSequenceKeypoint.new(1, 0),
|
||||
})
|
||||
|
||||
assert(not pcall(function()
|
||||
return NumberSequence.new()
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberSequence.new(false)
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberSequence.new("", "")
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberSequence.new(newproxy(true))
|
||||
end))
|
||||
|
||||
assert(#sequence.Keypoints == 3)
|
||||
assert(sequence.Keypoints[1] == NumberSequenceKeypoint.new(0, 1))
|
||||
assert(sequence.Keypoints[2] == NumberSequenceKeypoint.new(0.5, 0.5))
|
||||
assert(sequence.Keypoints[3] == NumberSequenceKeypoint.new(1, 0))
|
29
tests/roblox/datatypes/NumberSequenceKeypoint.luau
Normal file
29
tests/roblox/datatypes/NumberSequenceKeypoint.luau
Normal file
|
@ -0,0 +1,29 @@
|
|||
-- HACK: Make luau happy, with the mlua rust
|
||||
-- crate all globals are also present in _G
|
||||
local NumberSequenceKeypoint = _G.NumberSequenceKeypoint
|
||||
|
||||
-- Constructors & properties
|
||||
|
||||
NumberSequenceKeypoint.new(0, 0)
|
||||
NumberSequenceKeypoint.new(1, 0)
|
||||
NumberSequenceKeypoint.new(0.5, 0.5, 0.5)
|
||||
|
||||
assert(not pcall(function()
|
||||
return NumberSequenceKeypoint.new()
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberSequenceKeypoint.new(false)
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberSequenceKeypoint.new("", "")
|
||||
end))
|
||||
assert(not pcall(function()
|
||||
return NumberSequenceKeypoint.new(newproxy(true))
|
||||
end))
|
||||
|
||||
assert(NumberSequenceKeypoint.new(0, 0, 0).Time == 0)
|
||||
assert(NumberSequenceKeypoint.new(1, 0, 1).Time == 1)
|
||||
assert(NumberSequenceKeypoint.new(0, 0, 0).Value == 0)
|
||||
assert(NumberSequenceKeypoint.new(1, 1, 1).Value == 1)
|
||||
assert(NumberSequenceKeypoint.new(0, 0, 0).Envelope == 0)
|
||||
assert(NumberSequenceKeypoint.new(1, 1, 1).Envelope == 1)
|
|
@ -47,6 +47,6 @@ assert(UDim2.new(2, 4, 6, 8) - UDim2.new(1, 1, 1, 1) == UDim2.new(1, 3, 5, 7))
|
|||
|
||||
-- Methods
|
||||
|
||||
assert(UDim2.new(2, 4, 6, 8):Lerp(UDim2.new(1, 2, 3, 4), 0.0) == UDim2.new(2, 3, 6, 8))
|
||||
assert(UDim2.new(2, 4, 6, 8):Lerp(UDim2.new(1, 2, 3, 4), 0.0) == UDim2.new(2, 4, 6, 8))
|
||||
assert(UDim2.new(2, 4, 6, 8):Lerp(UDim2.new(1, 2, 3, 4), 0.5) == UDim2.new(1.5, 3, 4.5, 6))
|
||||
assert(UDim2.new(2, 4, 6, 8):Lerp(UDim2.new(1, 2, 3, 4), 1.0) == UDim2.new(1, 2, 3, 4))
|
||||
|
|
Loading…
Reference in a new issue