From 02bf210c51d2e203ed76a965be46c0ba2d2ab89e Mon Sep 17 00:00:00 2001 From: Nova Date: Fri, 21 Jun 2024 17:22:52 -0400 Subject: [PATCH] feat(fields): use new field ref and field types --- Cargo.lock | 4 +- codegen/src/lib.rs | 8 +- src/nodes/data.rs | 2 +- src/nodes/{fields/mod.rs => fields.rs} | 283 ++++++++++++------------- src/nodes/fields/box.rs | 60 ------ src/nodes/fields/cylinder.rs | 61 ------ src/nodes/fields/sphere.rs | 55 ----- src/nodes/fields/torus.rs | 60 ------ src/nodes/input/hand.rs | 2 +- src/nodes/input/method.rs | 2 +- src/nodes/input/pointer.rs | 2 +- src/nodes/input/tip.rs | 5 +- src/nodes/items/mod.rs | 2 +- src/nodes/spatial/mod.rs | 41 +++- src/nodes/spatial/zone.rs | 2 +- src/objects/input/eye_pointer.rs | 10 +- src/objects/input/mouse_pointer.rs | 2 +- src/objects/input/sk_controller.rs | 1 + src/objects/input/sk_hand.rs | 2 +- src/objects/play_space.rs | 18 +- 20 files changed, 214 insertions(+), 408 deletions(-) rename src/nodes/{fields/mod.rs => fields.rs} (63%) delete mode 100644 src/nodes/fields/box.rs delete mode 100644 src/nodes/fields/cylinder.rs delete mode 100644 src/nodes/fields/sphere.rs delete mode 100644 src/nodes/fields/torus.rs diff --git a/Cargo.lock b/Cargo.lock index a626d58..87a91f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2015,7 +2015,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d" [[package]] name = "stardust-xr" version = "0.45.0" -source = "git+https://github.com/StardustXR/core.git?branch=dev#a21dc0e610f6e7c905d42f80009700ff4474e583" +source = "git+https://github.com/StardustXR/core.git?branch=dev#4f2a7f87a864d07db4a2a783d52c30a4926e8925" dependencies = [ "cluFlock", "color-rs", @@ -2035,7 +2035,7 @@ dependencies = [ [[package]] name = "stardust-xr-schemas" version = "1.5.3" -source = "git+https://github.com/StardustXR/core.git?branch=dev#a21dc0e610f6e7c905d42f80009700ff4474e583" +source = "git+https://github.com/StardustXR/core.git?branch=dev#4f2a7f87a864d07db4a2a783d52c30a4926e8925" dependencies = [ "flatbuffers", "flexbuffers", diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 6794a82..1be760e 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -382,6 +382,11 @@ fn generate_handler(member: &Member) -> TokenStream { quote!(let (#argument_names): (#argument_types) = stardust_xr::schemas::flex::deserialize(_message.as_ref())?;) }) .unwrap_or_default(); + let serialize = generate_argument_serialize( + "result", + &member.return_type.clone().unwrap_or(ArgumentType::Empty), + false, + ); let argument_uses = member .arguments .iter() @@ -399,7 +404,8 @@ fn generate_handler(member: &Member) -> TokenStream { node.add_local_method(#opcode, |_node, _calling_client, _message, _method_response| { _method_response.wrap_async(async move { #deserialize - Ok((Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?, Vec::new())) + let result = Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?; + Ok((#serialize, Vec::new())) }); }); }, diff --git a/src/nodes/data.rs b/src/nodes/data.rs index 973f9ad..0fb2a6d 100644 --- a/src/nodes/data.rs +++ b/src/nodes/data.rs @@ -108,7 +108,7 @@ impl PulseSender { .get_aspect::() .unwrap() .field - .spatial_ref() + .spatial .node() .unwrap(), &tx_client, diff --git a/src/nodes/fields/mod.rs b/src/nodes/fields.rs similarity index 63% rename from src/nodes/fields/mod.rs rename to src/nodes/fields.rs index 524b595..4883d56 100644 --- a/src/nodes/fields/mod.rs +++ b/src/nodes/fields.rs @@ -1,14 +1,4 @@ -pub mod r#box; -mod cylinder; -mod sphere; -mod torus; - -use self::cylinder::CylinderField; -use self::r#box::BoxField; -use self::sphere::SphereField; -use self::torus::TorusField; - -use super::alias::AliasInfo; +use super::alias::{Alias, AliasInfo}; use super::spatial::{ Spatial, SPATIAL_REF_GET_LOCAL_BOUNDING_BOX_SERVER_OPCODE, SPATIAL_REF_GET_RELATIVE_BOUNDING_BOX_SERVER_OPCODE, SPATIAL_REF_GET_TRANSFORM_SERVER_OPCODE, @@ -19,11 +9,12 @@ use crate::create_interface; use crate::nodes::spatial::Transform; use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO; use crate::nodes::spatial::SPATIAL_REF_ASPECT_ALIAS_INFO; -use color_eyre::eyre::Result; -use glam::{vec2, vec3a, Mat4, Vec3, Vec3A}; -use mint::Vector3; +use color_eyre::eyre::{OptionExt, Result}; +use glam::{vec2, vec3, vec3a, Vec3, Vec3A, Vec3Swizzles}; use once_cell::sync::Lazy; -use std::ops::Deref; +use parking_lot::Mutex; +use rustc_hash::FxHashMap; +use stardust_xr::values::Vector3; use std::sync::Arc; // TODO: get SDFs working properly with non-uniform scale and so on, output distance relative to the spatial it's compared against @@ -33,16 +24,20 @@ pub static FIELD_ALIAS_INFO: Lazy = Lazy::new(|| AliasInfo { SPATIAL_REF_GET_TRANSFORM_SERVER_OPCODE, SPATIAL_REF_GET_LOCAL_BOUNDING_BOX_SERVER_OPCODE, SPATIAL_REF_GET_RELATIVE_BOUNDING_BOX_SERVER_OPCODE, - FIELD_DISTANCE_SERVER_OPCODE, - FIELD_NORMAL_SERVER_OPCODE, - FIELD_CLOSEST_POINT_SERVER_OPCODE, - FIELD_RAY_MARCH_SERVER_OPCODE, + FIELD_REF_DISTANCE_SERVER_OPCODE, + FIELD_REF_NORMAL_SERVER_OPCODE, + FIELD_REF_CLOSEST_POINT_SERVER_OPCODE, + FIELD_REF_RAY_MARCH_SERVER_OPCODE, ], ..Default::default() }); stardust_xr_server_codegen::codegen_field_protocol!(); +lazy_static::lazy_static! { + pub static ref EXPORTED_FIELDS: Mutex>> = Mutex::new(FxHashMap::default()); +} + pub trait FieldTrait: Send + Sync + 'static { fn spatial_ref(&self) -> &Spatial; @@ -122,60 +117,6 @@ pub trait FieldTrait: Send + Sync + 'static { result } } -impl FieldAspect for Fi { - async fn distance( - node: Arc, - _calling_client: Arc, - space: Arc, - point: mint::Vector3, - ) -> Result { - let reference_space = space.get_aspect::()?; - let this_field = node.get_aspect::()?; - Ok((*this_field).distance(reference_space.as_ref(), point.into())) - } - - async fn normal( - node: Arc, - _calling_client: Arc, - space: Arc, - point: mint::Vector3, - ) -> Result> { - let reference_space = space.get_aspect::()?; - let this_field = node.get_aspect::()?; - Ok(this_field - .normal(reference_space.as_ref(), point.into(), 0.001) - .into()) - } - - async fn closest_point( - node: Arc, - _calling_client: Arc, - space: Arc, - point: mint::Vector3, - ) -> Result> { - let reference_space = space.get_aspect::()?; - let this_field = node.get_aspect::()?; - Ok(this_field - .closest_point(reference_space.as_ref(), point.into(), 0.001) - .into()) - } - - async fn ray_march( - node: Arc, - _calling_client: Arc, - space: Arc, - ray_origin: mint::Vector3, - ray_direction: mint::Vector3, - ) -> Result { - let reference_space = space.get_aspect::()?; - let this_field = node.get_aspect::()?; - Ok(this_field.ray_march(Ray { - origin: ray_origin.into(), - direction: ray_direction.into(), - space: reference_space.clone(), - })) - } -} pub struct Ray { pub origin: Vec3, @@ -192,23 +133,113 @@ const MAX_RAY_MARCH: f32 = f32::MAX; // const MIN_RAY_LENGTH: f32 = 0_f32; const MAX_RAY_LENGTH: f32 = 1000_f32; -pub enum Field { - Box(BoxField), - Cylinder(CylinderField), - Sphere(SphereField), - Torus(TorusField), +pub struct Field { + pub spatial: Arc, + pub shape: Mutex, +} +impl Field { + pub fn add_to(node: &Arc, shape: Shape) -> Result<()> { + let spatial = node.get_aspect::()?; + let field = Field { + spatial, + shape: Mutex::new(shape), + }; + node.add_aspect(field); + Ok(()) + } } impl Aspect for Field { const NAME: &'static str = "Field"; } -impl Deref for Field { - type Target = dyn FieldTrait; - fn deref(&self) -> &Self::Target { - match self { - Field::Box(field) => field, - Field::Cylinder(field) => field, - Field::Sphere(field) => field, - Field::Torus(field) => field, +impl FieldRefAspect for Field { + async fn distance( + node: Arc, + _calling_client: Arc, + space: Arc, + point: Vector3, + ) -> Result { + let reference_space = space.get_aspect::()?; + let field = node.get_aspect::()?; + Ok(field.distance(&reference_space, point.into()).into()) + } + + async fn normal( + node: Arc, + _calling_client: Arc, + space: Arc, + point: Vector3, + ) -> Result> { + let reference_space = space.get_aspect::()?; + let field = node.get_aspect::()?; + Ok(field.normal(&reference_space, point.into(), 0.0001).into()) + } + + async fn closest_point( + node: Arc, + _calling_client: Arc, + space: Arc, + point: Vector3, + ) -> Result> { + let reference_space = space.get_aspect::()?; + let field = node.get_aspect::()?; + Ok(field + .closest_point(&reference_space, point.into(), 0.0001) + .into()) + } + + async fn ray_march( + node: Arc, + _calling_client: Arc, + space: Arc, + ray_origin: Vector3, + ray_direction: Vector3, + ) -> Result { + let space = space.get_aspect::()?; + let field = node.get_aspect::()?; + Ok(field.ray_march(Ray { + origin: ray_origin.into(), + direction: ray_direction.into(), + space, + })) + } +} +impl FieldAspect for Field { + fn set_shape(node: Arc, _calling_client: Arc, shape: Shape) -> Result<()> { + let field = node.get_aspect::()?; + *field.shape.lock() = shape; + Ok(()) + } + + async fn export_field(node: Arc, _calling_client: Arc) -> Result { + let id = rand::random(); + EXPORTED_FIELDS.lock().insert(id, node); + Ok(id) + } +} +impl FieldTrait for Field { + fn spatial_ref(&self) -> &Spatial { + &self.spatial + } + fn local_distance(&self, p: Vec3A) -> f32 { + match self.shape.lock().clone() { + Shape::Box(size) => { + let q = vec3( + p.x.abs() - (size.x * 0.5_f32), + p.y.abs() - (size.y * 0.5_f32), + p.z.abs() - (size.z * 0.5_f32), + ); + let v = vec3a(q.x.max(0_f32), q.y.max(0_f32), q.z.max(0_f32)); + v.length() + q.x.max(q.y.max(q.z)).min(0_f32) + } + Shape::Cylinder(CylinderShape { length, radius }) => { + let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (length * 0.5)); + d.x.max(d.y).min(0.0) + d.max(vec2(0.0, 0.0)).length() + } + Shape::Sphere(radius) => p.length() - radius, + Shape::Torus(TorusShape { radius_a, radius_b }) => { + let q = vec2(p.xz().length() - radius_a, p.y); + q.length() - radius_b + } } } } @@ -216,73 +247,39 @@ impl Deref for Field { create_interface!(FieldInterface); pub struct FieldInterface; impl InterfaceAspect for FieldInterface { - fn create_box_field( + async fn import_field_ref( + _node: Arc, + calling_client: Arc, + uid: u64, + ) -> Result> { + EXPORTED_FIELDS + .lock() + .get(&uid) + .map(|s| { + Alias::create( + s, + &calling_client, + FIELD_REF_ASPECT_ALIAS_INFO.clone(), + None, + ) + .unwrap() + }) + .ok_or_eyre("Couldn't find spatial with that ID") + } + + fn create_field( _node: Arc, calling_client: Arc, id: u64, parent: Arc, transform: Transform, - size: mint::Vector3, + shape: Shape, ) -> Result<()> { let transform = transform.to_mat4(true, true, false); let parent = parent.get_aspect::()?; let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?; Spatial::add_to(&node, Some(parent.clone()), transform, false); - BoxField::add_to(&node, size); - Ok(()) - } - - fn create_cylinder_field( - _node: Arc, - calling_client: Arc, - id: u64, - parent: Arc, - transform: Transform, - length: f32, - radius: f32, - ) -> Result<()> { - let transform = transform.to_mat4(true, true, false); - let parent = parent.get_aspect::()?; - let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?; - Spatial::add_to(&node, Some(parent.clone()), transform, false); - CylinderField::add_to(&node, length, radius); - Ok(()) - } - - fn create_sphere_field( - _node: Arc, - calling_client: Arc, - id: u64, - parent: Arc, - position: mint::Vector3, - radius: f32, - ) -> Result<()> { - let parent = parent.get_aspect::()?; - let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?; - Spatial::add_to( - &node, - Some(parent.clone()), - Mat4::from_translation(position.into()), - false, - ); - SphereField::add_to(&node, radius); - Ok(()) - } - - fn create_torus_field( - _node: Arc, - calling_client: Arc, - id: u64, - parent: Arc, - transform: Transform, - radius_a: f32, - radius_b: f32, - ) -> Result<()> { - let transform = transform.to_mat4(true, true, false); - let parent = parent.get_aspect::()?; - let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?; - Spatial::add_to(&node, Some(parent.clone()), transform, false); - TorusField::add_to(&node, radius_a, radius_b); + Field::add_to(&node, shape)?; Ok(()) } } diff --git a/src/nodes/fields/box.rs b/src/nodes/fields/box.rs deleted file mode 100644 index 41f7fa2..0000000 --- a/src/nodes/fields/box.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::{BoxFieldAspect, FieldTrait, Node}; -use crate::nodes::fields::FieldAspect; -use crate::nodes::spatial::Spatial; -use crate::{core::client::Client, nodes::fields::Field}; -use color_eyre::eyre::Result; -use glam::{vec3, vec3a, Vec3, Vec3A}; -use mint::Vector3; -use parking_lot::Mutex; -use std::sync::Arc; - -pub struct BoxField { - space: Arc, - size: Mutex, -} - -impl BoxField { - pub fn add_to(node: &Arc, size: Vector3) { - let box_field = BoxField { - space: node.get_aspect::().unwrap().clone(), - size: Mutex::new(size.into()), - }; - ::add_node_members(node); - ::add_node_members(node); - node.add_aspect(Field::Box(box_field)); - } - - pub fn set_size(&self, size: Vector3) { - *self.size.lock() = size.into(); - } -} - -impl FieldTrait for BoxField { - fn local_distance(&self, p: Vec3A) -> f32 { - let size = self.size.lock(); - let q = vec3( - p.x.abs() - (size.x * 0.5_f32), - p.y.abs() - (size.y * 0.5_f32), - p.z.abs() - (size.z * 0.5_f32), - ); - let v = vec3a(q.x.max(0_f32), q.y.max(0_f32), q.z.max(0_f32)); - v.length() + q.x.max(q.y.max(q.z)).min(0_f32) - } - fn spatial_ref(&self) -> &Spatial { - self.space.as_ref() - } -} -impl BoxFieldAspect for BoxField { - fn set_size( - node: Arc, - _calling_client: Arc, - size: mint::Vector3, - ) -> Result<()> { - let this_field = node.get_aspect::()?; - let Field::Box(this_field) = &*this_field else { - return Ok(()); - }; - this_field.set_size(size); - Ok(()) - } -} diff --git a/src/nodes/fields/cylinder.rs b/src/nodes/fields/cylinder.rs deleted file mode 100644 index de44fc5..0000000 --- a/src/nodes/fields/cylinder.rs +++ /dev/null @@ -1,61 +0,0 @@ -use super::{CylinderFieldAspect, Field, FieldTrait, Node}; -use crate::core::client::Client; -use crate::nodes::fields::FieldAspect; -use crate::nodes::spatial::Spatial; -use color_eyre::eyre::Result; -use glam::{swizzles::*, vec2, Vec3A}; -use portable_atomic::AtomicF32; - -use std::sync::atomic::Ordering; -use std::sync::Arc; - -pub struct CylinderField { - space: Arc, - length: AtomicF32, - radius: AtomicF32, -} - -impl CylinderField { - pub fn add_to(node: &Arc, length: f32, radius: f32) { - let cylinder_field = CylinderField { - space: node.get_aspect::().unwrap().clone(), - length: AtomicF32::new(length.abs()), - radius: AtomicF32::new(radius.abs()), - }; - ::add_node_members(node); - ::add_node_members(node); - node.add_aspect(Field::Cylinder(cylinder_field)); - } - - pub fn set_size(&self, length: f32, radius: f32) { - self.length.store(length.abs(), Ordering::Relaxed); - self.radius.store(radius.abs(), Ordering::Relaxed); - } -} -impl FieldTrait for CylinderField { - fn local_distance(&self, p: Vec3A) -> f32 { - let radius = self.radius.load(Ordering::Relaxed); - let length = self.length.load(Ordering::Relaxed); - let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (length * 0.5)); - - d.x.max(d.y).min(0.0) + d.max(vec2(0.0, 0.0)).length() - } - fn spatial_ref(&self) -> &Spatial { - self.space.as_ref() - } -} -impl CylinderFieldAspect for CylinderField { - fn set_size( - node: Arc, - _calling_client: Arc, - length: f32, - radius: f32, - ) -> Result<()> { - let this_field = node.get_aspect::()?; - let Field::Cylinder(this_field) = &*this_field else { - return Ok(()); - }; - this_field.set_size(length, radius); - Ok(()) - } -} diff --git a/src/nodes/fields/sphere.rs b/src/nodes/fields/sphere.rs deleted file mode 100644 index c198489..0000000 --- a/src/nodes/fields/sphere.rs +++ /dev/null @@ -1,55 +0,0 @@ -use super::{Field, FieldTrait, Node, SphereFieldAspect}; -use crate::core::client::Client; -use crate::nodes::fields::FieldAspect; -use crate::nodes::spatial::Spatial; -use color_eyre::eyre::Result; -use glam::Vec3A; -use portable_atomic::AtomicF32; -use std::sync::atomic::Ordering; -use std::sync::Arc; - -pub struct SphereField { - space: Arc, - radius: AtomicF32, -} - -impl SphereField { - pub fn add_to(node: &Arc, radius: f32) { - let sphere_field = SphereField { - space: node.get_aspect::().unwrap().clone(), - radius: AtomicF32::new(radius), - }; - ::add_node_members(node); - ::add_node_members(node); - node.add_aspect(Field::Sphere(sphere_field)); - } - - pub fn set_radius(&self, radius: f32) { - self.radius.store(radius, Ordering::Relaxed); - } -} - -impl FieldTrait for SphereField { - fn local_distance(&self, p: Vec3A) -> f32 { - p.length() - self.radius.load(Ordering::Relaxed) - } - fn local_normal(&self, p: Vec3A, _r: f32) -> Vec3A { - -p.normalize() - } - fn local_closest_point(&self, p: Vec3A, _r: f32) -> Vec3A { - p.normalize() * self.radius.load(Ordering::Relaxed) - } - fn spatial_ref(&self) -> &Spatial { - self.space.as_ref() - } -} -impl SphereFieldAspect for SphereField { - fn set_radius(node: Arc, _calling_client: Arc, radius: f32) -> Result<()> { - let this_field = node.get_aspect::()?; - let Field::Sphere(this_field) = &*this_field else { - return Ok(()); - }; - this_field.set_radius(radius); - Ok(()) - } -} diff --git a/src/nodes/fields/torus.rs b/src/nodes/fields/torus.rs deleted file mode 100644 index 902c764..0000000 --- a/src/nodes/fields/torus.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::{Field, FieldTrait, Node, TorusFieldAspect}; -use crate::core::client::Client; -use crate::nodes::fields::FieldAspect; -use crate::nodes::spatial::Spatial; -use color_eyre::eyre::Result; -use glam::{swizzles::*, vec2, Vec3A}; -use portable_atomic::AtomicF32; - -use std::sync::atomic::Ordering; -use std::sync::Arc; - -pub struct TorusField { - space: Arc, - radius_a: AtomicF32, - radius_b: AtomicF32, -} - -impl TorusField { - pub fn add_to(node: &Arc, radius_a: f32, radius_b: f32) { - let torus_field = TorusField { - space: node.get_aspect::().unwrap().clone(), - radius_a: AtomicF32::new(radius_a.abs()), - radius_b: AtomicF32::new(radius_b.abs()), - }; - ::add_node_members(node); - ::add_node_members(node); - node.add_aspect(Field::Torus(torus_field)); - } - - pub fn set_size(&self, radius_a: f32, radius_b: f32) { - self.radius_a.store(radius_a.abs(), Ordering::Relaxed); - self.radius_b.store(radius_b.abs(), Ordering::Relaxed); - } -} -impl FieldTrait for TorusField { - fn local_distance(&self, p: Vec3A) -> f32 { - let radius_a = self.radius_a.load(Ordering::Relaxed); - let radius_b = self.radius_b.load(Ordering::Relaxed); - let q = vec2(p.xz().length() - radius_a, p.y); - q.length() - radius_b - } - fn spatial_ref(&self) -> &Spatial { - self.space.as_ref() - } -} -impl TorusFieldAspect for TorusField { - fn set_size( - node: Arc, - _calling_client: Arc, - radius_a: f32, - radius_b: f32, - ) -> Result<()> { - let this_field = node.get_aspect::()?; - let Field::Torus(this_field) = &*this_field else { - return Ok(()); - }; - this_field.set_size(radius_a, radius_b); - Ok(()) - } -} diff --git a/src/nodes/input/hand.rs b/src/nodes/input/hand.rs index db7875e..391edf1 100644 --- a/src/nodes/input/hand.rs +++ b/src/nodes/input/hand.rs @@ -1,5 +1,5 @@ use super::{Finger, Hand, InputDataTrait, InputLink, Joint, Thumb}; -use crate::nodes::fields::Field; +use crate::nodes::fields::{Field, FieldTrait}; use crate::nodes::spatial::Spatial; use glam::{vec3a, Mat4, Quat}; use std::sync::Arc; diff --git a/src/nodes/input/method.rs b/src/nodes/input/method.rs index 36a33b6..7df106b 100644 --- a/src/nodes/input/method.rs +++ b/src/nodes/input/method.rs @@ -105,7 +105,7 @@ impl InputMethod { return; }; - let Some(handler_field_node) = handler.field.spatial_ref().node() else { + let Some(handler_field_node) = handler.field.spatial.node() else { return; }; // Handler's field diff --git a/src/nodes/input/pointer.rs b/src/nodes/input/pointer.rs index c0fdc13..e970eab 100644 --- a/src/nodes/input/pointer.rs +++ b/src/nodes/input/pointer.rs @@ -1,6 +1,6 @@ use super::{InputDataTrait, InputLink, Pointer}; use crate::nodes::{ - fields::{Field, Ray, RayMarchResult}, + fields::{Field, FieldTrait, Ray, RayMarchResult}, spatial::Spatial, }; use glam::{vec3, Mat4, Quat}; diff --git a/src/nodes/input/tip.rs b/src/nodes/input/tip.rs index ce48fc0..5282ce2 100644 --- a/src/nodes/input/tip.rs +++ b/src/nodes/input/tip.rs @@ -1,5 +1,8 @@ use super::{InputDataTrait, InputLink, Tip}; -use crate::nodes::{fields::Field, spatial::Spatial}; +use crate::nodes::{ + fields::{Field, FieldTrait}, + spatial::Spatial, +}; use glam::{Mat4, Quat}; use std::sync::Arc; diff --git a/src/nodes/items/mod.rs b/src/nodes/items/mod.rs index bc0f250..e32fda8 100644 --- a/src/nodes/items/mod.rs +++ b/src/nodes/items/mod.rs @@ -260,7 +260,7 @@ impl ItemUI { return; }; - let Some(acceptor_field_node) = acceptor.field.spatial_ref().node() else { + let Some(acceptor_field_node) = acceptor.field.spatial.node() else { return; }; let Ok(acceptor_field_alias) = Alias::create( diff --git a/src/nodes/spatial/mod.rs b/src/nodes/spatial/mod.rs index 726c2f3..b7069b8 100644 --- a/src/nodes/spatial/mod.rs +++ b/src/nodes/spatial/mod.rs @@ -1,17 +1,19 @@ pub mod zone; use self::zone::Zone; -use super::fields::Field; -use super::{Aspect, Node}; +use super::alias::Alias; +use super::fields::{Field, FieldTrait}; +use super::Aspect; use crate::core::client::Client; use crate::core::registry::Registry; use crate::create_interface; -use crate::nodes::OWNED_ASPECT_ALIAS_INFO; -use color_eyre::eyre::{eyre, Result}; +use crate::nodes::{Node, OWNED_ASPECT_ALIAS_INFO}; +use color_eyre::eyre::{eyre, OptionExt, Result}; use glam::{vec3a, Mat4, Quat, Vec3}; use mint::Vector3; use once_cell::sync::OnceCell; use parking_lot::Mutex; +use rustc_hash::FxHashMap; use std::fmt::Debug; use std::ptr; use std::sync::{Arc, Weak}; @@ -37,6 +39,10 @@ impl Transform { } } +lazy_static::lazy_static! { + pub static ref EXPORTED_SPATIALS: Mutex>> = Mutex::new(FxHashMap::default()); +} + static ZONEABLE_REGISTRY: Registry = Registry::new(); pub struct Spatial { @@ -354,6 +360,13 @@ impl SpatialAspect for Spatial { } Ok(()) } + + // legit gotta find a way to remove old ones, this just keeps the node alive + async fn export_spatial(node: Arc, _calling_client: Arc) -> Result { + let id = rand::random(); + EXPORTED_SPATIALS.lock().insert(id, node); + Ok(id) + } } impl PartialEq for Spatial { fn eq(&self, other: &Self) -> bool { @@ -426,6 +439,26 @@ impl InterfaceAspect for SpatialInterface { Zone::add_to(&node, space, field); Ok(()) } + + async fn import_spatial_ref( + _node: Arc, + calling_client: Arc, + uid: u64, + ) -> Result> { + EXPORTED_SPATIALS + .lock() + .get(&uid) + .map(|s| { + Alias::create( + s, + &calling_client, + SPATIAL_REF_ASPECT_ALIAS_INFO.clone(), + None, + ) + .unwrap() + }) + .ok_or_eyre("Couldn't find spatial with that ID") + } } create_interface!(SpatialInterface); diff --git a/src/nodes/spatial/zone.rs b/src/nodes/spatial/zone.rs index 140392d..b4703f4 100644 --- a/src/nodes/spatial/zone.rs +++ b/src/nodes/spatial/zone.rs @@ -6,7 +6,7 @@ use crate::{ core::{client::Client, registry::Registry}, nodes::{ alias::{get_original, Alias, AliasList}, - fields::Field, + fields::{Field, FieldTrait}, Aspect, Node, }, }; diff --git a/src/objects/input/eye_pointer.rs b/src/objects/input/eye_pointer.rs index 7145153..ce49151 100644 --- a/src/objects/input/eye_pointer.rs +++ b/src/objects/input/eye_pointer.rs @@ -1,7 +1,7 @@ use crate::{ core::client::INTERNAL_CLIENT, nodes::{ - fields::Ray, + fields::{FieldTrait, Ray}, input::{InputDataType, InputMethod, Pointer, INPUT_HANDLER_REGISTRY}, spatial::Spatial, Node, @@ -46,9 +46,11 @@ impl EyePointer { } pub fn update(&self) { let ray = Input::get_eyes(); - self.spatial.set_local_transform( - Mat4::from_rotation_translation(ray.orientation.into(), ray.position.into()), - ); + self.spatial + .set_local_transform(Mat4::from_rotation_translation( + ray.orientation.into(), + ray.position.into(), + )); { // Set pointer input datamap *self.pointer.datamap.lock() = Datamap::from_typed(EyeDatamap { eye: 2 }).unwrap(); diff --git a/src/objects/input/mouse_pointer.rs b/src/objects/input/mouse_pointer.rs index e4288f8..12941ca 100644 --- a/src/objects/input/mouse_pointer.rs +++ b/src/objects/input/mouse_pointer.rs @@ -4,7 +4,7 @@ use crate::{ data::{ mask_matches, pulse_receiver_client, PulseSender, KEYMAPS, PULSE_RECEIVER_REGISTRY, }, - fields::Ray, + fields::{FieldTrait, Ray}, input::{InputDataType, InputHandler, InputMethod, Pointer, INPUT_HANDLER_REGISTRY}, spatial::Spatial, Node, diff --git a/src/objects/input/sk_controller.rs b/src/objects/input/sk_controller.rs index d9b9c8d..1a84fac 100644 --- a/src/objects/input/sk_controller.rs +++ b/src/objects/input/sk_controller.rs @@ -1,6 +1,7 @@ use crate::{ core::client::INTERNAL_CLIENT, nodes::{ + fields::FieldTrait, input::{InputDataType, InputHandler, InputMethod, Tip, INPUT_HANDLER_REGISTRY}, spatial::Spatial, Node, diff --git a/src/objects/input/sk_hand.rs b/src/objects/input/sk_hand.rs index 209cad9..b54dbfe 100644 --- a/src/objects/input/sk_hand.rs +++ b/src/objects/input/sk_hand.rs @@ -1,5 +1,5 @@ use crate::core::client::INTERNAL_CLIENT; -use crate::nodes::fields::Field; +use crate::nodes::fields::{Field, FieldTrait}; use crate::nodes::input::{InputDataType, InputHandler, INPUT_HANDLER_REGISTRY}; use crate::nodes::{ input::{Hand, InputMethod, Joint}, diff --git a/src/objects/play_space.rs b/src/objects/play_space.rs index d5f6510..def6180 100644 --- a/src/objects/play_space.rs +++ b/src/objects/play_space.rs @@ -11,7 +11,7 @@ use crate::{ core::client::INTERNAL_CLIENT, nodes::{ data::PulseReceiver, - fields::{r#box::BoxField, Field}, + fields::{Field, Shape}, spatial::Spatial, Node, }, @@ -41,7 +41,7 @@ impl PlaySpace { pub fn new() -> Result { let node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph()?; let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false); - BoxField::add_to(&node, [0.0; 3].into()); + Field::add_to(&node, Shape::Box([0.0; 3].into()))?; let field = node.get_aspect::()?.clone(); let pulse_rx = PulseReceiver::add_to( @@ -59,12 +59,12 @@ impl PlaySpace { } pub fn update(&self) { let pose = World::get_bounds_pose(); - self.spatial.set_local_transform( - Mat4::from_rotation_translation(pose.orientation.into(), pose.position.into()), - ); - let Field::Box(box_field) = self.field.as_ref() else { - return; - }; - box_field.set_size([World::get_bounds_size().x, 0.0, World::get_bounds_size().y].into()); + self.spatial + .set_local_transform(Mat4::from_rotation_translation( + pose.orientation.into(), + pose.position.into(), + )); + *self.field.shape.lock() = + Shape::Box([World::get_bounds_size().x, 0.0, World::get_bounds_size().y].into()); } }