From 5379c79488a8f49c22674635526b643df98e8b27 Mon Sep 17 00:00:00 2001 From: ZachCurtis <31259055+ZachCurtis@users.noreply.github.com> Date: Sun, 21 Jul 2024 17:35:58 -0400 Subject: [PATCH 1/2] Add missing vector methods (#228) --- crates/lune-roblox/src/datatypes/types/vector2.rs | 15 +++++++++++++++ crates/lune-roblox/src/datatypes/types/vector3.rs | 4 ++++ tests/roblox/datatypes/Vector2.luau | 12 +++++++++++- tests/roblox/datatypes/Vector3.luau | 8 +++++++- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/crates/lune-roblox/src/datatypes/types/vector2.rs b/crates/lune-roblox/src/datatypes/types/vector2.rs index 343fb706..2248530c 100644 --- a/crates/lune-roblox/src/datatypes/types/vector2.rs +++ b/crates/lune-roblox/src/datatypes/types/vector2.rs @@ -52,6 +52,9 @@ impl LuaUserData for Vector2 { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { // Methods + methods.add_method("Angle", |_, this, rhs: LuaUserDataRef| { + Ok(this.0.angle_between(rhs.0)) + }); methods.add_method("Cross", |_, this, rhs: LuaUserDataRef| { let this_v3 = Vec3::new(this.0.x, this.0.y, 0f32); let rhs_v3 = Vec3::new(rhs.0.x, rhs.0.y, 0f32); @@ -60,6 +63,14 @@ impl LuaUserData for Vector2 { methods.add_method("Dot", |_, this, rhs: LuaUserDataRef| { Ok(this.0.dot(rhs.0)) }); + methods.add_method( + "FuzzyEq", + |_, this, (rhs, epsilon): (LuaUserDataRef, f32)| { + let eq_x = (rhs.0.x - this.0.x).abs() <= epsilon; + let eq_y = (rhs.0.y - this.0.y).abs() <= epsilon; + Ok(eq_x && eq_y) + }, + ); methods.add_method( "Lerp", |_, this, (rhs, alpha): (LuaUserDataRef, f32)| { @@ -72,6 +83,10 @@ impl LuaUserData for Vector2 { methods.add_method("Min", |_, this, rhs: LuaUserDataRef| { Ok(Vector2(this.0.min(rhs.0))) }); + methods.add_method("Abs", |_, this, ()| Ok(Vector2(this.0.abs()))); + methods.add_method("Ceil", |_, this, ()| Ok(Vector2(this.0.ceil()))); + methods.add_method("Floor", |_, this, ()| Ok(Vector2(this.0.floor()))); + methods.add_method("Sign", |_, this, ()| Ok(Vector2(this.0.signum()))); // Metamethods methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq); methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string); diff --git a/crates/lune-roblox/src/datatypes/types/vector3.rs b/crates/lune-roblox/src/datatypes/types/vector3.rs index 11bcd4a4..c976c543 100644 --- a/crates/lune-roblox/src/datatypes/types/vector3.rs +++ b/crates/lune-roblox/src/datatypes/types/vector3.rs @@ -133,6 +133,10 @@ impl LuaUserData for Vector3 { methods.add_method("Min", |_, this, rhs: LuaUserDataRef| { Ok(Vector3(this.0.min(rhs.0))) }); + methods.add_method("Abs", |_, this, ()| Ok(Vector3(this.0.abs()))); + methods.add_method("Ceil", |_, this, ()| Ok(Vector3(this.0.ceil()))); + methods.add_method("Floor", |_, this, ()| Ok(Vector3(this.0.floor()))); + methods.add_method("Sign", |_, this, ()| Ok(Vector3(this.0.signum()))); // Metamethods methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq); methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string); diff --git a/tests/roblox/datatypes/Vector2.luau b/tests/roblox/datatypes/Vector2.luau index 1ed391ee..523ba942 100644 --- a/tests/roblox/datatypes/Vector2.luau +++ b/tests/roblox/datatypes/Vector2.luau @@ -42,4 +42,14 @@ assert(Vector2.new(2, 4) / 2 == Vector2.new(1, 2)) assert(Vector2.new(7, 15) // Vector2.new(3, 7) == Vector2.new(2, 2)) assert(Vector2.new(3, 7) // 2 == Vector2.new(1, 3)) --- TODO: Vector math +-- Vector math methods +assert(Vector2.new(-1, -2):Abs() == Vector2.new(1, 2)) +assert(Vector2.new(-1.7, 2):Sign() == Vector2.new(-1, 1)) +assert(Vector2.new(-1.9, 2.1):Ceil() == Vector2.new(-1, 3)) +assert(Vector2.new(-1.1, 2.99):Floor() == Vector2.new(-2, 2)) + +assert(Vector2.new(1, 2):FuzzyEq(Vector2.new(1 - 1e-6, 2 + 1e-6), 1e-5)) +assert(not Vector2.new(1, 2):FuzzyEq(Vector2.new(1.2, 2), 0.1)) + +local angle = Vector2.new(1, 1):Angle(Vector2.new(-1, 1)) +assert(math.abs(angle - (math.pi / 2)) < 1e-5) diff --git a/tests/roblox/datatypes/Vector3.luau b/tests/roblox/datatypes/Vector3.luau index 4a4b7453..723e3abf 100644 --- a/tests/roblox/datatypes/Vector3.luau +++ b/tests/roblox/datatypes/Vector3.luau @@ -45,4 +45,10 @@ assert(Vector3.new(2, 4, 8) / 2 == Vector3.new(1, 2, 4)) assert(Vector3.new(7, 11, 15) // Vector3.new(3, 5, 7) == Vector3.new(2, 2, 2)) assert(Vector3.new(3, 5, 7) // 2 == Vector3.new(1, 2, 3)) --- TODO: Vector math +-- Vector math methods +assert(Vector3.new(-1, -2, -3):Abs() == Vector3.new(1, 2, 3)) +assert(Vector3.new(-1.7, 2, -3):Sign() == Vector3.new(-1, 1, -1)) +assert(Vector3.new(-1.9, 2.1, 3.5):Ceil() == Vector3.new(-1, 3, 4)) +assert(Vector3.new(-1.1, 2.99, 3.5):Floor() == Vector3.new(-2, 2, 3)) + +assert(Vector3.new(1, 2, 3):FuzzyEq(Vector3.new(1 - 1e-6, 2 + 1e-6, 3 + 1e-6), 1e-5)) From b585234b081e60ca2e2fc2356f37b55140b937b3 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Sun, 21 Jul 2024 23:50:55 +0200 Subject: [PATCH 2/2] Clarify some comments and expose more instance functions in lune-roblox --- crates/lune-roblox/src/instance/mod.rs | 42 ++++++++++++-------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/crates/lune-roblox/src/instance/mod.rs b/crates/lune-roblox/src/instance/mod.rs index da3ccb4b..99bd16b2 100644 --- a/crates/lune-roblox/src/instance/mod.rs +++ b/crates/lune-roblox/src/instance/mod.rs @@ -45,38 +45,26 @@ impl Instance { Creates a new `Instance` from an existing dom object ref. Panics if the instance does not exist in the internal dom, - or if the given dom object ref points to the dom root. + or if the given dom object ref points to the internal dom root. **WARNING:** Creating a new instance requires locking the internal dom, any existing lock must first be released to prevent any deadlocking. */ - pub(crate) fn new(dom_ref: DomRef) -> Self { - let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); - - let instance = dom - .get_by_ref(dom_ref) - .expect("Failed to find instance in document"); - - assert!( - !(instance.referent() == dom.root_ref()), - "Instances can not be created from dom roots" - ); - - Self { - dom_ref, - class_name: instance.class.clone(), - } + #[must_use] + pub fn new(dom_ref: DomRef) -> Self { + Self::new_opt(dom_ref).expect("Failed to find instance in document") } /** Creates a new `Instance` from a dom object ref, if the instance exists. - Panics if the given dom object ref points to the dom root. + Panics if the given dom object ref points to the internal dom root. **WARNING:** Creating a new instance requires locking the internal dom, any existing lock must first be released to prevent any deadlocking. */ - pub(crate) fn new_opt(dom_ref: DomRef) -> Option { + #[must_use] + pub fn new_opt(dom_ref: DomRef) -> Option { let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); if let Some(instance) = dom.get_by_ref(dom_ref) { @@ -97,12 +85,13 @@ impl Instance { /** Creates a new orphaned `Instance` with a given class name. - An orphaned instance is an instance at the root of a weak dom. + An orphaned instance is an instance at the root of Lune's internal weak dom. **WARNING:** Creating a new instance requires locking the internal dom, any existing lock must first be released to prevent any deadlocking. */ - pub(crate) fn new_orphaned(class_name: impl AsRef) -> Self { + #[must_use] + pub fn new_orphaned(class_name: impl AsRef) -> Self { let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let class_name = class_name.as_ref(); @@ -122,10 +111,11 @@ impl Instance { Creates a new orphaned `Instance` by transferring it from an external weak dom to the internal one. - An orphaned instance is an instance at the root of a weak dom. + An orphaned instance is an instance at the root of Lune's internal weak dom. Panics if the given dom ref is the root dom ref of the external weak dom. */ + #[must_use] pub fn from_external_dom(external_dom: &mut WeakDom, external_dom_ref: DomRef) -> Self { let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom_root = dom.root_ref(); @@ -151,6 +141,12 @@ impl Instance { cloned } + /** + Clones multiple instances to an external weak dom. + + This will place the instances as children of the + root of the weak dom, and return their referents. + */ pub fn clone_multiple_into_external_dom( referents: &[DomRef], external_dom: &mut WeakDom, @@ -324,7 +320,7 @@ impl Instance { If the provided parent is [`None`] the instance will become orphaned. - An orphaned instance is an instance at the root of a weak dom. + An orphaned instance is an instance at the root of Lune's internal weak dom. ### See Also * [`Parent`](https://create.roblox.com/docs/reference/engine/classes/Instance#Parent)