mirror of
https://github.com/lune-org/lune.git
synced 2025-01-05 19:09:10 +00:00
Implement roblox enum datatypes
This commit is contained in:
parent
709426d8ef
commit
158603d405
6 changed files with 208 additions and 3 deletions
|
@ -173,6 +173,8 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
||||||
RbxVariantType::Color3uint8 => convert::<Color3, rbx::Color3uint8>,
|
RbxVariantType::Color3uint8 => convert::<Color3, rbx::Color3uint8>,
|
||||||
RbxVariantType::ColorSequence => convert::<ColorSequence, rbx::ColorSequence>,
|
RbxVariantType::ColorSequence => convert::<ColorSequence, rbx::ColorSequence>,
|
||||||
|
|
||||||
|
RbxVariantType::Enum => convert::<EnumItem, rbx::Enum>,
|
||||||
|
|
||||||
RbxVariantType::UDim => convert::<UDim, rbx::UDim>,
|
RbxVariantType::UDim => convert::<UDim, rbx::UDim>,
|
||||||
RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>,
|
RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>,
|
||||||
|
|
||||||
|
|
64
packages/lib-roblox/src/datatypes/types/enum.rs
Normal file
64
packages/lib-roblox/src/datatypes/types/enum.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use rbx_reflection::EnumDescriptor;
|
||||||
|
|
||||||
|
use super::EnumItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the [Enum](https://create.roblox.com/docs/reference/engine/datatypes/Enum) Roblox datatype.
|
||||||
|
|
||||||
|
This implements all documented properties, methods & constructors of the Enum class as of March 2023.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Enum {
|
||||||
|
pub(crate) desc: &'static EnumDescriptor<'static>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for Enum {
|
||||||
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_method("GetEnumItems", |_, this, ()| {
|
||||||
|
Ok(this
|
||||||
|
.desc
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.map(|(name, value)| EnumItem {
|
||||||
|
parent: this.clone(),
|
||||||
|
name: name.to_string(),
|
||||||
|
value: *value,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>())
|
||||||
|
});
|
||||||
|
methods.add_meta_method(LuaMetaMethod::Index, |_, this, name: String| {
|
||||||
|
match this.desc.items.get(name.as_str()) {
|
||||||
|
Some(value) => Ok(EnumItem {
|
||||||
|
parent: this.clone(),
|
||||||
|
name: name.to_string(),
|
||||||
|
value: *value,
|
||||||
|
}),
|
||||||
|
None => Err(LuaError::RuntimeError(format!(
|
||||||
|
"The enum item '{}' does not exist for enum '{}'",
|
||||||
|
name, this.desc.name
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Enum {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Enum.{}", self.desc.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Enum {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.desc.name == other.desc.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&'static EnumDescriptor<'static>> for Enum {
|
||||||
|
fn from(value: &'static EnumDescriptor<'static>) -> Self {
|
||||||
|
Self { desc: value }
|
||||||
|
}
|
||||||
|
}
|
86
packages/lib-roblox/src/datatypes/types/enum_item.rs
Normal file
86
packages/lib-roblox/src/datatypes/types/enum_item.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use rbx_dom_weak::types::Enum as RbxEnum;
|
||||||
|
use rbx_reflection::DataType as RbxDataType;
|
||||||
|
|
||||||
|
use super::Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the [EnumItem](https://create.roblox.com/docs/reference/engine/datatypes/EnumItem) Roblox datatype.
|
||||||
|
|
||||||
|
This implements all documented properties, methods & constructors of the EnumItem class as of March 2023.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EnumItem {
|
||||||
|
pub(crate) parent: Enum,
|
||||||
|
pub(crate) name: String,
|
||||||
|
pub(crate) value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnumItem {
|
||||||
|
/**
|
||||||
|
Converts an instance property into an [`EnumItem`] datatype, if the property is known.
|
||||||
|
|
||||||
|
Enums are not strongly typed which means we can not convert directly from a [`rbx_dom_weak::types::Enum`]
|
||||||
|
into an `EnumItem` without losing information about its parent [`Enum`] and the `EnumItem` name.
|
||||||
|
|
||||||
|
This constructor exists as a shortcut to perform a [`rbx_reflection_database`] lookup for a particular
|
||||||
|
instance class and property to construct a strongly typed `EnumItem` with no loss of information.
|
||||||
|
*/
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn from_instance_property(
|
||||||
|
class_name: impl AsRef<str>,
|
||||||
|
prop_name: impl AsRef<str>,
|
||||||
|
value: u32,
|
||||||
|
) -> Option<Self> {
|
||||||
|
let db = rbx_reflection_database::get();
|
||||||
|
let prop = db
|
||||||
|
.classes
|
||||||
|
.get(class_name.as_ref())?
|
||||||
|
.properties
|
||||||
|
.get(prop_name.as_ref())?;
|
||||||
|
let prop_enum = match &prop.data_type {
|
||||||
|
RbxDataType::Enum(name) => db.enums.get(name.as_ref()),
|
||||||
|
_ => None,
|
||||||
|
}?;
|
||||||
|
let enum_name = prop_enum.items.iter().find_map(|(name, v)| {
|
||||||
|
if v == &value {
|
||||||
|
Some(name.to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
Some(Self {
|
||||||
|
parent: prop_enum.into(),
|
||||||
|
name: enum_name,
|
||||||
|
value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for EnumItem {
|
||||||
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("Name", |_, this| Ok(this.name.clone()));
|
||||||
|
fields.add_field_method_get("Value", |_, this| Ok(this.value));
|
||||||
|
fields.add_field_method_get("EnumType", |_, this| Ok(this.parent.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for EnumItem {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}.{}", self.parent, self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for EnumItem {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.parent == other.parent && self.value == other.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EnumItem> for RbxEnum {
|
||||||
|
fn from(v: EnumItem) -> Self {
|
||||||
|
RbxEnum::from_u32(v.value)
|
||||||
|
}
|
||||||
|
}
|
44
packages/lib-roblox/src/datatypes/types/enums.rs
Normal file
44
packages/lib-roblox/src/datatypes/types/enums.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::Enum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the [Enums](https://create.roblox.com/docs/reference/engine/datatypes/Enums) Roblox datatype.
|
||||||
|
|
||||||
|
This implements all documented properties, methods & constructors of the Enums class as of March 2023.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub struct Enums;
|
||||||
|
|
||||||
|
impl Enums {
|
||||||
|
pub(crate) fn make_singleton(lua: &Lua) -> LuaResult<LuaAnyUserData> {
|
||||||
|
lua.create_userdata(Self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for Enums {
|
||||||
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_method("GetEnums", |_, _, ()| {
|
||||||
|
let db = rbx_reflection_database::get();
|
||||||
|
Ok(db.enums.values().map(Enum::from).collect::<Vec<_>>())
|
||||||
|
});
|
||||||
|
methods.add_meta_method(LuaMetaMethod::Index, |_, _, name: String| {
|
||||||
|
let db = rbx_reflection_database::get();
|
||||||
|
match db.enums.get(name.as_str()) {
|
||||||
|
Some(desc) => Ok(Enum::from(desc)),
|
||||||
|
None => Err(LuaError::RuntimeError(format!(
|
||||||
|
"The enum '{}' does not exist",
|
||||||
|
name
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Enums {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Enum")
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,9 @@ mod brick_color;
|
||||||
mod color3;
|
mod color3;
|
||||||
mod color_sequence;
|
mod color_sequence;
|
||||||
mod color_sequence_keypoint;
|
mod color_sequence_keypoint;
|
||||||
|
mod r#enum;
|
||||||
|
mod r#enum_item;
|
||||||
|
mod r#enums;
|
||||||
mod udim;
|
mod udim;
|
||||||
mod udim2;
|
mod udim2;
|
||||||
mod vector2;
|
mod vector2;
|
||||||
|
@ -13,6 +16,9 @@ pub use brick_color::BrickColor;
|
||||||
pub use color3::Color3;
|
pub use color3::Color3;
|
||||||
pub use color_sequence::ColorSequence;
|
pub use color_sequence::ColorSequence;
|
||||||
pub use color_sequence_keypoint::ColorSequenceKeypoint;
|
pub use color_sequence_keypoint::ColorSequenceKeypoint;
|
||||||
|
pub use r#enum::Enum;
|
||||||
|
pub use r#enum_item::EnumItem;
|
||||||
|
pub use r#enums::Enums;
|
||||||
pub use udim::UDim;
|
pub use udim::UDim;
|
||||||
pub use udim2::UDim2;
|
pub use udim2::UDim2;
|
||||||
pub use vector2::Vector2;
|
pub use vector2::Vector2;
|
||||||
|
|
|
@ -7,20 +7,21 @@ pub mod instance;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
fn make_dt<F>(lua: &Lua, f: F) -> LuaResult<LuaTable>
|
fn make_dt<F>(lua: &Lua, f: F) -> LuaResult<LuaValue>
|
||||||
where
|
where
|
||||||
F: Fn(&Lua, &LuaTable) -> LuaResult<()>,
|
F: Fn(&Lua, &LuaTable) -> LuaResult<()>,
|
||||||
{
|
{
|
||||||
let tab = lua.create_table()?;
|
let tab = lua.create_table()?;
|
||||||
f(lua, &tab)?;
|
f(lua, &tab)?;
|
||||||
tab.set_readonly(true);
|
tab.set_readonly(true);
|
||||||
Ok(tab)
|
Ok(LuaValue::Table(tab))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> {
|
fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
||||||
use datatypes::types::*;
|
use datatypes::types::*;
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
|
// Classes
|
||||||
("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)?),
|
||||||
|
@ -31,6 +32,8 @@ fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaTable)>> {
|
||||||
("Vector2int16", make_dt(lua, Vector2int16::make_table)?),
|
("Vector2int16", make_dt(lua, Vector2int16::make_table)?),
|
||||||
("Vector3", make_dt(lua, Vector3::make_table)?),
|
("Vector3", make_dt(lua, Vector3::make_table)?),
|
||||||
("Vector3int16", make_dt(lua, Vector3int16::make_table)?),
|
("Vector3int16", make_dt(lua, Vector3int16::make_table)?),
|
||||||
|
// Singletons
|
||||||
|
("Enum", LuaValue::UserData(Enums::make_singleton(lua)?)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue