From 4730f0732b91d675d46510b626b4cbdfce55d98a Mon Sep 17 00:00:00 2001 From: Nova Date: Wed, 11 Sep 2024 13:55:15 -0400 Subject: [PATCH] refactor: alias_id --- Cargo.lock | 4 +- codegen/src/lib.rs | 151 +++++++++++++++++++++++++---------- src/core/idl_utils.rs | 11 --- src/core/mod.rs | 1 - src/core/scenegraph.rs | 20 +++-- src/main.rs | 2 - src/nodes/alias.rs | 28 ++++++- src/nodes/audio.rs | 11 +-- src/nodes/data.rs | 11 +-- src/nodes/drawable/lines.rs | 6 +- src/nodes/drawable/mod.rs | 24 ++++-- src/nodes/drawable/model.rs | 10 +-- src/nodes/drawable/text.rs | 6 +- src/nodes/fields.rs | 97 +++++++++++----------- src/nodes/input/handler.rs | 5 +- src/nodes/input/method.rs | 42 +++++----- src/nodes/input/mod.rs | 16 +++- src/nodes/items/camera.rs | 35 +++++--- src/nodes/items/mod.rs | 14 ++-- src/nodes/items/panel.rs | 38 ++++++--- src/nodes/mod.rs | 129 +++++++++++++++++------------- src/nodes/root.rs | 15 ++-- src/nodes/spatial/mod.rs | 138 ++++++++++++++++---------------- src/nodes/spatial/zone.rs | 6 +- src/objects/input/sk_hand.rs | 1 - src/wayland/mod.rs | 2 - 26 files changed, 467 insertions(+), 356 deletions(-) delete mode 100644 src/core/idl_utils.rs diff --git a/Cargo.lock b/Cargo.lock index 61dd02f..c107d96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2698,7 +2698,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d" [[package]] name = "stardust-xr" version = "0.45.0" -source = "git+https://github.com/StardustXR/core.git?branch=dev#8313d5ce425dfec9f460526d527536b52d58b963" +source = "git+https://github.com/StardustXR/core.git?branch=dev#22fcdda7937308a067a9f61ecbcffb0907739ecb" dependencies = [ "cluFlock", "dirs", @@ -2718,7 +2718,7 @@ dependencies = [ [[package]] name = "stardust-xr-schemas" version = "1.5.3" -source = "git+https://github.com/StardustXR/core.git?branch=dev#8313d5ce425dfec9f460526d527536b52d58b963" +source = "git+https://github.com/StardustXR/core.git?branch=dev#22fcdda7937308a067a9f61ecbcffb0907739ecb" dependencies = [ "flatbuffers", "flexbuffers", diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 5ededbe..ce06650 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -64,11 +64,25 @@ fn codegen_protocol(protocol: &'static str) -> proc_macro::TokenStream { }; let aspect = generate_aspect(&Aspect { name: "interface".to_string(), + id: 0, description: protocol.description.clone(), inherits: vec![], members: p.members, }); - quote!(#node_id #aspect) + quote! { + #node_id + #aspect + pub struct Interface; + impl crate::nodes::Aspect for Interface { + impl_aspect_for_interface_aspect!{} + } + pub fn create_interface(client: &std::sync::Arc) -> color_eyre::eyre::Result<()>{ + let node = crate::nodes::Node::from_id(client,INTERFACE_NODE_ID,false); + node.add_aspect(Interface); + node.add_to_scenegraph()?; + Ok(()) + } + } }) .unwrap_or_default(); let custom_enums = protocol @@ -177,7 +191,7 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream { Span::call_site(), ); let client_side_members = client_members - .map(generate_member) + .map(|m| generate_member(aspect.id, m)) .reduce(fold_tokens) .map(|t| { // TODO: properly import all dependencies @@ -190,11 +204,6 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream { }) .unwrap_or_default(); - let aspect_trait_name = Ident::new( - &format!("{}Aspect", &aspect.name.to_case(Case::Pascal)), - Span::call_site(), - ); - let opcodes = aspect .members .iter() @@ -219,31 +228,87 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream { let alias_info = generate_alias_info(aspect); let server_side_members = server_members - .map(generate_member) + .map(|m| generate_member(aspect.id, m)) .reduce(fold_tokens) .unwrap_or_default(); - let add_node_members = aspect + let aspect_trait_name = Ident::new( + &format!("{}Aspect", &aspect.name.to_case(Case::Pascal)), + Span::call_site(), + ); + let run_signals = aspect .members .iter() .filter(|m| m.side == Side::Server) - .map(generate_handler) + .filter(|m| m._type == MemberType::Signal) + .map(|m| generate_run_member(&aspect_trait_name, MemberType::Signal, m)) + .reduce(fold_tokens) + .unwrap_or_default(); + let run_methods = aspect + .members + .iter() + .filter(|m| m.side == Side::Server) + .filter(|m| m._type == MemberType::Method) + .map(|m| generate_run_member(&aspect_trait_name, MemberType::Method, m)) .reduce(fold_tokens) - .map(|members| { - quote! { - fn add_node_members(node: &crate::nodes::Node) { - #members - } - } - }) .unwrap_or_default(); let server_side_members = quote! { #[doc = #description] pub trait #aspect_trait_name { - #add_node_members #server_side_members } }; - quote!(#opcodes #alias_info #client_side_members #server_side_members) + let aspect_name = aspect.name.to_case(Case::Camel); + let aspect_macro_name = Ident::new( + &format!( + "impl_aspect_for_{}_aspect", + aspect.name.to_case(Case::Snake) + ), + Span::call_site(), + ); + let aspect_id = aspect.id; + let aspect_macro = quote! { + macro_rules! #aspect_macro_name { + () => { + fn name(&self) -> String { + #aspect_name.to_string() + } + fn id(&self) -> u64 { + #aspect_id + } + fn as_any(self: Arc) -> Arc { + self + } + fn run_signal( + &self, + _calling_client: std::sync::Arc, + _node: std::sync::Arc, + _signal: u64, + _message: crate::nodes::Message + ) -> Result<(), stardust_xr::scenegraph::ScenegraphError> { + match _signal { + #run_signals + _ => Err(stardust_xr::scenegraph::ScenegraphError::SignalNotFound) + } + } + fn run_method( + &self, + _calling_client: std::sync::Arc, + _node: std::sync::Arc, + _method: u64, + _message: crate::nodes::Message, + _method_response: crate::nodes::MethodResponseSender, + ) { + match _method { + #run_methods + _ => { + let _ = _method_response.send(Err(stardust_xr::scenegraph::ScenegraphError::MethodNotFound)); + } + } + } + }; + } + }; + quote!(#opcodes #alias_info #client_side_members #server_side_members #aspect_macro) } fn generate_alias_opcodes(aspect: &Aspect, side: Side, _type: MemberType) -> TokenStream { @@ -293,8 +358,8 @@ fn generate_alias_info(aspect: &Aspect) -> TokenStream { } } -fn generate_member(member: &Member) -> TokenStream { - let id = member.opcode; +fn generate_member(aspect_id: u64, member: &Member) -> TokenStream { + let opcode = member.opcode; let name = Ident::new(&member.name.to_case(Case::Snake), Span::call_site()); let description = &member.description; @@ -326,27 +391,21 @@ fn generate_member(member: &Member) -> TokenStream { .unwrap_or_else(|| quote!(())); match (side, _type) { - (Side::Client, MemberType::Method) => { - quote! { - #[doc = #description] - pub async fn #name(#argument_decls) -> color_eyre::eyre::Result<(#return_type, Vec)> { - _node.execute_remote_method_typed(#id, &(#argument_uses), vec![]).await - } - } - } (Side::Client, MemberType::Signal) => { quote! { #[doc = #description] pub fn #name(#argument_decls) -> color_eyre::eyre::Result<()> { let serialized = stardust_xr::schemas::flex::serialize((#argument_uses))?; - _node.send_remote_signal(#id, serialized) + _node.send_remote_signal(#aspect_id, #opcode, serialized) } } } - (Side::Server, MemberType::Method) => { + (Side::Client, MemberType::Method) => { quote! { #[doc = #description] - fn #name(#argument_decls) -> impl std::future::Future> + Send + 'static; + pub async fn #name(#argument_decls) -> color_eyre::eyre::Result<(#return_type, Vec)> { + _node.execute_remote_method_typed(#aspect_id, #opcode, &(#argument_uses), vec![]).await + } } } (Side::Server, MemberType::Signal) => { @@ -355,9 +414,15 @@ fn generate_member(member: &Member) -> TokenStream { fn #name(#argument_decls) -> color_eyre::eyre::Result<()>; } } + (Side::Server, MemberType::Method) => { + quote! { + #[doc = #description] + fn #name(#argument_decls) -> impl std::future::Future> + Send + Sync + 'static; + } + } } } -fn generate_handler(member: &Member) -> TokenStream { +fn generate_run_member(aspect_name: &Ident, _type: MemberType, member: &Member) -> TokenStream { let opcode = member.opcode; let member_name_ident = Ident::new(&member.name, Span::call_site()); @@ -393,21 +458,19 @@ fn generate_handler(member: &Member) -> TokenStream { .map(|a| generate_argument_deserialize(&a.name, &a._type, a.optional)) .reduce(|a, b| quote!(#a, #b)) .unwrap_or_default(); - match member._type { + match _type { MemberType::Signal => quote! { - node.add_local_signal(#opcode, |_node, _calling_client, _message| { + #opcode => (move || { #deserialize - Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses) - }); + ::#member_name_ident(_node, _calling_client.clone(), #argument_uses) + })().map_err(|e: color_eyre::Report| stardust_xr::scenegraph::ScenegraphError::SignalError { error: e.to_string() }), }, MemberType::Method => quote! { - node.add_local_method(#opcode, |_node, _calling_client, _message, _method_response| { - _method_response.wrap_async(async move { - #deserialize - let result = Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?; - Ok((#serialize, Vec::new())) - }); - }); + #opcode => _method_response.wrap_async(async move { + #deserialize + let result = ::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?; + Ok((#serialize, Vec::::new())) + }), }, } } diff --git a/src/core/idl_utils.rs b/src/core/idl_utils.rs deleted file mode 100644 index e84d53c..0000000 --- a/src/core/idl_utils.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[macro_export] -macro_rules! create_interface { - ($iface:ident) => { - pub fn create_interface(client: &Arc) -> Result<()> { - let node = Node::from_id(client, INTERFACE_NODE_ID, false); - <$iface as self::InterfaceAspect>::add_node_members(&node); - node.add_to_scenegraph()?; - Ok(()) - } - }; -} diff --git a/src/core/mod.rs b/src/core/mod.rs index 93931c2..d2acc81 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -2,7 +2,6 @@ pub mod client; pub mod client_state; pub mod delta; pub mod destroy_queue; -pub mod idl_utils; pub mod registry; pub mod resource; pub mod scenegraph; diff --git a/src/core/scenegraph.rs b/src/core/scenegraph.rs index 55c1d79..efbd103 100644 --- a/src/core/scenegraph.rs +++ b/src/core/scenegraph.rs @@ -86,19 +86,21 @@ fn map_method_return( impl scenegraph::Scenegraph for Scenegraph { fn send_signal( &self, - node: u64, + node_id: u64, + aspect_id: u64, method: u64, data: &[u8], fds: Vec, ) -> Result<(), ScenegraphError> { let Some(client) = self.get_client() else { - return Err(ScenegraphError::SignalNotFound); + return Err(ScenegraphError::NodeNotFound); }; - debug_span!("Handle signal", node, method).in_scope(|| { - self.get_node(node) + debug_span!("Handle signal", aspect_id, node_id, method).in_scope(|| { + self.get_node(node_id) .ok_or(ScenegraphError::NodeNotFound)? .send_local_signal( client, + aspect_id, method, Message { data: data.to_vec(), @@ -109,23 +111,25 @@ impl scenegraph::Scenegraph for Scenegraph { } fn execute_method( &self, - node: u64, + node_id: u64, + aspect_id: u64, method: u64, data: &[u8], fds: Vec, response: oneshot::Sender, Vec), ScenegraphError>>, ) { let Some(client) = self.get_client() else { - let _ = response.send(Err(ScenegraphError::MethodNotFound)); + let _ = response.send(Err(ScenegraphError::NodeNotFound)); return; }; - debug!(node, method, "Handle method"); - let Some(node) = self.get_node(node) else { + debug!(aspect_id, node_id, method, "Handle method"); + let Some(node) = self.get_node(node_id) else { let _ = response.send(Err(ScenegraphError::NodeNotFound)); return; }; node.execute_local_method( client, + aspect_id, method, Message { data: data.to_vec(), diff --git a/src/main.rs b/src/main.rs index 43679c2..30457f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -262,8 +262,6 @@ fn stereokit_loop( } info!("Cleanly shut down StereoKit"); - #[cfg(feature = "wayland")] - drop(wayland); } fn adaptive_sleep( diff --git a/src/nodes/alias.rs b/src/nodes/alias.rs index 9ba9386..e5c1381 100644 --- a/src/nodes/alias.rs +++ b/src/nodes/alias.rs @@ -69,7 +69,33 @@ impl Alias { } } impl Aspect for Alias { - const NAME: &'static str = "Alias"; + fn name(&self) -> String { + "Alias".to_string() + } + fn id(&self) -> u64 { + 0 + } + fn as_any(self: Arc) -> Arc { + self + } + fn run_signal( + &self, + _calling_client: Arc, + _node: Arc, + _signal: u64, + _message: super::Message, + ) -> Result<(), stardust_xr::scenegraph::ScenegraphError> { + Ok(()) + } + fn run_method( + &self, + _calling_client: Arc, + _node: Arc, + _method: u64, + _message: super::Message, + _response: crate::core::scenegraph::MethodResponseSender, + ) { + } } pub fn get_original(node: Arc, stop_on_disabled: bool) -> Option> { diff --git a/src/nodes/audio.rs b/src/nodes/audio.rs index c0c2a0f..725a9a2 100644 --- a/src/nodes/audio.rs +++ b/src/nodes/audio.rs @@ -3,9 +3,7 @@ use crate::core::client::Client; use crate::core::destroy_queue; use crate::core::registry::Registry; use crate::core::resource::get_resource_file; -use crate::create_interface; -use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO; -use crate::nodes::spatial::{Spatial, Transform}; +use crate::nodes::spatial::{Spatial, Transform, SPATIAL_ASPECT_ALIAS_INFO}; use color_eyre::eyre::{eyre, Result}; use glam::{vec3, Vec4Swizzles}; use once_cell::sync::OnceCell; @@ -49,7 +47,6 @@ impl Sound { }; let sound_arc = SOUND_REGISTRY.add(sound); node.add_aspect_raw(sound_arc.clone()); - ::add_node_members(node); Ok(sound_arc) } @@ -72,7 +69,7 @@ impl Sound { } } impl Aspect for Sound { - const NAME: &'static str = "Sound"; + impl_aspect_for_sound_aspect! {} } impl SoundAspect for Sound { fn play(node: Arc, _calling_client: Arc) -> Result<()> { @@ -101,9 +98,7 @@ pub fn update() { } } -create_interface!(AudioInterface); -struct AudioInterface; -impl InterfaceAspect for AudioInterface { +impl InterfaceAspect for Interface { #[doc = "Create a sound node. WAV and MP3 are supported."] fn create_sound( _node: Arc, diff --git a/src/nodes/data.rs b/src/nodes/data.rs index 0fb2a6d..2b50ac1 100644 --- a/src/nodes/data.rs +++ b/src/nodes/data.rs @@ -4,7 +4,6 @@ use super::spatial::{parse_transform, Spatial}; use super::{Alias, Aspect, Node}; use crate::core::client::Client; use crate::core::registry::Registry; -use crate::create_interface; use crate::nodes::fields::FIELD_ALIAS_INFO; use crate::nodes::spatial::Transform; use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO; @@ -71,7 +70,6 @@ impl PulseSender { field_aliases: AliasList::default(), }; - // ::add_node_members(node); let sender = PULSE_SENDER_REGISTRY.add(sender); node.add_aspect_raw(sender.clone()); for receiver in PULSE_RECEIVER_REGISTRY.get_valid_contents() { @@ -134,7 +132,7 @@ impl PulseSender { } } impl Aspect for PulseSender { - const NAME: &'static str = "PulseSender"; + impl_aspect_for_pulse_sender_aspect! {} } impl PulseSenderAspect for PulseSender {} impl Drop for PulseSender { @@ -161,7 +159,6 @@ impl PulseReceiver { }; let receiver = PULSE_RECEIVER_REGISTRY.add(receiver); - ::add_node_members(node); node.add_aspect_raw(receiver.clone()); for sender in PULSE_SENDER_REGISTRY.get_valid_contents() { sender.handle_new_receiver(&receiver); @@ -170,7 +167,7 @@ impl PulseReceiver { } } impl Aspect for PulseReceiver { - const NAME: &'static str = "PulseReceiver"; + impl_aspect_for_pulse_receiver_aspect! {} } impl PulseReceiverAspect for PulseReceiver { fn send_data( @@ -199,9 +196,7 @@ impl Drop for PulseReceiver { } } -create_interface!(DataInterface); -struct DataInterface; -impl InterfaceAspect for DataInterface { +impl InterfaceAspect for Interface { fn create_pulse_sender( _node: Arc, calling_client: Arc, diff --git a/src/nodes/drawable/lines.rs b/src/nodes/drawable/lines.rs index 1266755..7ecf767 100644 --- a/src/nodes/drawable/lines.rs +++ b/src/nodes/drawable/lines.rs @@ -1,7 +1,7 @@ use super::{Line, LinesAspect}; use crate::{ core::{client::Client, registry::Registry}, - nodes::{spatial::Spatial, Aspect, Node}, + nodes::{spatial::Spatial, Node}, }; use color_eyre::eyre::Result; use glam::Vec3; @@ -40,7 +40,6 @@ impl Lines { space: node.get_aspect::()?.clone(), data: Mutex::new(lines), }); - ::add_node_members(node); node.add_aspect_raw(lines.clone()); Ok(lines) @@ -83,9 +82,6 @@ impl Lines { } } } -impl Aspect for Lines { - const NAME: &'static str = "Lines"; -} impl LinesAspect for Lines { fn set_lines(node: Arc, _calling_client: Arc, lines: Vec) -> Result<()> { let lines_aspect = node.get_aspect::()?; diff --git a/src/nodes/drawable/mod.rs b/src/nodes/drawable/mod.rs index 43b2c64..a533a91 100644 --- a/src/nodes/drawable/mod.rs +++ b/src/nodes/drawable/mod.rs @@ -8,14 +8,12 @@ pub mod text; use self::{lines::Lines, model::Model, text::Text}; use super::{ spatial::{Spatial, Transform}, - Node, + Aspect, Node, }; +use crate::core::{client::Client, resource::get_resource_file}; use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO; -use crate::{ - core::{client::Client, resource::get_resource_file}, - create_interface, -}; use color_eyre::eyre::{self, Result}; +use model::ModelPart; use parking_lot::Mutex; use stardust_xr::values::ResourceID; use std::{ffi::OsStr, path::PathBuf, sync::Arc}; @@ -43,10 +41,20 @@ static QUEUED_SKYLIGHT: Mutex> = Mutex::new(None); static QUEUED_SKYTEX: Mutex> = Mutex::new(None); stardust_xr_server_codegen::codegen_drawable_protocol!(); -create_interface!(DrawableInterface); +impl Aspect for Lines { + impl_aspect_for_lines_aspect! {} +} +impl Aspect for Model { + impl_aspect_for_model_aspect! {} +} +impl Aspect for ModelPart { + impl_aspect_for_model_part_aspect! {} +} +impl Aspect for Text { + impl_aspect_for_text_aspect! {} +} -pub struct DrawableInterface; -impl InterfaceAspect for DrawableInterface { +impl InterfaceAspect for Interface { fn set_sky_tex(_node: Arc, calling_client: Arc, tex: ResourceID) -> Result<()> { let resource_path = get_resource_file(&tex, &calling_client, &[OsStr::new("hdr")]) .ok_or(eyre::eyre!("Could not find resource"))?; diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index 01c396f..a47a237 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -4,7 +4,7 @@ use crate::core::registry::Registry; use crate::core::resource::get_resource_file; use crate::nodes::alias::{Alias, AliasList}; use crate::nodes::spatial::Spatial; -use crate::nodes::{Aspect, Node}; +use crate::nodes::Node; use color_eyre::eyre::{bail, eyre, Result}; use glam::{Mat4, Vec2, Vec3}; use once_cell::sync::{Lazy, OnceCell}; @@ -204,7 +204,6 @@ impl ModelPart { pending_material_replacement: Mutex::new(None), aliases: AliasList::default(), }); - ::add_node_members(&node); node.add_aspect_raw(model_part.clone()); parts.push(model_part.clone()); Some(model_part) @@ -278,9 +277,6 @@ impl ModelPart { } } } -impl Aspect for ModelPart { - const NAME: &'static str = "ModelPart"; -} impl ModelPartAspect for ModelPart { #[doc = "Set this model part's material to one that cuts a hole in the world. Often used for overlays/passthrough where you want to show the background through an object."] fn apply_holdout_material(node: Arc, _calling_client: Arc) -> Result<()> { @@ -327,7 +323,6 @@ impl Model { sk_model: OnceCell::new(), parts: Mutex::new(Vec::default()), }); - ::add_node_members(node); MODEL_REGISTRY.add_raw(&model); // technically doing this in anything but the main thread isn't a good idea but dangit we need those model nodes ASAP @@ -361,9 +356,6 @@ impl Model { // TODO: proper hread safety in stereokit_rust (probably just bind stereokit directly) unsafe impl Send for Model {} unsafe impl Sync for Model {} -impl Aspect for Model { - const NAME: &'static str = "Model"; -} impl ModelAspect for Model { #[doc = "Bind a model part to the node with the ID input."] fn bind_model_part( diff --git a/src/nodes/drawable/text.rs b/src/nodes/drawable/text.rs index 33a757f..7f5c744 100644 --- a/src/nodes/drawable/text.rs +++ b/src/nodes/drawable/text.rs @@ -1,6 +1,6 @@ use crate::{ core::{client::Client, destroy_queue, registry::Registry, resource::get_resource_file}, - nodes::{spatial::Spatial, Aspect, Node}, + nodes::{spatial::Spatial, Node}, }; use color_eyre::eyre::{eyre, Result}; use glam::{vec3, Mat4, Vec2}; @@ -53,7 +53,6 @@ impl Text { text: Mutex::new(text), data: Mutex::new(style), }); - ::add_node_members(node); node.add_aspect_raw(text.clone()); Ok(text) @@ -132,9 +131,6 @@ impl Text { } } } -impl Aspect for Text { - const NAME: &'static str = "Text"; -} impl TextAspect for Text { fn set_character_height( node: Arc, diff --git a/src/nodes/fields.rs b/src/nodes/fields.rs index aa93c85..990d5d2 100644 --- a/src/nodes/fields.rs +++ b/src/nodes/fields.rs @@ -5,7 +5,6 @@ use super::spatial::{ }; use super::{Aspect, Node}; use crate::core::client::Client; -use crate::create_interface; use crate::nodes::spatial::Transform; use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO; use crate::nodes::spatial::SPATIAL_REF_ASPECT_ALIAS_INFO; @@ -145,15 +144,59 @@ impl Field { shape: Mutex::new(shape), }; let field = node.add_aspect(field); - ::add_node_members(node); - ::add_node_members(node); + node.add_aspect(FieldRef); Ok(field) } } impl Aspect for Field { - const NAME: &'static str = "Field"; + impl_aspect_for_field_aspect! {} } -impl FieldRefAspect for Field { +impl FieldAspect for Field { + fn set_shape(node: Arc, _calling_client: Arc, shape: Shape) -> Result<()> { + let field = node.get_aspect::()?; + *field.shape.lock() = shape; + Ok(()) + } + + async fn export_field(node: Arc, _calling_client: Arc) -> Result { + let id = rand::random(); + EXPORTED_FIELDS.lock().insert(id, node); + Ok(id) + } +} +impl FieldTrait for Field { + fn spatial_ref(&self) -> &Spatial { + &self.spatial + } + fn local_distance(&self, p: Vec3A) -> f32 { + match self.shape.lock().clone() { + Shape::Box(size) => { + let q = vec3( + p.x.abs() - (size.x * 0.5_f32), + p.y.abs() - (size.y * 0.5_f32), + p.z.abs() - (size.z * 0.5_f32), + ); + let v = vec3a(q.x.max(0_f32), q.y.max(0_f32), q.z.max(0_f32)); + v.length() + q.x.max(q.y.max(q.z)).min(0_f32) + } + Shape::Cylinder(CylinderShape { length, radius }) => { + let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (length * 0.5)); + d.x.max(d.y).min(0.0) + d.max(vec2(0.0, 0.0)).length() + } + Shape::Sphere(radius) => p.length() - radius, + Shape::Torus(TorusShape { radius_a, radius_b }) => { + let q = vec2(p.xz().length() - radius_a, p.y); + q.length() - radius_b + } + } + } +} + +pub struct FieldRef; +impl Aspect for FieldRef { + impl_aspect_for_field_ref_aspect! {} +} +impl FieldRefAspect for FieldRef { async fn distance( node: Arc, _calling_client: Arc, @@ -205,50 +248,8 @@ impl FieldRefAspect for Field { })) } } -impl FieldAspect for Field { - fn set_shape(node: Arc, _calling_client: Arc, shape: Shape) -> Result<()> { - let field = node.get_aspect::()?; - *field.shape.lock() = shape; - Ok(()) - } - async fn export_field(node: Arc, _calling_client: Arc) -> Result { - let id = rand::random(); - EXPORTED_FIELDS.lock().insert(id, node); - Ok(id) - } -} -impl FieldTrait for Field { - fn spatial_ref(&self) -> &Spatial { - &self.spatial - } - fn local_distance(&self, p: Vec3A) -> f32 { - match self.shape.lock().clone() { - Shape::Box(size) => { - let q = vec3( - p.x.abs() - (size.x * 0.5_f32), - p.y.abs() - (size.y * 0.5_f32), - p.z.abs() - (size.z * 0.5_f32), - ); - let v = vec3a(q.x.max(0_f32), q.y.max(0_f32), q.z.max(0_f32)); - v.length() + q.x.max(q.y.max(q.z)).min(0_f32) - } - Shape::Cylinder(CylinderShape { length, radius }) => { - let d = vec2(p.xy().length().abs() - radius, p.z.abs() - (length * 0.5)); - d.x.max(d.y).min(0.0) + d.max(vec2(0.0, 0.0)).length() - } - Shape::Sphere(radius) => p.length() - radius, - Shape::Torus(TorusShape { radius_a, radius_b }) => { - let q = vec2(p.xz().length() - radius_a, p.y); - q.length() - radius_b - } - } - } -} - -create_interface!(FieldInterface); -pub struct FieldInterface; -impl InterfaceAspect for FieldInterface { +impl InterfaceAspect for Interface { async fn import_field_ref( _node: Arc, calling_client: Arc, diff --git a/src/nodes/input/handler.rs b/src/nodes/input/handler.rs index 59e7fef..6bcd2c7 100644 --- a/src/nodes/input/handler.rs +++ b/src/nodes/input/handler.rs @@ -1,5 +1,5 @@ use super::{InputHandlerAspect, INPUT_HANDLER_REGISTRY, INPUT_METHOD_REGISTRY}; -use crate::nodes::{alias::AliasList, fields::Field, spatial::Spatial, Aspect, Node}; +use crate::nodes::{alias::AliasList, fields::Field, spatial::Spatial, Node}; use color_eyre::eyre::Result; use std::sync::Arc; @@ -23,9 +23,6 @@ impl InputHandler { Ok(()) } } -impl Aspect for InputHandler { - const NAME: &'static str = "InputHandler"; -} impl InputHandlerAspect for InputHandler {} impl PartialEq for InputHandler { fn eq(&self, other: &Self) -> bool { diff --git a/src/nodes/input/method.rs b/src/nodes/input/method.rs index d235050..392bb66 100644 --- a/src/nodes/input/method.rs +++ b/src/nodes/input/method.rs @@ -9,7 +9,7 @@ use crate::{ alias::{Alias, AliasList}, fields::{Field, FIELD_ALIAS_INFO}, spatial::Spatial, - Aspect, Node, + Node, }, }; use color_eyre::eyre::Result; @@ -45,13 +45,12 @@ impl InputMethod { internal_capture_requests: Registry::new(), captures: Registry::new(), }; - ::add_node_members(node); - ::add_node_members(node); for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() { method.handle_new_handler(&handler); } let method = INPUT_METHOD_REGISTRY.add(method); node.add_aspect_raw(method.clone()); + node.add_aspect(InputMethodRef); Ok(method) } @@ -154,25 +153,6 @@ impl InputMethod { } } } -impl Aspect for InputMethod { - const NAME: &'static str = "InputMethod"; -} -impl InputMethodRefAspect for InputMethod { - #[doc = "Have the input handler that this method reference came from capture the method for the next frame."] - fn request_capture( - node: Arc, - _calling_client: Arc, - handler: Arc, - ) -> Result<()> { - let input_method = node.get_aspect::()?; - let input_handler = handler.get_aspect::()?; - - input_method - .internal_capture_requests - .add_raw(&input_handler); - Ok(()) - } -} impl InputMethodAspect for InputMethod { #[doc = "Set the spatial input component of this input method. You must keep the same input data type throughout the entire thing."] fn set_input( @@ -231,3 +211,21 @@ impl Drop for InputMethod { INPUT_METHOD_REGISTRY.remove(self); } } + +pub struct InputMethodRef; +impl InputMethodRefAspect for InputMethodRef { + #[doc = "Have the input handler that this method reference came from capture the method for the next frame."] + fn request_capture( + node: Arc, + _calling_client: Arc, + handler: Arc, + ) -> Result<()> { + let input_method = node.get_aspect::()?; + let input_handler = handler.get_aspect::()?; + + input_method + .internal_capture_requests + .add_raw(&input_handler); + Ok(()) + } +} diff --git a/src/nodes/input/mod.rs b/src/nodes/input/mod.rs index 45e2955..eaa08bb 100644 --- a/src/nodes/input/mod.rs +++ b/src/nodes/input/mod.rs @@ -11,7 +11,7 @@ pub use method::*; use super::fields::Field; use super::spatial::Spatial; -use crate::create_interface; +use super::Aspect; use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO; use crate::nodes::spatial::SPATIAL_REF_ASPECT_ALIAS_INFO; use crate::{core::client::Client, nodes::Node}; @@ -25,6 +25,16 @@ pub static INPUT_HANDLER_REGISTRY: Registry = Registry::new(); stardust_xr_server_codegen::codegen_input_protocol!(); +impl Aspect for InputHandler { + impl_aspect_for_input_handler_aspect! {} +} +impl Aspect for InputMethod { + impl_aspect_for_input_method_aspect! {} +} +impl Aspect for InputMethodRef { + impl_aspect_for_input_method_ref_aspect! {} +} + pub trait InputDataTrait { fn transform(&mut self, method: &InputMethod, handler: &InputHandler); fn distance(&self, space: &Arc, field: &Field) -> f32; @@ -47,9 +57,7 @@ impl InputDataTrait for InputDataType { } } -create_interface!(InputInterface); -pub struct InputInterface; -impl InterfaceAspect for InputInterface { +impl InterfaceAspect for Interface { #[doc = "Create an input method node"] fn create_input_method( _node: Arc, diff --git a/src/nodes/items/camera.rs b/src/nodes/items/camera.rs index 55d65db..93fcfa9 100644 --- a/src/nodes/items/camera.rs +++ b/src/nodes/items/camera.rs @@ -1,11 +1,9 @@ -use super::{ - create_item_acceptor_flex, register_item_ui_flex, Item, ItemAcceptor, ItemInterface, ItemType, -}; +use super::{create_item_acceptor_flex, register_item_ui_flex, Item, ItemType}; use crate::nodes::items::ITEM_ACCEPTOR_ASPECT_ALIAS_INFO; use crate::nodes::items::ITEM_ASPECT_ALIAS_INFO; +use crate::nodes::Aspect; use crate::{ core::{client::Client, registry::Registry, scenegraph::MethodResponseSender}, - create_interface, nodes::{ drawable::{ model::{MaterialWrapper, ModelPart}, @@ -48,6 +46,12 @@ lazy_static! { ui: Default::default(), items: Registry::new(), acceptors: Registry::new(), + add_acceptor_aspect: |node| { + node.add_aspect(CameraItemAcceptor); + }, + add_ui_aspect: |node| { + node.add_aspect(CameraItemUi); + }, new_acceptor_fn: |node, acceptor, acceptor_field| { let _ = camera_item_ui_client::create_acceptor(node, acceptor, acceptor_field); } @@ -85,7 +89,7 @@ impl CameraItem { apply_to: Registry::new(), }), ); - // ::node_methods(node); + node.add_aspect(CameraItemUi); } fn frame_flex( @@ -169,7 +173,17 @@ impl CameraItem { } impl CameraItemAspect for CameraItem {} -impl CameraItemAcceptorAspect for ItemAcceptor { +pub struct CameraItemUi; +impl Aspect for CameraItemUi { + impl_aspect_for_camera_item_ui_aspect! {} +} +impl CameraItemUiAspect for CameraItemUi {} + +pub struct CameraItemAcceptor; +impl Aspect for CameraItemAcceptor { + impl_aspect_for_camera_item_acceptor_aspect! {} +} +impl CameraItemAcceptorAspect for CameraItemAcceptor { fn capture_item(node: Arc, _calling_client: Arc, item: Arc) -> Result<()> { super::acceptor_capture_item_flex(node, item) } @@ -184,8 +198,7 @@ pub fn update(token: &MainThreadToken) { } } -create_interface!(ItemInterface); -impl InterfaceAspect for ItemInterface { +impl InterfaceAspect for Interface { #[doc = "Create a camera item at a specific location"] fn create_camera_item( _node: Arc, @@ -206,19 +219,21 @@ impl InterfaceAspect for ItemInterface { } #[doc = "Register this client to manage camera items and create default 3D UI for them."] - fn register_camera_item_ui(_node: Arc, calling_client: Arc) -> Result<()> { + fn register_camera_item_ui(node: Arc, calling_client: Arc) -> Result<()> { + node.add_aspect(CameraItemUi); register_item_ui_flex(calling_client, &ITEM_TYPE_INFO_CAMERA) } #[doc = "Create an item acceptor to allow temporary ownership of a given type of item. Creates a node at `/item/camera/acceptor/`."] fn create_camera_item_acceptor( - _node: Arc, + node: Arc, calling_client: Arc, id: u64, parent: Arc, transform: Transform, field: Arc, ) -> Result<()> { + node.add_aspect(CameraItemAcceptor); create_item_acceptor_flex( calling_client, id, diff --git a/src/nodes/items/mod.rs b/src/nodes/items/mod.rs index e32fda8..f6c81cf 100644 --- a/src/nodes/items/mod.rs +++ b/src/nodes/items/mod.rs @@ -47,6 +47,8 @@ pub struct TypeInfo { pub ui: Mutex>, pub items: Registry, pub acceptors: Registry, + pub add_ui_aspect: fn(node: &Node), + pub add_acceptor_aspect: fn(node: &Node), pub new_acceptor_fn: fn(node: &Node, acceptor: &Arc, acceptor_field: &Arc), } impl Hash for TypeInfo { @@ -81,7 +83,6 @@ impl Item { }; let item = type_info.items.add(item); - ::add_node_members(node); if let Some(ui) = type_info.ui.lock().upgrade() { ui.handle_create_item(&item); } @@ -109,7 +110,7 @@ impl Item { } } impl Aspect for Item { - const NAME: &'static str = "Item"; + impl_aspect_for_item_aspect! {} } impl ItemAspect for Item { fn release(node: Arc, _calling_client: Arc) -> Result<()> { @@ -285,7 +286,7 @@ impl ItemUI { } } impl Aspect for ItemUI { - const NAME: &'static str = "Item"; + impl_aspect_for_item_ui_aspect! {} } impl Drop for ItemUI { fn drop(&mut self) { @@ -343,7 +344,7 @@ impl ItemAcceptor { } } impl Aspect for ItemAcceptor { - const NAME: &'static str = "ItemAcceptor"; + impl_aspect_for_item_acceptor_aspect! {} } impl ItemAcceptorAspect for ItemAcceptor {} impl Drop for ItemAcceptor { @@ -364,6 +365,7 @@ pub fn register_item_ui_flex( ) -> Result<()> { let ui = Node::from_id(&calling_client, type_info.ui_node_id, true).add_to_scenegraph()?; ItemUI::add_to(&ui, type_info)?; + (type_info.add_ui_aspect)(&ui); Ok(()) } fn create_item_acceptor_flex( @@ -381,6 +383,7 @@ fn create_item_acceptor_flex( let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?; Spatial::add_to(&node, Some(space.clone()), transform, false); ItemAcceptor::add_to(&node, type_info, field); + (type_info.add_acceptor_aspect)(&node); Ok(()) } @@ -391,6 +394,3 @@ fn acceptor_capture_item_flex(node: Arc, item: Arc) -> Result<()> { Ok(()) } - -struct ItemInterface; -// create_interface!(ItemInterface); diff --git a/src/nodes/items/panel.rs b/src/nodes/items/panel.rs index 32827c0..d7e8642 100644 --- a/src/nodes/items/panel.rs +++ b/src/nodes/items/panel.rs @@ -1,12 +1,13 @@ -use super::{create_item_acceptor_flex, register_item_ui_flex, ItemAcceptor, ItemInterface}; +use super::camera::CameraItemAcceptor; +use super::{create_item_acceptor_flex, register_item_ui_flex}; use crate::nodes::items::ITEM_ACCEPTOR_ASPECT_ALIAS_INFO; use crate::nodes::items::ITEM_ASPECT_ALIAS_INFO; +use crate::nodes::Aspect; use crate::{ core::{ client::{get_env, state, Client, INTERNAL_CLIENT}, registry::Registry, }, - create_interface, nodes::{ drawable::model::ModelPart, items::{Item, ItemType, TypeInfo}, @@ -39,6 +40,12 @@ lazy_static! { ui: Default::default(), items: Registry::new(), acceptors: Registry::new(), + add_acceptor_aspect: |node| { + node.add_aspect(PanelItemUi); + }, + add_ui_aspect: |node| { + node.add_aspect(PanelItemAcceptor); + }, new_acceptor_fn: |node, acceptor, acceptor_field| { let _ = panel_item_ui_client::create_acceptor(node, acceptor, acceptor_field); } @@ -115,7 +122,6 @@ impl PanelItem { &ITEM_TYPE_INFO_PANEL, ItemType::Panel(generic_panel_item), ); - ::add_node_members(&node); (node, panel_item) } @@ -198,8 +204,9 @@ impl PanelItem { } } -// make these stupid vectors u32 in the protocol somehow!!!!!!!1 - +impl Aspect for PanelItem { + impl_aspect_for_panel_item_aspect! {} +} #[allow(unused)] impl PanelItemAspect for PanelItem { #[doc = "Apply the cursor as a material to a model."] @@ -405,7 +412,17 @@ impl PanelItemAspect for PanelItem { } } -impl PanelItemAcceptorAspect for ItemAcceptor { +pub struct PanelItemUi; +impl Aspect for PanelItemUi { + impl_aspect_for_panel_item_ui_aspect! {} +} +impl PanelItemUiAspect for PanelItemUi {} + +pub struct PanelItemAcceptor; +impl Aspect for PanelItemAcceptor { + impl_aspect_for_panel_item_acceptor_aspect! {} +} +impl PanelItemAcceptorAspect for PanelItemAcceptor { fn capture_item(node: Arc, _calling_client: Arc, item: Arc) -> Result<()> { super::acceptor_capture_item_flex(node, item) } @@ -435,22 +452,23 @@ impl Drop for PanelItem { } } -create_interface!(ItemInterface); -impl InterfaceAspect for ItemInterface { +impl InterfaceAspect for Interface { #[doc = "Register this client to manage the items of a certain type and create default 3D UI for them."] - fn register_panel_item_ui(_node: Arc, calling_client: Arc) -> Result<()> { + fn register_panel_item_ui(node: Arc, calling_client: Arc) -> Result<()> { + node.add_aspect(CameraItemAcceptor); register_item_ui_flex(calling_client, &ITEM_TYPE_INFO_PANEL) } #[doc = "Create an item acceptor to allow temporary ownership of a given type of item. Creates a node at `/item//acceptor/`."] fn create_panel_item_acceptor( - _node: Arc, + node: Arc, calling_client: Arc, id: u64, parent: Arc, transform: Transform, field: Arc, ) -> Result<()> { + node.add_aspect(PanelItemAcceptor); create_item_acceptor_flex( calling_client, id, diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index 1af5a76..f6edc30 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -21,7 +21,7 @@ use spatial::Spatial; use stardust_xr::messenger::MessageSenderHandle; use stardust_xr::scenegraph::ScenegraphError; use stardust_xr::schemas::flex::{deserialize, serialize}; -use std::any::{Any, TypeId}; +use std::any::Any; use std::fmt::Debug; use std::os::fd::OwnedFd; use std::sync::{Arc, Weak}; @@ -46,11 +46,26 @@ impl AsRef<[u8]> for Message { } } -pub type Signal = fn(Arc, Arc, Message) -> Result<()>; -pub type Method = fn(Arc, Arc, Message, MethodResponseSender); - stardust_xr_server_codegen::codegen_node_protocol!(); +pub struct Owned; +impl Aspect for Owned { + impl_aspect_for_owned_aspect! {} +} +impl OwnedAspect for Owned { + fn set_enabled(node: Arc, _calling_client: Arc, enabled: bool) -> Result<()> { + node.set_enabled(enabled); + Ok(()) + } + + fn destroy(node: Arc, _calling_client: Arc) -> Result<()> { + if node.destroyable { + node.destroy(); + } + Ok(()) + } +} + pub struct OwnedNode(pub Arc); impl Drop for OwnedNode { fn drop(&mut self) { @@ -64,8 +79,6 @@ pub struct Node { client: Weak, message_sender_handle: Option, - local_signals: Mutex>, - local_methods: Mutex>, aliases: Registry, aspects: Aspects, destroyable: bool, @@ -87,13 +100,11 @@ impl Node { client: Arc::downgrade(client), message_sender_handle: client.message_sender_handle.clone(), id, - local_signals: Default::default(), - local_methods: Default::default(), aliases: Default::default(), aspects: Default::default(), destroyable, }; - ::add_node_members(&node); + node.aspects.add(Owned); node } pub fn add_to_scenegraph(self) -> Result> { @@ -146,13 +157,6 @@ impl Node { // Ok(serialize(pid)?.into()) // } - pub fn add_local_signal(&self, id: u64, signal: Signal) { - self.local_signals.lock().insert(id, signal); - } - pub fn add_local_method(&self, id: u64, method: Method) { - self.local_methods.lock().insert(id, method); - } - pub fn add_aspect(&self, aspect: A) -> Arc { self.aspects.add(aspect) } @@ -166,6 +170,7 @@ impl Node { pub fn send_local_signal( self: Arc, calling_client: Arc, + aspect_id: u64, method: u64, message: Message, ) -> Result<(), ScenegraphError> { @@ -177,22 +182,26 @@ impl Node { .original .upgrade() .ok_or(ScenegraphError::BrokenAlias)? - .send_local_signal(calling_client, method, message) + .send_local_signal(calling_client, aspect_id, method, message) } else { - let signal = self - .local_signals + let aspect = self + .aspects + .0 .lock() - .get(&method) - .cloned() - .ok_or(ScenegraphError::SignalNotFound)?; - signal(self, calling_client, message).map_err(|error| ScenegraphError::SignalError { - error: error.to_string(), - }) + .get(&aspect_id) + .ok_or(ScenegraphError::AspectNotFound)? + .clone(); + aspect + .run_signal(calling_client, self.clone(), method, message) + .map_err(|error| ScenegraphError::SignalError { + error: error.to_string(), + }) } } pub fn execute_local_method( self: Arc, calling_client: Arc, + aspect_id: u64, method: u64, message: Message, response: MethodResponseSender, @@ -208,6 +217,7 @@ impl Node { }; alias.execute_local_method( calling_client, + aspect_id, method, Message { data: message.data.clone(), @@ -216,14 +226,19 @@ impl Node { response, ) } else { - let Some(method) = self.local_methods.lock().get(&method).cloned() else { - response.send(Err(ScenegraphError::MethodNotFound)); + let Some(aspect) = self.aspects.0.lock().get(&aspect_id).cloned() else { + response.send(Err(ScenegraphError::AspectNotFound)); return; }; - method(self, calling_client, message, response); + aspect.run_method(calling_client, self.clone(), method, message, response); } } - pub fn send_remote_signal(&self, method: u64, message: impl Into) -> Result<()> { + pub fn send_remote_signal( + &self, + aspect_id: u64, + method: u64, + message: impl Into, + ) -> Result<()> { let message = message.into(); self.aliases .get_valid_contents() @@ -233,6 +248,7 @@ impl Node { .for_each(|node| { // Beware! file descriptors will not be sent to aliases!!! let _ = node.send_remote_signal( + aspect_id, method, Message { data: message.data.clone(), @@ -241,12 +257,13 @@ impl Node { ); }); if let Some(handle) = self.message_sender_handle.as_ref() { - handle.signal(self.id, method, &message.data, message.fds)?; + handle.signal(self.id, aspect_id, method, &message.data, message.fds)?; } Ok(()) } pub async fn execute_remote_method_typed( &self, + aspect_id: u64, method: u64, input: S, fds: Vec, @@ -258,7 +275,7 @@ impl Node { let serialized = serialize(input)?; let result = message_sender_handle - .method(self.id, method, &serialized, fds)? + .method(self.id, aspect_id, method, &serialized, fds)? .await .map_err(|e| eyre!(e))?; @@ -271,25 +288,10 @@ impl Debug for Node { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Node") .field("id", &self.id) - .field("local_signals", &self.local_signals.lock().keys()) - .field("local_methods", &self.local_methods.lock().keys()) .field("destroyable", &self.destroyable) .finish() } } -impl OwnedAspect for Node { - fn set_enabled(node: Arc, _calling_client: Arc, enabled: bool) -> Result<()> { - node.set_enabled(enabled); - Ok(()) - } - - fn destroy(node: Arc, _calling_client: Arc) -> Result<()> { - if node.destroyable { - node.destroy(); - } - Ok(()) - } -} impl Drop for Node { fn drop(&mut self) { // Debug breakpoint @@ -297,12 +299,28 @@ impl Drop for Node { } pub trait Aspect: Any + Send + Sync + 'static { - const NAME: &'static str; + fn name(&self) -> String; + fn id(&self) -> u64; + fn as_any(self: Arc) -> Arc; + fn run_signal( + &self, + calling_client: Arc, + node: Arc, + signal: u64, + message: Message, + ) -> Result<(), stardust_xr::scenegraph::ScenegraphError>; + fn run_method( + &self, + calling_client: Arc, + node: Arc, + method: u64, + message: Message, + response: MethodResponseSender, + ); } #[derive(Default)] -struct Aspects(Mutex>>); - +struct Aspects(Mutex>>); impl Aspects { fn add(&self, t: A) -> Arc { let aspect = Arc::new(t); @@ -310,18 +328,15 @@ impl Aspects { aspect } fn add_raw(&self, aspect: Arc) { - self.0.lock().insert(Self::type_key::(), aspect); + let id = aspect.id(); + self.0.lock().insert(id, aspect); } fn get(&self) -> Result> { self.0 .lock() - .get(&Self::type_key::()) - .and_then(|a| Arc::downcast(a.clone()).ok()) - .ok_or(eyre!("Couldn't get aspect {}", A::NAME.to_lowercase())) - } - - fn type_key() -> TypeId { - TypeId::of::() + .values() + .find_map(|a| Arc::downcast(a.clone().as_any()).ok()) + .ok_or(eyre!("Couldn't get aspect")) } } impl Drop for Aspects { diff --git a/src/nodes/root.rs b/src/nodes/root.rs index 558ee32..c221fed 100644 --- a/src/nodes/root.rs +++ b/src/nodes/root.rs @@ -1,5 +1,5 @@ use super::spatial::Spatial; -use super::Node; +use super::{Aspect, Node}; use crate::core::client::Client; use crate::core::client_state::ClientStateParsed; use crate::core::registry::Registry; @@ -23,14 +23,14 @@ pub struct Root { impl Root { pub fn create(client: &Arc, transform: Mat4) -> Result> { let node = Node::from_id(client, 0, false); - ::add_node_members(&node); let node = node.add_to_scenegraph()?; let _ = Spatial::add_to(&node, None, transform, false); - - Ok(ROOT_REGISTRY.add(Root { - node, + let root_aspect = node.add_aspect(Root { + node: node.clone(), connect_instant: Instant::now(), - })) + }); + ROOT_REGISTRY.add_raw(&root_aspect); + Ok(root_aspect) } pub fn send_frame_events(delta: f64) { @@ -54,6 +54,9 @@ impl Root { Ok(root_client::save_state(&self.node).await?.0) } } +impl Aspect for Root { + impl_aspect_for_root_aspect! {} +} impl RootAspect for Root { async fn get_state(_node: Arc, calling_client: Arc) -> Result { let Some(state) = calling_client.state.get() else { diff --git a/src/nodes/spatial/mod.rs b/src/nodes/spatial/mod.rs index b7069b8..b579e8a 100644 --- a/src/nodes/spatial/mod.rs +++ b/src/nodes/spatial/mod.rs @@ -6,7 +6,6 @@ use super::fields::{Field, FieldTrait}; use super::Aspect; use crate::core::client::Client; use crate::core::registry::Registry; -use crate::create_interface; use crate::nodes::{Node, OWNED_ASPECT_ALIAS_INFO}; use color_eyre::eyre::{eyre, OptionExt, Result}; use glam::{vec3a, Mat4, Quat, Vec3}; @@ -38,6 +37,9 @@ impl Transform { Mat4::from_scale_rotation_translation(scale.into(), rotation.into(), position.into()) } } +impl Aspect for Zone { + impl_aspect_for_zone_aspect! {} +} lazy_static::lazy_static! { pub static ref EXPORTED_SPATIALS: Mutex>> = Mutex::new(FxHashMap::default()); @@ -74,16 +76,14 @@ impl Spatial { zoneable: bool, ) -> Arc { let spatial = Spatial::new(Arc::downgrade(node), parent.clone(), transform); - ::add_node_members(node); if zoneable { ZONEABLE_REGISTRY.add_raw(&spatial); } if let Some(parent) = parent { parent.children.add_raw(&spatial); } - ::add_node_members(node); - ::add_node_members(node); node.add_aspect_raw(spatial.clone()); + node.add_aspect(SpatialRef); spatial } @@ -242,66 +242,7 @@ impl Spatial { } } impl Aspect for Spatial { - const NAME: &'static str = "Spatial"; -} -impl SpatialRefAspect for Spatial { - async fn get_local_bounding_box( - node: Arc, - _calling_client: Arc, - ) -> Result { - let this_spatial = node.get_aspect::()?; - let bounds = this_spatial.get_bounding_box(); - - Ok(BoundingBox { - center: Vec3::from(bounds.center).into(), - size: Vec3::from(bounds.dimensions).into(), - }) - } - - async fn get_relative_bounding_box( - node: Arc, - _calling_client: Arc, - relative_to: Arc, - ) -> Result { - let this_spatial = node.get_aspect::()?; - let relative_spatial = relative_to.get_aspect::()?; - let center = Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)) - .transform_point3([0.0; 3].into()); - let mut bounds = Bounds { - center: center.into(), - dimensions: [0.0; 3].into(), - }; - bounds.grown_box( - this_spatial.get_bounding_box(), - Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)), - ); - - Ok(BoundingBox { - center: Vec3::from(bounds.center).into(), - size: Vec3::from(bounds.dimensions).into(), - }) - } - - async fn get_transform( - node: Arc, - _calling_client: Arc, - relative_to: Arc, - ) -> Result { - let this_spatial = node.get_aspect::()?; - let relative_spatial = relative_to.get_aspect::()?; - - let (scale, rotation, position) = Spatial::space_to_space_matrix( - Some(this_spatial.as_ref()), - Some(relative_spatial.as_ref()), - ) - .to_scale_rotation_translation(); - - Ok(Transform { - translation: Some(position.into()), - rotation: Some(rotation.into()), - scale: Some(scale.into()), - }) - } + impl_aspect_for_spatial_aspect! {} } impl SpatialAspect for Spatial { fn set_local_transform( @@ -389,6 +330,70 @@ impl Drop for Spatial { } } +pub struct SpatialRef; +impl Aspect for SpatialRef { + impl_aspect_for_spatial_ref_aspect! {} +} +impl SpatialRefAspect for SpatialRef { + async fn get_local_bounding_box( + node: Arc, + _calling_client: Arc, + ) -> Result { + let this_spatial = node.get_aspect::()?; + let bounds = this_spatial.get_bounding_box(); + + Ok(BoundingBox { + center: Vec3::from(bounds.center).into(), + size: Vec3::from(bounds.dimensions).into(), + }) + } + + async fn get_relative_bounding_box( + node: Arc, + _calling_client: Arc, + relative_to: Arc, + ) -> Result { + let this_spatial = node.get_aspect::()?; + let relative_spatial = relative_to.get_aspect::()?; + let center = Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)) + .transform_point3([0.0; 3].into()); + let mut bounds = Bounds { + center: center.into(), + dimensions: [0.0; 3].into(), + }; + bounds.grown_box( + this_spatial.get_bounding_box(), + Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)), + ); + + Ok(BoundingBox { + center: Vec3::from(bounds.center).into(), + size: Vec3::from(bounds.dimensions).into(), + }) + } + + async fn get_transform( + node: Arc, + _calling_client: Arc, + relative_to: Arc, + ) -> Result { + let this_spatial = node.get_aspect::()?; + let relative_spatial = relative_to.get_aspect::()?; + + let (scale, rotation, position) = Spatial::space_to_space_matrix( + Some(this_spatial.as_ref()), + Some(relative_spatial.as_ref()), + ) + .to_scale_rotation_translation(); + + Ok(Transform { + translation: Some(position.into()), + rotation: Some(rotation.into()), + scale: Some(scale.into()), + }) + } +} + pub fn parse_transform(transform: Transform, position: bool, rotation: bool, scale: bool) -> Mat4 { let position = position .then_some(transform.translation) @@ -406,8 +411,7 @@ pub fn parse_transform(transform: Transform, position: bool, rotation: bool, sca Mat4::from_scale_rotation_translation(scale.into(), rotation.into(), position.into()) } -pub struct SpatialInterface; -impl InterfaceAspect for SpatialInterface { +impl InterfaceAspect for Interface { fn create_spatial( _node: Arc, calling_client: Arc, @@ -460,5 +464,3 @@ impl InterfaceAspect for SpatialInterface { .ok_or_eyre("Couldn't find spatial with that ID") } } - -create_interface!(SpatialInterface); diff --git a/src/nodes/spatial/zone.rs b/src/nodes/spatial/zone.rs index b4703f4..420f33c 100644 --- a/src/nodes/spatial/zone.rs +++ b/src/nodes/spatial/zone.rs @@ -7,7 +7,7 @@ use crate::{ nodes::{ alias::{get_original, Alias, AliasList}, fields::{Field, FieldTrait}, - Aspect, Node, + Node, }, }; use color_eyre::eyre::Result; @@ -73,7 +73,6 @@ impl Zone { intersecting: AliasList::default(), captured: AliasList::default(), }); - ::add_node_members(node); node.add_aspect_raw(zone.clone()); zone } @@ -124,9 +123,6 @@ impl Zone { Ok(()) } } -impl Aspect for Zone { - const NAME: &'static str = "Zone"; -} impl ZoneAspect for Zone { fn update(node: Arc, _calling_client: Arc) -> Result<()> { let zone = node.get_aspect::()?; diff --git a/src/objects/input/sk_hand.rs b/src/objects/input/sk_hand.rs index 06b1bde..730bd86 100644 --- a/src/objects/input/sk_hand.rs +++ b/src/objects/input/sk_hand.rs @@ -12,7 +12,6 @@ use color_eyre::eyre::Result; use glam::{Mat4, Quat, Vec3}; use serde::{Deserialize, Serialize}; use stardust_xr::values::Datamap; -use std::f32::INFINITY; use std::sync::Arc; use stereokit_rust::sk::{DisplayMode, MainThreadToken, Sk}; use stereokit_rust::system::{HandJoint, HandSource, Handed, Input, LinePoint, Lines}; diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index f129787..356e797 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -93,7 +93,6 @@ impl Drop for UnownedFd { pub struct Wayland { display: Arc, - pub socket_name: Option, join_handle: JoinHandle>, renderer: GlesRenderer, output: Output, @@ -133,7 +132,6 @@ impl Wayland { Ok(Wayland { display, - socket_name, join_handle, renderer, output,