From 08b358c192dedbb15628ac687169aa362f4901c2 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Wed, 23 Apr 2025 14:14:34 -0700 Subject: [PATCH] roblox_emulator: Vector2 --- .../src/runner/instance/instance.rs | 15 ++- lib/roblox_emulator/src/runner/mod.rs | 1 + lib/roblox_emulator/src/runner/runner.rs | 1 + lib/roblox_emulator/src/runner/vector2.rs | 93 +++++++++++++++++++ 4 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 lib/roblox_emulator/src/runner/vector2.rs diff --git a/lib/roblox_emulator/src/runner/instance/instance.rs b/lib/roblox_emulator/src/runner/instance/instance.rs index 2427c4c..844882d 100644 --- a/lib/roblox_emulator/src/runner/instance/instance.rs +++ b/lib/roblox_emulator/src/runner/instance/instance.rs @@ -298,6 +298,7 @@ impl mlua::UserData for Instance{ Some(rbx_types::Variant::Enum(e))=>return crate::runner::r#enum::EnumItem::from(e).into_lua(lua), Some(rbx_types::Variant::Color3(c))=>return crate::runner::color3::Color3::from(c).into_lua(lua), Some(rbx_types::Variant::CFrame(cf))=>return crate::runner::cframe::CFrame::from(cf).into_lua(lua), + Some(rbx_types::Variant::Vector2(v))=>return crate::runner::vector2::Vector2::from(v).into_lua(lua), Some(rbx_types::Variant::Vector3(v))=>return crate::runner::vector3::Vector3::from(v).into_lua(lua), None=>(), other=>return Err(mlua::Error::runtime(format!("Instance.__index Unsupported property type instance={} index={index_str} value={other:?}",instance.name))), @@ -338,10 +339,6 @@ impl mlua::UserData for Instance{ mlua::Error::runtime(format!("Property '{index_str}' missing on class '{}'",class.name)) )?; let value=match &property.data_type{ - rbx_reflection::DataType::Value(rbx_types::VariantType::Vector3)=>{ - let typed_value:Vector3=*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected Userdata"))?.borrow()?; - rbx_types::Variant::Vector3(typed_value.into()) - }, rbx_reflection::DataType::Value(rbx_types::VariantType::Float32)=>{ let typed_value=Number::from_lua(value.clone(),lua)?.to_f32(); rbx_types::Variant::Float32(typed_value) @@ -394,8 +391,16 @@ impl mlua::UserData for Instance{ let typed_value:&crate::runner::color_sequence::ColorSequence=&*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected ColorSequence"))?.borrow()?; rbx_types::Variant::ColorSequence(typed_value.clone().into()) }, + rbx_reflection::DataType::Value(rbx_types::VariantType::Vector2)=>{ + let typed_value:crate::runner::vector2::Vector2=*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected Vector2"))?.borrow()?; + rbx_types::Variant::Vector2(typed_value.clone().into()) + }, + rbx_reflection::DataType::Value(rbx_types::VariantType::Vector3)=>{ + let typed_value:crate::runner::vector3::Vector3=*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected Vector3"))?.borrow()?; + rbx_types::Variant::Vector3(typed_value.clone().into()) + }, rbx_reflection::DataType::Value(rbx_types::VariantType::CFrame)=>{ - let typed_value:&crate::runner::cframe::CFrame=&*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected CFrame"))?.borrow()?; + let typed_value:crate::runner::cframe::CFrame=*value.as_userdata().ok_or_else(||mlua::Error::runtime("Expected CFrame"))?.borrow()?; rbx_types::Variant::CFrame(typed_value.clone().into()) }, rbx_reflection::DataType::Value(rbx_types::VariantType::ContentId)=>{ diff --git a/lib/roblox_emulator/src/runner/mod.rs b/lib/roblox_emulator/src/runner/mod.rs index 171f50c..d7ee1da 100644 --- a/lib/roblox_emulator/src/runner/mod.rs +++ b/lib/roblox_emulator/src/runner/mod.rs @@ -10,6 +10,7 @@ mod udim2; mod color3; mod cframe; mod number; +mod vector2; mod vector3; mod brickcolor; mod tween_info; diff --git a/lib/roblox_emulator/src/runner/runner.rs b/lib/roblox_emulator/src/runner/runner.rs index fff425d..5ce3551 100644 --- a/lib/roblox_emulator/src/runner/runner.rs +++ b/lib/roblox_emulator/src/runner/runner.rs @@ -39,6 +39,7 @@ fn init(lua:&mlua::Lua)->mlua::Result<()>{ super::udim2::set_globals(lua,&globals)?; super::color3::set_globals(lua,&globals)?; super::brickcolor::set_globals(lua,&globals)?; + super::vector2::set_globals(lua,&globals)?; super::vector3::set_globals(lua,&globals)?; super::cframe::set_globals(lua,&globals)?; super::instance::instance::set_globals(lua,&globals)?; diff --git a/lib/roblox_emulator/src/runner/vector2.rs b/lib/roblox_emulator/src/runner/vector2.rs new file mode 100644 index 0000000..e5ddcda --- /dev/null +++ b/lib/roblox_emulator/src/runner/vector2.rs @@ -0,0 +1,93 @@ +use mlua::FromLua; + +use super::number::Number; + +#[derive(Clone,Copy)] +pub struct Vector2(glam::Vec2); + +impl Vector2{ + pub const fn new(x:f32,y:f32)->Self{ + Self(glam::vec2(x,y)) + } +} + +pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ + let table=lua.create_table()?; + + //Vector2.new + table.raw_set("new", + lua.create_function(|_,(x,y):(Option<Number>,Option<Number>)| + match (x,y){ + (Some(x),Some(y))=>Ok(Vector2::new(x.into(),y.into())), + (None,None)=>Ok(Vector2(glam::Vec2::ZERO)), + _=>Err(mlua::Error::runtime("Unsupported arguments to Vector2.new")), + } + )? + )?; + + globals.set("Vector2",table)?; + + Ok(()) +} + +impl From<Vector2> for rbx_types::Vector2{ + fn from(Vector2(v):Vector2)->rbx_types::Vector2{ + rbx_types::Vector2::new(v.x,v.y) + } +} + +impl From<rbx_types::Vector2> for Vector2{ + fn from(value:rbx_types::Vector2)->Vector2{ + Vector2::new(value.x,value.y) + } +} + +impl mlua::UserData for Vector2{ + fn add_fields<F:mlua::UserDataFields<Self>>(fields:&mut F){ + fields.add_field_method_get("magnitude",|_,Vector2(this)|Ok(this.length())); + fields.add_field_method_get("Magnitude",|_,Vector2(this)|Ok(this.length())); + fields.add_field_method_get("unit",|_,Vector2(this)|Ok(Vector2(this.normalize()))); + fields.add_field_method_get("Unit",|_,Vector2(this)|Ok(Vector2(this.normalize()))); + fields.add_field_method_get("x",|_,Vector2(this)|Ok(this.x)); + fields.add_field_method_get("X",|_,Vector2(this)|Ok(this.x)); + fields.add_field_method_get("y",|_,Vector2(this)|Ok(this.y)); + fields.add_field_method_get("Y",|_,Vector2(this)|Ok(this.y)); + } + + fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){ + //methods.add_method("area",|_,this,()| Ok(this.length * this.width)); + + methods.add_meta_function(mlua::MetaMethod::Add,|_,(Vector2(this),Vector2(val)):(Self,Self)|Ok(Self(this+val))); + methods.add_meta_function(mlua::MetaMethod::Sub,|_,(Vector2(this),Vector2(val)):(Self,Self)|Ok(Self(this-val))); + methods.add_meta_function(mlua::MetaMethod::Mul,|lua,(lhs,rhs):(mlua::Value,mlua::Value)|{ + match (lhs,rhs){ + (mlua::Value::UserData(lhs),mlua::Value::UserData(rhs))=>lhs.borrow_scoped(|Vector2(lhs):&Vector2|rhs.borrow_scoped(|Vector2(rhs):&Vector2|Self(lhs*rhs)))?, + (lhs,mlua::Value::UserData(rhs))=>{ + let lhs=Number::from_lua(lhs,lua)?; + rhs.borrow_scoped(|Vector2(rhs):&Vector2|Self(lhs.to_f32()*rhs)) + }, + (mlua::Value::UserData(lhs),rhs)=>{ + let rhs=Number::from_lua(rhs,lua)?; + lhs.borrow_scoped(|Vector2(lhs):&Vector2|Self(lhs*rhs.to_f32())) + }, + _=>Err(mlua::Error::runtime(format!("Expected Vector2"))) + } + }); + methods.add_meta_function(mlua::MetaMethod::Div,|_,(Vector2(this),val):(Self,mlua::Value)|{ + match val{ + mlua::Value::Integer(n)=>Ok(Self(this/(n as f32))), + mlua::Value::Number(n)=>Ok(Self(this/(n as f32))), + mlua::Value::UserData(ud)=>ud.borrow_scoped(|Vector2(rhs):&Vector2|Self(this/rhs)), + other=>Err(mlua::Error::runtime(format!("Attempt to divide Vector2 by {other:?}"))), + } + }); + methods.add_meta_function(mlua::MetaMethod::ToString,|_,Vector2(this):Self| + Ok(format!("Vector2.new({},{})", + this.x, + this.y, + )) + ); + } +} + +type_from_lua_userdata!(Vector2);