mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
Implement PhysicalProperties roblox datatype
This commit is contained in:
parent
e57abbe5d9
commit
e57316341b
5 changed files with 290 additions and 14 deletions
|
@ -113,23 +113,28 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
fn rbx_variant_to_lua(lua: &'lua Lua, variant: &RbxVariant) -> DatatypeConversionResult<Self> {
|
fn rbx_variant_to_lua(lua: &'lua Lua, variant: &RbxVariant) -> DatatypeConversionResult<Self> {
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
use RbxVariant as Rbx;
|
use RbxVariant as Rbx;
|
||||||
|
use rbx_dom_weak::types as rbx;
|
||||||
|
|
||||||
// NOTE: Enum is intentionally left out here, it has a custom
|
/*
|
||||||
// conversion going from instance property > datatype instead,
|
NOTES:
|
||||||
// check `EnumItem::from_instance_property` for specifics
|
|
||||||
|
1. Enum is intentionally left out here, it has a custom
|
||||||
|
conversion going from instance property > datatype instead,
|
||||||
|
check `EnumItem::from_instance_property` for specifics
|
||||||
|
|
||||||
|
2. PhysicalProperties can only be converted if they are custom
|
||||||
|
physical properties, since default physical properties values
|
||||||
|
depend on what other related properties an instance might have
|
||||||
|
|
||||||
|
*/
|
||||||
Ok(match variant.clone() {
|
Ok(match variant.clone() {
|
||||||
// Not yet implemented datatypes
|
// Not yet implemented datatypes
|
||||||
// Rbx::Font(_) => todo!(),
|
// Rbx::Font(_) => todo!(),
|
||||||
// Rbx::PhysicalProperties(_) => todo!(),
|
|
||||||
|
|
||||||
Rbx::Axes(value) => lua.create_userdata(Axes::from(value))?,
|
Rbx::Axes(value) => lua.create_userdata(Axes::from(value))?,
|
||||||
Rbx::Faces(value) => lua.create_userdata(Faces::from(value))?,
|
Rbx::Faces(value) => lua.create_userdata(Faces::from(value))?,
|
||||||
|
|
||||||
Rbx::CFrame(value) => lua.create_userdata(CFrame::from(value))?,
|
Rbx::CFrame(value) => lua.create_userdata(CFrame::from(value))?,
|
||||||
Rbx::OptionalCFrame(value) => match value {
|
|
||||||
Some(value) => lua.create_userdata(CFrame::from(value))?,
|
|
||||||
None => lua.create_userdata(CFrame::IDENTITY)?
|
|
||||||
},
|
|
||||||
|
|
||||||
Rbx::BrickColor(value) => lua.create_userdata(BrickColor::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))?,
|
||||||
|
@ -152,6 +157,15 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
Rbx::Vector3(value) => lua.create_userdata(Vector3::from(value))?,
|
Rbx::Vector3(value) => lua.create_userdata(Vector3::from(value))?,
|
||||||
Rbx::Vector3int16(value) => lua.create_userdata(Vector3int16::from(value))?,
|
Rbx::Vector3int16(value) => lua.create_userdata(Vector3int16::from(value))?,
|
||||||
|
|
||||||
|
Rbx::OptionalCFrame(value) => match value {
|
||||||
|
Some(value) => lua.create_userdata(CFrame::from(value))?,
|
||||||
|
None => lua.create_userdata(CFrame::IDENTITY)?
|
||||||
|
},
|
||||||
|
|
||||||
|
Rbx::PhysicalProperties(rbx::PhysicalProperties::Custom(value)) => {
|
||||||
|
lua.create_userdata(PhysicalProperties::from(value))?
|
||||||
|
},
|
||||||
|
|
||||||
v => {
|
v => {
|
||||||
return Err(DatatypeConversionError::FromRbxVariant {
|
return Err(DatatypeConversionError::FromRbxVariant {
|
||||||
from: v.variant_name(),
|
from: v.variant_name(),
|
||||||
|
@ -177,11 +191,7 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
||||||
RbxVariantType::Axes => convert::<Axes, rbx::Axes>,
|
RbxVariantType::Axes => convert::<Axes, rbx::Axes>,
|
||||||
RbxVariantType::Faces => convert::<Faces, rbx::Faces>,
|
RbxVariantType::Faces => convert::<Faces, rbx::Faces>,
|
||||||
|
|
||||||
RbxVariantType::CFrame => convert::<CFrame, rbx::CFrame>,
|
RbxVariantType::CFrame => convert::<CFrame, rbx::CFrame>,
|
||||||
RbxVariantType::OptionalCFrame => return match self.borrow::<CFrame>() {
|
|
||||||
Ok(value) => Ok(RbxVariant::OptionalCFrame(Some(rbx::CFrame::from(*value)))),
|
|
||||||
Err(e) => Err(lua_userdata_error_to_conversion_error(variant_type, e)),
|
|
||||||
},
|
|
||||||
|
|
||||||
RbxVariantType::BrickColor => convert::<BrickColor, rbx::BrickColor>,
|
RbxVariantType::BrickColor => convert::<BrickColor, rbx::BrickColor>,
|
||||||
RbxVariantType::Color3 => convert::<Color3, rbx::Color3>,
|
RbxVariantType::Color3 => convert::<Color3, rbx::Color3>,
|
||||||
|
@ -206,6 +216,20 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
||||||
RbxVariantType::Vector3 => convert::<Vector3, rbx::Vector3>,
|
RbxVariantType::Vector3 => convert::<Vector3, rbx::Vector3>,
|
||||||
RbxVariantType::Vector3int16 => convert::<Vector3int16, rbx::Vector3int16>,
|
RbxVariantType::Vector3int16 => convert::<Vector3int16, rbx::Vector3int16>,
|
||||||
|
|
||||||
|
RbxVariantType::OptionalCFrame => return match self.borrow::<CFrame>() {
|
||||||
|
Ok(value) => Ok(RbxVariant::OptionalCFrame(Some(rbx::CFrame::from(*value)))),
|
||||||
|
Err(e) => Err(lua_userdata_error_to_conversion_error(variant_type, e)),
|
||||||
|
},
|
||||||
|
|
||||||
|
RbxVariantType::PhysicalProperties => return match self.borrow::<PhysicalProperties>() {
|
||||||
|
Ok(value) => {
|
||||||
|
let props = rbx::CustomPhysicalProperties::from(*value);
|
||||||
|
let custom = rbx::PhysicalProperties::Custom(props);
|
||||||
|
Ok(RbxVariant::PhysicalProperties(custom))
|
||||||
|
},
|
||||||
|
Err(e) => Err(lua_userdata_error_to_conversion_error(variant_type, e)),
|
||||||
|
},
|
||||||
|
|
||||||
_ => return Err(DatatypeConversionError::ToRbxVariant {
|
_ => return Err(DatatypeConversionError::ToRbxVariant {
|
||||||
to: variant_type.variant_name(),
|
to: variant_type.variant_name(),
|
||||||
from: "userdata",
|
from: "userdata",
|
||||||
|
@ -213,7 +237,7 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
f(self, variant_type)
|
f(self, variant_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ mod faces;
|
||||||
mod number_range;
|
mod number_range;
|
||||||
mod number_sequence;
|
mod number_sequence;
|
||||||
mod number_sequence_keypoint;
|
mod number_sequence_keypoint;
|
||||||
|
mod physical_properties;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod rect;
|
mod rect;
|
||||||
mod region3;
|
mod region3;
|
||||||
|
@ -32,6 +33,7 @@ pub use faces::Faces;
|
||||||
pub use number_range::NumberRange;
|
pub use number_range::NumberRange;
|
||||||
pub use number_sequence::NumberSequence;
|
pub use number_sequence::NumberSequence;
|
||||||
pub use number_sequence_keypoint::NumberSequenceKeypoint;
|
pub use number_sequence_keypoint::NumberSequenceKeypoint;
|
||||||
|
pub use physical_properties::PhysicalProperties;
|
||||||
pub use r#enum::Enum;
|
pub use r#enum::Enum;
|
||||||
pub use r#enum_item::EnumItem;
|
pub use r#enum_item::EnumItem;
|
||||||
pub use r#enums::Enums;
|
pub use r#enums::Enums;
|
||||||
|
@ -99,6 +101,7 @@ mod tests {
|
||||||
number_range: "datatypes/NumberRange",
|
number_range: "datatypes/NumberRange",
|
||||||
number_sequence: "datatypes/NumberSequence",
|
number_sequence: "datatypes/NumberSequence",
|
||||||
number_sequence_keypoint: "datatypes/NumberSequenceKeypoint",
|
number_sequence_keypoint: "datatypes/NumberSequenceKeypoint",
|
||||||
|
physical_properties: "datatypes/PhysicalProperties",
|
||||||
ray: "datatypes/Ray",
|
ray: "datatypes/Ray",
|
||||||
rect: "datatypes/Rect",
|
rect: "datatypes/Rect",
|
||||||
udim: "datatypes/UDim",
|
udim: "datatypes/UDim",
|
||||||
|
|
183
packages/lib-roblox/src/datatypes/types/physical_properties.rs
Normal file
183
packages/lib-roblox/src/datatypes/types/physical_properties.rs
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use rbx_dom_weak::types::CustomPhysicalProperties as RbxCustomPhysicalProperties;
|
||||||
|
|
||||||
|
use super::{super::*, EnumItem};
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the [PhysicalProperties](https://create.roblox.com/docs/reference/engine/datatypes/PhysicalProperties) Roblox datatype.
|
||||||
|
|
||||||
|
This implements all documented properties, methods & constructors of the PhysicalProperties class as of March 2023.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub struct PhysicalProperties {
|
||||||
|
pub(crate) density: f32,
|
||||||
|
pub(crate) friction: f32,
|
||||||
|
pub(crate) friction_weight: f32,
|
||||||
|
pub(crate) elasticity: f32,
|
||||||
|
pub(crate) elasticity_weight: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhysicalProperties {
|
||||||
|
pub(crate) fn from_material(material_enum_item: &EnumItem) -> Option<PhysicalProperties> {
|
||||||
|
MATERIAL_ENUM_MAP
|
||||||
|
.iter()
|
||||||
|
.find(|props| props.0 == material_enum_item.name)
|
||||||
|
.map(|props| PhysicalProperties {
|
||||||
|
density: props.1,
|
||||||
|
friction: props.2,
|
||||||
|
elasticity: props.3,
|
||||||
|
friction_weight: props.4,
|
||||||
|
elasticity_weight: props.5,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||||
|
type ArgsMaterial = EnumItem;
|
||||||
|
type ArgsNumbers = (f32, f32, f32, Option<f32>, Option<f32>);
|
||||||
|
datatype_table.set(
|
||||||
|
"new",
|
||||||
|
lua.create_function(|lua, args: LuaMultiValue| {
|
||||||
|
if let Ok(value) = ArgsMaterial::from_lua_multi(args.clone(), lua) {
|
||||||
|
if value.parent.desc.name == "Material" {
|
||||||
|
match PhysicalProperties::from_material(&value) {
|
||||||
|
Some(props) => Ok(props),
|
||||||
|
None => Err(LuaError::RuntimeError(format!(
|
||||||
|
"Found unknown Material '{}'",
|
||||||
|
value.name
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(LuaError::RuntimeError(format!(
|
||||||
|
"Expected argument #1 to be a Material, got {}",
|
||||||
|
value.parent.desc.name
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
} else if let Ok((
|
||||||
|
density,
|
||||||
|
friction,
|
||||||
|
elasticity,
|
||||||
|
friction_weight,
|
||||||
|
elasticity_weight,
|
||||||
|
)) = ArgsNumbers::from_lua_multi(args, lua)
|
||||||
|
{
|
||||||
|
Ok(PhysicalProperties {
|
||||||
|
density,
|
||||||
|
friction,
|
||||||
|
friction_weight: friction_weight.unwrap_or(1.0),
|
||||||
|
elasticity,
|
||||||
|
elasticity_weight: elasticity_weight.unwrap_or(1.0),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// FUTURE: Better error message here using given arg types
|
||||||
|
Err(LuaError::RuntimeError(
|
||||||
|
"Invalid arguments to constructor".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for PhysicalProperties {
|
||||||
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("Density", |_, this| Ok(this.density));
|
||||||
|
fields.add_field_method_get("Friction", |_, this| Ok(this.friction));
|
||||||
|
fields.add_field_method_get("FrictionWeight", |_, this| Ok(this.friction_weight));
|
||||||
|
fields.add_field_method_get("Elasticity", |_, this| Ok(this.elasticity));
|
||||||
|
fields.add_field_method_get("ElasticityWeight", |_, this| Ok(this.elasticity_weight));
|
||||||
|
}
|
||||||
|
|
||||||
|
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 PhysicalProperties {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}, {}, {}, {}, {}",
|
||||||
|
self.density,
|
||||||
|
self.friction,
|
||||||
|
self.elasticity,
|
||||||
|
self.friction_weight,
|
||||||
|
self.elasticity_weight
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RbxCustomPhysicalProperties> for PhysicalProperties {
|
||||||
|
fn from(v: RbxCustomPhysicalProperties) -> Self {
|
||||||
|
Self {
|
||||||
|
density: v.density,
|
||||||
|
friction: v.friction,
|
||||||
|
friction_weight: v.friction_weight,
|
||||||
|
elasticity: v.elasticity,
|
||||||
|
elasticity_weight: v.elasticity_weight,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PhysicalProperties> for RbxCustomPhysicalProperties {
|
||||||
|
fn from(v: PhysicalProperties) -> Self {
|
||||||
|
RbxCustomPhysicalProperties {
|
||||||
|
density: v.density,
|
||||||
|
friction: v.friction,
|
||||||
|
friction_weight: v.friction_weight,
|
||||||
|
elasticity: v.elasticity,
|
||||||
|
elasticity_weight: v.elasticity_weight,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
NOTE: The material definitions below are generated using the
|
||||||
|
physical_properties_enum_map script in the scripts dir next
|
||||||
|
to src, which can be ran in the Roblox Studio command bar
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const MATERIAL_ENUM_MAP: &[(&str, f32, f32, f32, f32, f32)] = &[
|
||||||
|
("Plastic", 0.70, 0.30, 0.50, 1.00, 1.00),
|
||||||
|
("Wood", 0.35, 0.48, 0.20, 1.00, 1.00),
|
||||||
|
("Slate", 2.69, 0.40, 0.20, 1.00, 1.00),
|
||||||
|
("Concrete", 2.40, 0.70, 0.20, 0.30, 1.00),
|
||||||
|
("CorrodedMetal", 7.85, 0.70, 0.20, 1.00, 1.00),
|
||||||
|
("DiamondPlate", 7.85, 0.35, 0.25, 1.00, 1.00),
|
||||||
|
("Foil", 2.70, 0.40, 0.25, 1.00, 1.00),
|
||||||
|
("Grass", 0.90, 0.40, 0.10, 1.00, 1.50),
|
||||||
|
("Ice", 0.92, 0.02, 0.15, 3.00, 1.00),
|
||||||
|
("Marble", 2.56, 0.20, 0.17, 1.00, 1.00),
|
||||||
|
("Granite", 2.69, 0.40, 0.20, 1.00, 1.00),
|
||||||
|
("Brick", 1.92, 0.80, 0.15, 0.30, 1.00),
|
||||||
|
("Pebble", 2.40, 0.40, 0.17, 1.00, 1.50),
|
||||||
|
("Sand", 1.60, 0.50, 0.05, 5.00, 2.50),
|
||||||
|
("Fabric", 0.70, 0.35, 0.05, 1.00, 1.00),
|
||||||
|
("SmoothPlastic", 0.70, 0.20, 0.50, 1.00, 1.00),
|
||||||
|
("Metal", 7.85, 0.40, 0.25, 1.00, 1.00),
|
||||||
|
("WoodPlanks", 0.35, 0.48, 0.20, 1.00, 1.00),
|
||||||
|
("Cobblestone", 2.69, 0.50, 0.17, 1.00, 1.00),
|
||||||
|
("Air", 0.01, 0.01, 0.01, 1.00, 1.00),
|
||||||
|
("Water", 1.00, 0.00, 0.01, 1.00, 1.00),
|
||||||
|
("Rock", 2.69, 0.50, 0.17, 1.00, 1.00),
|
||||||
|
("Glacier", 0.92, 0.05, 0.15, 2.00, 1.00),
|
||||||
|
("Snow", 0.90, 0.30, 0.03, 3.00, 4.00),
|
||||||
|
("Sandstone", 2.69, 0.50, 0.15, 5.00, 1.00),
|
||||||
|
("Mud", 0.90, 0.30, 0.07, 3.00, 4.00),
|
||||||
|
("Basalt", 2.69, 0.70, 0.15, 0.30, 1.00),
|
||||||
|
("Ground", 0.90, 0.45, 0.10, 1.00, 1.00),
|
||||||
|
("CrackedLava", 2.69, 0.65, 0.15, 1.00, 1.00),
|
||||||
|
("Neon", 0.70, 0.30, 0.20, 1.00, 1.00),
|
||||||
|
("Glass", 2.40, 0.25, 0.20, 1.00, 1.00),
|
||||||
|
("Asphalt", 2.36, 0.80, 0.20, 0.30, 1.00),
|
||||||
|
("LeafyGrass", 0.90, 0.40, 0.10, 2.00, 2.00),
|
||||||
|
("Salt", 2.16, 0.50, 0.05, 1.00, 1.00),
|
||||||
|
("Limestone", 2.69, 0.50, 0.15, 1.00, 1.00),
|
||||||
|
("Pavement", 2.69, 0.50, 0.17, 0.30, 1.00),
|
||||||
|
("ForceField", 2.40, 0.25, 0.20, 1.00, 1.00),
|
||||||
|
];
|
|
@ -29,6 +29,7 @@ fn make_all_datatypes(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
||||||
("NumberRange", make_dt(lua, NumberRange::make_table)?),
|
("NumberRange", make_dt(lua, NumberRange::make_table)?),
|
||||||
("NumberSequence", make_dt(lua, NumberSequence::make_table)?),
|
("NumberSequence", make_dt(lua, NumberSequence::make_table)?),
|
||||||
("NumberSequenceKeypoint", make_dt(lua, NumberSequenceKeypoint::make_table)?),
|
("NumberSequenceKeypoint", make_dt(lua, NumberSequenceKeypoint::make_table)?),
|
||||||
|
("PhysicalProperties", make_dt(lua, PhysicalProperties::make_table)?),
|
||||||
("Ray", make_dt(lua, Ray::make_table)?),
|
("Ray", make_dt(lua, Ray::make_table)?),
|
||||||
("Rect", make_dt(lua, Rect::make_table)?),
|
("Rect", make_dt(lua, Rect::make_table)?),
|
||||||
("UDim", make_dt(lua, UDim::make_table)?),
|
("UDim", make_dt(lua, UDim::make_table)?),
|
||||||
|
|
65
tests/roblox/datatypes/PhysicalProperties.luau
Normal file
65
tests/roblox/datatypes/PhysicalProperties.luau
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
-- HACK: Make luau happy, with the mlua rust
|
||||||
|
-- crate all globals are also present in _G
|
||||||
|
local PhysicalProperties = _G.PhysicalProperties
|
||||||
|
local Enum = _G.Enum
|
||||||
|
|
||||||
|
-- Constructors & properties
|
||||||
|
|
||||||
|
PhysicalProperties.new(Enum.Material.SmoothPlastic)
|
||||||
|
PhysicalProperties.new(0, 0, 0)
|
||||||
|
PhysicalProperties.new(0, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
assert(not pcall(function()
|
||||||
|
return PhysicalProperties.new()
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return PhysicalProperties.new(false)
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return PhysicalProperties.new({})
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return PhysicalProperties.new(newproxy(true))
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return PhysicalProperties.new(Enum.Axis.X)
|
||||||
|
end))
|
||||||
|
|
||||||
|
assert(PhysicalProperties.new(1, 2, 3).FrictionWeight == 1)
|
||||||
|
assert(PhysicalProperties.new(1, 2, 3).ElasticityWeight == 1)
|
||||||
|
|
||||||
|
assert(PhysicalProperties.new(1, 2, 3, 4, 5).Density == 1)
|
||||||
|
assert(PhysicalProperties.new(1, 2, 3, 4, 5).Friction == 2)
|
||||||
|
assert(PhysicalProperties.new(1, 2, 3, 4, 5).Elasticity == 3)
|
||||||
|
assert(PhysicalProperties.new(1, 2, 3, 4, 5).FrictionWeight == 4)
|
||||||
|
assert(PhysicalProperties.new(1, 2, 3, 4, 5).ElasticityWeight == 5)
|
||||||
|
|
||||||
|
local function fuzzyEq(n0: number, n1: number)
|
||||||
|
return math.abs(n1 - n0) <= 0.0001
|
||||||
|
end
|
||||||
|
|
||||||
|
local plastic = PhysicalProperties.new(Enum.Material.Plastic)
|
||||||
|
assert(fuzzyEq(plastic.Density, 0.7))
|
||||||
|
assert(fuzzyEq(plastic.Friction, 0.3))
|
||||||
|
assert(fuzzyEq(plastic.Elasticity, 0.5))
|
||||||
|
|
||||||
|
local splastic = PhysicalProperties.new(Enum.Material.SmoothPlastic)
|
||||||
|
assert(fuzzyEq(splastic.Density, 0.7))
|
||||||
|
assert(fuzzyEq(splastic.Friction, 0.2))
|
||||||
|
assert(fuzzyEq(splastic.Elasticity, 0.5))
|
||||||
|
|
||||||
|
local sand = PhysicalProperties.new(Enum.Material.Sand)
|
||||||
|
assert(fuzzyEq(sand.Density, 1.6))
|
||||||
|
assert(fuzzyEq(sand.Friction, 0.5))
|
||||||
|
assert(fuzzyEq(sand.Elasticity, 0.05))
|
||||||
|
assert(fuzzyEq(sand.FrictionWeight, 5))
|
||||||
|
assert(fuzzyEq(sand.ElasticityWeight, 2.5))
|
||||||
|
|
||||||
|
-- Ops
|
||||||
|
|
||||||
|
assert(not pcall(function()
|
||||||
|
return PhysicalProperties.new() + PhysicalProperties.new()
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return PhysicalProperties.new() / PhysicalProperties.new()
|
||||||
|
end))
|
Loading…
Reference in a new issue