diff --git a/src/core/registry.rs b/src/core/registry.rs index f42d968..8f90e6d 100644 --- a/src/core/registry.rs +++ b/src/core/registry.rs @@ -74,7 +74,7 @@ impl Registry { .filter_map(|pair| pair.1.upgrade()) .collect() } - pub fn retain bool>(&self, f: F) { + pub fn retain) -> bool>(&self, f: F) { self.lock().retain(|_, v| { let Some(v) = v.upgrade() else { return true; diff --git a/src/core/scenegraph.rs b/src/core/scenegraph.rs index 2c10536..fcf19b2 100644 --- a/src/core/scenegraph.rs +++ b/src/core/scenegraph.rs @@ -1,10 +1,9 @@ -use crate::nodes::alias::Alias; +use crate::nodes::alias::get_original; use crate::nodes::Node; use crate::{core::client::Client, nodes::Message}; use color_eyre::eyre::Result; use once_cell::sync::OnceCell; use parking_lot::Mutex; -use portable_atomic::Ordering; use rustc_hash::FxHashMap; use serde::Serialize; use stardust_xr::scenegraph; @@ -38,15 +37,8 @@ impl Scenegraph { } pub fn get_node(&self, node: u64) -> Option> { - let mut node = self.nodes.lock().get(&node)?.clone(); - while let Ok(alias) = node.get_aspect::() { - if alias.enabled.load(Ordering::Acquire) { - node = alias.original.upgrade()?; - } else { - return None; - } - } - Some(node) + let node = self.nodes.lock().get(&node)?.clone(); + get_original(node, true) } pub fn remove_node(&self, node: u64) -> Option> { diff --git a/src/nodes/alias.rs b/src/nodes/alias.rs index 5493c1f..810ab32 100644 --- a/src/nodes/alias.rs +++ b/src/nodes/alias.rs @@ -1,7 +1,6 @@ use super::{Aspect, Node}; use crate::core::{client::Client, registry::Registry}; use color_eyre::eyre::Result; -use portable_atomic::AtomicBool; use std::{ ops::Add, sync::{Arc, Weak}, @@ -23,12 +22,11 @@ impl Add for AliasInfo { } } +#[derive(Debug)] pub struct Alias { - pub enabled: Arc, pub(super) node: Weak, - pub original: Weak, - - pub info: AliasInfo, + pub(super) original: Weak, + pub(super) info: AliasInfo, } impl Alias { pub fn create( @@ -61,7 +59,6 @@ impl Alias { fn add_to(new_node: &Arc, original: &Arc, info: AliasInfo) -> Result<()> { let alias = Alias { - enabled: Arc::new(AtomicBool::new(true)), node: Arc::downgrade(&new_node), original: Arc::downgrade(original), info, @@ -75,11 +72,14 @@ impl Aspect for Alias { const NAME: &'static str = "Alias"; } -pub fn get_original(node: Arc) -> Option> { +pub fn get_original(node: Arc, stop_on_disabled: bool) -> Option> { let Ok(alias) = node.get_aspect::() else { return Some(node); }; - get_original(alias.original.upgrade()?) + if stop_on_disabled && !node.enabled() { + return None; + } + get_original(alias.original.upgrade()?, stop_on_disabled) } #[derive(Debug, Default, Clone)] @@ -89,19 +89,26 @@ impl AliasList { self.0.add_raw(node); } pub fn get(&self, aspect: &A) -> Option> { - self.0.get_valid_contents().into_iter().find(|node| { - let Ok(aspect2) = node.get_aspect::() else { - return false; - }; - Arc::as_ptr(&aspect2) != (aspect as *const A) - }) + self.0 + .get_valid_contents() + .into_iter() + .filter_map(|n| get_original(n, false)) + .find(|node| { + let Ok(aspect2) = node.get_aspect::() else { + return false; + }; + Arc::as_ptr(&aspect2) == (aspect as *const A) + }) } pub fn get_aliases(&self) -> Vec> { self.0.get_valid_contents() } pub fn remove_aspect(&self, aspect: &A) { self.0.retain(|node| { - let Ok(aspect2) = node.get_aspect::() else { + let Some(original) = get_original(node.clone(), false) else { + return false; + }; + let Ok(aspect2) = original.get_aspect::() else { return false; }; Arc::as_ptr(&aspect2) != (aspect as *const A) diff --git a/src/nodes/drawable/lines.rs b/src/nodes/drawable/lines.rs index 33b5a32..5d0d9ca 100644 --- a/src/nodes/drawable/lines.rs +++ b/src/nodes/drawable/lines.rs @@ -6,7 +6,6 @@ use crate::{ use color_eyre::eyre::Result; use glam::Vec3; use parking_lot::Mutex; -use portable_atomic::{AtomicBool, Ordering}; use prisma::Lerp; use std::{collections::VecDeque, sync::Arc}; use stereokit_rust::{ @@ -16,7 +15,6 @@ use stereokit_rust::{ static LINES_REGISTRY: Registry = Registry::new(); pub struct Lines { - enabled: Arc, space: Arc, data: Mutex>, } @@ -39,7 +37,6 @@ impl Lines { }); let lines = LINES_REGISTRY.add(Lines { - enabled: node.enabled.clone(), space: node.get_aspect::()?.clone(), data: Mutex::new(lines), }); @@ -104,7 +101,7 @@ impl Drop for Lines { pub fn draw_all(token: &MainThreadToken) { for lines in LINES_REGISTRY.get_valid_contents() { - if lines.enabled.load(Ordering::Relaxed) { + if lines.space.node().unwrap().enabled() { lines.draw(token); } } diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index de2aede..6c56942 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -8,7 +8,6 @@ use color_eyre::eyre::{bail, eyre, Result}; use glam::{Mat4, Vec2, Vec3}; use once_cell::sync::OnceCell; use parking_lot::Mutex; -use portable_atomic::{AtomicBool, Ordering}; use rustc_hash::FxHashMap; use send_wrapper::SendWrapper; use stardust_xr::values::ResourceID; @@ -244,7 +243,6 @@ impl ModelPartAspect for ModelPart { } pub struct Model { - enabled: Arc, space: Arc, _resource_id: ResourceID, sk_model: OnceCell, @@ -260,7 +258,6 @@ impl Model { .ok_or_else(|| eyre!("Resource not found"))?; let model = Arc::new(Model { - enabled: node.enabled.clone(), space: node.get_aspect::().unwrap().clone(), _resource_id: resource_id, sk_model: OnceCell::new(), @@ -290,7 +287,7 @@ impl Model { } drop(parts); - if self.enabled.load(Ordering::Relaxed) { + if self.space.node().unwrap().enabled() { sk_model.draw(token, self.space.global_transform(), None, None); } } diff --git a/src/nodes/drawable/text.rs b/src/nodes/drawable/text.rs index d525afd..ef3ac3a 100644 --- a/src/nodes/drawable/text.rs +++ b/src/nodes/drawable/text.rs @@ -6,7 +6,6 @@ use color_eyre::eyre::{eyre, Result}; use glam::{vec3, Mat4, Vec2}; use once_cell::sync::OnceCell; use parking_lot::Mutex; -use portable_atomic::{AtomicBool, Ordering}; use std::{ffi::OsStr, path::PathBuf, sync::Arc}; use stereokit_rust::{ font::Font, @@ -34,7 +33,6 @@ fn convert_align(x_align: super::XAlign, y_align: super::YAlign) -> TextAlign { } pub struct Text { - enabled: Arc, space: Arc, font_path: Option, style: OnceCell, @@ -46,7 +44,6 @@ impl Text { pub fn add_to(node: &Arc, text: String, style: TextStyle) -> Result> { let client = node.get_client().ok_or_else(|| eyre!("Client not found"))?; let text = TEXT_REGISTRY.add(Text { - enabled: node.enabled.clone(), space: node.get_aspect::().unwrap().clone(), font_path: style.font.as_ref().and_then(|res| { get_resource_file(&res, &client, &[OsStr::new("ttf"), OsStr::new("otf")]) @@ -166,7 +163,7 @@ impl Drop for Text { pub fn draw_all(token: &MainThreadToken) { for text in TEXT_REGISTRY.get_valid_contents() { - if text.enabled.load(Ordering::Relaxed) { + if text.space.node().unwrap().enabled() { text.draw(token); } } diff --git a/src/nodes/input/handler.rs b/src/nodes/input/handler.rs index 7800348..64a67e3 100644 --- a/src/nodes/input/handler.rs +++ b/src/nodes/input/handler.rs @@ -2,7 +2,12 @@ use super::{ input_handler_client, InputHandlerAspect, InputLink, INPUT_HANDLER_REGISTRY, INPUT_METHOD_REGISTRY, }; -use crate::nodes::{alias::AliasList, fields::Field, spatial::Spatial, Aspect, Node}; +use crate::nodes::{ + alias::AliasList, + fields::Field, + spatial::Spatial, + Aspect, Node, +}; use color_eyre::eyre::Result; use stardust_xr::values::Datamap; use std::sync::Arc; @@ -21,7 +26,6 @@ impl InputHandler { method_aliases: AliasList::default(), }; for method in INPUT_METHOD_REGISTRY.get_valid_contents() { - method.make_alias(&handler); method.handle_new_handler(&handler); } let handler = INPUT_HANDLER_REGISTRY.add(handler); diff --git a/src/nodes/input/method.rs b/src/nodes/input/method.rs index c793df9..227bcf2 100644 --- a/src/nodes/input/method.rs +++ b/src/nodes/input/method.rs @@ -14,13 +14,10 @@ use crate::{ }; use color_eyre::eyre::Result; use parking_lot::Mutex; -use portable_atomic::Ordering; use stardust_xr::values::Datamap; use std::sync::{Arc, Weak}; pub struct InputMethod { - pub node: Weak, - pub enabled: Mutex, pub spatial: Arc, pub data: Mutex, pub datamap: Mutex, @@ -38,8 +35,6 @@ impl InputMethod { datamap: Datamap, ) -> Result> { let method = InputMethod { - node: Arc::downgrade(node), - enabled: Mutex::new(true), spatial: node.get_aspect::().unwrap().clone(), data: Mutex::new(data), datamap: Mutex::new(datamap), @@ -52,7 +47,6 @@ impl InputMethod { }; for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() { method.handle_new_handler(&handler); - method.make_alias(&handler); } let method = INPUT_METHOD_REGISTRY.add(method); ::add_node_members(node); @@ -61,8 +55,16 @@ impl InputMethod { Ok(method) } + pub fn distance(&self, to: &Field) -> f32 { + self.data.lock().distance(&self.spatial, to) + } + + pub fn set_handler_order<'a>(&self, handlers: impl Iterator>) { + *self.handler_order.lock() = handlers.map(Arc::downgrade).collect(); + } + pub(super) fn make_alias(&self, handler: &InputHandler) { - let Some(method_node) = self.node.upgrade() else { + let Some(method_node) = self.spatial.node() else { return; }; let Some(handler_node) = handler.spatial.node() else { @@ -79,19 +81,12 @@ impl InputMethod { ) else { return; }; - method_alias.enabled.store(false, Ordering::Relaxed); + method_alias.set_enabled(false); } - - pub fn distance(&self, to: &Field) -> f32 { - self.data.lock().distance(&self.spatial, to) - } - - pub fn set_handler_order<'a>(&self, handlers: impl Iterator>) { - *self.handler_order.lock() = handlers.map(Arc::downgrade).collect(); - } - pub(super) fn handle_new_handler(&self, handler: &InputHandler) { - let Some(method_node) = self.node.upgrade() else { + self.make_alias(handler); + + let Some(method_node) = self.spatial.node() else { return; }; let Some(method_client) = method_node.get_client() else { @@ -126,7 +121,7 @@ impl InputMethod { let _ = input_method_client::create_handler(&method_node, &handler_alias, &rx_field_alias); } pub(super) fn handle_drop_handler(&self, handler: &InputHandler) { - let Some(tx_node) = self.node.upgrade() else { + let Some(tx_node) = self.spatial.node() else { return; }; let Some(handler_alias) = self.handler_aliases.get(handler) else { diff --git a/src/nodes/input/mod.rs b/src/nodes/input/mod.rs index 4a26cc9..a6fa1e6 100644 --- a/src/nodes/input/mod.rs +++ b/src/nodes/input/mod.rs @@ -10,12 +10,10 @@ pub use method::*; use super::fields::Field; use super::spatial::Spatial; use crate::create_interface; -use crate::nodes::alias::Alias; use crate::{core::client::Client, nodes::Node}; use crate::{core::registry::Registry, nodes::spatial::Transform}; use color_eyre::eyre::Result; use glam::Mat4; -use portable_atomic::Ordering; use stardust_xr::values::Datamap; use std::sync::{Arc, Weak}; use tracing::{debug_span, instrument}; @@ -126,14 +124,20 @@ pub fn process_input() { INPUT_METHOD_REGISTRY .get_valid_contents() .into_iter() - .filter(|method| *method.enabled.lock()) + .filter(|method| { + let Some(node) = method.spatial.node() else { + return false; + }; + node.enabled() + }) }); + for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() { + for method_alias in handler.method_aliases.get_aliases() { + method_alias.set_enabled(false); + } + } // const LIMIT: usize = 50; for method in methods { - for alias in method.node.upgrade().unwrap().aliases.get_valid_contents() { - alias.enabled.store(false, Ordering::Release); - } - debug_span!("Process input method").in_scope(|| { // Get all valid input handlers and convert them to InputLink objects let input_links: Vec = debug_span!("Generate input links").in_scope(|| { @@ -158,9 +162,8 @@ pub fn process_input() { .handler .method_aliases .get(input_link.method.as_ref()) - .and_then(|a| a.get_aspect::().ok()) { - method_alias.enabled.store(true, Ordering::Release); + method_alias.set_enabled(true); } input_link.send_input( i as u32, diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index d84c7e4..b642655 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -9,6 +9,10 @@ pub mod items; pub mod root; pub mod spatial; +use self::alias::Alias; +use crate::core::client::Client; +use crate::core::registry::Registry; +use crate::core::scenegraph::MethodResponseSender; use color_eyre::eyre::{eyre, Result}; use parking_lot::Mutex; use portable_atomic::{AtomicBool, Ordering}; @@ -23,12 +27,6 @@ use std::os::fd::OwnedFd; use std::sync::{Arc, Weak}; use std::vec::Vec; -use crate::core::client::Client; -use crate::core::registry::Registry; -use crate::core::scenegraph::MethodResponseSender; - -use self::alias::Alias; - #[derive(Default)] pub struct Message { pub data: Vec, @@ -54,7 +52,7 @@ pub type Method = fn(Arc, Arc, Message, MethodResponseSender); stardust_xr_server_codegen::codegen_node_protocol!(); pub struct Node { - enabled: Arc, + enabled: AtomicBool, id: u64, client: Weak, message_sender_handle: Option, @@ -78,7 +76,7 @@ impl Node { } pub fn from_id(client: &Arc, id: u64, destroyable: bool) -> Self { let node = Node { - enabled: Arc::new(AtomicBool::new(true)), + enabled: AtomicBool::new(true), client: Arc::downgrade(client), message_sender_handle: client.message_sender_handle.clone(), id, @@ -101,6 +99,9 @@ impl Node { pub fn enabled(&self) -> bool { self.enabled.load(Ordering::Relaxed) } + pub fn set_enabled(&self, enabled: bool) { + self.enabled.store(enabled, Ordering::Relaxed) + } pub fn destroy(&self) { if let Some(client) = self.get_client() { client.scenegraph.remove_node(self.get_id()); @@ -244,12 +245,17 @@ impl Node { } impl Debug for Node { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Node").field("id", &self.id).finish() + f.debug_struct("Node") + .field("id", &self.id) + .field("local_signals", &self.local_signals.lock().keys()) + .field("local_methods", &self.local_methods.lock().keys()) + .field("destroyable", &self.destroyable) + .finish() } } impl OwnedAspect for Node { fn set_enabled(node: Arc, _calling_client: Arc, enabled: bool) -> Result<()> { - node.enabled.store(enabled, Ordering::Relaxed); + node.set_enabled(enabled); Ok(()) } @@ -272,6 +278,7 @@ pub trait Aspect: Any + Send + Sync + 'static { #[derive(Default)] struct Aspects(Mutex>>); + impl Aspects { fn add(&self, t: A) -> Arc { let aspect = Arc::new(t); @@ -281,7 +288,7 @@ impl Aspects { fn add_raw(&self, aspect: Arc) { self.0.lock().insert(Self::type_key::(), aspect); } - fn get(&self) -> Result> { + fn get(&self) -> Result> { self.0 .lock() .get(&Self::type_key::()) diff --git a/src/nodes/spatial/zone.rs b/src/nodes/spatial/zone.rs index 92c96ad..140392d 100644 --- a/src/nodes/spatial/zone.rs +++ b/src/nodes/spatial/zone.rs @@ -153,7 +153,7 @@ impl Drop for Zone { .captured .get_aliases() .into_iter() - .filter_map(get_original) + .filter_map(|n| get_original(n, false)) .filter_map(|n| n.get_aspect::().ok()) { release(&captured); diff --git a/src/objects/input/sk_controller.rs b/src/objects/input/sk_controller.rs index a615d3d..146da0c 100644 --- a/src/objects/input/sk_controller.rs +++ b/src/objects/input/sk_controller.rs @@ -54,8 +54,9 @@ impl SkController { } pub fn update(&mut self, token: &MainThreadToken) { let controller = Input::controller(self.handed); - *self.input.enabled.lock() = controller.tracked.is_active(); - if *self.input.enabled.lock() { + let input_node = self.input.spatial.node().unwrap(); + input_node.set_enabled(controller.tracked.is_active()); + if input_node.enabled() { let world_transform = Mat4::from_rotation_translation( controller.aim.orientation.into(), controller.aim.position.into(), diff --git a/src/objects/input/sk_hand.rs b/src/objects/input/sk_hand.rs index b1ca256..5db7fc7 100644 --- a/src/objects/input/sk_hand.rs +++ b/src/objects/input/sk_hand.rs @@ -63,8 +63,10 @@ impl SkHand { if let InputDataType::Hand(hand) = &mut *self.input.data.lock() { let controller_active = controller_enabled && Input::controller(self.handed).is_tracked(); - *self.input.enabled.lock() = !controller_active && sk_hand.tracked.is_active(); - if *self.input.enabled.lock() { + + let input_node = self.input.spatial.node().unwrap(); + input_node.set_enabled(!controller_active && sk_hand.tracked.is_active()); + if input_node.enabled() { hand.thumb.tip = convert_joint(sk_hand.fingers[0][4]); hand.thumb.distal = convert_joint(sk_hand.fingers[0][3]); hand.thumb.proximal = convert_joint(sk_hand.fingers[0][2]);