From a0058fcc2ee77f10d9767b3941e0f54e1652da4b Mon Sep 17 00:00:00 2001 From: Nova Date: Wed, 30 Nov 2022 07:04:06 -0500 Subject: [PATCH] fix(alias): make output optional --- src/nodes/alias.rs | 27 ++++--- src/nodes/data.rs | 52 ++++++------- src/nodes/hmd.rs | 2 +- src/nodes/items/environment.rs | 16 ++-- src/nodes/items/mod.rs | 87 ++++++++++++++-------- src/nodes/spatial/zone.rs | 129 +++++++++++++++------------------ 6 files changed, 163 insertions(+), 150 deletions(-) diff --git a/src/nodes/alias.rs b/src/nodes/alias.rs index 7211347..5570001 100644 --- a/src/nodes/alias.rs +++ b/src/nodes/alias.rs @@ -24,15 +24,22 @@ impl Alias { name: &str, original: &Arc, info: AliasInfo, - ) -> Arc { - let node = Node::create(client, parent, name, true).add_to_scenegraph(); - let alias = Alias { - node: Arc::downgrade(&node), - original: Arc::downgrade(original), - info, - }; - let alias = original.aliases.add(alias); - let _ = node.alias.set(alias); - node + ) -> Option> { + let node_free = client + .scenegraph + .get_node(&(parent.to_string() + "/" + name)) + .is_none(); + + node_free.then(|| { + let node = Node::create(client, parent, name, true).add_to_scenegraph(); + let alias = Alias { + node: Arc::downgrade(&node), + original: Arc::downgrade(original), + info, + }; + let alias = original.aliases.add(alias); + let _ = node.alias.set(alias); + node + }) } } diff --git a/src/nodes/data.rs b/src/nodes/data.rs index 21f845b..347bace 100644 --- a/src/nodes/data.rs +++ b/src/nodes/data.rs @@ -81,18 +81,9 @@ impl PulseSender { if !mask_matches(&self.mask, &receiver.mask) { return; } - let tx_node = match self.node.upgrade() { - Some(v) => v, - _ => return, - }; - let tx_client = match tx_node.get_client() { - Some(v) => v, - _ => return, - }; - let rx_node = match receiver.node.upgrade() { - Some(v) => v, - _ => return, - }; + let Some(tx_node) = self.node.upgrade() else { return }; + let Some(tx_client) = tx_node.get_client() else { return }; + let Some(rx_node) = receiver.node.upgrade() else { return }; // Receiver itself let rx_alias = Alias::create( &tx_client, @@ -104,22 +95,26 @@ impl PulseSender { ..Default::default() }, ); - self.aliases.add(receiver.uid.clone(), &rx_alias); + if let Some(rx_alias) = rx_alias { + self.aliases.add(receiver.uid.clone(), &rx_alias); - if let Some(rx_field_node) = receiver.field.spatial_ref().node.upgrade() { - // Receiver's field - let rx_field_alias = Alias::create( - &tx_client, - rx_alias.get_path(), - "field", - &rx_field_node, - AliasInfo { - local_methods: vec!["sendData", "getTransform"], - ..Default::default() - }, - ); - self.aliases - .add(receiver.uid.clone() + "-field", &rx_field_alias); + if let Some(rx_field_node) = receiver.field.spatial_ref().node.upgrade() { + // Receiver's field + let rx_field_alias = Alias::create( + &tx_client, + rx_alias.get_path(), + "field", + &rx_field_node, + AliasInfo { + local_methods: vec!["sendData", "getTransform"], + ..Default::default() + }, + ); + if let Some(rx_field_alias) = rx_field_alias { + self.aliases + .add(receiver.uid.clone() + "-field", &rx_field_alias); + } + } } #[derive(Serialize)] @@ -158,8 +153,7 @@ impl PulseSender { fn send_data_flex(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { let info: SendDataInfo = deserialize(data)?; - let capture_path = node.path.clone() + "/" + info.uid; - let receiver_node = calling_client.get_node("Pulse receiver", &capture_path)?; + let receiver_node = calling_client.get_node("Pulse receiver", info.uid)?; let receiver = receiver_node.get_aspect("Pulse Receiver", "pulse receiver", |n| &n.pulse_receiver)?; let receiver_mask = &receiver_node diff --git a/src/nodes/hmd.rs b/src/nodes/hmd.rs index 8a78729..1954b91 100644 --- a/src/nodes/hmd.rs +++ b/src/nodes/hmd.rs @@ -28,7 +28,7 @@ pub fn frame(sk: &StereoKit) { ); } -pub fn make_alias(client: &Arc) -> Arc { +pub fn make_alias(client: &Arc) -> Option> { Alias::create( client, "", diff --git a/src/nodes/items/environment.rs b/src/nodes/items/environment.rs index acb3393..2f6be65 100644 --- a/src/nodes/items/environment.rs +++ b/src/nodes/items/environment.rs @@ -45,12 +45,10 @@ impl EnvironmentItem { } fn get_path_flex(node: &Node, _calling_client: Arc, _data: &[u8]) -> Result> { - #[allow(unreachable_patterns)] - let path: Result = match &node.item.get().unwrap().specialization { - ItemType::Environment(env) => Ok(env.path.clone()), - _ => Err(anyhow!("")), + let ItemType::Environment(environment_item) = &node.item.get().unwrap().specialization else { + return Err(anyhow!("Wrong item type?")) }; - Ok(flexbuffers::singleton(path?.as_str())) + Ok(flexbuffers::singleton(environment_item.path.as_str())) } } impl ItemSpecialization for EnvironmentItem { @@ -72,16 +70,16 @@ pub(super) fn create_environment_item_flex( item_data: String, } let info: CreateEnvironmentItemInfo = deserialize(data)?; - let parent_name = format!("/item/{}/item/", ITEM_TYPE_INFO_ENVIRONMENT.type_name); - let node = Node::create(&INTERNAL_CLIENT, &parent_name, info.name, true); + let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_ENVIRONMENT.type_name); let space = find_spatial_parent(&calling_client, info.parent_path)?; let transform = parse_transform(info.transform, true, true, false)?; - let node = node.add_to_scenegraph(); + + let node = Node::create(&INTERNAL_CLIENT, &parent_name, info.name, false).add_to_scenegraph(); Spatial::add_to(&node, None, transform * space.global_transform(), false)?; EnvironmentItem::add_to(&node, info.item_data); node.item .get() .unwrap() - .make_alias(&calling_client, &parent_name); + .make_alias_named(&calling_client, &parent_name, info.name); Ok(()) } diff --git a/src/nodes/items/mod.rs b/src/nodes/items/mod.rs index fe33682..0d0cca3 100644 --- a/src/nodes/items/mod.rs +++ b/src/nodes/items/mod.rs @@ -4,7 +4,7 @@ use self::environment::{EnvironmentItem, ITEM_TYPE_INFO_ENVIRONMENT}; use super::fields::Field; use super::spatial::{find_spatial_parent, parse_transform, Spatial}; use super::{Alias, Node}; -use crate::core::client::{Client, INTERNAL_CLIENT}; +use crate::core::client::Client; use crate::core::node_collections::LifeLinkedNodeList; use crate::core::registry::Registry; use crate::nodes::alias::AliasInfo; @@ -80,7 +80,7 @@ impl Item { ) -> Arc { let item = Item { node: Arc::downgrade(node), - uid: nanoid!(), + uid: node.uid.clone(), type_info, captured_acceptor: Default::default(), specialization, @@ -94,11 +94,16 @@ impl Item { let _ = node.item.set(item.clone()); item } - fn make_alias(&self, client: &Arc, parent: &str) -> (Arc, Arc) { - let node = Alias::create( + fn make_alias_named( + &self, + client: &Arc, + parent: &str, + name: &str, + ) -> Option> { + Alias::create( client, parent, - &self.uid, + name, &self.node.upgrade().unwrap(), AliasInfo { local_signals: [ @@ -117,9 +122,10 @@ impl Item { ] .concat(), }, - ); - let alias = node.alias.get().unwrap().clone(); - (node, alias) + ) + } + fn make_alias(&self, client: &Arc, parent: &str) -> Option> { + self.make_alias_named(client, parent, &self.uid) } fn release_flex(node: &Node, _calling_client: Arc, _data: &[u8]) -> Result<()> { @@ -196,8 +202,10 @@ impl ItemUI { let Some(node) = self.node.upgrade() else { return }; let Some(client) = node.get_client() else { return }; - let (alias_node, _) = item.make_alias(&client, &(node.get_path().to_string() + "/item")); - self.aliases.add(Arc::downgrade(&alias_node)); + if let Some(alias_node) = item.make_alias(&client, &(node.get_path().to_string() + "/item")) + { + self.aliases.add(Arc::downgrade(&alias_node)); + } let _ = node.send_remote_signal( "create_item", @@ -231,8 +239,12 @@ impl ItemUI { &client, &format!("/item/{}/acceptor", self.type_info.type_name), ); - self.aliases.add(Arc::downgrade(&alias)); - self.aliases.add(Arc::downgrade(&field_alias)); + if let Some(alias) = alias { + self.aliases.add(Arc::downgrade(&alias)); + } + if let Some(field_alias) = field_alias { + self.aliases.add(Arc::downgrade(&field_alias)); + } let _ = node.send_remote_signal("create_acceptor", &serialize(&acceptor.uid).unwrap()); } fn handle_destroy_acceptor(&self, acceptor: &ItemAcceptor) { @@ -269,7 +281,7 @@ impl ItemAcceptor { } fn capture_flex(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { - let acceptor = node.get_aspect("Item acceptor", "item acceptor", |n| &n.item_acceptor)?; + let acceptor = node.item_acceptor.get().unwrap(); let item_path: &str = deserialize(data)?; let item_node = calling_client.get_node("Item", item_path)?; let item = item_node.get_aspect("Item", "item", |n| &n.item)?; @@ -277,7 +289,12 @@ impl ItemAcceptor { Ok(()) } - fn make_aliases(&self, client: &Arc, parent: &str) -> (Arc, Arc) { + + fn make_aliases( + &self, + client: &Arc, + parent: &str, + ) -> (Option>, Option>) { let acceptor_node = &self.node.upgrade().unwrap(); let acceptor_alias = Alias::create( client, @@ -289,35 +306,41 @@ impl ItemAcceptor { ..Default::default() }, ); - let acceptor_field_alias = Alias::create( - client, - acceptor_alias.get_path(), - "field", - &self.field.spatial_ref().node.upgrade().unwrap(), - AliasInfo::default(), - ); + + let acceptor_field_alias = acceptor_alias.as_ref().and_then(|acceptor_alias| { + Alias::create( + client, + acceptor_alias.get_path(), + "field", + &self.field.spatial_ref().node.upgrade().unwrap(), + AliasInfo::default(), + ) + }); (acceptor_alias, acceptor_field_alias) } - fn send_event(&self, state: &str, name: &str) { + fn handle_capture(&self, item: &Arc) { + self.accepted.add_raw(item); + let _ = self.node.upgrade().unwrap().send_remote_signal( + "capture", + &item.specialization.serialize_start_data(&item.uid), + ); + } + fn handle_release(&self, item: &Item) { + self.accepted.remove(item); let _ = self .node .upgrade() .unwrap() - .send_remote_signal(state, flexbuffers::singleton(name).as_slice()); - } - fn handle_capture(&self, item: &Arc) { - self.accepted.add_raw(item); - self.send_event("capture", item.uid.as_str()); - } - fn handle_release(&self, item: &Item) { - self.accepted.remove(item); - self.send_event("release", item.uid.as_str()); + .send_remote_signal("release", &serialize(&item.uid).unwrap()); } } impl Drop for ItemAcceptor { fn drop(&mut self) { self.type_info.acceptors.remove(self); + for accepted in self.accepted.get_valid_contents() { + release(&accepted); + } if let Some(ui) = self.type_info.ui.lock().upgrade() { ui.handle_destroy_acceptor(self); } @@ -372,7 +395,7 @@ fn create_item_acceptor_flex(_node: &Node, calling_client: Arc, data: &[ let type_info = type_info(info.item_type)?; let node = Node::create( - &INTERNAL_CLIENT, + &calling_client, &format!("/item/{}/acceptor", type_info.type_name), info.name, true, diff --git a/src/nodes/spatial/zone.rs b/src/nodes/spatial/zone.rs index 0b1bc92..3e807f1 100644 --- a/src/nodes/spatial/zone.rs +++ b/src/nodes/spatial/zone.rs @@ -68,84 +68,75 @@ impl Zone { } fn capture_flex(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { let zone = node.zone.get().unwrap(); - let capture_uid: &str = deserialize(data)?; - let capture_path = node.path.clone() + "/" + capture_uid; - let spatial = find_spatial(&calling_client, "Spatial", &capture_path)?; + let capture_path: &str = deserialize(data)?; + let spatial = find_spatial(&calling_client, "Spatial", capture_path)?; capture(&spatial, zone); Ok(()) } - fn release_flex(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { - let capture_uid: &str = deserialize(data)?; - let capture_path = node.path.clone() + "/" + capture_uid; - let spatial = find_spatial(&calling_client, "Spatial", &capture_path)?; + fn release_flex(_node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { + let capture_path: &str = deserialize(data)?; + let spatial = find_spatial(&calling_client, "Spatial", capture_path)?; release(&spatial); Ok(()) } fn update(node: &Node, _calling_client: Arc, _data: &[u8]) -> Result<()> { let zone = node.zone.get().unwrap(); - if let Some(field) = zone.field.upgrade() { - if let Some((zone_client, zone_node)) = zone - .spatial - .node - .upgrade() - .and_then(|n| n.get_client().zip(Some(n))) - { - let mut old_zoneables = zone.zoneables.lock(); - for (_uid, zoneable) in old_zoneables.iter() { - zoneable.destroy(); - } - let captured = zone.captured.get_valid_contents(); - let zoneables = ZONEABLE_REGISTRY - .get_valid_contents() - .into_iter() - .filter(|zoneable| zoneable.node.upgrade().is_some()) - .filter(|zoneable| { - if captured - .iter() - .any(|captured| Arc::ptr_eq(captured, zoneable)) - { - return true; - } - let spatial_zone_distance = zoneable.zone_distance(); - let self_zone_distance = field.distance(zoneable, vec3a(0.0, 0.0, 0.0)); - self_zone_distance < 0.0 && spatial_zone_distance > self_zone_distance - }) - .map(|zoneable| { - let alias = Alias::create( - &zone_client, - zone_node.get_path(), - &zoneable.uid, - &zoneable.node.upgrade().unwrap(), - AliasInfo { - local_signals: vec![ - "set_transform", - "set_spatial_parent", - "set_spatial_parent_in_place", - ], - local_methods: vec!["get_transform"], - ..Default::default() - }, - ); - (zoneable.uid.clone(), alias) - }) - .collect::>>(); - - for entered_uid in zoneables.keys().filter(|k| !old_zoneables.contains_key(*k)) { - node.send_remote_signal("enter", &serialize(entered_uid)?)?; - } - for left_uid in old_zoneables.keys().filter(|k| !zoneables.contains_key(*k)) { - node.send_remote_signal("leave", &serialize(left_uid)?)?; - } - - *old_zoneables = zoneables; - - Ok(()) - } else { - Err(anyhow::anyhow!("No client on node?")) - } - } else { - Err(anyhow::anyhow!("Zone's field has been destroyed")) + let Some(field) = zone.field.upgrade() else { return Err(anyhow::anyhow!("Zone's field has been destroyed")) }; + let Some((zone_client, zone_node)) = zone + .spatial + .node + .upgrade() + .and_then(|n| n.get_client().zip(Some(n))) else { return Err(anyhow::anyhow!("No client on node?")) }; + let mut old_zoneables = zone.zoneables.lock(); + for (_uid, zoneable) in old_zoneables.iter() { + zoneable.destroy(); } + let captured = zone.captured.get_valid_contents(); + let zoneables = ZONEABLE_REGISTRY + .get_valid_contents() + .into_iter() + .filter(|zoneable| zoneable.node.upgrade().is_some()) + .filter(|zoneable| { + if captured + .iter() + .any(|captured| Arc::ptr_eq(captured, zoneable)) + { + return true; + } + let spatial_zone_distance = zoneable.zone_distance(); + let self_zone_distance = field.distance(zoneable, vec3a(0.0, 0.0, 0.0)); + self_zone_distance < 0.0 && spatial_zone_distance > self_zone_distance + }) + .filter_map(|zoneable| { + let alias = Alias::create( + &zone_client, + zone_node.get_path(), + &zoneable.uid, + &zoneable.node.upgrade().unwrap(), + AliasInfo { + local_signals: vec![ + "set_transform", + "set_spatial_parent", + "set_spatial_parent_in_place", + ], + local_methods: vec!["get_transform"], + ..Default::default() + }, + )?; + Some((zoneable.uid.clone(), alias)) + }) + .collect::>>(); + + for entered_uid in zoneables.keys().filter(|k| !old_zoneables.contains_key(*k)) { + node.send_remote_signal("enter", &serialize(entered_uid)?)?; + } + for left_uid in old_zoneables.keys().filter(|k| !zoneables.contains_key(*k)) { + node.send_remote_signal("leave", &serialize(left_uid)?)?; + } + + *old_zoneables = zoneables; + + Ok(()) } } impl Drop for Zone {