diff --git a/src/main.rs b/src/main.rs index fd43a7a..a0b1e21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,8 +15,8 @@ use core::client::Client; use core::task; use directories::ProjectDirs; use nodes::spatial::Spatial; -use objects::hmd::HMD; -use objects::ServerObjects; +use objects::play_space::PlaySpaceBounds; +use objects::{ServerObjects, SpatialRef}; use once_cell::sync::OnceCell; use session::{launch_start, save_session}; use stardust_xr::server; @@ -26,7 +26,7 @@ use std::time::Duration; use stereokit_rust::material::Material; use stereokit_rust::shader::Shader; use stereokit_rust::sk::{sk_quit, AppMode, DepthMode, DisplayBlend, QuitReason, SkSettings}; -use stereokit_rust::system::{LogLevel, Renderer}; +use stereokit_rust::system::{LogLevel, Renderer, World}; use stereokit_rust::tex::{SHCubemap, Tex, TexFormat, TexType}; use stereokit_rust::ui::Ui; use stereokit_rust::util::{Color128, Time}; @@ -110,8 +110,15 @@ async fn main() { error!("Unable to get Stardust project directories, default skybox and startup script will not work."); } - let dbus_connection = Connection::session().await.unwrap(); - let hmd = HMD::create(&dbus_connection).await; + 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(); dbus_connection .request_name("org.stardustxr.HMD") .await @@ -123,13 +130,16 @@ async fn main() { let project_dirs = project_dirs.clone(); let flatscreen = cli_args.flatscreen; let overlay_priority = cli_args.overlay_priority; + let dbus_connection = dbus_connection.clone(); move || { stereokit_loop( sk_ready_notifier, project_dirs, flatscreen, overlay_priority, + dbus_connection, hmd, + play_space, ) } }); @@ -159,7 +169,9 @@ fn stereokit_loop( project_dirs: Option, intentional_flatscreen: bool, overlay_priority: Option, + dbus_connection: Arc, hmd: Arc, + play_space: Arc, ) { let sk = SkSettings::default() .app_name("Stardust XR") @@ -218,7 +230,31 @@ fn stereokit_loop( sk_ready_notifier.notify_waiters(); info!("Stardust ready!"); - let mut objects = ServerObjects::new(intentional_flatscreen, &sk, hmd); + let mut objects = ServerObjects::new( + intentional_flatscreen, + &sk, + hmd, + World::has_bounds().then(move || 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 last_frame_delta = Duration::ZERO; let mut sleep_duration = Duration::ZERO; diff --git a/src/objects/hmd.rs b/src/objects/hmd.rs deleted file mode 100644 index 345f332..0000000 --- a/src/objects/hmd.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::{ - core::client::INTERNAL_CLIENT, - nodes::{ - spatial::{Spatial, EXPORTED_SPATIALS}, - Node, - }, -}; -use glam::Mat4; -use std::sync::Arc; -use zbus::{interface, Connection}; - -pub struct HMD; -impl HMD { - pub async fn create(connection: &Connection) -> Arc { - let node = Arc::new(Node::generate(&INTERNAL_CLIENT, false)); - let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false); - EXPORTED_SPATIALS.lock().insert(0, node); - connection.object_server().at("/hmd", Self).await.unwrap(); - spatial - } -} -#[interface(name = "org.stardustxr.SpatialRef")] -impl HMD { - #[zbus(property)] - pub fn uid(&self) -> u64 { - 0 - } -} diff --git a/src/objects/mod.rs b/src/objects/mod.rs index 9f02a00..126507c 100644 --- a/src/objects/mod.rs +++ b/src/objects/mod.rs @@ -1,33 +1,47 @@ -use crate::nodes::spatial::Spatial; +#![allow(unused)] + +use crate::{ + core::client::INTERNAL_CLIENT, + nodes::{ + fields::{Field, Shape, EXPORTED_FIELDS}, + spatial::{Spatial, EXPORTED_SPATIALS}, + Node, + }, +}; use glam::{vec3, Mat4}; use input::{ eye_pointer::EyePointer, mouse_pointer::MousePointer, sk_controller::SkController, sk_hand::SkHand, }; -use play_space::PlaySpace; use std::sync::Arc; use stereokit_rust::{ sk::{DisplayMode, MainThreadToken, Sk}, system::{Handed, Input, World}, util::Device, }; +use zbus::{interface, Connection}; -pub mod hmd; pub mod input; pub mod play_space; pub struct ServerObjects { hmd: Arc, + play_space: Option>, mouse_pointer: Option, hands: Option<(SkHand, SkHand)>, controllers: Option<(SkController, SkController)>, eye_pointer: Option, - play_space: Option, } impl ServerObjects { - pub fn new(intentional_flatscreen: bool, sk: &Sk, hmd: Arc) -> ServerObjects { + pub fn new( + intentional_flatscreen: bool, + sk: &Sk, + hmd: Arc, + play_space: Option>, + ) -> ServerObjects { ServerObjects { hmd, + play_space, mouse_pointer: intentional_flatscreen .then(MousePointer::new) .transpose() @@ -51,7 +65,6 @@ impl ServerObjects { .then(EyePointer::new) .transpose() .unwrap(), - play_space: World::has_bounds().then(|| PlaySpace::new().ok()).flatten(), } } @@ -64,6 +77,14 @@ impl ServerObjects { hmd_pose.position.into(), )); + 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(), + )); + } + if let Some(mouse_pointer) = self.mouse_pointer.as_mut() { mouse_pointer.update(); } @@ -78,8 +99,52 @@ impl ServerObjects { if let Some(eye_pointer) = self.eye_pointer.as_ref() { eye_pointer.update(); } - if let Some(play_space) = self.play_space.as_ref() { - play_space.update(); - } + } +} + +pub struct SpatialRef(u64); +impl SpatialRef { + pub async fn create(connection: &Connection, path: &str) -> Arc { + let node = Arc::new(Node::generate(&INTERNAL_CLIENT, false)); + 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 + } +} +#[interface(name = "org.stardustxr.SpatialRef")] +impl SpatialRef { + #[zbus(property)] + fn uid(&self) -> u64 { + self.0 + } +} + +pub struct FieldRef(u64); +impl FieldRef { + pub async fn create(connection: &Connection, path: &str, shape: Shape) -> Arc { + let node = Arc::new(Node::generate(&INTERNAL_CLIENT, false)); + Spatial::add_to(&node, None, Mat4::IDENTITY, false); + 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 + } +} +#[interface(name = "org.stardustxr.FieldRef")] +impl FieldRef { + #[zbus(property)] + fn uid(&self) -> u64 { + self.0 } } diff --git a/src/objects/play_space.rs b/src/objects/play_space.rs index def6180..498ceb4 100644 --- a/src/objects/play_space.rs +++ b/src/objects/play_space.rs @@ -1,70 +1,26 @@ -use std::sync::Arc; - -use color_eyre::eyre::Result; -use glam::Mat4; -use mint::Vector2; -use serde::{Deserialize, Serialize}; -use stardust_xr::values::Datamap; use stereokit_rust::system::World; +use zbus::{interface, Connection, ObjectServer}; -use crate::{ - core::client::INTERNAL_CLIENT, - nodes::{ - data::PulseReceiver, - fields::{Field, Shape}, - spatial::Spatial, - Node, - }, -}; - -#[derive(Debug, Deserialize, Serialize)] -struct PlaySpaceMap { - play_space: (), - size: Vector2, -} -impl Default for PlaySpaceMap { - fn default() -> Self { - Self { - play_space: (), - size: [0.0; 2].into(), - } +pub struct PlaySpaceBounds; +impl PlaySpaceBounds { + pub async fn create(connection: &Connection) { + connection + .object_server() + .at("/org/stardustxr/PlaySpace", Self) + .await + .unwrap(); } } - -pub struct PlaySpace { - _node: Arc, - spatial: Arc, - field: Arc, - _pulse_rx: Arc, -} -impl PlaySpace { - pub fn new() -> Result { - let node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph()?; - let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false); - Field::add_to(&node, Shape::Box([0.0; 3].into()))?; - let field = node.get_aspect::()?.clone(); - - let pulse_rx = PulseReceiver::add_to( - &node, - field.clone(), - Datamap::from_typed(PlaySpaceMap::default())?, - )?; - - Ok(PlaySpace { - _node: node, - spatial, - field, - _pulse_rx: pulse_rx, - }) - } - pub fn update(&self) { - let pose = World::get_bounds_pose(); - self.spatial - .set_local_transform(Mat4::from_rotation_translation( - pose.orientation.into(), - pose.position.into(), - )); - *self.field.shape.lock() = - Shape::Box([World::get_bounds_size().x, 0.0, World::get_bounds_size().y].into()); +#[interface(name = "org.stardustxr.PlaySpace")] +impl PlaySpaceBounds { + #[zbus(property)] + fn bounds(&self) -> Vec<(f64, f64)> { + let bounds = World::get_bounds_size(); + vec![ + ((bounds.x).into(), (bounds.y).into()), + ((bounds.x).into(), (-bounds.y).into()), + ((-bounds.x).into(), (-bounds.y).into()), + ((-bounds.x).into(), (bounds.y).into()), + ] } }