diff --git a/src/main.rs b/src/main.rs index dcc22ce..355e84d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,9 +14,7 @@ use clap::Parser; use core::client::Client; use core::task; use directories::ProjectDirs; -use nodes::spatial::Spatial; -use objects::play_space::PlaySpaceBounds; -use objects::{ServerObjects, SpatialRef}; +use objects::ServerObjects; use once_cell::sync::OnceCell; use session::{launch_start, save_session}; use stardust_xr::server; @@ -26,7 +24,7 @@ use std::time::Duration; use stereokit_rust::material::Material; use stereokit_rust::shader::Shader; use stereokit_rust::sk::{sk_quit, AppMode, DepthMode, QuitReason, SkSettings}; -use stereokit_rust::system::{LogLevel, Renderer, World}; +use stereokit_rust::system::{LogLevel, Renderer}; use stereokit_rust::tex::{SHCubemap, Tex, TexFormat, TexType}; use stereokit_rust::ui::Ui; use stereokit_rust::util::{Color128, Time}; @@ -114,15 +112,7 @@ async fn main() { error!("Unable to get Stardust project directories, default skybox and startup script will not work."); } - let dbus_connection = Arc::new(Connection::session().await.unwrap()); - let hmd = SpatialRef::create(&dbus_connection, "/org/stardustxr/HMD") - .await - .get_aspect::() - .unwrap(); - let play_space = SpatialRef::create(&dbus_connection, "/org/stardustxr/PlaySpace") - .await - .get_aspect::() - .unwrap(); + let dbus_connection = Connection::session().await.unwrap(); dbus_connection .request_name("org.stardustxr.HMD") .await @@ -140,16 +130,7 @@ async fn main() { let project_dirs = project_dirs.clone(); let cli_args = cli_args.clone(); let dbus_connection = dbus_connection.clone(); - move || { - stereokit_loop( - sk_ready_notifier, - project_dirs, - cli_args, - dbus_connection, - hmd, - play_space, - ) - } + move || stereokit_loop(sk_ready_notifier, project_dirs, cli_args, dbus_connection) }); sk_ready_notifier.notified().await; let mut startup_children = project_dirs @@ -176,9 +157,7 @@ fn stereokit_loop( sk_ready_notifier: Arc, project_dirs: Option, args: CliArgs, - dbus_connection: Arc, - hmd: Arc, - play_space: Arc, + dbus_connection: Connection, ) { let sk = SkSettings::default() .app_name("Stardust XR") @@ -236,26 +215,7 @@ fn stereokit_loop( sk_ready_notifier.notify_waiters(); info!("Stardust ready!"); - let mut objects = ServerObjects::new(&sk, hmd, World::has_bounds().then_some(play_space)); - if World::has_bounds() && World::get_bounds_size().x != 0.0 && World::get_bounds_size().y != 0.0 - { - let dbus_connection = dbus_connection.clone(); - tokio::task::spawn(async move { - PlaySpaceBounds::create(&dbus_connection).await; - dbus_connection - .request_name("org.stardustxr.PlaySpace") - .await - .unwrap(); - }); - } else { - tokio::task::spawn(async move { - dbus_connection - .object_server() - .remove::("/org/stardustxr/PlaySpace") - .await - .unwrap(); - }); - } + let mut objects = ServerObjects::new(dbus_connection.clone(), &sk); let mut last_frame_delta = Duration::ZERO; let mut sleep_duration = Duration::ZERO; diff --git a/src/nodes/fields.rs b/src/nodes/fields.rs index f860465..aa93c85 100644 --- a/src/nodes/fields.rs +++ b/src/nodes/fields.rs @@ -138,16 +138,16 @@ pub struct Field { pub shape: Mutex, } impl Field { - pub fn add_to(node: &Arc, shape: Shape) -> Result<()> { + pub fn add_to(node: &Arc, shape: Shape) -> Result> { let spatial = node.get_aspect::()?; let field = Field { spatial, shape: Mutex::new(shape), }; - node.add_aspect(field); + let field = node.add_aspect(field); ::add_node_members(node); ::add_node_members(node); - Ok(()) + Ok(field) } } impl Aspect for Field { diff --git a/src/objects/mod.rs b/src/objects/mod.rs index 002dce7..ef0b94e 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -13,12 +13,14 @@ use input::{ eye_pointer::EyePointer, mouse_pointer::MousePointer, sk_controller::SkController, sk_hand::SkHand, }; +use play_space::PlaySpaceBounds; use std::sync::Arc; use stereokit_rust::{ sk::{DisplayMode, MainThreadToken, Sk}, system::{Handed, Input, Key, World}, util::Device, }; +use tokio::task::AbortHandle; use zbus::{interface, Connection}; pub mod input; @@ -31,17 +33,35 @@ enum Inputs { eye_pointer: Option, }, MousePointer(MousePointer), - Controllers((SkController, SkController)), + // Controllers((SkController, SkController)), Hands((SkHand, SkHand)), } pub struct ServerObjects { - hmd: Arc, - play_space: Option>, + connection: Connection, + hmd: (Arc, AbortHandle), + play_space: Option<(Arc, AbortHandle)>, inputs: Inputs, } impl ServerObjects { - pub fn new(sk: &Sk, hmd: Arc, play_space: Option>) -> ServerObjects { + pub fn new(connection: Connection, sk: &Sk) -> ServerObjects { + let hmd = SpatialRef::create(&connection, "/org/stardustxr/HMD"); + + let play_space = (World::has_bounds() + && World::get_bounds_size().x != 0.0 + && World::get_bounds_size().y != 0.0) + .then(|| SpatialRef::create(&connection, "/org/stardustxr/PlaySpace")); + if play_space.is_some() { + let dbus_connection = connection.clone(); + tokio::task::spawn(async move { + PlaySpaceBounds::create(&dbus_connection).await; + dbus_connection + .request_name("org.stardustxr.PlaySpace") + .await + .unwrap(); + }); + } + let inputs = if sk.get_active_display_mode() == DisplayMode::MixedReality { Inputs::XR { controllers: ( @@ -62,6 +82,7 @@ impl ServerObjects { }; ServerObjects { + connection, hmd, play_space, inputs, @@ -71,6 +92,7 @@ impl ServerObjects { pub fn update(&mut self, sk: &Sk, token: &MainThreadToken) { let hmd_pose = Input::get_head(); self.hmd + .0 .set_local_transform(Mat4::from_scale_rotation_translation( vec3(1.0, 1.0, 1.0), hmd_pose.orientation.into(), @@ -79,22 +101,24 @@ impl ServerObjects { if let Some(play_space) = self.play_space.as_ref() { let pose = World::get_bounds_pose(); - play_space.set_local_transform(Mat4::from_rotation_translation( - pose.orientation.into(), - pose.position.into(), - )); + play_space + .0 + .set_local_transform(Mat4::from_rotation_translation( + pose.orientation.into(), + pose.position.into(), + )); } if sk.get_active_display_mode() != DisplayMode::MixedReality { if Input::key(Key::F6).is_just_inactive() { self.inputs = Inputs::MousePointer(MousePointer::new().unwrap()); } - if Input::key(Key::F7).is_just_inactive() { - self.inputs = Inputs::Controllers(( - SkController::new(Handed::Left).unwrap(), - SkController::new(Handed::Right).unwrap(), - )); - } + // if Input::key(Key::F7).is_just_inactive() { + // self.inputs = Inputs::Controllers(( + // SkController::new(Handed::Left).unwrap(), + // SkController::new(Handed::Right).unwrap(), + // )); + // } if Input::key(Key::F8).is_just_inactive() { self.inputs = Inputs::Hands(( SkHand::new(Handed::Left).unwrap(), @@ -118,10 +142,10 @@ impl ServerObjects { } } Inputs::MousePointer(mouse_pointer) => mouse_pointer.update(), - Inputs::Controllers((left, right)) => { - left.update(token); - right.update(token); - } + // Inputs::Controllers((left, right)) => { + // left.update(token); + // right.update(token); + // } Inputs::Hands((left, right)) => { left.update(sk, token); right.update(sk, token); @@ -129,20 +153,36 @@ impl ServerObjects { } } } +impl Drop for ServerObjects { + fn drop(&mut self) { + self.hmd.1.abort(); + if let Some((_, play_space)) = self.play_space.take() { + play_space.abort(); + } + } +} pub struct SpatialRef(u64); impl SpatialRef { - pub async fn create(connection: &Connection, path: &str) -> Arc { + pub fn create(connection: &Connection, path: &str) -> (Arc, AbortHandle) { let node = Arc::new(Node::generate(&INTERNAL_CLIENT, false)); - Spatial::add_to(&node, None, Mat4::IDENTITY, false); + let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false); let uid: u64 = rand::random(); EXPORTED_SPATIALS.lock().insert(uid, node.clone()); - connection - .object_server() - .at(path, Self(uid)) - .await - .unwrap(); - node + + let connection = connection.clone(); + let path = path.to_string(); + ( + spatial, + tokio::task::spawn(async move { + connection + .object_server() + .at(path, Self(uid)) + .await + .unwrap(); + }) + .abort_handle(), + ) } } #[interface(name = "org.stardustxr.SpatialRef")] @@ -155,18 +195,26 @@ impl SpatialRef { pub struct FieldRef(u64); impl FieldRef { - pub async fn create(connection: &Connection, path: &str, shape: Shape) -> Arc { + 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); - Field::add_to(&node, shape).unwrap(); + let field = Field::add_to(&node, shape).unwrap(); let uid: u64 = rand::random(); EXPORTED_FIELDS.lock().insert(uid, node.clone()); - connection - .object_server() - .at(path, Self(uid)) - .await - .unwrap(); - node + + let connection = connection.clone(); + let path = path.to_string(); + ( + field, + tokio::task::spawn(async move { + connection + .object_server() + .at(path, Self(uid)) + .await + .unwrap(); + }) + .abort_handle(), + ) } } #[interface(name = "org.stardustxr.FieldRef")]