From 709426d8efc557fe5cf0745d81a1513d6190723f Mon Sep 17 00:00:00 2001 From: Filip Tibell <filip.tibell@gmail.com> Date: Wed, 15 Mar 2023 16:14:17 +0100 Subject: [PATCH] Implement ColorSequence roblox datatype --- .../lib-roblox/src/datatypes/conversion.rs | 13 +-- .../src/datatypes/types/color_sequence.rs | 104 ++++++++++++++++++ .../types/color_sequence_keypoint.rs | 60 ++++++++++ .../lib-roblox/src/datatypes/types/mod.rs | 4 + packages/lib-roblox/src/lib.rs | 18 +-- 5 files changed, 184 insertions(+), 15 deletions(-) create mode 100644 packages/lib-roblox/src/datatypes/types/color_sequence.rs create mode 100644 packages/lib-roblox/src/datatypes/types/color_sequence_keypoint.rs diff --git a/packages/lib-roblox/src/datatypes/conversion.rs b/packages/lib-roblox/src/datatypes/conversion.rs index 54a6660..d49d44d 100644 --- a/packages/lib-roblox/src/datatypes/conversion.rs +++ b/packages/lib-roblox/src/datatypes/conversion.rs @@ -120,9 +120,6 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> { // Not yet implemented datatypes // Rbx::Axes(_) => todo!(), // Rbx::CFrame(_) => todo!(), - // Rbx::Color3(_) => todo!(), - // Rbx::Color3uint8(_) => todo!(), - // Rbx::ColorSequence(_) => todo!(), // Rbx::Enum(_) => todo!(), // Rbx::Faces(_) => todo!(), // Rbx::NumberRange(_) => todo!(), @@ -136,8 +133,9 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> { Rbx::BrickColor(value) => lua.create_userdata(BrickColor::from(value))?, - Rbx::Color3(value) => lua.create_userdata(Color3::from(value))?, - Rbx::Color3uint8(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::ColorSequence(value) => lua.create_userdata(ColorSequence::from(value))?, Rbx::UDim(value) => lua.create_userdata(UDim::from(value))?, Rbx::UDim2(value) => lua.create_userdata(UDim2::from(value))?, @@ -171,8 +169,9 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> { let f = match variant_type { RbxVariantType::BrickColor => convert::<BrickColor, rbx::BrickColor>, - RbxVariantType::Color3 => convert::<Color3, rbx::Color3>, - RbxVariantType::Color3uint8 => convert::<Color3, rbx::Color3uint8>, + RbxVariantType::Color3 => convert::<Color3, rbx::Color3>, + RbxVariantType::Color3uint8 => convert::<Color3, rbx::Color3uint8>, + RbxVariantType::ColorSequence => convert::<ColorSequence, rbx::ColorSequence>, RbxVariantType::UDim => convert::<UDim, rbx::UDim>, RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>, diff --git a/packages/lib-roblox/src/datatypes/types/color_sequence.rs b/packages/lib-roblox/src/datatypes/types/color_sequence.rs new file mode 100644 index 0000000..742dc30 --- /dev/null +++ b/packages/lib-roblox/src/datatypes/types/color_sequence.rs @@ -0,0 +1,104 @@ +use core::fmt; + +use mlua::prelude::*; +use rbx_dom_weak::types::{ + ColorSequence as RbxColorSequence, ColorSequenceKeypoint as RbxColorSequenceKeypoint, +}; + +use super::{Color3, ColorSequenceKeypoint}; + +/** + An implementation of the [ColorSequence](https://create.roblox.com/docs/reference/engine/datatypes/ColorSequence) Roblox datatype. + + This implements all documented properties, methods & constructors of the ColorSequence class as of March 2023. +*/ +#[derive(Debug, Clone, PartialEq)] +pub struct ColorSequence { + pub(crate) keypoints: Vec<ColorSequenceKeypoint>, +} + +impl ColorSequence { + pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> { + type ArgsColor = Color3; + type ArgsColors = (Color3, Color3); + type ArgsKeypoints = Vec<ColorSequenceKeypoint>; + datatype_table.set( + "new", + lua.create_function(|lua, args: LuaMultiValue| { + if let Ok(color) = ArgsColor::from_lua_multi(args.clone(), lua) { + Ok(ColorSequence { + keypoints: vec![ + ColorSequenceKeypoint { time: 0.0, color }, + ColorSequenceKeypoint { time: 1.0, color }, + ], + }) + } else if let Ok((c0, c1)) = ArgsColors::from_lua_multi(args.clone(), lua) { + Ok(ColorSequence { + keypoints: vec![ + ColorSequenceKeypoint { + time: 0.0, + color: c0, + }, + ColorSequenceKeypoint { + time: 1.0, + color: c1, + }, + ], + }) + } else if let Ok(keypoints) = ArgsKeypoints::from_lua_multi(args, lua) { + Ok(ColorSequence { keypoints }) + } else { + // FUTURE: Better error message here using given arg types + Err(LuaError::RuntimeError( + "Invalid arguments to constructor".to_string(), + )) + } + })?, + ) + } +} + +impl LuaUserData for ColorSequence { + fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_method_get("Keypoints", |_, this| Ok(this.keypoints.clone())); + } +} + +impl fmt::Display for ColorSequence { + 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<RbxColorSequence> for ColorSequence { + fn from(v: RbxColorSequence) -> Self { + Self { + keypoints: v + .keypoints + .iter() + .cloned() + .map(ColorSequenceKeypoint::from) + .collect(), + } + } +} + +impl From<ColorSequence> for RbxColorSequence { + fn from(v: ColorSequence) -> Self { + Self { + keypoints: v + .keypoints + .iter() + .cloned() + .map(RbxColorSequenceKeypoint::from) + .collect(), + } + } +} diff --git a/packages/lib-roblox/src/datatypes/types/color_sequence_keypoint.rs b/packages/lib-roblox/src/datatypes/types/color_sequence_keypoint.rs new file mode 100644 index 0000000..8b7fe8e --- /dev/null +++ b/packages/lib-roblox/src/datatypes/types/color_sequence_keypoint.rs @@ -0,0 +1,60 @@ +use core::fmt; + +use mlua::prelude::*; +use rbx_dom_weak::types::ColorSequenceKeypoint as RbxColorSequenceKeypoint; + +use super::Color3; + +/** + An implementation of the [ColorSequenceKeypoint](https://create.roblox.com/docs/reference/engine/datatypes/ColorSequenceKeypoint) Roblox datatype. + + This implements all documented properties, methods & constructors of the ColorSequenceKeypoint class as of March 2023. +*/ +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct ColorSequenceKeypoint { + pub(crate) time: f32, + pub(crate) color: Color3, +} + +impl ColorSequenceKeypoint { + pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> { + datatype_table.set( + "new", + lua.create_function(|_, (time, color): (f32, Color3)| { + Ok(ColorSequenceKeypoint { time, color }) + })?, + )?; + Ok(()) + } +} + +impl LuaUserData for ColorSequenceKeypoint { + 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.color)); + } +} + +impl fmt::Display for ColorSequenceKeypoint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} > {}", self.time, self.color) + } +} + +impl From<RbxColorSequenceKeypoint> for ColorSequenceKeypoint { + fn from(v: RbxColorSequenceKeypoint) -> Self { + Self { + time: v.time, + color: v.color.into(), + } + } +} + +impl From<ColorSequenceKeypoint> for RbxColorSequenceKeypoint { + fn from(v: ColorSequenceKeypoint) -> Self { + Self { + time: v.time, + color: v.color.into(), + } + } +} diff --git a/packages/lib-roblox/src/datatypes/types/mod.rs b/packages/lib-roblox/src/datatypes/types/mod.rs index 71fca58..54631e3 100644 --- a/packages/lib-roblox/src/datatypes/types/mod.rs +++ b/packages/lib-roblox/src/datatypes/types/mod.rs @@ -1,5 +1,7 @@ mod brick_color; mod color3; +mod color_sequence; +mod color_sequence_keypoint; mod udim; mod udim2; mod vector2; @@ -9,6 +11,8 @@ mod vector3int16; pub use brick_color::BrickColor; pub use color3::Color3; +pub use color_sequence::ColorSequence; +pub use color_sequence_keypoint::ColorSequenceKeypoint; pub use udim::UDim; pub use udim2::UDim2; pub use vector2::Vector2; diff --git a/packages/lib-roblox/src/lib.rs b/packages/lib-roblox/src/lib.rs index 0323605..1ca677f 100644 --- a/packages/lib-roblox/src/lib.rs +++ b/packages/lib-roblox/src/lib.rs @@ -21,14 +21,16 @@ where fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> { use datatypes::types::*; Ok(vec![ - ("BrickColor", make_dt(lua, BrickColor::make_table)?), - ("Color3", make_dt(lua, Color3::make_table)?), - ("UDim", make_dt(lua, UDim::make_table)?), - ("UDim2", make_dt(lua, UDim2::make_table)?), - ("Vector2", make_dt(lua, Vector2::make_table)?), - ("Vector2int16", make_dt(lua, Vector2int16::make_table)?), - ("Vector3", make_dt(lua, Vector3::make_table)?), - ("Vector3int16", make_dt(lua, Vector3int16::make_table)?), + ("BrickColor", make_dt(lua, BrickColor::make_table)?), + ("Color3", make_dt(lua, Color3::make_table)?), + ("ColorSequence", make_dt(lua, ColorSequence::make_table)?), + ("ColorSequenceKeypoint", make_dt(lua, ColorSequenceKeypoint::make_table)?), + ("UDim", make_dt(lua, UDim::make_table)?), + ("UDim2", make_dt(lua, UDim2::make_table)?), + ("Vector2", make_dt(lua, Vector2::make_table)?), + ("Vector2int16", make_dt(lua, Vector2int16::make_table)?), + ("Vector3", make_dt(lua, Vector3::make_table)?), + ("Vector3int16", make_dt(lua, Vector3int16::make_table)?), ]) }