feat: add Tracked Interface to dbus to allow clients to query the tracking state of controllers/hands
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
input::{INPUT_HANDLER_REGISTRY, InputDataType, InputHandler, InputMethod, Tip},
|
input::{INPUT_HANDLER_REGISTRY, InputDataType, InputHandler, InputMethod, Tip},
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
},
|
},
|
||||||
objects::{ObjectHandle, SpatialRef},
|
objects::{ObjectHandle, SpatialRef, Tracked},
|
||||||
};
|
};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{Mat4, Vec2, Vec3};
|
use glam::{Mat4, Vec2, Vec3};
|
||||||
@@ -40,19 +40,19 @@ pub struct SkController {
|
|||||||
material: Material,
|
material: Material,
|
||||||
capture_manager: CaptureManager,
|
capture_manager: CaptureManager,
|
||||||
datamap: ControllerDatamap,
|
datamap: ControllerDatamap,
|
||||||
|
tracked: ObjectHandle<Tracked>,
|
||||||
}
|
}
|
||||||
impl SkController {
|
impl SkController {
|
||||||
pub fn new(connection: &Connection, handed: Handed) -> Result<Self> {
|
pub fn new(connection: &Connection, handed: Handed) -> Result<Self> {
|
||||||
Input::set_controller_model(handed, Some(Model::new()));
|
Input::set_controller_model(handed, Some(Model::new()));
|
||||||
let (spatial, object_handle) = SpatialRef::create(
|
let path = "/org/stardustxr/Controller/".to_string()
|
||||||
connection,
|
+ match handed {
|
||||||
&("/org/stardustxr/Controller/".to_string()
|
Handed::Left => "left",
|
||||||
+ match handed {
|
_ => "right",
|
||||||
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(
|
||||||
let model = Model::copy(Model::from_memory(
|
|
||||||
"cursor.glb",
|
"cursor.glb",
|
||||||
include_bytes!("cursor.glb"),
|
include_bytes!("cursor.glb"),
|
||||||
None,
|
None,
|
||||||
@@ -75,13 +75,22 @@ impl SkController {
|
|||||||
material,
|
material,
|
||||||
capture_manager: CaptureManager::default(),
|
capture_manager: CaptureManager::default(),
|
||||||
datamap: Default::default(),
|
datamap: Default::default(),
|
||||||
|
tracked,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn update(&mut self, token: &MainThreadToken) {
|
pub fn update(&mut self, token: &MainThreadToken) {
|
||||||
let controller = Input::controller(self.handed);
|
let controller = Input::controller(self.handed);
|
||||||
let input_node = self.input.spatial.node().unwrap();
|
let input_node = self.input.spatial.node().unwrap();
|
||||||
input_node.set_enabled(controller.tracked.is_active());
|
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(
|
let world_transform = Mat4::from_rotation_translation(
|
||||||
controller.aim.orientation.into(),
|
controller.aim.orientation.into(),
|
||||||
controller.aim.position.into(),
|
controller.aim.position.into(),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::nodes::{
|
|||||||
input::{Hand, InputMethod, Joint},
|
input::{Hand, InputMethod, Joint},
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
};
|
};
|
||||||
use crate::objects::{ObjectHandle, SpatialRef};
|
use crate::objects::{ObjectHandle, SpatialRef, Tracked};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{Mat4, Quat, Vec3};
|
use glam::{Mat4, Quat, Vec3};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -44,6 +44,7 @@ pub struct SkHand {
|
|||||||
input: Arc<InputMethod>,
|
input: Arc<InputMethod>,
|
||||||
capture_manager: CaptureManager,
|
capture_manager: CaptureManager,
|
||||||
datamap: HandDatamap,
|
datamap: HandDatamap,
|
||||||
|
tracked: ObjectHandle<Tracked>,
|
||||||
}
|
}
|
||||||
impl SkHand {
|
impl SkHand {
|
||||||
pub fn new(connection: &Connection, handed: Handed) -> Result<Self> {
|
pub fn new(connection: &Connection, handed: Handed) -> Result<Self> {
|
||||||
@@ -55,6 +56,14 @@ impl SkHand {
|
|||||||
_ => "right",
|
_ => "right",
|
||||||
} + "/palm"),
|
} + "/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()?;
|
let _node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph_owned()?;
|
||||||
Spatial::add_to(&_node.0, None, Mat4::IDENTITY, false);
|
Spatial::add_to(&_node.0, None, Mat4::IDENTITY, false);
|
||||||
let hand = InputDataType::Hand(Hand {
|
let hand = InputDataType::Hand(Hand {
|
||||||
@@ -71,6 +80,7 @@ impl SkHand {
|
|||||||
palm_object,
|
palm_object,
|
||||||
handed,
|
handed,
|
||||||
input,
|
input,
|
||||||
|
tracked,
|
||||||
capture_manager: CaptureManager::default(),
|
capture_manager: CaptureManager::default(),
|
||||||
datamap: Default::default(),
|
datamap: Default::default(),
|
||||||
})
|
})
|
||||||
@@ -84,7 +94,15 @@ impl SkHand {
|
|||||||
(real_hand || sk.get_active_display_mode() == DisplayMode::Flatscreen)
|
(real_hand || sk.get_active_display_mode() == DisplayMode::Flatscreen)
|
||||||
&& sk_hand.tracked.is_active(),
|
&& 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.tip = convert_joint(sk_hand.fingers[0][4]);
|
||||||
hand.thumb.distal = convert_joint(sk_hand.fingers[0][3]);
|
hand.thumb.distal = convert_joint(sk_hand.fingers[0][3]);
|
||||||
hand.thumb.proximal = convert_joint(sk_hand.fingers[0][2]);
|
hand.thumb.proximal = convert_joint(sk_hand.fingers[0][2]);
|
||||||
|
|||||||
@@ -14,8 +14,12 @@ use input::{
|
|||||||
sk_hand::SkHand,
|
sk_hand::SkHand,
|
||||||
};
|
};
|
||||||
use play_space::PlaySpaceBounds;
|
use play_space::PlaySpaceBounds;
|
||||||
|
use portable_atomic::AtomicBool;
|
||||||
use stardust_xr::schemas::dbus::object_registry::ObjectRegistry;
|
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::{
|
use stereokit_rust::{
|
||||||
material::Material,
|
material::Material,
|
||||||
sk::{DisplayMode, MainThreadToken, Sk},
|
sk::{DisplayMode, MainThreadToken, Sk},
|
||||||
@@ -200,6 +204,12 @@ impl ServerObjects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ObjectHandle<I: Interface>(Connection, OwnedObjectPath, PhantomData<I>);
|
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::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<I: Interface> Drop for ObjectHandle<I> {
|
impl<I: Interface> Drop for ObjectHandle<I> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let connection = self.0.clone();
|
let connection = self.0.clone();
|
||||||
@@ -247,6 +257,54 @@ impl SpatialRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Tracked(bool);
|
||||||
|
impl Tracked {
|
||||||
|
pub fn new(connection: &Connection, path: &str) -> ObjectHandle<Tracked> {
|
||||||
|
let bool = Arc::new(AtomicBool::new(false));
|
||||||
|
tokio::task::spawn({
|
||||||
|
let connection = connection.clone();
|
||||||
|
let path = path.to_string();
|
||||||
|
let bool = bool.clone();
|
||||||
|
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);
|
pub struct FieldRef(u64, OwnedNode);
|
||||||
impl FieldRef {
|
impl FieldRef {
|
||||||
pub fn create(
|
pub fn create(
|
||||||
|
|||||||
Reference in New Issue
Block a user