diff --git a/src/core/client.rs b/src/core/client.rs index c5a8c6c..faf98ad 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,4 +1,5 @@ use super::scenegraph::Scenegraph; +use crate::nodes::spatial; use libstardustxr::messenger::Messenger; use mio::net::UnixStream; use rccell::{RcCell, WeakCell}; @@ -6,7 +7,7 @@ use rccell::{RcCell, WeakCell}; pub struct Client<'a> { weak_ref: WeakCell>, messenger: Messenger<'a>, - scenegraph: Option>, + scenegraph: Scenegraph<'a>, } impl<'a> Client<'a> { @@ -16,20 +17,22 @@ impl<'a> Client<'a> { scenegraph: Default::default(), messenger: Messenger::new(connection), }); + client.borrow_mut().scenegraph.set_client(client.clone()); client.borrow_mut().weak_ref = client.downgrade(); + spatial::create_interface(client.clone()); client } pub fn dispatch(&self) -> Result<(), std::io::Error> { - self.messenger.dispatch(self.scenegraph.as_ref().unwrap()) + self.messenger.dispatch(&self.scenegraph) } pub fn get_messenger(&self) -> &Messenger<'a> { &self.messenger } pub fn get_scenegraph(&self) -> &Scenegraph<'a> { - self.scenegraph.as_ref().unwrap() + &self.scenegraph } pub fn get_scenegraph_mut(&mut self) -> &mut Scenegraph<'a> { - self.scenegraph.as_mut().unwrap() + &mut self.scenegraph } } diff --git a/src/core/scenegraph.rs b/src/core/scenegraph.rs index b3065aa..bba4a58 100644 --- a/src/core/scenegraph.rs +++ b/src/core/scenegraph.rs @@ -11,6 +11,19 @@ pub struct Scenegraph<'a> { pub nodes: HashMap>>, } +impl<'a> Scenegraph<'a> { + pub fn set_client(&mut self, client: RcCell>) { + self.client = client.downgrade(); + } + + pub fn add_node(&mut self, node: Node<'a>) -> RcCell> { + let path = node.get_path().to_string(); + let node_rc = RcCell::new(node); + self.nodes.insert(path, node_rc.clone()); + node_rc + } +} + impl<'a> Default for Scenegraph<'a> { fn default() -> Self { Scenegraph { diff --git a/src/nodes/core.rs b/src/nodes/core.rs index f29f313..6a26256 100644 --- a/src/nodes/core.rs +++ b/src/nodes/core.rs @@ -29,23 +29,24 @@ impl<'a> Node<'a> { self.path.as_str() } - pub fn from_path( + pub fn create( client: WeakCell>, - path: &str, + parent: &str, + name: &str, destroyable: bool, - ) -> Result> { - ensure!(path.starts_with('/'), "Invalid path {}", path); - Ok(Node { + ) -> Self { + let mut path = parent.to_string(); + path.push('/'); + path.push_str(name); + Node { client, - path: path.to_string(), - trailing_slash_pos: path - .rfind('/') - .ok_or_else(|| anyhow!("Invalid path {}", path))?, + path: path, + trailing_slash_pos: parent.len(), local_signals: HashMap::new(), local_methods: HashMap::new(), destroyable, spatial: None, - }) + } } pub fn add_local_signal(&mut self, method: &str, signal: Signal<'a>) { diff --git a/src/nodes/spatial.rs b/src/nodes/spatial.rs index db0ddde..0915608 100644 --- a/src/nodes/spatial.rs +++ b/src/nodes/spatial.rs @@ -1,6 +1,6 @@ use super::core::Node; use crate::core::client::Client; -use anyhow::{anyhow, ensure, Result}; +use anyhow::{anyhow, bail, ensure, Result}; use glam::{Mat4, Quat, Vec3}; use libstardustxr::{flex_to_quat, flex_to_vec3}; use rccell::{RcCell, WeakCell}; @@ -12,10 +12,17 @@ pub struct Spatial<'a> { } impl<'a> Spatial<'a> { - pub fn new(node: RcCell>, transform: Mat4) -> Self { + pub fn add_to( + node: RcCell>, + parent: WeakCell>, + transform: Mat4, + ) -> Result<()> { + if node.borrow_mut().spatial.is_none() { + bail!("Node already has a Spatial aspect!"); + } let spatial = Spatial { node: node.downgrade(), - parent: WeakCell::new(), + parent, transform, }; let node_captured = node.clone(); @@ -24,7 +31,6 @@ impl<'a> Spatial<'a> { Box::new(move |calling_client, data| { let root = flexbuffers::Reader::get_root(data)?; let flex_vec = root.get_vector()?; - // let node = node. let client = node_captured .borrow() .get_client() @@ -52,7 +58,8 @@ impl<'a> Spatial<'a> { Ok(()) }), ); - spatial + node.borrow_mut().spatial = Some(spatial); + Ok(()) } pub fn local_transform(&self) -> Mat4 { @@ -80,3 +87,34 @@ impl<'a> Spatial<'a> { // pub fn relative_transform(&self, space: WeakCell) {} } + +pub fn create_interface(client: RcCell) { + let mut node = Node::create(client.downgrade(), "", "spatial", false); + node.add_local_signal( + "createSpatial", + Box::new(move |calling_client, data| { + let root = flexbuffers::Reader::get_root(data)?; + let flex_vec = root.get_vector()?; + let node = Node::create( + calling_client.downgrade(), + "/spatial", + flex_vec.idx(0).get_str()?, + true, + ); + let pos = flex_to_vec3!(flex_vec.idx(2)).ok_or(anyhow!("Position not found"))?; + let rot = flex_to_quat!(flex_vec.idx(3)).ok_or(anyhow!("Rotation not found"))?; + let scl = flex_to_vec3!(flex_vec.idx(4)).ok_or(anyhow!("Scale not found"))?; + let node_rc = calling_client + .borrow_mut() + .get_scenegraph_mut() + .add_node(node); + Spatial::add_to( + node_rc, + WeakCell::new(), + Mat4::from_scale_rotation_translation(scl.into(), rot.into(), pos.into()), + )?; + Ok(()) + }), + ); + client.borrow_mut().get_scenegraph_mut().add_node(node); +}