Tracking Dbus interface #38

Merged
Schmarni-Dev merged 2 commits from tracking_state into dev 2025-02-24 19:00:26 -05:00
3 changed files with 95 additions and 13 deletions

View File

@@ -7,7 +7,7 @@ use crate::{
input::{INPUT_HANDLER_REGISTRY, InputDataType, InputHandler, InputMethod, Tip},
spatial::Spatial,
},
objects::{ObjectHandle, SpatialRef},
objects::{ObjectHandle, SpatialRef, Tracked},
};
use color_eyre::eyre::Result;
use glam::{Mat4, Vec2, Vec3};
@@ -40,18 +40,18 @@ pub struct SkController {
material: Material,
capture_manager: CaptureManager,
datamap: ControllerDatamap,
tracked: ObjectHandle<Tracked>,
}
impl SkController {
pub fn new(connection: &Connection, handed: Handed) -> Result<Self> {
Input::set_controller_model(handed, Some(Model::new()));
let (spatial, object_handle) = SpatialRef::create(
connection,
&("/org/stardustxr/Controller/".to_string()
+ match handed {
Handed::Left => "left",
_ => "right",
}),
);
let path = "/org/stardustxr/Controller/".to_string()
+ match handed {
Handed::Left => "left",
_ => "right",
};
let (spatial, object_handle) = SpatialRef::create(connection, &path);
let tracked = Tracked::new(connection, &path);
let model = Model::copy(&Model::from_memory(
"cursor.glb",
include_bytes!("cursor.glb"),
@@ -75,13 +75,22 @@ impl SkController {
material,
capture_manager: CaptureManager::default(),
datamap: Default::default(),
tracked,
})
}
pub fn update(&mut self, token: &MainThreadToken) {
let controller = Input::controller(self.handed);
let input_node = self.input.spatial.node().unwrap();
input_node.set_enabled(controller.tracked.is_active());
if input_node.enabled() {
let enabled = input_node.enabled();
tokio::spawn({
// this is suboptimal since it probably allocates a fresh string every frame
let handle = self.tracked.clone();
async move {
handle.set_tracked(enabled).await;
}
});
if enabled {
let world_transform = Mat4::from_rotation_translation(
controller.aim.orientation.into(),
controller.aim.position.into(),

View File

@@ -7,7 +7,7 @@ use crate::nodes::{
input::{Hand, InputMethod, Joint},
spatial::Spatial,
};
use crate::objects::{ObjectHandle, SpatialRef};
use crate::objects::{ObjectHandle, SpatialRef, Tracked};
use color_eyre::eyre::Result;
use glam::{Mat4, Quat, Vec3};
use serde::{Deserialize, Serialize};
@@ -44,6 +44,7 @@ pub struct SkHand {
input: Arc<InputMethod>,
capture_manager: CaptureManager,
datamap: HandDatamap,
tracked: ObjectHandle<Tracked>,
}
impl SkHand {
pub fn new(connection: &Connection, handed: Handed) -> Result<Self> {
@@ -55,6 +56,14 @@ impl SkHand {
_ => "right",
} + "/palm"),
);
let tracked = Tracked::new(
connection,
&("/org/stardustxr/Hand/".to_string()
+ match handed {
Handed::Left => "left",
_ => "right",
}),
);
let _node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph_owned()?;
Spatial::add_to(&_node.0, None, Mat4::IDENTITY, false);
let hand = InputDataType::Hand(Hand {
@@ -71,6 +80,7 @@ impl SkHand {
palm_object,
handed,
input,
tracked,
capture_manager: CaptureManager::default(),
datamap: Default::default(),
})
@@ -84,7 +94,15 @@ impl SkHand {
(real_hand || sk.get_active_display_mode() == DisplayMode::Flatscreen)
&& sk_hand.tracked.is_active(),
);
if input_node.enabled() {
let enabled = input_node.enabled();
tokio::spawn({
// this is suboptimal since it probably allocates a fresh string every frame
let handle = self.tracked.clone();
async move {
handle.set_tracked(enabled).await;
}
});
if 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]);

View File

@@ -15,7 +15,10 @@ use input::{
};
use play_space::PlaySpaceBounds;
use stardust_xr::schemas::dbus::object_registry::ObjectRegistry;
use std::{marker::PhantomData, sync::Arc};
use std::{
marker::PhantomData,
sync::{atomic::Ordering, Arc},
};
use stereokit_rust::{
material::Material,
sk::{DisplayMode, MainThreadToken, Sk},
@@ -200,6 +203,12 @@ impl ServerObjects {
}
pub struct ObjectHandle<I: Interface>(Connection, OwnedObjectPath, PhantomData<I>);
impl<I: Interface> Clone for ObjectHandle<I> {
fn clone(&self) -> Self {
Self(self.0.clone(), self.1.clone(), PhantomData)
}
}
impl<I: Interface> Drop for ObjectHandle<I> {
fn drop(&mut self) {
let connection = self.0.clone();
@@ -247,6 +256,52 @@ impl SpatialRef {
}
}
pub struct Tracked(bool);
impl Tracked {
pub fn new(connection: &Connection, path: &str) -> ObjectHandle<Tracked> {
tokio::task::spawn({
let connection = connection.clone();
let path = path.to_string();
async move {
connection
.object_server()
.at(path, Self(false))
.await
.unwrap();
}
});
ObjectHandle(
connection.clone(),
OwnedObjectPath::try_from(path.to_string()).unwrap(),
PhantomData,
)
}
}
impl ObjectHandle<Tracked> {
pub async fn set_tracked(&self, is_tracked: bool) -> zbus::Result<()> {
let tracked_ref = self
.0
.object_server()
.interface::<_, Tracked>(self.1.as_ref())
.await?;
let mut tracked = tracked_ref.get_mut().await;
if tracked.0 != is_tracked {
tracked.0 = is_tracked;
tracked
.is_tracked_changed(tracked_ref.signal_emitter())
.await;
}
Ok(())
}
}
#[interface(name = "org.stardustxr.Tracked")]
impl Tracked {
#[zbus(property)]
fn is_tracked(&self) -> bool {
self.0
}
}
pub struct FieldRef(u64, OwnedNode);
impl FieldRef {
pub fn create(