mirror of
https://github.com/lune-org/lune.git
synced 2024-12-13 13:30:38 +00:00
Implement tests for getting & setting roblox instance properties
Also fix some related bugs
This commit is contained in:
parent
afdde26a18
commit
201f38d44e
3 changed files with 91 additions and 28 deletions
|
@ -663,6 +663,11 @@ impl LuaUserData for Instance {
|
||||||
.to_lua(lua)
|
.to_lua(lua)
|
||||||
} else if let Some(prop_default) = info.value_default {
|
} else if let Some(prop_default) = info.value_default {
|
||||||
Ok(LuaValue::dom_value_to_lua(lua, prop_default)?)
|
Ok(LuaValue::dom_value_to_lua(lua, prop_default)?)
|
||||||
|
} else if info.value_type.is_some() {
|
||||||
|
Err(LuaError::RuntimeError(format!(
|
||||||
|
"Failed to get property '{}' - missing default value",
|
||||||
|
prop_name
|
||||||
|
)))
|
||||||
} else {
|
} else {
|
||||||
Err(LuaError::RuntimeError(format!(
|
Err(LuaError::RuntimeError(format!(
|
||||||
"Failed to get property '{}' - malformed property info",
|
"Failed to get property '{}' - malformed property info",
|
||||||
|
@ -730,13 +735,13 @@ impl LuaUserData for Instance {
|
||||||
|
|
||||||
if let Some(enum_name) = info.enum_name {
|
if let Some(enum_name) = info.enum_name {
|
||||||
match EnumItem::from_lua(prop_value, lua) {
|
match EnumItem::from_lua(prop_value, lua) {
|
||||||
Ok(given_enum) if given_enum.name == enum_name => {
|
Ok(given_enum) if given_enum.parent.desc.name == enum_name => {
|
||||||
this.set_property(prop_name, DomValue::Enum(given_enum.into()));
|
this.set_property(prop_name, DomValue::Enum(given_enum.into()));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Ok(given_enum) => Err(LuaError::RuntimeError(format!(
|
Ok(given_enum) => Err(LuaError::RuntimeError(format!(
|
||||||
"Failed to set property '{}' - expected Enum.{}, got Enum.{}",
|
"Failed to set property '{}' - expected Enum.{}, got Enum.{}",
|
||||||
prop_name, enum_name, given_enum.name
|
prop_name, enum_name, given_enum.parent.desc.name
|
||||||
))),
|
))),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,9 @@ pub(crate) struct PropertyInfo {
|
||||||
/**
|
/**
|
||||||
Finds the info of a property of the given class.
|
Finds the info of a property of the given class.
|
||||||
|
|
||||||
|
This will also check superclasses if the property
|
||||||
|
was not directly found for the given class.
|
||||||
|
|
||||||
Returns `None` if the class or property does not exist.
|
Returns `None` if the class or property does not exist.
|
||||||
*/
|
*/
|
||||||
pub(crate) fn find_property_info(
|
pub(crate) fn find_property_info(
|
||||||
|
@ -20,14 +23,18 @@ pub(crate) fn find_property_info(
|
||||||
property_name: impl AsRef<str>,
|
property_name: impl AsRef<str>,
|
||||||
) -> Option<PropertyInfo> {
|
) -> Option<PropertyInfo> {
|
||||||
let db = rbx_reflection_database::get();
|
let db = rbx_reflection_database::get();
|
||||||
let class = db.classes.get(instance_class.as_ref())?;
|
|
||||||
|
|
||||||
|
let instance_class = instance_class.as_ref();
|
||||||
let property_name = property_name.as_ref();
|
let property_name = property_name.as_ref();
|
||||||
let prop_definition = class.properties.get(property_name)?;
|
|
||||||
let prop_default = class.default_properties.get(property_name);
|
|
||||||
|
|
||||||
match &prop_definition.data_type {
|
let mut current_class = Cow::Borrowed(instance_class);
|
||||||
DataType::Enum(enum_name) => Some(PropertyInfo {
|
while let Some(class) = db.classes.get(current_class.as_ref()) {
|
||||||
|
if let Some(prop_definition) = class.properties.get(property_name) {
|
||||||
|
// We found a property, we should map it to a property
|
||||||
|
// info containing name/type and default property value
|
||||||
|
let prop_default = class.default_properties.get(property_name);
|
||||||
|
return Some(match &prop_definition.data_type {
|
||||||
|
DataType::Enum(enum_name) => PropertyInfo {
|
||||||
enum_name: Some(Cow::Borrowed(enum_name)),
|
enum_name: Some(Cow::Borrowed(enum_name)),
|
||||||
enum_default: prop_default.and_then(|default| match default {
|
enum_default: prop_default.and_then(|default| match default {
|
||||||
DomValue::Enum(enum_default) => Some(enum_default.to_u32()),
|
DomValue::Enum(enum_default) => Some(enum_default.to_u32()),
|
||||||
|
@ -35,22 +42,31 @@ pub(crate) fn find_property_info(
|
||||||
}),
|
}),
|
||||||
value_type: None,
|
value_type: None,
|
||||||
value_default: None,
|
value_default: None,
|
||||||
}),
|
},
|
||||||
DataType::Value(value_type) => Some(PropertyInfo {
|
DataType::Value(value_type) => PropertyInfo {
|
||||||
enum_name: None,
|
enum_name: None,
|
||||||
enum_default: None,
|
enum_default: None,
|
||||||
value_type: Some(*value_type),
|
value_type: Some(*value_type),
|
||||||
value_default: prop_default,
|
value_default: prop_default,
|
||||||
}),
|
},
|
||||||
_ => Some(PropertyInfo {
|
_ => PropertyInfo {
|
||||||
enum_name: None,
|
enum_name: None,
|
||||||
enum_default: None,
|
enum_default: None,
|
||||||
value_type: None,
|
value_type: None,
|
||||||
value_default: None,
|
value_default: None,
|
||||||
}),
|
},
|
||||||
|
});
|
||||||
|
} else if let Some(sup) = &class.superclass {
|
||||||
|
// No property found, we should look at the superclass
|
||||||
|
current_class = Cow::Borrowed(sup)
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks if an instance class exists in the reflection database.
|
Checks if an instance class exists in the reflection database.
|
||||||
*/
|
*/
|
||||||
|
|
42
tests/roblox/instance/properties.luau
Normal file
42
tests/roblox/instance/properties.luau
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
local roblox = require("@lune/roblox") :: any
|
||||||
|
local BrickColor = roblox.BrickColor
|
||||||
|
local Instance = roblox.Instance
|
||||||
|
local Vector3 = roblox.Vector3
|
||||||
|
local CFrame = roblox.CFrame
|
||||||
|
local Enum = roblox.Enum
|
||||||
|
|
||||||
|
local part = Instance.new("Part")
|
||||||
|
|
||||||
|
-- Primitive type properties should work (note that these are inherited from BasePart)
|
||||||
|
|
||||||
|
part.Anchored = true
|
||||||
|
part.CanCollide = true
|
||||||
|
part.CanQuery = false
|
||||||
|
|
||||||
|
assert(part.Anchored == true)
|
||||||
|
assert(part.CanCollide == true)
|
||||||
|
assert(part.CanQuery == false)
|
||||||
|
|
||||||
|
-- More complex types like Vector3 should work
|
||||||
|
|
||||||
|
part.Size = Vector3.one
|
||||||
|
part.CFrame = CFrame.identity
|
||||||
|
part.BrickColor = BrickColor.Red()
|
||||||
|
|
||||||
|
assert(part.Size == Vector3.one)
|
||||||
|
assert(part.CFrame == CFrame.identity)
|
||||||
|
assert(part.BrickColor == BrickColor.Red())
|
||||||
|
|
||||||
|
-- Enums should work (note that these are specific to Part and not on BasePart)
|
||||||
|
|
||||||
|
part.Shape = Enum.PartType.Ball
|
||||||
|
|
||||||
|
assert(part.Shape == Enum.PartType.Ball)
|
||||||
|
|
||||||
|
-- Properties that don't exist for a class should error
|
||||||
|
|
||||||
|
local meshPart = Instance.new("MeshPart")
|
||||||
|
|
||||||
|
assert(not pcall(function()
|
||||||
|
meshPart.Shape = Enum.PartType.Ball
|
||||||
|
end))
|
Loading…
Reference in a new issue