From 101fadd55d00770fca30c12da5c401f557540f65 Mon Sep 17 00:00:00 2001 From: Nova Date: Sat, 24 Sep 2022 13:20:43 -0400 Subject: [PATCH] feat: startup settings --- src/core/client.rs | 32 +++++++++---------- src/nodes/mod.rs | 5 +++ src/nodes/root.rs | 21 +++++++++++- src/nodes/startup.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 src/nodes/startup.rs diff --git a/src/core/client.rs b/src/core/client.rs index b39b0f1..c5b94cf 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,26 +1,22 @@ -use super::eventloop::EventLoop; -use super::scenegraph::Scenegraph; -use crate::nodes::data; -use crate::nodes::fields; -use crate::nodes::hmd; -use crate::nodes::input; -use crate::nodes::items; -use crate::nodes::model; -use crate::nodes::root::Root; -use crate::nodes::spatial; +use super::{eventloop::EventLoop, scenegraph::Scenegraph}; +use crate::{ + core::registry::Registry, + nodes::{data, fields, hmd, input, items, model, root::Root, spatial, startup}, +}; use anyhow::Result; use lazy_static::lazy_static; use once_cell::sync::OnceCell; use parking_lot::Mutex; use stardust_xr::messenger::Messenger; -use std::path::PathBuf; -use std::sync::{Arc, Weak}; -use tokio::net::UnixStream; -use tokio::sync::Notify; -use tokio::task::JoinHandle; +use std::{ + path::PathBuf, + sync::{Arc, Weak}, +}; +use tokio::{net::UnixStream, sync::Notify, task::JoinHandle}; lazy_static! { - pub static ref INTERNAL_CLIENT: Arc = Arc::new(Client { + pub static ref CLIENTS: Registry = Registry::new(); + pub static ref INTERNAL_CLIENT: Arc = CLIENTS.add(Client { event_loop: Weak::new(), index: 0, @@ -52,7 +48,7 @@ impl Client { connection: UnixStream, ) -> Arc { println!("New client connected"); - let client = Arc::new(Client { + let client = CLIENTS.add(Client { event_loop: Arc::downgrade(event_loop), index, stop_notifier: Default::default(), @@ -75,6 +71,7 @@ impl Client { data::create_interface(&client); items::create_interface(&client); input::create_interface(&client); + startup::create_interface(&client); let _ = client.join_handle.set(tokio::spawn({ let client = client.clone(); @@ -126,6 +123,7 @@ impl Client { impl Drop for Client { fn drop(&mut self) { self.stop_notifier.notify_one(); + CLIENTS.remove(self); println!("Client disconnected"); } } diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index 588d3c0..e7c342a 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -7,10 +7,12 @@ pub mod items; pub mod model; pub mod root; pub mod spatial; +pub mod startup; use anyhow::{anyhow, Result}; use nanoid::nanoid; use once_cell::sync::OnceCell; +use parking_lot::Mutex; use stardust_xr::scenegraph::ScenegraphError; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Weak}; @@ -31,6 +33,7 @@ use self::input::{InputHandler, InputMethod}; use self::items::{Item, ItemAcceptor, ItemUI}; use self::model::Model; use self::spatial::Spatial; +use self::startup::StartupSettings; pub type Signal = fn(&Node, Arc, &[u8]) -> Result<()>; pub type Method = fn(&Node, Arc, &[u8]) -> Result>; @@ -56,6 +59,7 @@ pub struct Node { pub item_ui: OnceCell>, pub input_method: OnceCell>, pub input_handler: OnceCell>, + pub startup_settings: OnceCell>, pub(crate) client: Weak, } @@ -100,6 +104,7 @@ impl Node { item_ui: OnceCell::new(), input_method: OnceCell::new(), input_handler: OnceCell::new(), + startup_settings: OnceCell::new(), }; node.add_local_signal("destroy", Node::destroy_flex); node diff --git a/src/nodes/root.rs b/src/nodes/root.rs index 1e09100..d9fb9e8 100644 --- a/src/nodes/root.rs +++ b/src/nodes/root.rs @@ -1,8 +1,9 @@ use super::spatial::Spatial; +use super::startup::DESKTOP_STARTUP_IDS; use super::Node; use crate::core::client::Client; use crate::core::registry::Registry; -use anyhow::Result; +use anyhow::{anyhow, Result}; use glam::Mat4; use stardust_xr::flex::flexbuffer_from_vector_arguments; use std::path::PathBuf; @@ -18,6 +19,7 @@ pub struct Root { impl Root { pub fn create(client: &Arc) -> Arc { let node = Node::create(client, "", "", false); + node.add_local_signal("applyDesktopStartupID", Root::apply_desktop_startup_id); node.add_local_signal("subscribeLogicStep", Root::subscribe_logic_step); node.add_local_signal("setBasePrefixes", Root::set_base_prefixes); let node = node.add_to_scenegraph(); @@ -29,6 +31,23 @@ impl Root { }) } + fn apply_desktop_startup_id( + node: &Node, + _calling_client: Arc, + data: &[u8], + ) -> Result<()> { + let startup_settings = DESKTOP_STARTUP_IDS + .lock() + .remove(flexbuffers::Reader::get_root(data)?.get_str()?) + .ok_or_else(|| anyhow!("Desktop startup ID not found in the list!"))?; + node.spatial + .get() + .unwrap() + .set_local_transform(startup_settings.transform); + + Ok(()) + } + fn subscribe_logic_step(_node: &Node, calling_client: Arc, _data: &[u8]) -> Result<()> { calling_client .root diff --git a/src/nodes/startup.rs b/src/nodes/startup.rs new file mode 100644 index 0000000..1b31384 --- /dev/null +++ b/src/nodes/startup.rs @@ -0,0 +1,76 @@ +use crate::core::client::Client; + +use super::Node; +use anyhow::{anyhow, Result}; +use glam::Mat4; +use parking_lot::Mutex; +use rustc_hash::FxHashMap; +use std::sync::Arc; + +lazy_static::lazy_static! { + pub static ref DESKTOP_STARTUP_IDS: Mutex> = Default::default(); +} + +#[derive(Debug, Default, Clone)] +pub struct StartupSettings { + pub transform: Mat4, +} +impl StartupSettings { + pub fn add_to(node: &Arc) { + node.startup_settings + .set(Mutex::new(StartupSettings::default())) + .unwrap(); + } + + fn set_root_flex(node: &Node, calling_client: Arc, data: &[u8]) -> Result<()> { + let startup_id = flexbuffers::Reader::get_root(data)?.get_str()?; + let spatial_node = calling_client + .scenegraph + .get_node(startup_id) + .ok_or_else(|| anyhow!("Root spatial node does not exist"))?; + let spatial = spatial_node + .spatial + .get() + .ok_or_else(|| anyhow!("Root spatial node is not a spatial"))?; + node.startup_settings.get().unwrap().lock().transform = spatial.global_transform(); + + Ok(()) + } + + fn generate_desktop_startup_id_flex( + node: &Node, + _calling_client: Arc, + _data: &[u8], + ) -> Result> { + let id = nanoid::nanoid!(); + let data = flexbuffers::singleton(id.as_str()); + DESKTOP_STARTUP_IDS + .lock() + .insert(id, node.startup_settings.get().unwrap().lock().clone()); + Ok(data) + } +} + +pub fn create_interface(client: &Arc) { + let node = Node::create(client, "", "startup", false); + node.add_local_signal("createStartupSettings", create_startup_settings_flex); + node.add_to_scenegraph(); +} + +pub fn create_startup_settings_flex( + _node: &Node, + calling_client: Arc, + data: &[u8], +) -> Result<()> { + let name = flexbuffers::Reader::get_root(data)?.get_str()?; + let node = Node::create(&calling_client, "/startup/settings", name, true).add_to_scenegraph(); + StartupSettings::add_to(&node); + + node.add_local_signal("setRoot", StartupSettings::set_root_flex); + node.add_local_method( + "generateDesktopStartupID", + StartupSettings::generate_desktop_startup_id_flex, + ); + + Ok(()) +}