From be41f11b83b828cff64c8016f95a4f6bfb34b4cb Mon Sep 17 00:00:00 2001 From: Nova Date: Sat, 25 Feb 2023 16:39:30 -0500 Subject: [PATCH] feat(input): new system --- src/core/node_collections.rs | 48 ++++++++-------- src/nodes/input/mod.rs | 106 +++++++++++++++++------------------ src/nodes/mod.rs | 27 +++++---- 3 files changed, 88 insertions(+), 93 deletions(-) diff --git a/src/core/node_collections.rs b/src/core/node_collections.rs index 2253ab7..95f04e2 100644 --- a/src/core/node_collections.rs +++ b/src/core/node_collections.rs @@ -6,31 +6,31 @@ use std::{ sync::{Arc, Weak}, }; -// #[derive(Default)] -// pub struct LifeLinkedNodeList { -// nodes: Mutex>>, -// } -// impl LifeLinkedNodeList { -// pub fn add(&self, node: Weak) { -// self.nodes.lock().push(node); -// } +#[derive(Default)] +pub struct LifeLinkedNodeList { + nodes: Mutex>>, +} +impl LifeLinkedNodeList { + pub fn add(&self, node: Weak) { + self.nodes.lock().push(node); + } -// pub fn clear(&self) { -// self.nodes -// .lock() -// .iter() -// .filter_map(|node| node.upgrade()) -// .for_each(|node| { -// node.destroy(); -// }); -// self.nodes.lock().clear(); -// } -// } -// impl Drop for LifeLinkedNodeList { -// fn drop(&mut self) { -// self.clear(); -// } -// } + pub fn clear(&self) { + self.nodes + .lock() + .iter() + .filter_map(|node| node.upgrade()) + .for_each(|node| { + node.destroy(); + }); + self.nodes.lock().clear(); + } +} +impl Drop for LifeLinkedNodeList { + fn drop(&mut self) { + self.clear(); + } +} #[derive(Default)] pub struct LifeLinkedNodeMap { diff --git a/src/nodes/input/mod.rs b/src/nodes/input/mod.rs index 5edf9b1..25ce373 100644 --- a/src/nodes/input/mod.rs +++ b/src/nodes/input/mod.rs @@ -7,23 +7,21 @@ use self::pointer::Pointer; use self::tip::Tip; use super::{ + alias::{Alias, AliasInfo}, fields::{find_field, Field}, spatial::{find_spatial_parent, parse_transform, Spatial}, Node, }; -use crate::core::registry::Registry; -use crate::core::{client::Client, task}; -use crate::core::{eventloop::FRAME, node_collections::LifeLinkedNodeMap}; +use crate::core::client::Client; +use crate::core::eventloop::FRAME; +use crate::core::{node_collections::LifeLinkedNodeList, registry::Registry}; use color_eyre::eyre::{ensure, Result}; use glam::Mat4; use parking_lot::Mutex; use portable_atomic::AtomicBool; use serde::Deserialize; +use stardust_xr::schemas::flat::{Datamap, InputDataType}; use stardust_xr::schemas::{flat::InputData, flex::deserialize}; -use stardust_xr::schemas::{ - flat::{Datamap, InputDataType}, - flex::flexbuffers, -}; use stardust_xr::values::Transform; use std::ops::Deref; use std::sync::atomic::Ordering; @@ -60,11 +58,11 @@ impl Deref for InputType { pub struct InputMethod { node: Weak, - pub uid: String, + uid: String, pub enabled: Mutex, pub spatial: Arc, pub specialization: Mutex, - pub captures: Registry, + captures: Registry, pub datamap: Mutex>, } impl InputMethod { @@ -79,7 +77,8 @@ impl InputMethod { "Internal: Node does not have a spatial attached!" ); - node.add_local_signal("set_datamap", InputMethod::set_datamap); + node.add_local_signal("capture", InputMethod::capture_flex); + node.add_local_signal("set_datamap", InputMethod::set_datamap_flex); let method = InputMethod { node: Arc::downgrade(node), @@ -95,13 +94,18 @@ impl InputMethod { Ok(method) } - fn set_datamap(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { - node.input_method - .get() - .unwrap() - .datamap - .lock() - .replace(Datamap::new(data.to_vec())?); + fn capture_flex(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { + let method = node.get_aspect("Input Method", "input method", |n| &n.input_method)?; + let handler_node = calling_client.get_node("Input Handler", deserialize(data)?)?; + let handler = + handler_node.get_aspect("Input Handler", "input handler", |n| &n.input_handler)?; + + method.captures.add_raw(&handler); + Ok(()) + } + fn set_datamap_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + let method = node.get_aspect("Input Method", "input method", |n| &n.input_method)?; + method.datamap.lock().replace(Datamap::new(data.to_vec())?); Ok(()) } @@ -121,17 +125,30 @@ impl Drop for InputMethod { } pub struct DistanceLink { - pub distance: f32, - pub method: Arc, - pub handler: Arc, + distance: f32, + method: Arc, + handler: Arc, } impl DistanceLink { - fn from(method: Arc, handler: Arc) -> Self { - DistanceLink { + fn from(method: Arc, handler: Arc) -> Option { + let handler_node = handler.node.upgrade()?; + let method_alias = Alias::create( + &handler_node.get_client()?, + handler_node.get_path(), + &method.uid, + &method.node.upgrade()?, + AliasInfo { + local_signals: vec!["capture"], + ..Default::default() + }, + ) + .ok()?; + handler.method_aliases.add(Arc::downgrade(&method_alias)); + Some(DistanceLink { distance: method.compare_distance(&handler.field), method, handler, - } + }) } fn send_input(&self, frame: u64, datamap: Datamap) { @@ -158,8 +175,8 @@ pub struct InputHandler { enabled: Arc, node: Weak, spatial: Arc, - pub field: Arc, - method_aliases: LifeLinkedNodeMap, + field: Arc, + method_aliases: LifeLinkedNodeList, } impl InputHandler { pub fn add_to(node: &Arc, field: &Arc) -> Result<()> { @@ -173,7 +190,7 @@ impl InputHandler { node: Arc::downgrade(node), spatial: node.spatial.get().unwrap().clone(), field: field.clone(), - method_aliases: LifeLinkedNodeMap::default(), + method_aliases: LifeLinkedNodeList::default(), }; let handler = INPUT_HANDLER_REGISTRY.add(handler); let _ = node.input_handler.set(handler); @@ -182,30 +199,8 @@ impl InputHandler { #[instrument(level = "debug", skip(self, distance_link))] fn send_input(&self, frame: u64, distance_link: &DistanceLink, datamap: Datamap) { - let data = distance_link.serialize(datamap); let Some(node) = self.node.upgrade() else {return}; - let method = Arc::downgrade(&distance_link.method); - let handler = Arc::downgrade(&distance_link.handler); - - if let Ok(data) = node.execute_remote_method("input", data) { - let _ = task::new(|| "input capture", async move { - if let Ok(data) = data.await { - if frame == FRAME.load(Ordering::Relaxed) { - let capture = flexbuffers::Reader::get_root(data.as_slice()) - .and_then(|data| data.get_bool()) - .unwrap_or(false); - - if capture { - if let Some(method) = method.upgrade() { - if let Some(handler) = handler.upgrade() { - method.captures.add_raw(&handler); - } - } - } - } - } - }); - } + let _ = node.send_remote_signal("input", &distance_link.serialize(datamap)); } } impl PartialEq for InputHandler { @@ -259,18 +254,19 @@ pub fn process_input() { .filter(|method| *method.enabled.lock()) .filter(|method| method.datamap.lock().is_some()) }); - let handlers = INPUT_HANDLER_REGISTRY - .get_valid_contents() - .into_iter() - .filter(|handler| handler.enabled.load(Ordering::Relaxed)); + let handlers = INPUT_HANDLER_REGISTRY.get_valid_contents(); + for handler in &handlers { + handler.method_aliases.clear(); + } for method in methods { debug_span!("Process input method").in_scope(|| { // Get all valid input handlers and convert them to DistanceLink objects let mut distance_links: Vec = debug_span!("Generate distance links") .in_scope(|| { handlers - .clone() - .map(|handler| DistanceLink::from(method.clone(), handler)) + .iter() + .filter(|handler| handler.enabled.load(Ordering::Relaxed)) + .filter_map(|handler| DistanceLink::from(method.clone(), handler.clone())) .collect() }); diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index ec0cc7c..2a8bfd9 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -22,7 +22,6 @@ use stardust_xr::messenger::MessageSenderHandle; use stardust_xr::scenegraph::ScenegraphError; use stardust_xr::schemas::flex::deserialize; use std::fmt::Debug; -use std::future::Future; use std::sync::{Arc, Weak}; use std::vec::Vec; use tracing::{debug_span, instrument}; @@ -249,21 +248,21 @@ impl Node { .transpose()?; Ok(()) } - #[instrument(level = "debug", skip_all)] - pub fn execute_remote_method( - &self, - method: &str, - data: Vec, - ) -> Result>>> { - let message_sender_handle = self - .message_sender_handle - .as_ref() - .ok_or(eyre!("Messenger does not exist for this node"))?; + // #[instrument(level = "debug", skip_all)] + // pub fn execute_remote_method( + // &self, + // method: &str, + // data: Vec, + // ) -> Result>>> { + // let message_sender_handle = self + // .message_sender_handle + // .as_ref() + // .ok_or(eyre!("Messenger does not exist for this node"))?; - let future = message_sender_handle.method(self.path.as_str(), method, &data)?; + // let future = message_sender_handle.method(self.path.as_str(), method, &data)?; - Ok(async { future.await.map_err(|e| eyre!(e)) }) - } + // Ok(async { future.await.map_err(|e| eyre!(e)) }) + // } } impl Debug for Node { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {