From 1709d19da2f30e7900f6e0c54d864b188e8ad036 Mon Sep 17 00:00:00 2001 From: Nova Date: Sun, 22 May 2022 12:35:22 -0400 Subject: [PATCH] refactor(spatial): store weak reference to parent node --- src/core/client.rs | 13 +++++++------ src/core/scenegraph.rs | 23 +++++++---------------- src/nodes/core.rs | 25 +++++++++++-------------- src/nodes/spatial.rs | 10 +++++----- 4 files changed, 30 insertions(+), 41 deletions(-) diff --git a/src/core/client.rs b/src/core/client.rs index d286087..6dbaa5b 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,23 +1,24 @@ use super::scenegraph::Scenegraph; -use crate::nodes::core::{Node, NodeRef}; use libstardustxr::messenger::Messenger; use mio::net::UnixStream; use std::rc::{Rc, Weak}; pub struct Client<'a> { messenger: Rc>, - pub scenegraph: Scenegraph<'a>, + pub scenegraph: Option>, } impl<'a> Client<'a> { pub fn from_connection(connection: UnixStream) -> Self { - Client { - scenegraph: Default::default(), + let mut client = Client { + scenegraph: None, messenger: Rc::new(Messenger::new(connection)), - } + }; + client.scenegraph = Some(Scenegraph::new(&mut client)); + client } pub fn dispatch(&self) -> Result<(), std::io::Error> { - self.messenger.dispatch(&self.scenegraph) + self.messenger.dispatch(self.scenegraph.as_ref().unwrap()) } pub fn get_weak_messenger(&self) -> Weak> { diff --git a/src/core/scenegraph.rs b/src/core/scenegraph.rs index 0829392..3622759 100644 --- a/src/core/scenegraph.rs +++ b/src/core/scenegraph.rs @@ -14,6 +14,13 @@ pub struct Scenegraph<'a> { } impl<'a> Scenegraph<'a> { + pub fn new(client: &mut Client<'a>) -> Self { + Scenegraph { + nodes: HashMap::new(), + root: Spatial::new_node(Some(client), "/", Default::default()).unwrap(), + hmd: Spatial::new_node(Some(client), "/hmd", Default::default()).unwrap(), + } + } pub fn add_node(&mut self, node: RcCell>) { let path = node.borrow().get_path().to_string(); self.nodes.insert(path, node); @@ -28,22 +35,6 @@ impl<'a> Scenegraph<'a> { .get(path) .map_or(WeakCell::new(), RcCell::downgrade) } - - pub fn add_interfaces(&mut self, client: &mut Client<'a>) -> Result<()> { - self.root = Spatial::new_node(Some(client), "/", Default::default())?; - self.hmd = Spatial::new_node(Some(client), "/hmd", Default::default())?; - Ok(()) - } -} - -impl<'a> Default for Scenegraph<'a> { - fn default() -> Self { - Scenegraph { - nodes: HashMap::new(), - root: WeakCell::new(), - hmd: WeakCell::new(), - } - } } impl<'a> scenegraph::Scenegraph for Scenegraph<'a> { diff --git a/src/nodes/core.rs b/src/nodes/core.rs index 0479d75..e24e5de 100644 --- a/src/nodes/core.rs +++ b/src/nodes/core.rs @@ -2,12 +2,7 @@ use crate::core::client::Client; use anyhow::{anyhow, ensure, Result}; use libstardustxr::messenger::Messenger; use rccell::{RcCell, WeakCell}; -use std::{ - cell::RefCell, - collections::HashMap, - rc::{Rc, Weak}, - vec::Vec, -}; +use std::{collections::HashMap, rc::Weak, vec::Vec}; use super::spatial::Spatial; @@ -39,12 +34,16 @@ impl<'a> Node<'a> { self.path.as_str() } - pub fn from_path(client: Option<&mut Client<'a>>, path: &str) -> Result> { + pub fn from_path( + client: Option<&mut Client<'a>>, + path: &str, + data_closure: impl FnOnce(NodeRef<'a>) -> NodeData<'a>, + ) -> Result> { ensure!(path.starts_with('/'), "Invalid path {}", path); let mut weak_messenger = Weak::default(); - if client.is_some() { - weak_messenger = client.as_ref().unwrap().get_weak_messenger(); - } + client + .as_ref() + .map(|c| weak_messenger = c.get_weak_messenger()); let node = Node { path: path.to_string(), trailing_slash_pos: path @@ -58,10 +57,8 @@ impl<'a> Node<'a> { }; let node_ref = RcCell::new(node); let weak_node = node_ref.downgrade(); - match client { - Some(client_) => client_.scenegraph.add_node(node_ref), - None => {} - }; + node_ref.borrow_mut().data = data_closure(weak_node.clone()); + client.map(|c| c.scenegraph.as_mut().unwrap().add_node(node_ref)); Ok(weak_node) } diff --git a/src/nodes/spatial.rs b/src/nodes/spatial.rs index c99a3fb..c7f9ca4 100644 --- a/src/nodes/spatial.rs +++ b/src/nodes/spatial.rs @@ -4,12 +4,12 @@ use anyhow::Result; use vek::mat::repr_c::row_major::Mat4; pub struct Spatial<'a> { - node: &'a Node<'a>, + node: NodeRef<'a>, transform: Mat4, } impl<'a> Spatial<'a> { - pub fn new(node: &'a Node<'a>, transform: Mat4) -> Self { + pub fn new(node: NodeRef<'a>, transform: Mat4) -> Self { Spatial { node, transform } } @@ -18,8 +18,8 @@ impl<'a> Spatial<'a> { path: &str, transform: Mat4, ) -> Result> { - let node = Node::from_path(client, path)?; - node.upgrade().unwrap().borrow_mut().spatial = Some(Spatial::new(transform)); - Ok(node) + Node::from_path(client, path, move |node| { + NodeData::Spatial(Spatial::new(node, transform)) + }) } }