diff --git a/src/main.rs b/src/main.rs index 39563cb..665a36e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,14 +124,20 @@ fn main() -> Result<()> { } let mouse_pointer = cli_args.flatscreen.then(MousePointer::new).transpose()?; - let mut hands = - (!cli_args.flatscreen).then(|| (SkHand::new(Handed::Left), SkHand::new(Handed::Right))); - let mut controllers = (!cli_args.flatscreen && !cli_args.disable_controller).then(|| { - ( - SkController::new(Handed::Left), - SkController::new(Handed::Right), - ) - }); + let mut hands = (!cli_args.flatscreen) + .then(|| { + let left = SkHand::new(Handed::Left).ok(); + let right = SkHand::new(Handed::Right).ok(); + left.zip(right) + }) + .flatten(); + let mut controllers = (!cli_args.flatscreen && !cli_args.disable_controller) + .then(|| { + let left = SkController::new(Handed::Left).ok(); + let right = SkController::new(Handed::Right).ok(); + left.zip(right) + }) + .flatten(); if hands.is_none() { unsafe { diff --git a/src/nodes/input/mod.rs b/src/nodes/input/mod.rs index 0be6497..5edf9b1 100644 --- a/src/nodes/input/mod.rs +++ b/src/nodes/input/mod.rs @@ -11,12 +11,11 @@ use super::{ spatial::{find_spatial_parent, parse_transform, Spatial}, Node, }; -use crate::core::eventloop::FRAME; use crate::core::registry::Registry; use crate::core::{client::Client, task}; +use crate::core::{eventloop::FRAME, node_collections::LifeLinkedNodeMap}; use color_eyre::eyre::{ensure, Result}; use glam::Mat4; -use nanoid::nanoid; use parking_lot::Mutex; use portable_atomic::AtomicBool; use serde::Deserialize; @@ -60,6 +59,7 @@ impl Deref for InputType { } pub struct InputMethod { + node: Weak, pub uid: String, pub enabled: Mutex, pub spatial: Arc, @@ -68,17 +68,6 @@ pub struct InputMethod { pub datamap: Mutex>, } impl InputMethod { - pub fn new(spatial: Arc, specialization: InputType) -> Arc { - let method = InputMethod { - uid: nanoid!(), - enabled: Mutex::new(true), - spatial, - specialization: Mutex::new(specialization), - captures: Registry::new(), - datamap: Mutex::new(None), - }; - INPUT_METHOD_REGISTRY.add(method) - } #[allow(dead_code)] pub fn add_to( node: &Arc, @@ -93,6 +82,7 @@ impl InputMethod { node.add_local_signal("set_datamap", InputMethod::set_datamap); let method = InputMethod { + node: Arc::downgrade(node), uid: node.uid.clone(), enabled: Mutex::new(true), spatial: node.spatial.get().unwrap().clone(), @@ -134,17 +124,14 @@ pub struct DistanceLink { pub distance: f32, pub method: Arc, pub handler: Arc, - pub handler_field: Arc, } impl DistanceLink { - fn from(method: Arc, handler: Arc) -> Option { - let handler_field = handler.field.upgrade()?; - Some(DistanceLink { - distance: method.compare_distance(&handler_field), + fn from(method: Arc, handler: Arc) -> Self { + DistanceLink { + distance: method.compare_distance(&handler.field), method, handler, - handler_field, - }) + } } fn send_input(&self, frame: u64, datamap: Datamap) { @@ -160,9 +147,7 @@ impl DistanceLink { let root = InputData { uid: self.method.uid.clone(), input, - distance: self - .method - .true_distance(&self.handler.field.upgrade().unwrap()), + distance: self.method.true_distance(&self.handler.field), datamap, }; root.serialize() @@ -173,7 +158,8 @@ pub struct InputHandler { enabled: Arc, node: Weak, spatial: Arc, - pub field: Weak, + pub field: Arc, + method_aliases: LifeLinkedNodeMap, } impl InputHandler { pub fn add_to(node: &Arc, field: &Arc) -> Result<()> { @@ -186,7 +172,8 @@ impl InputHandler { enabled: node.enabled.clone(), node: Arc::downgrade(node), spatial: node.spatial.get().unwrap().clone(), - field: Arc::downgrade(field), + field: field.clone(), + method_aliases: LifeLinkedNodeMap::default(), }; let handler = INPUT_HANDLER_REGISTRY.add(handler); let _ = node.input_handler.set(handler); @@ -275,8 +262,7 @@ pub fn process_input() { let handlers = INPUT_HANDLER_REGISTRY .get_valid_contents() .into_iter() - .filter(|handler| handler.enabled.load(Ordering::Relaxed)) - .filter(|handler| handler.field.upgrade().is_some()); + .filter(|handler| handler.enabled.load(Ordering::Relaxed)); for method in methods { debug_span!("Process input method").in_scope(|| { // Get all valid input handlers and convert them to DistanceLink objects @@ -284,7 +270,7 @@ pub fn process_input() { .in_scope(|| { handlers .clone() - .filter_map(|handler| DistanceLink::from(method.clone(), handler)) + .map(|handler| DistanceLink::from(method.clone(), handler)) .collect() }); diff --git a/src/nodes/input/pointer.rs b/src/nodes/input/pointer.rs index 54d9515..1827741 100644 --- a/src/nodes/input/pointer.rs +++ b/src/nodes/input/pointer.rs @@ -41,10 +41,7 @@ impl InputSpecialization for Pointer { ) -> InputDataType { let (_, orientation, origin) = local_to_handler_matrix.to_scale_rotation_translation(); let direction = local_to_handler_matrix.transform_vector3(vec3(0_f32, 0_f32, 1_f32)); - let ray_march = self.ray_march( - &distance_link.method.spatial, - &distance_link.handler.field.upgrade().unwrap(), - ); + let ray_march = self.ray_march(&distance_link.method.spatial, &distance_link.handler.field); let deepest_point = (direction * ray_march.deepest_point_distance) + origin; InputDataType::Pointer(FlatPointer { diff --git a/src/objects/input/sk_controller.rs b/src/objects/input/sk_controller.rs index fd9db74..b3dc9d5 100644 --- a/src/objects/input/sk_controller.rs +++ b/src/objects/input/sk_controller.rs @@ -1,36 +1,45 @@ -use crate::nodes::{ - input::{tip::Tip, InputMethod, InputType}, - spatial::Spatial, +use crate::{ + core::client::INTERNAL_CLIENT, + nodes::{ + input::{tip::Tip, InputMethod, InputType}, + spatial::Spatial, + Node, + }, }; +use color_eyre::eyre::Result; use glam::Mat4; +use nanoid::nanoid; use stardust_xr::{ schemas::{flat::Datamap, flex::flexbuffers}, values::Transform, }; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use stereokit::input::{ButtonState, Handed, StereoKitInput}; use tracing::instrument; pub struct SkController { - tip: Arc, + _node: Arc, + input: Arc, handed: Handed, } impl SkController { - pub fn new(handed: Handed) -> Self { - SkController { - tip: InputMethod::new( - Spatial::new(Weak::new(), None, Mat4::IDENTITY), - InputType::Tip(Tip::default()), - ), + pub fn new(handed: Handed) -> Result { + let _node = Node::create(&INTERNAL_CLIENT, "", &nanoid!(), false).add_to_scenegraph()?; + Spatial::add_to(&_node, None, Mat4::IDENTITY, false)?; + let tip = InputType::Tip(Tip::default()); + let input = InputMethod::add_to(&_node, tip, None)?; + Ok(SkController { + _node, + input, handed, - } + }) } #[instrument(level = "debug", name = "Update StereoKit Tip Input Method", skip_all)] pub fn update(&mut self, sk: &impl StereoKitInput) { let controller = sk.input_controller(self.handed); - *self.tip.enabled.lock() = controller.tracked.contains(ButtonState::Active); - if *self.tip.enabled.lock() { - self.tip.spatial.set_local_transform_components( + *self.input.enabled.lock() = controller.tracked.contains(ButtonState::Active); + if *self.input.enabled.lock() { + self.input.spatial.set_local_transform_components( None, Transform::from_position_rotation( controller.pose.position, @@ -43,6 +52,6 @@ impl SkController { map.push("select", controller.trigger); map.push("grab", controller.grip); map.end_map(); - *self.tip.datamap.lock() = Datamap::new(fbb.take_buffer()).ok(); + *self.input.datamap.lock() = Datamap::new(fbb.take_buffer()).ok(); } } diff --git a/src/objects/input/sk_hand.rs b/src/objects/input/sk_hand.rs index 57652be..fcb98d7 100644 --- a/src/objects/input/sk_hand.rs +++ b/src/objects/input/sk_hand.rs @@ -1,13 +1,19 @@ -use crate::nodes::{ - input::{hand::Hand, InputMethod, InputType}, - spatial::Spatial, +use crate::{ + core::client::INTERNAL_CLIENT, + nodes::{ + input::{hand::Hand, InputMethod, InputType}, + spatial::Spatial, + Node, + }, }; +use color_eyre::eyre::Result; use glam::Mat4; +use nanoid::nanoid; use stardust_xr::schemas::{ flat::{Datamap, Hand as FlatHand, Joint}, flex::flexbuffers, }; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use stereokit::{ input::{ButtonState, Handed, Joint as SkJoint, StereoKitInput}, lifecycle::StereoKitDraw, @@ -23,32 +29,35 @@ fn convert_joint(joint: SkJoint) -> Joint { } pub struct SkHand { - hand: Arc, + _node: Arc, + input: Arc, handed: Handed, } impl SkHand { - pub fn new(handed: Handed) -> Self { - SkHand { - hand: InputMethod::new( - Spatial::new(Weak::new(), None, Mat4::IDENTITY), - InputType::Hand(Box::new(Hand { - base: FlatHand { - right: handed == Handed::Right, - ..Default::default() - }, - })), - ), + pub fn new(handed: Handed) -> Result { + let _node = Node::create(&INTERNAL_CLIENT, "", &nanoid!(), false).add_to_scenegraph()?; + Spatial::add_to(&_node, None, Mat4::IDENTITY, false)?; + let hand = InputType::Hand(Box::new(Hand { + base: FlatHand { + right: handed == Handed::Right, + ..Default::default() + }, + })); + let input = InputMethod::add_to(&_node, hand, None)?; + Ok(SkHand { + _node, + input, handed, - } + }) } #[instrument(level = "debug", name = "Update Hand Input Method", skip_all)] pub fn update(&mut self, sk: &StereoKitDraw) { let sk_hand = sk.input_hand(self.handed); - if let InputType::Hand(hand) = &mut *self.hand.specialization.lock() { + if let InputType::Hand(hand) = &mut *self.input.specialization.lock() { let controller = sk.input_controller(self.handed); - *self.hand.enabled.lock() = controller.tracked.contains(ButtonState::Inactive) + *self.input.enabled.lock() = controller.tracked.contains(ButtonState::Inactive) && sk_hand.tracked_state.contains(ButtonState::Active); - if *self.hand.enabled.lock() { + if *self.input.enabled.lock() { hand.base.thumb.tip = convert_joint(sk_hand.fingers[0][4]); hand.base.thumb.distal = convert_joint(sk_hand.fingers[0][3]); hand.base.thumb.proximal = convert_joint(sk_hand.fingers[0][2]); @@ -85,6 +94,6 @@ impl SkHand { map.push("grab_strength", sk_hand.grip_activation); map.push("pinch_strength", sk_hand.pinch_activation); map.end_map(); - *self.hand.datamap.lock() = Datamap::new(fbb.take_buffer()).ok(); + *self.input.datamap.lock() = Datamap::new(fbb.take_buffer()).ok(); } }