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

Add functionalities to Vector3 and Vector3int16 #46

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## Unreleased Changes

* Add Color3.fromRGB(red, blue, green) ([#44](https://github.com/rojo-rbx/remodel/issues/44))
* Added support for Vector3, and improved Vector3int16 ([#46](https://github.com/rojo-rbx/remodel/pull/46))
* Added Color3.fromRGB(red, blue, green) ([#44](https://github.com/rojo-rbx/remodel/pull/44))

## 0.8.1 (2021-04-09)
* Updated to latest rbx_xml, which should fix `OptionalCoordinateFrame`-related issues.
Expand Down
37 changes: 31 additions & 6 deletions src/roblox_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rlua::{Context, UserData, UserDataMethods};

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

pub use instance::LuaInstance;
Expand All @@ -17,6 +17,7 @@ pub struct RobloxApi;
impl RobloxApi {
pub fn inject(context: Context<'_>) -> rlua::Result<()> {
context.globals().set("Instance", Instance)?;
context.globals().set("Vector3", Vector3)?;
context.globals().set("Vector3int16", Vector3int16)?;
context.globals().set("Color3", Color3)?;

Expand Down Expand Up @@ -51,15 +52,39 @@ impl UserData for Instance {
}
}

struct Vector3;

impl UserData for Vector3 {
fn add_methods<'lua, T: UserDataMethods<'lua, Self>>(methods: &mut T) {
methods.add_function(
"new",
|_context, (x, y, z): (Option<f32>, Option<f32>, Option<f32>)| {
Ok(Vector3Value::new(rbx_dom_weak::types::Vector3::new(
x.unwrap_or(0.0),
y.unwrap_or(0.0),
z.unwrap_or(0.0),
)))
},
);
}
}

struct Vector3int16;

impl UserData for Vector3int16 {
fn add_methods<'lua, T: UserDataMethods<'lua, Self>>(methods: &mut T) {
methods.add_function("new", |_context, (x, y, z): (i16, i16, i16)| {
Ok(Vector3int16Value::new(
rbx_dom_weak::types::Vector3int16::new(x, y, z),
))
})
methods.add_function(
"new",
|_context, (x, y, z): (Option<i16>, Option<i16>, Option<i16>)| {
Ok(Vector3int16Value::new(
rbx_dom_weak::types::Vector3int16::new(
x.unwrap_or(0),
y.unwrap_or(0),
z.unwrap_or(0),
),
))
},
)
}
}

Expand Down
136 changes: 134 additions & 2 deletions src/value.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//! Defines how to turn Variant values into Lua values and back.

use rbx_dom_weak::types::{Color3, Color3uint8, Variant, VariantType, Vector3int16};
use rbx_dom_weak::types::{Color3, Color3uint8, Variant, VariantType, Vector3, Vector3int16};
use rlua::{
Context, MetaMethod, Result as LuaResult, ToLua, UserData, UserDataMethods, Value as LuaValue,
};
use std::fmt;
use std::ops;

pub fn rbxvalue_to_lua<'lua>(context: Context<'lua>, value: &Variant) -> LuaResult<LuaValue<'lua>> {
fn unimplemented_type(name: &str) -> LuaResult<LuaValue<'_>> {
Expand Down Expand Up @@ -84,6 +85,10 @@ pub fn lua_to_rbxvalue(ty: VariantType, value: LuaValue<'_>) -> LuaResult<Varian
Ok(color.into())
}

(VariantType::Vector3, LuaValue::UserData(ref user_data)) => {
let vector3 = &*user_data.borrow::<Vector3Value>()?;
Ok(vector3.into())
}
(VariantType::Vector3int16, LuaValue::UserData(ref user_data)) => {
let vector3int16 = &*user_data.borrow::<Vector3int16Value>()?;
Ok(vector3int16.into())
Expand Down Expand Up @@ -215,6 +220,86 @@ impl UserData for Color3uint8Value {
}
}

#[derive(Debug, Clone, Copy)]
pub struct Vector3Value(Vector3);

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

impl Vector3Value {
pub fn new(value: Vector3) -> Self {
Self(value)
}

fn meta_index<'lua>(
&self,
context: Context<'lua>,
key: &str,
) -> rlua::Result<rlua::Value<'lua>> {
match key {
"X" => self.0.x.to_lua(context),
"Y" => self.0.y.to_lua(context),
"Z" => self.0.z.to_lua(context),
_ => Err(rlua::Error::external(format!(
"'{}' is not a valid member of Vector3",
key
))),
}
}
}

impl ops::Add for Vector3Value {
type Output = Vector3Value;
fn add(self, other: Self) -> Self::Output {
Vector3Value::new(Vector3::new(
self.0.x + other.0.x,
self.0.y + other.0.y,
self.0.z + other.0.z,
))
}
}

impl ops::Sub for Vector3Value {
type Output = Vector3Value;
fn sub(self, other: Self) -> Self::Output {
Vector3Value::new(Vector3::new(
self.0.x - other.0.x,
self.0.y - other.0.y,
self.0.z - other.0.z,
))
}
}

impl From<&Vector3Value> for Variant {
fn from(vector: &Vector3Value) -> Variant {
Variant::Vector3(vector.0)
}
}

impl UserData for Vector3Value {
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::Add, |context, this, rhs: Self| {
(*this + rhs).to_lua(context)
});
methods.add_meta_method(MetaMethod::Sub, |context, this, rhs: Self| {
(*this - rhs).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 Vector3int16Value(Vector3int16);

Expand All @@ -228,6 +313,44 @@ impl Vector3int16Value {
pub fn new(value: Vector3int16) -> Self {
Self(value)
}

fn meta_index<'lua>(
&self,
context: Context<'lua>,
key: &str,
) -> rlua::Result<rlua::Value<'lua>> {
match key {
"X" => self.0.x.to_lua(context),
"Y" => self.0.y.to_lua(context),
"Z" => self.0.z.to_lua(context),
_ => Err(rlua::Error::external(format!(
"'{}' is not a valid member of Vector3",
key
))),
}
}
}

impl ops::Add for Vector3int16Value {
type Output = Vector3int16Value;
fn add(self, other: Self) -> Self::Output {
Vector3int16Value::new(Vector3int16::new(
self.0.x + other.0.x,
self.0.y + other.0.y,
self.0.z + other.0.z,
))
}
}

impl ops::Sub for Vector3int16Value {
type Output = Vector3int16Value;
fn sub(self, other: Self) -> Self::Output {
Vector3int16Value::new(Vector3int16::new(
self.0.x - other.0.x,
self.0.y - other.0.y,
self.0.z - other.0.z,
))
}
}

impl From<&Vector3int16Value> for Variant {
Expand All @@ -238,10 +361,19 @@ impl From<&Vector3int16Value> for Variant {

impl UserData for Vector3int16Value {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Eq, |context, this, rhs: Vector3int16Value| {
methods.add_meta_method(MetaMethod::Eq, |context, this, rhs: Self| {
(this.0 == rhs.0).to_lua(context)
});
methods.add_meta_method(MetaMethod::Add, |context, this, rhs: Self| {
(*this + rhs).to_lua(context)
});
methods.add_meta_method(MetaMethod::Sub, |context, this, rhs: Self| {
(*this - rhs).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)
});
Expand Down
18 changes: 18 additions & 0 deletions test-scripts/type-vector3.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local function assertVector(vec, x, y, z)
assert(vec.X == x, ("%f ~= %f"):format(vec.X, x))
assert(vec.Y == y, ("%f ~= %f"):format(vec.Y, y))
assert(vec.Z == z, ("%f ~= %f"):format(vec.Z, z))
end

assertVector(Vector3.new(), 0, 0, 0)
assertVector(Vector3.new(1), 1, 0, 0)
assertVector(Vector3.new(1, 2), 1, 2, 0)
assertVector(Vector3.new(1, 2, 3), 1, 2, 3)

assert(tostring(Vector3.new(1, 2, 3)) == "1, 2, 3")

assertVector(Vector3.new(1, 2, 3) + Vector3.new(1, 2, 3), 2, 4, 6)
assertVector(Vector3.new(1, 2, 3) - Vector3.new(1, 2, 3), 0, 0, 0)

assert(Vector3.new(1, 2, 3) == Vector3.new(1, 2, 3))
assert(Vector3.new() ~= Vector3.new(1, 2, 3))
19 changes: 19 additions & 0 deletions test-scripts/type-vector3int16.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
local function assertVector(vec, x, y, z)
assert(vec.X == x, ("%f ~= %f"):format(vec.X, x))
assert(vec.Y == y, ("%f ~= %f"):format(vec.Y, y))
assert(vec.Z == z, ("%f ~= %f"):format(vec.Z, z))
end

assertVector(Vector3int16.new(), 0, 0, 0)
assertVector(Vector3int16.new(1), 1, 0, 0)
assertVector(Vector3int16.new(1, 2), 1, 2, 0)
assertVector(Vector3int16.new(1, 2, 3), 1, 2, 3)

assertVector(Vector3int16.new(1, 2, 3) + Vector3int16.new(1, 2, 3), 2, 4, 6)
assertVector(Vector3int16.new(1, 2, 3) - Vector3int16.new(1, 2, 3), 0, 0, 0)

assert(Vector3int16.new(1, 2, 3) == Vector3int16.new(1, 2, 3))
assert(Vector3int16.new() ~= Vector3int16.new(1, 2, 3))

assert(tostring(Vector3int16.new(1, 2, 3)) == "1, 2, 3")

local terrainRegion = remodel.readModelFile("test-models/terrain-region.rbxmx")[1]

assert(remodel.getRawProperty(terrainRegion, "ExtentsMax") == Vector3int16.new(32000, 32000, 32000))
Expand Down