From ae40158decf7602dd68d01608a7002a4c65012f1 Mon Sep 17 00:00:00 2001 From: Nova Date: Thu, 18 Jul 2024 09:19:06 -0400 Subject: [PATCH] feat(objects): controllers --- src/objects/input/sk_controller.rs | 20 ++++-- src/objects/mod.rs | 107 ++++++++++++++++++----------- 2 files changed, 81 insertions(+), 46 deletions(-) diff --git a/src/objects/input/sk_controller.rs b/src/objects/input/sk_controller.rs index 8912d48..ee64ca7 100644 --- a/src/objects/input/sk_controller.rs +++ b/src/objects/input/sk_controller.rs @@ -6,6 +6,7 @@ use crate::{ spatial::Spatial, Node, OwnedNode, }, + objects::{ObjectHandle, SpatialRef}, }; use color_eyre::eyre::Result; use glam::{Mat4, Vec2, Vec3}; @@ -19,6 +20,7 @@ use stereokit_rust::{ system::{Handed, Input}, util::Color128, }; +use zbus::Connection; #[derive(Default, Deserialize, Serialize)] struct ControllerDatamap { @@ -28,7 +30,7 @@ struct ControllerDatamap { } pub struct SkController { - _node: OwnedNode, + object_handle: ObjectHandle, input: Arc, handed: Handed, model: Model, @@ -37,9 +39,15 @@ pub struct SkController { datamap: ControllerDatamap, } impl SkController { - pub fn new(handed: Handed) -> Result { - let _node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph_owned()?; - Spatial::add_to(&_node.0, None, Mat4::IDENTITY, false); + pub fn new(connection: &Connection, handed: Handed) -> Result { + let (spatial, object_handle) = SpatialRef::create( + connection, + &("/org/stardustxr/Controller/".to_string() + + match handed { + Handed::Left => "left", + _ => "right", + }), + ); let model = Model::copy(Model::from_memory( "cursor.glb", include_bytes!("cursor.glb"), @@ -51,12 +59,12 @@ impl SkController { model_node.material(&material); let tip = InputDataType::Tip(Tip::default()); let input = InputMethod::add_to( - &_node.0, + &spatial.node().unwrap(), tip, Datamap::from_typed(ControllerDatamap::default())?, )?; Ok(SkController { - _node, + object_handle, input, handed, model, diff --git a/src/objects/mod.rs b/src/objects/mod.rs index f6980ee..77e08d9 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -5,7 +5,7 @@ use crate::{ nodes::{ fields::{Field, Shape, EXPORTED_FIELDS}, spatial::{Spatial, EXPORTED_SPATIALS}, - Node, + Node, OwnedNode, }, }; use glam::{vec3, Mat4}; @@ -14,14 +14,13 @@ use input::{ sk_hand::SkHand, }; use play_space::PlaySpaceBounds; -use std::sync::Arc; +use std::{marker::PhantomData, sync::Arc}; use stereokit_rust::{ sk::{DisplayMode, MainThreadToken, Sk}, system::{Handed, Input, Key, World}, util::Device, }; -use tokio::task::AbortHandle; -use zbus::{interface, Connection}; +use zbus::{interface, object_server::Interface, zvariant::OwnedObjectPath, Connection}; pub mod input; pub mod play_space; @@ -44,8 +43,8 @@ enum Inputs { pub struct ServerObjects { connection: Connection, - hmd: (Arc, AbortHandle), - play_space: Option<(Arc, AbortHandle)>, + hmd: (Arc, ObjectHandle), + play_space: Option<(Arc, ObjectHandle)>, inputs: Inputs, } impl ServerObjects { @@ -68,9 +67,18 @@ impl ServerObjects { } let inputs = if sk.get_active_display_mode() == DisplayMode::MixedReality { + tokio::task::spawn({ + let connection = connection.clone(); + async move { + connection + .request_name("org.stardustxr.Controllers") + .await + .unwrap(); + } + }); Inputs::XR { - controller_left: SkController::new(Handed::Left).unwrap(), - controller_right: SkController::new(Handed::Right).unwrap(), + controller_left: SkController::new(&connection, Handed::Left).unwrap(), + controller_right: SkController::new(&connection, Handed::Right).unwrap(), hand_left: SkHand::new(Handed::Left).unwrap(), hand_right: SkHand::new(Handed::Right).unwrap(), eye_pointer: Device::has_eye_gaze() @@ -156,35 +164,44 @@ impl ServerObjects { } } } -impl Drop for ServerObjects { + +pub struct ObjectHandle(Connection, OwnedObjectPath, PhantomData); +impl Drop for ObjectHandle { fn drop(&mut self) { - self.hmd.1.abort(); - if let Some((_, play_space)) = self.play_space.take() { - play_space.abort(); - } + let connection = self.0.clone(); + let object_path = self.1.clone(); + tokio::task::spawn(async move { + connection.object_server().remove::(object_path); + }); } } -pub struct SpatialRef(u64); +pub struct SpatialRef(u64, OwnedNode); impl SpatialRef { - pub fn create(connection: &Connection, path: &str) -> (Arc, AbortHandle) { - let node = Arc::new(Node::generate(&INTERNAL_CLIENT, false)); - let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false); + pub fn create(connection: &Connection, path: &str) -> (Arc, ObjectHandle) { + let node = OwnedNode(Arc::new(Node::generate(&INTERNAL_CLIENT, false))); + let spatial = Spatial::add_to(&node.0, None, Mat4::IDENTITY, false); let uid: u64 = rand::random(); - EXPORTED_SPATIALS.lock().insert(uid, node.clone()); + EXPORTED_SPATIALS.lock().insert(uid, node.0.clone()); - let connection = connection.clone(); - let path = path.to_string(); - ( - spatial, - tokio::task::spawn(async move { + tokio::task::spawn({ + let connection = connection.clone(); + let path = path.to_string(); + async move { connection .object_server() - .at(path, Self(uid)) + .at(path, Self(uid, node)) .await .unwrap(); - }) - .abort_handle(), + } + }); + ( + spatial, + ObjectHandle( + connection.clone(), + OwnedObjectPath::try_from(path.to_string()).unwrap(), + PhantomData, + ), ) } } @@ -196,27 +213,37 @@ impl SpatialRef { } } -pub struct FieldRef(u64); +pub struct FieldRef(u64, OwnedNode); impl FieldRef { - pub fn create(connection: &Connection, path: &str, shape: Shape) -> (Arc, AbortHandle) { - let node = Arc::new(Node::generate(&INTERNAL_CLIENT, false)); - Spatial::add_to(&node, None, Mat4::IDENTITY, false); - let field = Field::add_to(&node, shape).unwrap(); + pub fn create( + connection: &Connection, + path: &str, + shape: Shape, + ) -> (Arc, ObjectHandle) { + let node = OwnedNode(Arc::new(Node::generate(&INTERNAL_CLIENT, false))); + Spatial::add_to(&node.0, None, Mat4::IDENTITY, false); + let field = Field::add_to(&node.0, shape).unwrap(); let uid: u64 = rand::random(); - EXPORTED_FIELDS.lock().insert(uid, node.clone()); + EXPORTED_FIELDS.lock().insert(uid, node.0.clone()); - let connection = connection.clone(); - let path = path.to_string(); - ( - field, - tokio::task::spawn(async move { + tokio::task::spawn({ + let connection = connection.clone(); + let path = path.to_string(); + async move { connection .object_server() - .at(path, Self(uid)) + .at(path, Self(uid, node)) .await .unwrap(); - }) - .abort_handle(), + } + }); + ( + field, + ObjectHandle( + connection.clone(), + OwnedObjectPath::try_from(path.to_string()).unwrap(), + PhantomData, + ), ) } }