mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 13:00:37 +00:00
Implement Ray roblox datatype
This commit is contained in:
parent
f0aadc6dfe
commit
6d76df7524
5 changed files with 150 additions and 1 deletions
|
@ -121,7 +121,6 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
// Not yet implemented datatypes
|
// Not yet implemented datatypes
|
||||||
// Rbx::Font(_) => todo!(),
|
// Rbx::Font(_) => todo!(),
|
||||||
// Rbx::PhysicalProperties(_) => todo!(),
|
// Rbx::PhysicalProperties(_) => todo!(),
|
||||||
// Rbx::Ray(_) => 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))?,
|
||||||
|
@ -140,6 +139,8 @@ impl<'lua> RbxVariantToLua<'lua> for LuaAnyUserData<'lua> {
|
||||||
Rbx::NumberRange(value) => lua.create_userdata(NumberRange::from(value))?,
|
Rbx::NumberRange(value) => lua.create_userdata(NumberRange::from(value))?,
|
||||||
Rbx::NumberSequence(value) => lua.create_userdata(NumberSequence::from(value))?,
|
Rbx::NumberSequence(value) => lua.create_userdata(NumberSequence::from(value))?,
|
||||||
|
|
||||||
|
Rbx::Ray(value) => lua.create_userdata(Ray::from(value))?,
|
||||||
|
|
||||||
Rbx::Rect(value) => lua.create_userdata(Rect::from(value))?,
|
Rbx::Rect(value) => lua.create_userdata(Rect::from(value))?,
|
||||||
Rbx::UDim(value) => lua.create_userdata(UDim::from(value))?,
|
Rbx::UDim(value) => lua.create_userdata(UDim::from(value))?,
|
||||||
Rbx::UDim2(value) => lua.create_userdata(UDim2::from(value))?,
|
Rbx::UDim2(value) => lua.create_userdata(UDim2::from(value))?,
|
||||||
|
@ -196,6 +197,8 @@ impl<'lua> LuaToRbxVariant<'lua> for LuaAnyUserData<'lua> {
|
||||||
RbxVariantType::UDim => convert::<UDim, rbx::UDim>,
|
RbxVariantType::UDim => convert::<UDim, rbx::UDim>,
|
||||||
RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>,
|
RbxVariantType::UDim2 => convert::<UDim2, rbx::UDim2>,
|
||||||
|
|
||||||
|
RbxVariantType::Ray => convert::<Ray, rbx::Ray>,
|
||||||
|
|
||||||
RbxVariantType::Region3 => convert::<Region3, rbx::Region3>,
|
RbxVariantType::Region3 => convert::<Region3, rbx::Region3>,
|
||||||
RbxVariantType::Region3int16 => convert::<Region3int16, rbx::Region3int16>,
|
RbxVariantType::Region3int16 => convert::<Region3int16, rbx::Region3int16>,
|
||||||
RbxVariantType::Vector2 => convert::<Vector2, rbx::Vector2>,
|
RbxVariantType::Vector2 => convert::<Vector2, rbx::Vector2>,
|
||||||
|
|
|
@ -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 ray;
|
||||||
mod rect;
|
mod rect;
|
||||||
mod region3;
|
mod region3;
|
||||||
mod region3int16;
|
mod region3int16;
|
||||||
|
@ -34,6 +35,7 @@ pub use number_sequence_keypoint::NumberSequenceKeypoint;
|
||||||
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;
|
||||||
|
pub use ray::Ray;
|
||||||
pub use rect::Rect;
|
pub use rect::Rect;
|
||||||
pub use region3::Region3;
|
pub use region3::Region3;
|
||||||
pub use region3int16::Region3int16;
|
pub use region3int16::Region3int16;
|
||||||
|
@ -97,6 +99,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",
|
||||||
|
ray: "datatypes/Ray",
|
||||||
rect: "datatypes/Rect",
|
rect: "datatypes/Rect",
|
||||||
udim: "datatypes/UDim",
|
udim: "datatypes/UDim",
|
||||||
udim2: "datatypes/UDim2",
|
udim2: "datatypes/UDim2",
|
||||||
|
|
92
packages/lib-roblox/src/datatypes/types/ray.rs
Normal file
92
packages/lib-roblox/src/datatypes/types/ray.rs
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use glam::Vec3;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use rbx_dom_weak::types::Ray as RbxRay;
|
||||||
|
|
||||||
|
use super::{super::*, Vector3};
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the [Ray](https://create.roblox.com/docs/reference/engine/datatypes/Ray)
|
||||||
|
Roblox datatype, backed by [`glam::Vec3`].
|
||||||
|
|
||||||
|
This implements all documented properties, methods & constructors of the Ray class as of March 2023.
|
||||||
|
*/
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
pub struct Ray {
|
||||||
|
pub(crate) origin: Vec3,
|
||||||
|
pub(crate) direction: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ray {
|
||||||
|
fn closest_point(&self, point: Vec3) -> Vec3 {
|
||||||
|
let norm = self.direction.normalize();
|
||||||
|
let lhs = point - self.origin;
|
||||||
|
|
||||||
|
let dot_product = lhs.dot(norm).max(0.0);
|
||||||
|
self.origin + norm * dot_product
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn make_table(lua: &Lua, datatype_table: &LuaTable) -> LuaResult<()> {
|
||||||
|
datatype_table.set(
|
||||||
|
"new",
|
||||||
|
lua.create_function(|_, (origin, direction): (Vector3, Vector3)| {
|
||||||
|
Ok(Ray {
|
||||||
|
origin: origin.0,
|
||||||
|
direction: direction.0,
|
||||||
|
})
|
||||||
|
})?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LuaUserData for Ray {
|
||||||
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("Origin", |_, this| Ok(Vector3(this.origin)));
|
||||||
|
fields.add_field_method_get("Direction", |_, this| Ok(Vector3(this.direction)));
|
||||||
|
fields.add_field_method_get("Unit", |_, this| {
|
||||||
|
Ok(Ray {
|
||||||
|
origin: this.origin,
|
||||||
|
direction: this.direction.normalize(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
// Methods
|
||||||
|
methods.add_method("ClosestPoint", |_, this, to: Vector3| {
|
||||||
|
Ok(Vector3(this.closest_point(to.0)))
|
||||||
|
});
|
||||||
|
methods.add_method("Distance", |_, this, to: Vector3| {
|
||||||
|
let closest = this.closest_point(to.0);
|
||||||
|
Ok((closest - to.0).length())
|
||||||
|
});
|
||||||
|
// Metamethods
|
||||||
|
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
|
||||||
|
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Ray {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}, {}", Vector3(self.origin), Vector3(self.direction))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RbxRay> for Ray {
|
||||||
|
fn from(v: RbxRay) -> Self {
|
||||||
|
Ray {
|
||||||
|
origin: Vector3::from(v.origin).0,
|
||||||
|
direction: Vector3::from(v.direction).0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Ray> for RbxRay {
|
||||||
|
fn from(v: Ray) -> Self {
|
||||||
|
RbxRay {
|
||||||
|
origin: Vector3(v.origin).into(),
|
||||||
|
direction: Vector3(v.direction).into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)?),
|
||||||
|
("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)?),
|
||||||
("UDim2", make_dt(lua, UDim2::make_table)?),
|
("UDim2", make_dt(lua, UDim2::make_table)?),
|
||||||
|
|
50
tests/roblox/datatypes/Ray.luau
Normal file
50
tests/roblox/datatypes/Ray.luau
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
-- HACK: Make luau happy, with the mlua rust
|
||||||
|
-- crate all globals are also present in _G
|
||||||
|
local Ray = _G.Ray
|
||||||
|
local Vector3 = _G.Vector3
|
||||||
|
|
||||||
|
local origin = Vector3.zero
|
||||||
|
local direction = Vector3.zAxis * 10
|
||||||
|
|
||||||
|
-- Constructors & properties
|
||||||
|
|
||||||
|
Ray.new(origin, direction)
|
||||||
|
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Ray.new(false)
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Ray.new("", "")
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Ray.new(newproxy(true))
|
||||||
|
end))
|
||||||
|
|
||||||
|
assert(Ray.new(origin, direction).Origin == origin)
|
||||||
|
assert(Ray.new(origin, direction).Direction == direction)
|
||||||
|
|
||||||
|
assert(Ray.new(origin, direction).Unit.Origin == origin)
|
||||||
|
assert(Ray.new(origin, direction).Unit.Direction == direction.Unit)
|
||||||
|
|
||||||
|
-- Ops
|
||||||
|
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Ray.new(origin, direction) + Ray.new(origin, direction)
|
||||||
|
end))
|
||||||
|
assert(not pcall(function()
|
||||||
|
return Ray.new(origin, direction) / Ray.new(origin, direction)
|
||||||
|
end))
|
||||||
|
|
||||||
|
-- Methods
|
||||||
|
|
||||||
|
assert(Ray.new(origin, direction):ClosestPoint(origin) == origin)
|
||||||
|
assert(Ray.new(origin, direction):Distance(origin) == 0)
|
||||||
|
|
||||||
|
for z = 0, 10, 1 do
|
||||||
|
local x = if z % 2 == 0 then 2.5 else 7.5
|
||||||
|
assert(
|
||||||
|
Ray.new(origin, direction):ClosestPoint(Vector3.new(x, 0, z))
|
||||||
|
== Vector3.zero + Vector3.zAxis * z
|
||||||
|
)
|
||||||
|
assert(Ray.new(origin, direction):Distance(Vector3.new(x, 0, z)) == x)
|
||||||
|
end
|
Loading…
Reference in a new issue