diff --git a/src/core/client.rs b/src/core/client.rs index 1246f29..32a88ee 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -6,8 +6,8 @@ use mio::net::UnixStream; use std::rc::Rc; pub struct Client { - messenger: Messenger, - scenegraph: Scenegraph, + pub messenger: Messenger, + pub scenegraph: Scenegraph, } impl Client { @@ -24,11 +24,4 @@ impl Client { pub fn dispatch(&self) -> Result<(), std::io::Error> { self.messenger.dispatch(&self.scenegraph) } - - pub fn get_messenger(&self) -> &Messenger { - &self.messenger - } - pub fn get_scenegraph(&self) -> &Scenegraph { - &self.scenegraph - } } diff --git a/src/core/scenegraph.rs b/src/core/scenegraph.rs index 8859754..6357af8 100644 --- a/src/core/scenegraph.rs +++ b/src/core/scenegraph.rs @@ -3,9 +3,9 @@ use crate::nodes::core::Node; use anyhow::Result; use libstardustxr::scenegraph; use libstardustxr::scenegraph::ScenegraphError; -use rccell::RcCell; use std::cell::RefCell; use std::rc::{Rc, Weak}; +use std::sync::Arc; use core::hash::BuildHasherDefault; use dashmap::DashMap; @@ -14,7 +14,7 @@ use rustc_hash::FxHasher; #[derive(Default)] pub struct Scenegraph { client: RefCell>, - nodes: DashMap, BuildHasherDefault>, + nodes: DashMap, BuildHasherDefault>, } impl Scenegraph { @@ -26,20 +26,20 @@ impl Scenegraph { *self.client.borrow_mut() = Rc::downgrade(client); } - pub fn add_node(&self, node: Node) -> RcCell { + pub fn add_node(&self, node: Node) -> Arc { let mut node = node; node.client = Rc::downgrade(&self.get_client()); let path = node.get_path().to_string(); - let node_rc = RcCell::new(node); - self.nodes.insert(path, node_rc.clone()); - node_rc + let node_arc = Arc::new(node); + self.nodes.insert(path, node_arc.clone()); + node_arc } - pub fn get_node(&self, path: &str) -> Option> { + pub fn get_node(&self, path: &str) -> Option> { Some(self.nodes.get(path)?.clone()) } - pub fn remove_node(&self, path: &str) -> Option> { + pub fn remove_node(&self, path: &str) -> Option> { let (_, node) = self.nodes.remove(path)?; Some(node) } @@ -49,7 +49,6 @@ impl scenegraph::Scenegraph for Scenegraph { fn send_signal(&self, path: &str, method: &str, data: &[u8]) -> Result<(), ScenegraphError> { self.get_node(path) .ok_or(ScenegraphError::NodeNotFound)? - .borrow() .send_local_signal(self.get_client(), method, data) } fn execute_method( @@ -60,7 +59,6 @@ impl scenegraph::Scenegraph for Scenegraph { ) -> Result, ScenegraphError> { self.get_node(path) .ok_or(ScenegraphError::NodeNotFound)? - .borrow() .execute_local_method(self.get_client(), method, data) } } diff --git a/src/nodes/core.rs b/src/nodes/core.rs index 799a3ac..b784b1a 100644 --- a/src/nodes/core.rs +++ b/src/nodes/core.rs @@ -4,13 +4,15 @@ use super::spatial::Spatial; use crate::core::client::Client; use anyhow::{anyhow, Result}; use libstardustxr::scenegraph::ScenegraphError; -use rccell::{RcCell, WeakCell}; +use nanoid::nanoid; +use parking_lot::RwLock; use std::rc::{Rc, Weak}; -use std::sync::Arc; -use std::{collections::HashMap, vec::Vec}; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, Weak as WeakArc}; +use std::vec::Vec; use core::hash::BuildHasherDefault; -use nanoid::nanoid; +use dashmap::DashMap; use rustc_hash::FxHasher; pub type Signal = fn(&Node, Rc, &[u8]) -> Result<()>; @@ -21,14 +23,14 @@ pub struct Node { pub(crate) client: Weak, path: String, // trailing_slash_pos: usize, - local_signals: HashMap>, - local_methods: HashMap>, - destroyable: bool, + local_signals: DashMap>, + local_methods: DashMap>, + destroyable: AtomicBool, - alias: Option, - pub spatial: Option>, - pub field: Option>, - pub pulse_sender: Option>, + alias: RwLock>, + pub spatial: RwLock>>, + pub field: RwLock>>, + pub pulse_sender: RwLock>>, } impl Node { @@ -42,33 +44,33 @@ impl Node { self.path.as_str() } pub fn is_destroyable(&self) -> bool { - self.destroyable + self.destroyable.load(Ordering::Relaxed) } pub fn create(parent: &str, name: &str, destroyable: bool) -> Self { let mut path = parent.to_string(); path.push('/'); path.push_str(name); - let mut node = Node { + let node = Node { uid: nanoid!(), client: Weak::new(), path, // trailing_slash_pos: parent.len(), local_signals: Default::default(), local_methods: Default::default(), - destroyable, + destroyable: AtomicBool::from(destroyable), - alias: None, - spatial: None, - field: None, - pulse_sender: None, + alias: RwLock::new(None), + spatial: RwLock::new(None), + field: RwLock::new(None), + pulse_sender: RwLock::new(None), }; node.add_local_signal("destroy", Node::destroy_flex); node } pub fn destroy(&self) { if let Some(client) = self.get_client() { - let _ = client.get_scenegraph().remove_node(self.get_path()); + let _ = client.scenegraph.remove_node(self.get_path()); } } @@ -79,10 +81,10 @@ impl Node { Ok(()) } - pub fn add_local_signal(&mut self, name: &str, signal: Signal) { + pub fn add_local_signal(&self, name: &str, signal: Signal) { self.local_signals.insert(name.to_string(), signal); } - pub fn add_local_method(&mut self, name: &str, method: Method) { + pub fn add_local_method(&self, name: &str, method: Method) { self.local_methods.insert(name.to_string(), method); } @@ -92,15 +94,14 @@ impl Node { method: &str, data: &[u8], ) -> Result<(), ScenegraphError> { - if let Some(alias) = self.alias.as_ref() { + if let Some(alias) = self.alias.read().as_ref() { if !alias.signals.contains(&method.to_string()) { return Err(ScenegraphError::SignalNotFound); } alias .original .upgrade() - .ok_or_else(|| ScenegraphError::BrokenAlias)? - .borrow() + .ok_or(ScenegraphError::BrokenAlias)? .send_local_signal(calling_client, method, data) } else { let signal = self @@ -117,15 +118,14 @@ impl Node { method: &str, data: &[u8], ) -> Result, ScenegraphError> { - if let Some(alias) = self.alias.as_ref() { + if let Some(alias) = self.alias.read().as_ref() { if !alias.methods.contains(&method.to_string()) { return Err(ScenegraphError::MethodNotFound); } alias .original .upgrade() - .ok_or_else(|| ScenegraphError::BrokenAlias)? - .borrow() + .ok_or(ScenegraphError::BrokenAlias)? .execute_local_method(calling_client, method, data) } else { let method = self @@ -139,7 +139,7 @@ impl Node { pub fn send_remote_signal(&self, method: &str, data: &[u8]) -> Result<()> { self.get_client() .ok_or_else(|| anyhow!("Node has no client, can't send remote signal!"))? - .get_messenger() + .messenger .send_remote_signal(self.path.as_str(), method, data) .map_err(|_| anyhow!("Unable to write in messenger")) } @@ -151,27 +151,27 @@ impl Node { // ) -> Result<()> { // self.get_client() // .ok_or_else(|| anyhow!("Node has no client, can't send remote signal!"))? - // .get_messenger() + // .messenger // .execute_remote_method(self.path.as_str(), method, data, callback) // .map_err(|_| anyhow!("Unable to write in messenger")) // } } struct Alias { - original: WeakCell, + original: WeakArc, signals: Vec, methods: Vec, } impl Alias { pub fn add_to( - node: &RcCell, - original: &RcCell, + node: &Arc, + original: &Arc, signals: Vec, methods: Vec, ) { - node.borrow_mut().alias = Some(Alias { - original: original.downgrade(), + *node.alias.write() = Some(Alias { + original: Arc::downgrade(original), signals, methods, }); diff --git a/src/nodes/data.rs b/src/nodes/data.rs index c8af84e..99e615e 100644 --- a/src/nodes/data.rs +++ b/src/nodes/data.rs @@ -2,7 +2,7 @@ use super::core::Node; use crate::core::registry::Registry; use anyhow::{ensure, Result}; use lazy_static::lazy_static; -use rccell::RcCell; +use std::sync::Arc; lazy_static! { static ref PULSE_SENDER_REGISTRY: Registry = Default::default(); @@ -11,15 +11,15 @@ lazy_static! { pub struct PulseSender {} impl PulseSender { - pub fn add_to(node: &RcCell) -> Result<()> { + pub fn add_to(node: &Arc) -> Result<()> { ensure!( - node.borrow().spatial.is_some(), + node.spatial.read().is_some(), "Internal: Node does not have a spatial attached!" ); let sender = PulseSender {}; let sender = PULSE_SENDER_REGISTRY.add(sender)?; - node.borrow_mut().pulse_sender = Some(sender); + *node.pulse_sender.write() = Some(sender); Ok(()) } } diff --git a/src/nodes/field.rs b/src/nodes/field.rs index e84a3b6..262cd06 100644 --- a/src/nodes/field.rs +++ b/src/nodes/field.rs @@ -7,7 +7,6 @@ use libstardustxr::fusion::flex::FlexBuffable; use libstardustxr::{flex_to_quat, flex_to_vec3}; use parking_lot::Mutex; use portable_atomic::AtomicF32; -use rccell::RcCell; use std::ops::Deref; use std::rc::Rc; use std::sync::atomic::Ordering; @@ -55,85 +54,87 @@ pub trait FieldTrait { .transform_point3a(self.local_closest_point(local_p, r)) } - fn add_field_methods(&self, node: &RcCell) { - node.borrow_mut() - .add_local_method("distance", |node, calling_client, data| { - let root = flexbuffers::Reader::get_root(data)?; - let flex_vec = root.get_vector()?; - let reference_space_path = flex_vec.idx(0).as_str(); - let reference_space = calling_client - .get_scenegraph() - .get_node(reference_space_path) - .ok_or_else(|| anyhow!("Reference space node does not exist"))? - .borrow() - .spatial - .as_ref() - .ok_or_else(|| anyhow!("Reference space node does not have a spatial"))? - .clone(); - let point = - flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?; - - let field = node - .field - .as_ref() - .ok_or_else(|| anyhow!("Node does not have a field!"))?; - let distance = field.distance(reference_space.as_ref(), point.into()); - Ok(FlexBuffable::from(distance).build_singleton()) - }); - node.borrow_mut() - .add_local_method("normal", |node, calling_client, data| { - let root = flexbuffers::Reader::get_root(data)?; - let flex_vec = root.get_vector()?; - let reference_space_path = flex_vec.idx(0).as_str(); - let reference_space = calling_client - .get_scenegraph() - .get_node(reference_space_path) - .ok_or_else(|| anyhow!("Reference space node does not exist"))? - .borrow() - .spatial - .as_ref() - .ok_or_else(|| anyhow!("Reference space node does not have a spatial"))? - .clone(); - let point = - flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?; - - let field = node - .field - .as_ref() - .ok_or_else(|| anyhow!("Node does not have a field!"))?; - let normal = field.normal(reference_space.as_ref(), point.into(), 0.001_f32); - Ok(FlexBuffable::from(mint::Vector3::from(normal)).build_singleton()) - }); - node.borrow_mut() - .add_local_method("closest_point", |node, calling_client, data| { - let root = flexbuffers::Reader::get_root(data)?; - let flex_vec = root.get_vector()?; - let reference_space_path = flex_vec.idx(0).as_str(); - let reference_space = calling_client - .get_scenegraph() - .get_node(reference_space_path) - .ok_or_else(|| anyhow!("Reference space node does not exist"))? - .borrow() - .spatial - .as_ref() - .ok_or_else(|| anyhow!("Reference space node does not have a spatial"))? - .clone(); - let point = - flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?; - - let field = node - .field - .as_ref() - .ok_or_else(|| anyhow!("Node does not have a field!"))?; - let closest_point = - field.closest_point(reference_space.as_ref(), point.into(), 0.001_f32); - Ok(FlexBuffable::from(mint::Vector3::from(closest_point)).build_singleton()) - }); + fn add_field_methods(&self, node: &Arc) { + node.add_local_method("distance", field_distance_flex); + node.add_local_method("normal", field_normal_flex); + node.add_local_method("closest_point", field_closest_point_flex); } fn spatial_ref(&self) -> &Spatial; } +fn field_distance_flex(node: &Node, calling_client: Rc, data: &[u8]) -> Result> { + let root = flexbuffers::Reader::get_root(data)?; + let flex_vec = root.get_vector()?; + let reference_space_path = flex_vec.idx(0).as_str(); + let reference_space = calling_client + .scenegraph + .get_node(reference_space_path) + .ok_or_else(|| anyhow!("Reference space node does not exist"))? + .spatial + .read() + .as_ref() + .ok_or_else(|| anyhow!("Reference space node does not have a spatial"))? + .clone(); + let point = flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?; + + let distance = node + .field + .read() + .as_ref() + .unwrap() + .distance(reference_space.as_ref(), point.into()); + Ok(FlexBuffable::from(distance).build_singleton()) +} +fn field_normal_flex(node: &Node, calling_client: Rc, data: &[u8]) -> Result> { + let root = flexbuffers::Reader::get_root(data)?; + let flex_vec = root.get_vector()?; + let reference_space_path = flex_vec.idx(0).as_str(); + let reference_space = calling_client + .scenegraph + .get_node(reference_space_path) + .ok_or_else(|| anyhow!("Reference space node does not exist"))? + .spatial + .read() + .as_ref() + .ok_or_else(|| anyhow!("Reference space node does not have a spatial"))? + .clone(); + let point = flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?; + + let normal = node.field.read().as_ref().unwrap().normal( + reference_space.as_ref(), + point.into(), + 0.001_f32, + ); + Ok(FlexBuffable::from(mint::Vector3::from(normal)).build_singleton()) +} +fn field_closest_point_flex( + node: &Node, + calling_client: Rc, + data: &[u8], +) -> Result> { + let root = flexbuffers::Reader::get_root(data)?; + let flex_vec = root.get_vector()?; + let reference_space_path = flex_vec.idx(0).as_str(); + let reference_space = calling_client + .scenegraph + .get_node(reference_space_path) + .ok_or_else(|| anyhow!("Reference space node does not exist"))? + .spatial + .read() + .as_ref() + .ok_or_else(|| anyhow!("Reference space node does not have a spatial"))? + .clone(); + let point = flex_to_vec3!(flex_vec.idx(1)).ok_or_else(|| anyhow!("Point is invalid"))?; + + let closest_point = node.field.read().as_ref().unwrap().closest_point( + reference_space.as_ref(), + point.into(), + 0.001_f32, + ); + Ok(FlexBuffable::from(mint::Vector3::from(closest_point)).build_singleton()) +} + pub enum Field { Box(BoxField), Cylinder(CylinderField), @@ -157,23 +158,22 @@ pub struct BoxField { } impl BoxField { - pub fn add_to(node: &RcCell, size: Vec3) -> Result<()> { + pub fn add_to(node: &Arc, size: Vec3) -> Result<()> { ensure!( - node.borrow().spatial.is_some(), + node.spatial.read().is_some(), "Internal: Node does not have a spatial attached!" ); ensure!( - node.borrow().field.is_none(), + node.field.read().is_none(), "Internal: Node already has a field attached!" ); let box_field = BoxField { - space: node.borrow().spatial.as_ref().unwrap().clone(), + space: node.spatial.read().as_ref().unwrap().clone(), size: Mutex::new(size), }; box_field.add_field_methods(node); - node.borrow_mut() - .add_local_signal("setSize", BoxField::set_size_flex); - node.borrow_mut().field = Some(Arc::new(Field::Box(box_field))); + node.add_local_signal("setSize", BoxField::set_size_flex); + *node.field.write() = Some(Arc::new(Field::Box(box_field))); Ok(()) } @@ -184,11 +184,7 @@ impl BoxField { pub fn set_size_flex(node: &Node, _calling_client: Rc, data: &[u8]) -> Result<()> { let root = flexbuffers::Reader::get_root(data)?; let size = flex_to_vec3!(root).ok_or_else(|| anyhow!("Size is invalid"))?; - let field = node - .field - .as_ref() - .ok_or_else(|| anyhow!("Node does not have a field"))?; - if let Field::Box(box_field) = field.as_ref() { + if let Field::Box(box_field) = node.field.read().as_ref().unwrap().as_ref() { box_field.set_size(size.into()); } Ok(()) @@ -218,24 +214,23 @@ pub struct CylinderField { } impl CylinderField { - pub fn add_to(node: &RcCell, length: f32, radius: f32) -> Result<()> { + pub fn add_to(node: &Arc, length: f32, radius: f32) -> Result<()> { ensure!( - node.borrow().spatial.is_some(), + node.spatial.read().is_some(), "Internal: Node does not have a spatial attached!" ); ensure!( - node.borrow().field.is_none(), + node.field.read().is_none(), "Internal: Node already has a field attached!" ); let cylinder_field = CylinderField { - space: node.borrow().spatial.as_ref().unwrap().clone(), + space: node.spatial.read().as_ref().unwrap().clone(), length: AtomicF32::new(length), radius: AtomicF32::new(radius), }; cylinder_field.add_field_methods(node); - node.borrow_mut() - .add_local_signal("setSize", CylinderField::set_size_flex); - node.borrow_mut().field = Some(Arc::new(Field::Cylinder(cylinder_field))); + node.add_local_signal("setSize", CylinderField::set_size_flex); + *node.field.write() = Some(Arc::new(Field::Cylinder(cylinder_field))); Ok(()) } @@ -249,11 +244,7 @@ impl CylinderField { let flex_vec = root.get_vector()?; let length = flex_vec.idx(0).as_f32(); let radius = flex_vec.idx(1).as_f32(); - let field = node - .field - .as_ref() - .ok_or_else(|| anyhow!("Node does not have a field"))?; - if let Field::Cylinder(cylinder_field) = field.as_ref() { + if let Field::Cylinder(cylinder_field) = node.field.read().as_ref().unwrap().as_ref() { cylinder_field.set_size(length, radius); } Ok(()) @@ -283,23 +274,22 @@ pub struct SphereField { } impl SphereField { - pub fn add_to(node: &RcCell, radius: f32) -> Result<()> { + pub fn add_to(node: &Arc, radius: f32) -> Result<()> { ensure!( - node.borrow().spatial.is_some(), + node.spatial.read().is_some(), "Internal: Node does not have a spatial attached!" ); ensure!( - node.borrow().field.is_none(), + node.field.read().is_none(), "Internal: Node already has a field attached!" ); let sphere_field = SphereField { - space: node.borrow().spatial.as_ref().unwrap().clone(), + space: node.spatial.read().as_ref().unwrap().clone(), radius: AtomicF32::new(radius), }; sphere_field.add_field_methods(node); - node.borrow_mut() - .add_local_signal("setRadius", SphereField::set_radius_flex); - node.borrow_mut().field = Some(Arc::new(Field::Sphere(sphere_field))); + node.add_local_signal("setRadius", SphereField::set_radius_flex); + *node.field.write() = Some(Arc::new(Field::Sphere(sphere_field))); Ok(()) } @@ -309,11 +299,7 @@ impl SphereField { pub fn set_radius_flex(node: &Node, _calling_client: Rc, data: &[u8]) -> Result<()> { let root = flexbuffers::Reader::get_root(data)?; - let field = node - .field - .as_ref() - .ok_or_else(|| anyhow!("Node does not have a field"))?; - if let Field::Sphere(sphere_field) = field.as_ref() { + if let Field::Sphere(sphere_field) = node.field.read().as_ref().unwrap().as_ref() { sphere_field.set_radius(root.as_f32()); } Ok(()) @@ -336,11 +322,11 @@ impl FieldTrait for SphereField { } pub fn create_interface(client: Rc) { - let mut node = Node::create("", "field", false); + let node = Node::create("", "field", false); node.add_local_signal("createBoxField", create_box_field_flex); node.add_local_signal("createCylinderField", create_cylinder_field_flex); node.add_local_signal("createSphereField", create_sphere_field_flex); - client.get_scenegraph().add_node(node); + client.scenegraph.add_node(node); } pub fn create_box_field_flex(_node: &Node, calling_client: Rc, data: &[u8]) -> Result<()> { @@ -348,9 +334,9 @@ pub fn create_box_field_flex(_node: &Node, calling_client: Rc, data: &[u let flex_vec = root.get_vector()?; let node = Node::create("/field", flex_vec.idx(0).get_str()?, true); let parent = calling_client - .get_scenegraph() + .scenegraph .get_node(flex_vec.idx(1).as_str()) - .and_then(|node| node.borrow().spatial.clone()); + .and_then(|node| node.spatial.read().clone()); let transform = Mat4::from_rotation_translation( flex_to_quat!(flex_vec.idx(3)) .ok_or_else(|| anyhow!("Rotation not found"))? @@ -360,7 +346,7 @@ pub fn create_box_field_flex(_node: &Node, calling_client: Rc, data: &[u .into(), ); let size = flex_to_vec3!(flex_vec.idx(4)).ok_or_else(|| anyhow!("Size invalid"))?; - let node_rc = calling_client.get_scenegraph().add_node(node); + let node_rc = calling_client.scenegraph.add_node(node); Spatial::add_to(&node_rc, parent, transform)?; BoxField::add_to(&node_rc, size.into())?; Ok(()) @@ -375,9 +361,9 @@ pub fn create_cylinder_field_flex( let flex_vec = root.get_vector()?; let node = Node::create("/field", flex_vec.idx(0).get_str()?, true); let parent = calling_client - .get_scenegraph() + .scenegraph .get_node(flex_vec.idx(1).as_str()) - .and_then(|node| node.borrow().spatial.clone()); + .and_then(|node| node.spatial.read().clone()); let transform = Mat4::from_rotation_translation( flex_to_quat!(flex_vec.idx(3)) .ok_or_else(|| anyhow!("Rotation not found"))? @@ -388,7 +374,7 @@ pub fn create_cylinder_field_flex( ); let length = flex_vec.idx(0).as_f32(); let radius = flex_vec.idx(1).as_f32(); - let node_rc = calling_client.get_scenegraph().add_node(node); + let node_rc = calling_client.scenegraph.add_node(node); Spatial::add_to(&node_rc, parent, transform)?; CylinderField::add_to(&node_rc, length, radius)?; Ok(()) @@ -403,15 +389,15 @@ pub fn create_sphere_field_flex( let flex_vec = root.get_vector()?; let node = Node::create("/field", flex_vec.idx(0).get_str()?, true); let parent = calling_client - .get_scenegraph() + .scenegraph .get_node(flex_vec.idx(1).as_str()) - .and_then(|node| node.borrow().spatial.clone()); + .and_then(|node| node.spatial.read().clone()); let transform = Mat4::from_translation( flex_to_vec3!(flex_vec.idx(2)) .ok_or_else(|| anyhow!("Position not found"))? .into(), ); - let node_rc = calling_client.get_scenegraph().add_node(node); + let node_rc = calling_client.scenegraph.add_node(node); Spatial::add_to(&node_rc, parent, transform)?; SphereField::add_to(&node_rc, flex_vec.idx(3).as_f32())?; Ok(()) diff --git a/src/nodes/spatial.rs b/src/nodes/spatial.rs index 56f1ccb..4eaa5d0 100644 --- a/src/nodes/spatial.rs +++ b/src/nodes/spatial.rs @@ -6,24 +6,23 @@ use libstardustxr::flex::flexbuffer_from_vector_arguments; use libstardustxr::push_to_vec; use libstardustxr::{flex_to_quat, flex_to_vec3}; use parking_lot::RwLock; -use rccell::RcCell; use std::rc::Rc; use std::sync::Arc; pub struct Spatial { - // node: WeakCell, + // node: Weak, parent: RwLock>>, transform: RwLock, } impl Spatial { pub fn add_to( - node: &RcCell, + node: &Arc, parent: Option>, transform: Mat4, ) -> Result> { ensure!( - node.borrow_mut().spatial.is_none(), + node.spatial.read().is_none(), "Internal: Node already has a Spatial aspect!" ); let spatial = Spatial { @@ -31,12 +30,10 @@ impl Spatial { parent: RwLock::new(parent), transform: RwLock::new(transform), }; - node.borrow_mut() - .add_local_method("getTransform", Spatial::get_transform_flex); - node.borrow_mut() - .add_local_signal("setTransform", Spatial::set_transform_flex); + node.add_local_method("getTransform", Spatial::get_transform_flex); + node.add_local_signal("setTransform", Spatial::set_transform_flex); let spatial_arc = Arc::new(spatial); - node.borrow_mut().spatial = Some(spatial_arc.clone()); + *node.spatial.write() = Some(spatial_arc.clone()); Ok(spatial_arc) } @@ -100,12 +97,13 @@ impl Spatial { let root = flexbuffers::Reader::get_root(data)?; let this_spatial = node .spatial + .read() .clone() .ok_or_else(|| anyhow!("Node doesn't have a spatial?"))?; let relative_spatial = calling_client - .get_scenegraph() + .scenegraph .get_node(root.as_str()) - .and_then(|node| node.borrow().spatial.clone()) + .and_then(|node| node.spatial.read().clone()) .ok_or_else(|| anyhow!("Space not found"))?; let (scale, rotation, position) = Spatial::space_to_space_matrix( @@ -126,40 +124,40 @@ impl Spatial { pub fn set_transform_flex(node: &Node, calling_client: Rc, data: &[u8]) -> Result<()> { let root = flexbuffers::Reader::get_root(data)?; let flex_vec = root.get_vector()?; - let spatial = node - .spatial - .as_ref() - .ok_or_else(|| anyhow!("Node somehow is not spatial"))?; let reference_space_path = flex_vec.idx(0).as_str(); let reference_space_transform = if reference_space_path.is_empty() { None } else { Some( calling_client - .get_scenegraph() + .scenegraph .get_node(reference_space_path) .ok_or_else(|| anyhow!("Other spatial node not found"))? - .borrow() .spatial + .read() .as_ref() .ok_or_else(|| anyhow!("Node is not a Spatial!"))? .clone(), ) }; - spatial.set_local_transform_components( - reference_space_transform.as_deref(), - flex_to_vec3!(flex_vec.idx(1)).map(|v| v.into()), - flex_to_quat!(flex_vec.idx(2)).map(|v| v.into()), - flex_to_vec3!(flex_vec.idx(3)).map(|v| v.into()), - ); + node.spatial + .read() + .as_ref() + .unwrap() + .set_local_transform_components( + reference_space_transform.as_deref(), + flex_to_vec3!(flex_vec.idx(1)).map(|v| v.into()), + flex_to_quat!(flex_vec.idx(2)).map(|v| v.into()), + flex_to_vec3!(flex_vec.idx(3)).map(|v| v.into()), + ); Ok(()) } } pub fn create_interface(client: Rc) { - let mut node = Node::create("", "spatial", false); + let node = Node::create("", "spatial", false); node.add_local_signal("createSpatial", create_spatial_flex); - client.get_scenegraph().add_node(node); + client.scenegraph.add_node(node); } pub fn create_spatial_flex(_node: &Node, calling_client: Rc, data: &[u8]) -> Result<()> { @@ -167,9 +165,9 @@ pub fn create_spatial_flex(_node: &Node, calling_client: Rc, data: &[u8] let flex_vec = root.get_vector()?; let spatial = Node::create("/spatial/spatial", flex_vec.idx(0).get_str()?, true); let parent = calling_client - .get_scenegraph() + .scenegraph .get_node(flex_vec.idx(1).as_str()) - .and_then(|node| node.borrow().spatial.clone()); + .and_then(|node| node.spatial.read().clone()); let transform = Mat4::from_scale_rotation_translation( flex_to_vec3!(flex_vec.idx(4)) .ok_or_else(|| anyhow!("Scale not found"))? @@ -181,7 +179,7 @@ pub fn create_spatial_flex(_node: &Node, calling_client: Rc, data: &[u8] .ok_or_else(|| anyhow!("Position not found"))? .into(), ); - let spatial_rc = calling_client.get_scenegraph().add_node(spatial); + let spatial_rc = calling_client.scenegraph.add_node(spatial); Spatial::add_to(&spatial_rc, parent, transform)?; Ok(()) }