Skip to content
This repository has been archived by the owner on Jul 22, 2023. It is now read-only.

Add Region3 and Region3int16 #51

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased Changes

* Added Region3 and Region3int16 types ([#51](https://github.com/rojo-rbx/remodel/pull/51))
## 0.9.1 (2021-10-11)
* Updated to latest rbx-dom libraries.
* Increased Roblox API request timeout from 30 seconds to 3 minutes. ([#63])
Expand Down
35 changes: 34 additions & 1 deletion src/roblox_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rlua::{Context, UserData, UserDataMethods};

use crate::{
remodel_context::RemodelContext,
value::{Color3Value, Vector3Value, Vector3int16Value},
value::{Color3Value, Region3Value, Region3int16Value, Vector3Value, Vector3int16Value},
};

use cframe::CFrameUserData;
Expand All @@ -23,6 +23,8 @@ impl RobloxApi {
context.globals().set("Vector3int16", Vector3int16)?;
context.globals().set("Color3", Color3)?;
context.globals().set("CFrame", CFrameUserData)?;
context.globals().set("Region3", Region3)?;
context.globals().set("Region3int16", Region3int16)?;

Ok(())
}
Expand Down Expand Up @@ -107,3 +109,34 @@ impl UserData for Color3 {
});
}
}

struct Region3;

impl UserData for Region3 {
fn add_methods<'lua, T: UserDataMethods<'lua, Self>>(methods: &mut T) {
methods.add_function(
"new",
|_context, (min, max): (Vector3Value, Vector3Value)| {
Ok(Region3Value::new(rbx_dom_weak::types::Region3::new(
min.inner(),
max.inner(),
)))
},
);
}
}

struct Region3int16;

impl UserData for Region3int16 {
fn add_methods<'lua, T: UserDataMethods<'lua, Self>>(methods: &mut T) {
methods.add_function(
"new",
|_context, (min, max): (Vector3int16Value, Vector3int16Value)| {
Ok(Region3int16Value::new(
rbx_dom_weak::types::Region3int16::new(min.inner(), max.inner()),
))
},
);
}
}
154 changes: 153 additions & 1 deletion src/value.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Defines how to turn Variant values into Lua values and back.

use rbx_dom_weak::types::{
CFrame, Color3, Color3uint8, Variant, VariantType, Vector3, Vector3int16,
CFrame, Color3, Color3uint8, Matrix3, Region3, Region3int16, Variant, VariantType, Vector3,
Vector3int16,
};
use rlua::{
Context, MetaMethod, Result as LuaResult, ToLua, UserData, UserDataMethods, Value as LuaValue,
Expand Down Expand Up @@ -39,6 +40,8 @@ pub fn rbxvalue_to_lua<'lua>(context: Context<'lua>, value: &Variant) -> LuaResu
Variant::Ray(_) => unimplemented_type("Ray"),
Variant::Rect(_) => unimplemented_type("Rect"),
Variant::Ref(_) => unimplemented_type("Ref"),
Variant::Region3(value) => Region3Value::new(*value).to_lua(context),
Variant::Region3int16(value) => Region3int16Value::new(*value).to_lua(context),
Variant::SharedString(_) => unimplemented_type("SharedString"),
Variant::String(value) => value.as_str().to_lua(context),
Variant::UDim(_) => unimplemented_type("UDim"),
Expand Down Expand Up @@ -87,6 +90,15 @@ pub fn lua_to_rbxvalue(ty: VariantType, value: LuaValue<'_>) -> LuaResult<Varian
Ok(color.into())
}

(VariantType::Region3, LuaValue::UserData(ref user_data)) => {
let region3 = &*user_data.borrow::<Region3Value>()?;
Ok(region3.into())
}
(VariantType::Region3int16, LuaValue::UserData(ref user_data)) => {
let region3int16 = &*user_data.borrow::<Region3int16Value>()?;
Ok(region3int16.into())
}

(VariantType::Vector3, LuaValue::UserData(ref user_data)) => {
let vector3 = &*user_data.borrow::<Vector3Value>()?;
Ok(vector3.into())
Expand Down Expand Up @@ -132,6 +144,8 @@ pub fn type_from_str(name: &str) -> Option<VariantType> {
"Ray" => Some(Ray),
"Rect" => Some(Rect),
"Ref" => Some(Ref),
"Region3" => Some(Region3),
"Region3int16" => Some(Region3int16),
"SharedString" => Some(SharedString),
"String" => Some(String),
"UDim" => Some(UDim),
Expand Down Expand Up @@ -320,6 +334,10 @@ impl Vector3int16Value {
Self(value)
}

pub fn inner(&self) -> Vector3int16 {
self.0
}

fn meta_index<'lua>(
&self,
context: Context<'lua>,
Expand Down Expand Up @@ -460,6 +478,140 @@ impl fmt::Display for CFrameValue {
}

impl UserData for CFrameValue {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Eq, |context, this, rhs: Self| {
(this.0 == rhs.0).to_lua(context)
});

methods.add_meta_method(MetaMethod::Index, |context, this, key: String| {
this.meta_index(context, &key)
});
methods.add_meta_method(MetaMethod::ToString, |context, this, _arg: ()| {
this.to_string().to_lua(context)
});
}
}

#[derive(Debug, Clone, Copy)]
pub struct Region3Value(Region3);

impl Region3Value {
pub fn new(value: Region3) -> Self {
Self(value)
}

fn meta_index<'lua>(
&self,
context: Context<'lua>,
key: &str,
) -> rlua::Result<rlua::Value<'lua>> {
match key {
"CFrame" => self.get_cframe().to_lua(context),
"Size" => self.get_size().to_lua(context),
_ => Err(rlua::Error::external(format!(
"'{}' is not a valid member of Region3",
key
))),
}
}

fn get_size(&self) -> Vector3Value {
let max = Vector3Value::new(self.0.max);
let min = Vector3Value::new(self.0.min);
Vector3Value::new((max - min).0)
}

fn get_cframe(&self) -> CFrameValue {
let position = Vector3::new(
(self.0.max.x + self.0.min.x) / 2.0,
(self.0.max.y + self.0.min.y) / 2.0,
(self.0.max.z + self.0.min.z) / 2.0,
);

CFrameValue::new(CFrame::new(
position,
// TODO: replace with `rbx_dom_weak::types::Matrix3::identity()` once
// a version higher than 0.3.0 of rbx_types ships
Matrix3::new(
Vector3::new(1.0, 0.0, 0.0),
Vector3::new(0.0, 1.0, 0.0),
Vector3::new(0.0, 0.0, 1.0),
),
))
}
}

impl From<&Region3Value> for Variant {
fn from(region: &Region3Value) -> Variant {
Variant::Region3(region.0)
}
}

impl fmt::Display for Region3Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let cframe = self.get_cframe();
let size = self.get_size();
write!(f, "{}; {}", cframe.to_string(), size.to_string())
}
}

impl UserData for Region3Value {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Eq, |context, this, rhs: Self| {
(this.0 == rhs.0).to_lua(context)
});

methods.add_meta_method(MetaMethod::Index, |context, this, key: String| {
this.meta_index(context, &key)
});

methods.add_meta_method(MetaMethod::ToString, |context, this, _arg: ()| {
this.to_string().to_lua(context)
});
}
}

#[derive(Debug, Clone, Copy)]
pub struct Region3int16Value(Region3int16);

impl Region3int16Value {
pub fn new(value: Region3int16) -> Self {
Self(value)
}

fn meta_index<'lua>(
&self,
context: Context<'lua>,
key: &str,
) -> rlua::Result<rlua::Value<'lua>> {
match key {
"Min" => Vector3int16Value::new(self.0.min).to_lua(context),
"Max" => Vector3int16Value::new(self.0.max).to_lua(context),
_ => Err(rlua::Error::external(format!(
"'{}' is not a valid member of Region3int16",
key
))),
}
}
}

impl From<&Region3int16Value> for Variant {
fn from(region: &Region3int16Value) -> Variant {
Variant::Region3int16(region.0)
}
}

impl fmt::Display for Region3int16Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}, {}, {}; {}, {}, {}",
self.0.min.x, self.0.min.y, self.0.min.z, self.0.max.x, self.0.max.y, self.0.max.z
)
}
}

impl UserData for Region3int16Value {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Eq, |context, this, rhs: Self| {
(this.0 == rhs.0).to_lua(context)
Expand Down
4 changes: 4 additions & 0 deletions test-scripts/type-cframe.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ assertVector(CFrame.new().UpVector, 0, 1, 0)
assertVector(CFrame.new().LookVector, -0, -0, -1)

assert(tostring(CFrame.new(7, 8, 9)) == "7, 8, 9, 1, 0, 0, 0, 1, 0, 0, 0, 1", "got " .. tostring(CFrame.new()))

-- operators
assert(CFrame.new() == CFrame.new())
assert(CFrame.new(1, 1, 1) ~= CFrame.new(1, 2, 1))
26 changes: 26 additions & 0 deletions test-scripts/type-region3.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
local function assertRegion3(region, cframe, size)
assert(
region.CFrame == cframe,
("CFrame %s ~= %s"):format(region.CFrame, cframe)
)
assert(
region.Size == size,
("Size %s ~= %s"):format(region.Size, size)
)
end

assertRegion3(
Region3.new(Vector3.new(2, 3, 4), Vector3.new(8, 6, 5)),
CFrame.new(5, 4.5, 4.5),
Vector3.new(6, 3, 1)
)

do
local region = Region3.new(Vector3.new(1, 2, 3), Vector3.new(7, 8, 9))
local format = tostring(region)
assert(format == "4, 5, 6, 1, 0, 0, 0, 1, 0, 0, 0, 1; 6, 6, 6", "got " .. format)
end

local min = Vector3.new(2, 3, 4)
local max = Vector3.new(8, 6, 5)
assert(Region3.new(min, max) == Region3.new(min, max))
26 changes: 26 additions & 0 deletions test-scripts/type-region3int16.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
local function assertRegion3int16(region, min, max)
assert(
region.Min == min,
("Min %s ~= %s"):format(region.Min, min)
)
assert(
region.Max == max,
("Max %s ~= %s"):format(region.Max, max)
)
end

assertRegion3int16(
Region3int16.new(Vector3int16.new(2, 3, 4), Vector3int16.new(8, 6, 5)),
Vector3int16.new(2, 3, 4),
Vector3int16.new(8, 6, 5)
)

do
local region = Region3int16.new(Vector3int16.new(1, 2, 3), Vector3int16.new(7, 8, 9))
local format = tostring(region)
assert(format == "1, 2, 3; 7, 8, 9", "got " .. format)
end

local min = Vector3int16.new(2, 3, 4)
local max = Vector3int16.new(8, 6, 5)
assert(Region3int16.new(min, max) == Region3int16.new(min, max))