diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 1d233a3..8e80aa4 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -77,12 +77,12 @@ fn codegen_protocol(protocol: &'static str) -> proc_macro::TokenStream { .map(generate_custom_struct) .reduce(fold_tokens) .unwrap_or_default(); - // let aspects = protocol - // .aspects - // .iter() - // .map(generate_aspect) - // .reduce(fold_tokens) - // .unwrap_or_default(); + let aspects = protocol + .aspects + .iter() + .map(generate_aspect) + .reduce(fold_tokens) + .unwrap_or_default(); // let nodes = protocol // .nodes // .iter() @@ -96,7 +96,7 @@ fn codegen_protocol(protocol: &'static str) -> proc_macro::TokenStream { // .reduce(fold_tokens) // .unwrap_or_default(); // quote!(#custom_enums #custom_unions #custom_structs #aspects #nodes #interfaces).into() - quote!(#custom_enums #custom_unions #custom_structs).into() + quote!(#custom_enums #custom_unions #custom_structs #aspects).into() } fn generate_custom_enum(custom_enum: &CustomEnum) -> TokenStream { @@ -149,28 +149,6 @@ fn generate_union_option(union_option: &UnionOption) -> TokenStream { let _type = generate_argument_type(&union_option._type, true); quote! (#description #identifier(#_type)) } -fn argument_type_option_name(argument_type: &ArgumentType) -> String { - match argument_type { - ArgumentType::Bool => "Bool".to_string(), - ArgumentType::Int => "Int".to_string(), - ArgumentType::UInt => "UInt".to_string(), - ArgumentType::Float => "Float".to_string(), - ArgumentType::Vec2 => "Vec2".to_string(), - ArgumentType::Vec3 => "Vec3".to_string(), - ArgumentType::Quat => "Quat".to_string(), - ArgumentType::Color => "Color".to_string(), - ArgumentType::String => "String".to_string(), - ArgumentType::Bytes => "Bytes".to_string(), - ArgumentType::Vec(v) => format!("{}Vector", argument_type_option_name(&v)), - ArgumentType::Map(m) => format!("{}Map", argument_type_option_name(&m)), - ArgumentType::Datamap => "Datamap".to_string(), - ArgumentType::ResourceID => "ResourceID".to_string(), - ArgumentType::Enum(e) => e.clone(), - ArgumentType::Union(u) => u.clone(), - ArgumentType::Struct(s) => s.clone(), - ArgumentType::Node { _type, .. } => _type.clone(), - } -} fn generate_custom_struct(custom_struct: &CustomStruct) -> TokenStream { let name = Ident::new(&custom_struct.name.to_case(Case::Pascal), Span::call_site()); let description = &custom_struct.description; @@ -257,25 +235,6 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream { } }) .unwrap_or_default(); - let aspect_wrap = aspect - .members - .iter() - .filter(|m| m.side == Side::Client) - .map(generate_handler) - .reduce(fold_tokens).map(|handlers| { - quote! { - #[must_use = "Dropping this handler wrapper would immediately drop the handler"] - fn wrap(self, handler: H) -> NodeResult> { - self.wrap_raw(std::sync::Arc::new(parking_lot::Mutex::new(handler))) - } - #[must_use = "Dropping this handler wrapper would immediately drop the handler"] - fn wrap_raw(self, handler: std::sync::Arc>) -> NodeResult> { - let handler_wrapper = crate::HandlerWrapper::new_raw(self, handler); - #handlers - Ok(handler_wrapper) - } - } - }).unwrap_or_default(); let aspect_trait_name = Ident::new( &format!("{}Aspect", &aspect.name.to_case(Case::Pascal)), @@ -285,10 +244,24 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream { .map(generate_member) .reduce(fold_tokens) .unwrap_or_default(); + let add_node_members = aspect + .members + .iter() + .filter(|m| m.side == Side::Server) + .map(generate_handler) + .reduce(fold_tokens) + .map(|members| { + quote! { + fn add_node_members(node: &Node) { + #members + } + } + }) + .unwrap_or_default(); let server_side_members = quote! { #[doc = #description] - pub trait #aspect_trait_name: crate::node::NodeType { - #aspect_wrap + pub trait #aspect_trait_name { + #add_node_members #server_side_members } }; @@ -303,20 +276,16 @@ fn generate_member(member: &Member) -> TokenStream { let side = member.side; let _type = member._type; - let first_arg = if member.interface_path.is_some() { - quote!(client: &std::sync::Arc) + let first_args = if member.side == Side::Server { + quote!(_node: std::sync::Arc, _calling_client: std::sync::Arc, _fds: Vec) } else { - if member.side == Side::Server { - quote!(&self) - } else { - quote!(&mut self) - } + quote!(&mut self) }; let argument_decls = member .arguments .iter() - .map(|a| generate_argument_decl(a, member.side == Side::Client)) - .fold(first_arg, |a, b| quote!(#a, #b)); + .map(|a| generate_argument_decl(a, member.side == Side::Server)) + .fold(first_args, |a, b| quote!(#a, #b)); let argument_uses = member .arguments @@ -331,7 +300,7 @@ fn generate_member(member: &Member) -> TokenStream { .unwrap_or_else(|| quote!(())); match (side, _type) { - (Side::Server, MemberType::Method) => { + (Side::Client, MemberType::Method) => { let body = if let Some(interface_path) = &member.interface_path { quote! { let data = stardust_xr::schemas::flex::serialize(&(#argument_uses))?; @@ -350,8 +319,8 @@ fn generate_member(member: &Member) -> TokenStream { } } } - (Side::Server, MemberType::Signal) => { - let mut body = if let Some(interface_path) = &member.interface_path { + (Side::Client, MemberType::Signal) => { + let body = if let Some(interface_path) = &member.interface_path { quote! { client.message_sender_handle.signal(#interface_path, #name_str, &stardust_xr::schemas::flex::serialize(&(#argument_uses))?, Vec::new()) } @@ -360,33 +329,6 @@ fn generate_member(member: &Member) -> TokenStream { self.node().send_remote_signal(#name_str, &(#argument_uses)) } }; - body = if let Some(ArgumentType::Node { - _type: _, - return_info, - }) = &member.return_type - { - if let Some(return_info) = return_info { - let parent = &return_info.parent; - let name_argument = Ident::new(&return_info.name_argument, Span::call_site()); - let get_client = if member.interface_path.is_some() { - quote!(client) - } else { - quote!(self.node().client()?) - }; - quote! { - #body?; - Ok(<#return_type as crate::node::NodeType>::from_parent_name(#get_client, #parent, &#name_argument, true)) - } - } else { - quote! { - Ok(#body?) - } - } - } else { - quote! { - Ok(#body?) - } - }; quote! { #[doc = #description] fn #name(#argument_decls) -> crate::node::NodeResult<#return_type> { @@ -394,23 +336,23 @@ fn generate_member(member: &Member) -> TokenStream { } } } - (Side::Client, MemberType::Method) => { + (Side::Server, MemberType::Method) => { quote! { #[doc = #description] - fn #name(#argument_decls) -> crate::node::MethodResult<#return_type>; + fn #name(#argument_decls) -> impl std::future::Future)>> + Send + 'static; } } - (Side::Client, MemberType::Signal) => { + (Side::Server, MemberType::Signal) => { quote! { #[doc = #description] - fn #name(#argument_decls); + fn #name(#argument_decls) -> color_eyre::eyre::Result<#return_type>; } } } } fn generate_handler(member: &Member) -> TokenStream { - let name = &member.name; - let name_ident = Ident::new(&name, Span::call_site()); + let member_name = &member.name; + let member_name_ident = Ident::new(&member_name, Span::call_site()); let argument_names = member .arguments @@ -429,48 +371,56 @@ fn generate_handler(member: &Member) -> TokenStream { .clone() .zip(argument_types) .map(|(argument_names, argument_types)| { - quote!(let (#argument_names): (#argument_types) = stardust_xr::schemas::flex::deserialize(_data)?;) + quote!(let (#argument_names): (#argument_types) = stardust_xr::schemas::flex::deserialize(_message.as_ref())?;) }) .unwrap_or_default(); let argument_uses = member .arguments .iter() .map(|a| generate_argument_deserialize(&a.name, &a._type, a.optional)) - .fold(TokenStream::default(), |a, b| quote!(#a, #b)); - let handler_wrapper_method_name = match member._type { - MemberType::Signal => quote!(add_handled_signal), - MemberType::Method => quote!(add_handled_method), - }; - - quote! { - handler_wrapper.#handler_wrapper_method_name(#name, |_node, _handler, _data, _fds| { - #deserialize - let _client = _node.client()?; - let mut _handler_lock = _handler.lock(); - Ok(H::#name_ident(&mut *_handler_lock #argument_uses)) - })?; + .reduce(|a, b| quote!(#a, #b)) + .unwrap_or_default(); + match member._type { + MemberType::Signal => quote! { + node.add_local_signal(#member_name, |_node, _calling_client, _message| { + #deserialize + let _fds = _message.fds; + Self::#member_name_ident(_node, _calling_client.clone(), _fds, #argument_uses) + }); + }, + MemberType::Method => quote! { + node.add_local_method(#member_name, |_node, _calling_client, _message, _method_response| { + _method_response.wrap_async(async move { + #deserialize + let _fds = _message.fds; + Self::#member_name_ident(_node, _calling_client.clone(), _fds, #argument_uses).await + }); + }); + }, } } fn generate_argument_name(argument: &Argument) -> TokenStream { Ident::new(&argument.name.to_case(Case::Snake), Span::call_site()).to_token_stream() } + +fn convert_deserializeable_argument_type(argument_type: &ArgumentType) -> ArgumentType { + match argument_type { + ArgumentType::Node { .. } => ArgumentType::String, + f => f.clone(), + } +} fn generate_argument_deserialize( argument_name: &str, argument_type: &ArgumentType, optional: bool, ) -> TokenStream { let name = Ident::new(&argument_name.to_case(Case::Snake), Span::call_site()); + match argument_type { - ArgumentType::Node { - _type, - return_info: _, - } => { - let node_type = Ident::new(&_type.to_case(Case::Pascal), Span::call_site()); - match optional { - true => quote!(#name.map(|n| #node_type::from_path(&_client, n, false))), - false => quote!(#node_type::from_path(&_client, #name, false)), - } - } + ArgumentType::Node { .. } => match optional { + true => quote!(#name.map(|n| _calling_client.get_node(#argument_name, &n)?)), + false => quote!(_calling_client.get_node(#argument_name, &#name)?), + }, ArgumentType::Color => quote!(color::rgba_linear!(#name[0], #name[1], #name[2], #name[3])), ArgumentType::Vec(v) => { let mapping = generate_argument_deserialize("a", v, false); @@ -483,13 +433,6 @@ fn generate_argument_deserialize( _ => quote!(#name), } } -fn convert_deserializeable_argument_type(argument_type: &ArgumentType) -> ArgumentType { - match argument_type { - ArgumentType::Node { .. } => ArgumentType::String, - f => f.clone(), - } -} - fn generate_argument_serialize( argument_name: &str, argument_type: &ArgumentType, @@ -524,6 +467,28 @@ fn generate_argument_decl(argument: &Argument, returned: bool) -> TokenStream { } quote!(#name: #_type) } +fn argument_type_option_name(argument_type: &ArgumentType) -> String { + match argument_type { + ArgumentType::Bool => "Bool".to_string(), + ArgumentType::Int => "Int".to_string(), + ArgumentType::UInt => "UInt".to_string(), + ArgumentType::Float => "Float".to_string(), + ArgumentType::Vec2 => "Vec2".to_string(), + ArgumentType::Vec3 => "Vec3".to_string(), + ArgumentType::Quat => "Quat".to_string(), + ArgumentType::Color => "Color".to_string(), + ArgumentType::String => "String".to_string(), + ArgumentType::Bytes => "Bytes".to_string(), + ArgumentType::Vec(v) => format!("{}Vector", argument_type_option_name(&v)), + ArgumentType::Map(m) => format!("{}Map", argument_type_option_name(&m)), + ArgumentType::Datamap => "Datamap".to_string(), + ArgumentType::ResourceID => "ResourceID".to_string(), + ArgumentType::Enum(e) => e.clone(), + ArgumentType::Union(u) => u.clone(), + ArgumentType::Struct(s) => s.clone(), + ArgumentType::Node { _type, .. } => _type.clone(), + } +} fn generate_argument_type(argument_type: &ArgumentType, owned: bool) -> TokenStream { match argument_type { ArgumentType::Bool => quote!(bool), @@ -595,16 +560,7 @@ fn generate_argument_type(argument_type: &ArgumentType, owned: bool) -> TokenStr _type, return_info: _, } => { - if !owned { - let aspect = Ident::new( - &format!("{}Aspect", _type.to_case(Case::Pascal)), - Span::call_site(), - ); - quote!(&impl #aspect) - } else { - let node = Ident::new(&_type.to_case(Case::Pascal), Span::call_site()); - quote!(#node) - } + quote!(Arc) } } } diff --git a/src/core/scenegraph.rs b/src/core/scenegraph.rs index d09e3a6..11e1cbe 100644 --- a/src/core/scenegraph.rs +++ b/src/core/scenegraph.rs @@ -5,8 +5,11 @@ use once_cell::sync::OnceCell; use parking_lot::Mutex; use portable_atomic::Ordering; use rustc_hash::FxHashMap; +use serde::Serialize; use stardust_xr::scenegraph; use stardust_xr::scenegraph::ScenegraphError; +use stardust_xr::schemas::flex::serialize; +use std::future::Future; use std::os::fd::OwnedFd; use std::sync::{Arc, Weak}; use tokio::sync::oneshot; @@ -57,11 +60,35 @@ impl MethodResponseSender { pub fn send(self, t: Result) { let _ = self.0.send(t.map(|m| (m.data, m.fds))); } + // pub fn send_method_return( + // self, + // result: color_eyre::eyre::Result<(T, Vec)>, + // ) { + // let _ = self.0.send(map_method_return(result)); + // } pub fn wrap_sync color_eyre::eyre::Result>(self, f: F) { self.send(f().map_err(|e| ScenegraphError::MethodError { error: e.to_string(), })) } + pub fn wrap_async( + self, + f: impl Future)>> + Send + 'static, + ) { + tokio::task::spawn(async move { self.0.send(map_method_return(f.await)) }); + } +} +fn map_method_return( + result: color_eyre::eyre::Result<(T, Vec)>, +) -> Result<(Vec, Vec), ScenegraphError> { + let (value, fds) = result.map_err(|e| ScenegraphError::MethodError { + error: e.to_string(), + })?; + + let serialized_value = serialize(value).map_err(|e| ScenegraphError::MethodError { + error: format!("Internal: Serialization failed: {e}"), + })?; + Ok((serialized_value, fds)) } impl scenegraph::Scenegraph for Scenegraph { fn send_signal( diff --git a/src/nodes/audio.rs b/src/nodes/audio.rs index c89e508..f0da82e 100644 --- a/src/nodes/audio.rs +++ b/src/nodes/audio.rs @@ -83,13 +83,17 @@ impl Sound { } } - fn play_flex(node: &Node, _calling_client: Arc, _message: Message) -> Result<()> { + fn play_flex(node: Arc, _calling_client: Arc, _message: Message) -> Result<()> { let sound = node.sound.get().unwrap(); sound.play.lock().replace(()); Ok(()) } - pub fn stop_flex(node: &Node, _calling_client: Arc, _message: Message) -> Result<()> { + pub fn stop_flex( + node: Arc, + _calling_client: Arc, + _message: Message, + ) -> Result<()> { let sound = node.sound.get().unwrap(); sound.stop.lock().replace(()); Ok(()) @@ -108,7 +112,7 @@ pub fn create_interface(client: &Arc) -> Result<()> { node.add_to_scenegraph().map(|_| ()) } -pub fn create_flex(_node: &Node, calling_client: Arc, message: Message) -> Result<()> { +pub fn create_flex(_node: Arc, calling_client: Arc, message: Message) -> Result<()> { #[derive(Deserialize)] struct CreateSoundInfo<'a> { name: &'a str, diff --git a/src/nodes/data.rs b/src/nodes/data.rs index c980970..b89d1f0 100644 --- a/src/nodes/data.rs +++ b/src/nodes/data.rs @@ -188,7 +188,11 @@ impl PulseSender { let _ = tx_node.send_remote_signal("drop_receiver", data); } - fn send_data_flex(node: &Node, calling_client: Arc, message: Message) -> Result<()> { + fn send_data_flex( + node: Arc, + calling_client: Arc, + message: Message, + ) -> Result<()> { let info: SendDataInfo = deserialize(message.as_ref())?; let receiver_node = calling_client.get_node("Pulse receiver", info.uid)?; let receiver = @@ -271,7 +275,7 @@ pub fn create_interface(client: &Arc) -> Result<()> { } pub fn create_pulse_sender_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { @@ -297,7 +301,7 @@ pub fn create_pulse_sender_flex( } pub fn create_pulse_receiver_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { @@ -324,7 +328,7 @@ pub fn create_pulse_receiver_flex( } pub fn register_keymap_flex( - _node: &Node, + _node: Arc, _calling_client: Arc, message: Message, response: MethodResponseSender, @@ -348,7 +352,7 @@ pub fn register_keymap_flex( }); } pub fn get_keymap_flex( - _node: &Node, + _node: Arc, _calling_client: Arc, message: Message, response: MethodResponseSender, diff --git a/src/nodes/drawable/lines.rs b/src/nodes/drawable/lines.rs index 8e25e10..50381f1 100644 --- a/src/nodes/drawable/lines.rs +++ b/src/nodes/drawable/lines.rs @@ -119,7 +119,7 @@ impl Lines { } pub fn set_lines_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -149,7 +149,7 @@ pub fn draw_all(draw_ctx: &impl StereoKitDraw) { } } -pub fn create_flex(_node: &Node, calling_client: Arc, message: Message) -> Result<()> { +pub fn create_flex(_node: Arc, calling_client: Arc, message: Message) -> Result<()> { #[derive(Deserialize)] struct CreateLinesInfo<'a> { name: &'a str, diff --git a/src/nodes/drawable/mod.rs b/src/nodes/drawable/mod.rs index 10eb2a2..c035c3f 100644 --- a/src/nodes/drawable/mod.rs +++ b/src/nodes/drawable/mod.rs @@ -56,7 +56,11 @@ pub fn draw(sk: &impl StereoKitDraw) { static QUEUED_SKYLIGHT: Mutex> = Mutex::new(None); static QUEUED_SKYTEX: Mutex> = Mutex::new(None); -fn set_sky_file_flex(_node: &Node, _calling_client: Arc, message: Message) -> Result<()> { +fn set_sky_file_flex( + _node: Arc, + _calling_client: Arc, + message: Message, +) -> Result<()> { #[derive(Deserialize)] struct SkyFileInfo { path: PathBuf, diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index f6c2785..ed833f0 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -244,7 +244,7 @@ impl ModelPart { } fn apply_holdout_material_flex( - node: &Node, + node: Arc, _calling_client: Arc, _message: Message, ) -> Result<()> { @@ -256,7 +256,7 @@ impl ModelPart { } fn set_material_parameter_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -403,7 +403,7 @@ pub fn draw_all(sk: &impl StereoKitDraw) { } } -pub fn create_flex(_node: &Node, calling_client: Arc, message: Message) -> Result<()> { +pub fn create_flex(_node: Arc, calling_client: Arc, message: Message) -> Result<()> { #[derive(Deserialize)] struct CreateModelInfo<'a> { name: &'a str, diff --git a/src/nodes/drawable/text.rs b/src/nodes/drawable/text.rs index 8084285..7990e18 100644 --- a/src/nodes/drawable/text.rs +++ b/src/nodes/drawable/text.rs @@ -146,7 +146,7 @@ impl Text { } pub fn set_character_height_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -159,7 +159,7 @@ impl Text { } pub fn set_text_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -188,7 +188,7 @@ pub fn draw_all(sk: &impl StereoKitDraw) { } } -pub fn create_flex(_node: &Node, calling_client: Arc, message: Message) -> Result<()> { +pub fn create_flex(_node: Arc, calling_client: Arc, message: Message) -> Result<()> { #[derive(Deserialize)] struct CreateTextInfo<'a> { name: &'a str, diff --git a/src/nodes/fields/box.rs b/src/nodes/fields/box.rs index 31872dd..fac9a81 100644 --- a/src/nodes/fields/box.rs +++ b/src/nodes/fields/box.rs @@ -42,7 +42,7 @@ impl BoxField { } pub fn set_size_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -72,7 +72,7 @@ impl FieldTrait for BoxField { } pub fn create_box_field_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/fields/cylinder.rs b/src/nodes/fields/cylinder.rs index e23658a..4427c22 100644 --- a/src/nodes/fields/cylinder.rs +++ b/src/nodes/fields/cylinder.rs @@ -44,7 +44,7 @@ impl CylinderField { } pub fn set_size_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -71,7 +71,7 @@ impl FieldTrait for CylinderField { } pub fn create_cylinder_field_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/fields/mod.rs b/src/nodes/fields/mod.rs index f6a9a63..5857f21 100644 --- a/src/nodes/fields/mod.rs +++ b/src/nodes/fields/mod.rs @@ -137,7 +137,7 @@ const MAX_RAY_MARCH: f32 = f32::MAX; const MAX_RAY_LENGTH: f32 = 1000_f32; fn field_distance_flex( - node: &Node, + node: Arc, calling_client: Arc, message: Message, response: MethodResponseSender, @@ -160,7 +160,7 @@ fn field_distance_flex( }); } fn field_normal_flex( - node: &Node, + node: Arc, calling_client: Arc, message: Message, response: MethodResponseSender, @@ -183,7 +183,7 @@ fn field_normal_flex( }); } fn field_closest_point_flex( - node: &Node, + node: Arc, calling_client: Arc, message: Message, response: MethodResponseSender, @@ -206,7 +206,7 @@ fn field_closest_point_flex( }); } fn field_ray_march_flex( - node: &Node, + node: Arc, calling_client: Arc, message: Message, response: MethodResponseSender, diff --git a/src/nodes/fields/sphere.rs b/src/nodes/fields/sphere.rs index 1d5f15c..b87de24 100644 --- a/src/nodes/fields/sphere.rs +++ b/src/nodes/fields/sphere.rs @@ -41,11 +41,13 @@ impl SphereField { } pub fn set_radius_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { - let Field::Sphere(sphere_field) = node.field.get().unwrap().as_ref() else { return Ok(()) }; + let Field::Sphere(sphere_field) = node.field.get().unwrap().as_ref() else { + return Ok(()); + }; sphere_field.set_radius(deserialize(message.as_ref())?); Ok(()) } @@ -67,7 +69,7 @@ impl FieldTrait for SphereField { } pub fn create_sphere_field_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/fields/torus.rs b/src/nodes/fields/torus.rs index 587576d..b491702 100644 --- a/src/nodes/fields/torus.rs +++ b/src/nodes/fields/torus.rs @@ -44,7 +44,7 @@ impl TorusField { } pub fn set_size_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -71,7 +71,7 @@ impl FieldTrait for TorusField { } pub fn create_torus_field_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/input/mod.rs b/src/nodes/input/mod.rs index e3a363e..2b781ed 100644 --- a/src/nodes/input/mod.rs +++ b/src/nodes/input/mod.rs @@ -109,23 +109,31 @@ impl InputMethod { .cloned() } - fn capture_flex(node: &Node, calling_client: Arc, message: Message) -> Result<()> { - let method = InputMethod::get(node)?; + fn capture_flex(node: Arc, calling_client: Arc, message: Message) -> Result<()> { + let method = InputMethod::get(&node)?; let handler = InputHandler::find(&calling_client, deserialize(message.as_ref())?)?; method.captures.add_raw(&handler); node.send_remote_signal("capture", message) } - fn set_datamap_flex(node: &Node, _calling_client: Arc, message: Message) -> Result<()> { - let method = InputMethod::get(node)?; + fn set_datamap_flex( + node: Arc, + _calling_client: Arc, + message: Message, + ) -> Result<()> { + let method = InputMethod::get(&node)?; method .datamap .lock() .replace(Datamap::from_raw(message.data)?); Ok(()) } - fn set_handlers_flex(node: &Node, calling_client: Arc, message: Message) -> Result<()> { - let method = InputMethod::get(node)?; + fn set_handlers_flex( + node: Arc, + calling_client: Arc, + message: Message, + ) -> Result<()> { + let method = InputMethod::get(&node)?; let handler_paths: Vec<&str> = deserialize(message.as_ref())?; let handlers: Vec> = handler_paths .into_iter() @@ -352,7 +360,7 @@ pub fn create_interface(client: &Arc) -> Result<()> { } pub fn create_input_handler_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/input/pointer.rs b/src/nodes/input/pointer.rs index 5eb58c7..7f8dbac 100644 --- a/src/nodes/input/pointer.rs +++ b/src/nodes/input/pointer.rs @@ -66,7 +66,7 @@ impl InputSpecialization for Pointer { } pub fn create_pointer_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> color_eyre::eyre::Result<()> { diff --git a/src/nodes/input/tip.rs b/src/nodes/input/tip.rs index e6395d5..6679628 100644 --- a/src/nodes/input/tip.rs +++ b/src/nodes/input/tip.rs @@ -18,7 +18,7 @@ pub struct Tip { pub radius: f32, } impl Tip { - fn set_radius(node: &Node, _calling_client: Arc, message: Message) -> Result<()> { + fn set_radius(node: Arc, _calling_client: Arc, message: Message) -> Result<()> { if let InputType::Tip(tip) = &mut *node.input_method.get().unwrap().specialization.lock() { tip.radius = deserialize(message.as_ref())?; } @@ -46,7 +46,11 @@ impl InputSpecialization for Tip { } } -pub fn create_tip_flex(_node: &Node, calling_client: Arc, message: Message) -> Result<()> { +pub fn create_tip_flex( + _node: Arc, + calling_client: Arc, + message: Message, +) -> Result<()> { #[derive(Deserialize)] struct CreateTipInfo<'a> { name: &'a str, diff --git a/src/nodes/items/camera.rs b/src/nodes/items/camera.rs index 3c51c1e..01171f7 100644 --- a/src/nodes/items/camera.rs +++ b/src/nodes/items/camera.rs @@ -77,7 +77,7 @@ impl CameraItem { } fn frame_flex( - node: &Node, + node: Arc, _calling_client: Arc, _message: Message, response: MethodResponseSender, @@ -91,7 +91,7 @@ impl CameraItem { } fn apply_preview_material_flex( - node: &Node, + node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { @@ -164,7 +164,7 @@ pub fn update(sk: &impl StereoKitDraw) { } pub(super) fn create_camera_item_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/items/environment.rs b/src/nodes/items/environment.rs index f753e01..9cb0ff4 100644 --- a/src/nodes/items/environment.rs +++ b/src/nodes/items/environment.rs @@ -45,7 +45,7 @@ impl EnvironmentItem { } fn get_path_flex( - node: &Node, + node: Arc, _calling_client: Arc, _message: Message, response: MethodResponseSender, @@ -65,7 +65,7 @@ impl EnvironmentItem { } pub(super) fn create_environment_item_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/items/mod.rs b/src/nodes/items/mod.rs index 3465811..1e77e76 100644 --- a/src/nodes/items/mod.rs +++ b/src/nodes/items/mod.rs @@ -156,7 +156,11 @@ impl Item { self.make_alias_named(client, parent, &self.uid) } - fn release_flex(node: &Node, _calling_client: Arc, _message: Message) -> Result<()> { + fn release_flex( + node: Arc, + _calling_client: Arc, + _message: Message, + ) -> Result<()> { let item = node.get_aspect("Item", "item", |n| &n.item)?; release(item); @@ -341,7 +345,7 @@ impl ItemAcceptor { let _ = node.item_acceptor.set(acceptor); } - fn capture_flex(node: &Node, calling_client: Arc, message: Message) -> Result<()> { + fn capture_flex(node: Arc, calling_client: Arc, message: Message) -> Result<()> { if !node.enabled.load(Ordering::Relaxed) { return Ok(()); } @@ -443,7 +447,7 @@ fn type_info(name: &str) -> Result<&'static TypeInfo> { } pub fn register_item_ui_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { @@ -460,7 +464,7 @@ pub fn register_item_ui_flex( } fn create_item_acceptor_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/items/panel.rs b/src/nodes/items/panel.rs index 0679cc7..7bb381f 100644 --- a/src/nodes/items/panel.rs +++ b/src/nodes/items/panel.rs @@ -95,8 +95,8 @@ impl<'de> Visitor<'de> for SurfaceIDVisitor { fn visit_seq>(self, mut seq: A) -> Result { let Some(discrim) = seq.next_element()? else { - return Err(A::Error::missing_field("discrim")); - }; + return Err(A::Error::missing_field("discrim")); + }; // idk if you wanna check for extraneous elements // I didn't bother @@ -106,8 +106,8 @@ impl<'de> Visitor<'de> for SurfaceIDVisitor { "Toplevel" => Ok(SurfaceID::Toplevel), "Child" => { let Some(text) = seq.next_element()? else { - return Err(A::Error::missing_field("child_text")); - }; + return Err(A::Error::missing_field("child_text")); + }; Ok(SurfaceID::Child(text)) } _ => Err(A::Error::unknown_variant( @@ -203,7 +203,9 @@ pub trait Backend: Send + Sync + 'static { } pub fn panel_item_from_node(node: &Node) -> Option> { - let ItemType::Panel(panel_item) = &node.item.get()?.specialization else {return None}; + let ItemType::Panel(panel_item) = &node.item.get()?.specialization else { + return None; + }; Some(panel_item.clone()) } @@ -270,7 +272,9 @@ impl PanelItem { panel_item } pub fn drop_toplevel(&self) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; node.destroy(); } } @@ -278,60 +282,88 @@ impl PanelItem { // Remote signals impl PanelItem { pub fn toplevel_parent_changed(&self, parent: &str) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("toplevel_parent_changed", serialize(parent).unwrap()); } pub fn toplevel_title_changed(&self, title: &str) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("toplevel_title_changed", serialize(title).unwrap()); } pub fn toplevel_app_id_changed(&self, app_id: &str) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("toplevel_app_id_changed", serialize(app_id).unwrap()); } pub fn toplevel_fullscreen_active(&self, active: bool) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("toplevel_fullscreen_active", serialize(active).unwrap()); } pub fn toplevel_move_request(&self) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("toplevel_move_request", Vec::::new()); } pub fn toplevel_resize_request(&self, up: bool, down: bool, left: bool, right: bool) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal( "toplevel_resize_request", serialize((up, down, left, right)).unwrap(), ); } pub fn toplevel_size_changed(&self, size: Vector2) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("toplevel_size_changed", serialize(size).unwrap()); } pub fn set_cursor(&self, geometry: Option) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("set_cursor", serialize(geometry).unwrap()); } pub fn new_child(&self, uid: &str, info: ChildInfo) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("new_child", serialize((uid, info)).unwrap()); } pub fn reposition_child(&self, uid: &str, geometry: Geometry) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("reposition_child", serialize((uid, geometry)).unwrap()); } pub fn drop_child(&self, uid: &str) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; let _ = node.send_remote_signal("drop_child", serialize(uid).unwrap()); } } // Local signals macro_rules! flex_no_args { ($fn_name: ident, $trait_fn: ident) => { - fn $fn_name(node: &Node, _calling_client: Arc, _message: Message) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + fn $fn_name( + node: Arc, + _calling_client: Arc, + _message: Message, + ) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; panel_item.$trait_fn(); Ok(()) } @@ -339,8 +371,10 @@ macro_rules! flex_no_args { } macro_rules! flex_deserialize { ($fn_name: ident, $trait_fn: ident) => { - fn $fn_name(node: &Node, _calling_client: Arc, message: Message) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + fn $fn_name(node: Arc, _calling_client: Arc, message: Message) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; panel_item.$trait_fn(deserialize(message.as_ref())?); Ok(()) } @@ -348,11 +382,13 @@ macro_rules! flex_deserialize { } impl PanelItem { fn apply_surface_material_flex( - node: &Node, + node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; #[derive(Debug, Deserialize)] struct SurfaceMaterialInfo<'a> { @@ -366,7 +402,9 @@ impl PanelItem { .scenegraph .get_node(info.model_node_path) .ok_or_else(|| eyre!("Model node not found"))?; - let Some(Drawable::ModelPart(model_part)) = model_node.drawable.get() else {bail!("Node is not a model")}; + let Some(Drawable::ModelPart(model_part)) = model_node.drawable.get() else { + bail!("Node is not a model") + }; debug!(?info, "Apply surface material"); panel_item.apply_surface_material(info.surface, model_part); @@ -379,11 +417,13 @@ impl PanelItem { flex_deserialize!(set_toplevel_size_changed_flex, set_toplevel_size); fn pointer_motion_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; let (surface_id, position): (SurfaceID, Vector2) = deserialize(message.as_ref())?; debug!(?surface_id, ?position, "Pointer deactivate"); @@ -393,11 +433,13 @@ impl PanelItem { Ok(()) } fn pointer_button_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; let (surface_id, button, state): (SurfaceID, u32, u32) = deserialize(message.as_ref())?; debug!(?surface_id, button, state, "Pointer button"); @@ -406,11 +448,13 @@ impl PanelItem { Ok(()) } fn pointer_scroll_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; #[derive(Debug, Deserialize)] struct PointerScrollInfo { @@ -427,11 +471,13 @@ impl PanelItem { } fn keyboard_keys_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; let (surface_id, keymap_id, keys): (SurfaceID, &str, Vec) = deserialize(message.as_ref())?; debug!(?keys, "Set keyboard key state"); @@ -441,14 +487,22 @@ impl PanelItem { Ok(()) } pub fn grab_keyboard(&self, sid: Option) { - let Some(node) = self.node.upgrade() else {return}; + let Some(node) = self.node.upgrade() else { + return; + }; - let Ok(message) = serialize(sid) else {return}; + let Ok(message) = serialize(sid) else { return }; let _ = node.send_remote_signal("grab_keyboard", message); } - fn touch_down_flex(node: &Node, _calling_client: Arc, message: Message) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + fn touch_down_flex( + node: Arc, + _calling_client: Arc, + message: Message, + ) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; let (surface_id, id, position): (SurfaceID, u32, Vector2) = deserialize(message.as_ref())?; @@ -458,8 +512,14 @@ impl PanelItem { Ok(()) } - fn touch_move_flex(node: &Node, _calling_client: Arc, message: Message) -> Result<()> { - let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) }; + fn touch_move_flex( + node: Arc, + _calling_client: Arc, + message: Message, + ) -> Result<()> { + let Some(panel_item) = panel_item_from_node(&node) else { + return Ok(()); + }; let (id, position): (u32, Vector2) = deserialize(message.as_ref())?; debug!(?position, "Touch move"); diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index b4b35bf..f733375 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -57,8 +57,8 @@ impl AsRef<[u8]> for Message { } } -pub type Signal = fn(&Node, Arc, Message) -> Result<()>; -pub type Method = fn(&Node, Arc, Message, MethodResponseSender); +pub type Signal = fn(Arc, Arc, Message) -> Result<()>; +pub type Method = fn(Arc, Arc, Message, MethodResponseSender); pub struct Node { pub enabled: Arc, @@ -158,7 +158,7 @@ impl Node { } pub fn set_enabled_flex( - node: &Node, + node: Arc, _calling_client: Arc, message: Message, ) -> Result<()> { @@ -168,7 +168,7 @@ impl Node { } // very much up for debate if we should allow this, as you can match objects using this // pub fn get_client_pid_flex( - // node: &Node, + // node: Arc, // _calling_client: Arc, // _message: Message, // ) -> Result { @@ -180,7 +180,7 @@ impl Node { // Ok(serialize(pid)?.into()) // } pub fn destroy_flex( - node: &Node, + node: Arc, _calling_client: Arc, _message: Message, ) -> Result<()> { @@ -197,12 +197,7 @@ impl Node { self.local_methods.lock().insert(name.to_string(), method); } - pub fn get_aspect( - &self, - node_name: &'static str, - aspect_type: &'static str, - aspect_fn: F, - ) -> Result<&T> + pub fn get_aspect(&self, node_name: &str, aspect_type: &str, aspect_fn: F) -> Result<&T> where F: FnOnce(&Node) -> &OnceCell, { @@ -212,7 +207,7 @@ impl Node { } pub fn send_local_signal( - &self, + self: Arc, calling_client: Arc, method: &str, message: Message, @@ -239,7 +234,7 @@ impl Node { } } pub fn execute_local_method( - &self, + self: Arc, calling_client: Arc, method: &str, message: Message, diff --git a/src/nodes/root.rs b/src/nodes/root.rs index ed718a9..118fb0c 100644 --- a/src/nodes/root.rs +++ b/src/nodes/root.rs @@ -45,7 +45,7 @@ impl Root { } fn subscribe_frame_flex( - _node: &Node, + _node: Arc, calling_client: Arc, _message: Message, ) -> Result<()> { @@ -70,7 +70,7 @@ impl Root { } fn set_base_prefixes_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { @@ -79,7 +79,7 @@ impl Root { } fn state_token_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, response: MethodResponseSender, @@ -116,7 +116,7 @@ macro_rules! var_env_insert { }; } pub fn get_connection_environment_flex( - _node: &Node, + _node: Arc, _calling_client: Arc, _message: Message, response: MethodResponseSender, diff --git a/src/nodes/spatial/mod.rs b/src/nodes/spatial/mod.rs index cfa88a2..d348d57 100644 --- a/src/nodes/spatial/mod.rs +++ b/src/nodes/spatial/mod.rs @@ -4,7 +4,6 @@ use self::zone::{create_zone_flex, Zone}; use super::{Message, Node}; use crate::core::client::Client; use crate::core::registry::Registry; -use crate::core::scenegraph::MethodResponseSender; use color_eyre::eyre::{ensure, eyre, Result}; use glam::{vec3a, Mat4, Quat}; use mint::Vector3; @@ -12,13 +11,32 @@ use nanoid::nanoid; use once_cell::sync::OnceCell; use parking_lot::Mutex; use serde::Deserialize; -use stardust_xr::schemas::flex::{deserialize, serialize}; +use stardust_xr::schemas::flex::deserialize; use std::fmt::Debug; +use std::os::fd::OwnedFd; use std::ptr; use std::sync::{Arc, Weak}; use stereokit::{bounds_grow_to_fit_box, Bounds}; stardust_xr_server_codegen::codegen_spatial_protocol!(); +// impl Transform { +// pub fn to_mat4(self, position: bool, rotation: bool, scale: bool) -> Mat4 { +// let position = position +// .then_some(self.translation) +// .flatten() +// .unwrap_or_else(|| Vector3::from([0.0; 3])); +// let rotation = rotation +// .then_some(self.rotation) +// .flatten() +// .unwrap_or_else(|| Quat::IDENTITY.into()); +// let scale = scale +// .then_some(self.scale) +// .flatten() +// .unwrap_or_else(|| Vector3::from([1.0; 3])); + +// Mat4::from_scale_rotation_translation(scale.into(), rotation.into(), position.into()) +// } +// } static ZONEABLE_REGISTRY: Registry = Registry::new(); @@ -59,18 +77,7 @@ impl Spatial { "Internal: Node already has a Spatial aspect!" ); let spatial = Spatial::new(Arc::downgrade(node), parent.clone(), transform); - node.add_local_method("get_bounding_box", Spatial::get_bounding_box_flex); - node.add_local_method("get_transform", Spatial::get_transform_flex); - node.add_local_signal("set_transform", Spatial::set_transform_flex); - node.add_local_signal("set_spatial_parent", Spatial::set_spatial_parent_flex); - node.add_local_signal( - "set_spatial_parent_in_place", - Spatial::set_spatial_parent_in_place_flex, - ); - node.add_local_signal("set_zoneable", Spatial::set_zoneable_flex); - node.add_local_method("field_distance", Spatial::field_distance_flex); - node.add_local_method("field_normal", Spatial::field_normal_flex); - node.add_local_method("field_closest_point", Spatial::field_closest_point_flex); + ::add_node_members(node); if zoneable { ZONEABLE_REGISTRY.add_raw(&spatial); } @@ -209,7 +216,6 @@ impl Spatial { Ok(()) } - pub fn set_spatial_parent_in_place(&self, parent: Option>) -> Result<()> { let is_ancestor = parent .as_ref() @@ -228,61 +234,84 @@ impl Spatial { Ok(()) } - pub fn get_bounding_box_flex( - node: &Node, - calling_client: Arc, - message: Message, - response: MethodResponseSender, - ) { - response.wrap_sync(move || { + pub(self) fn zone_distance(&self) -> f32 { + self.zone + .lock() + .upgrade() + .and_then(|zone| zone.field.upgrade()) + .map(|field| field.distance(self, vec3a(0.0, 0.0, 0.0))) + .unwrap_or(f32::MAX) + } +} +impl SpatialAspect for Spatial { + fn get_local_bounding_box( + node: Arc, + _calling_client: Arc, + _fds: Vec, + ) -> impl std::future::Future)>> + Send + 'static { + async move { let this_spatial = node .spatial .get() .ok_or_else(|| eyre!("Node doesn't have a spatial?"))?; - let relative_spatial_path: Option<&str> = deserialize(message.as_ref())?; - let bounds = if let Some(relative_spatial_path) = relative_spatial_path { - let relative_spatial = - find_reference_space(&calling_client, relative_spatial_path)?; - let center = - Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)) - .transform_point3([0.0; 3].into()); - let bounds: Bounds = Bounds { - center, - dimensions: [0.0; 3].into(), - }; - bounds_grow_to_fit_box( - bounds, - this_spatial.get_bounding_box(), - Some(Spatial::space_to_space_matrix( - Some(&this_spatial), - Some(&relative_spatial), - )), - ) - } else { - this_spatial.get_bounding_box() - }; + let bounds = this_spatial.get_bounding_box(); - Ok(serialize(( - mint::Vector3::from(bounds.center), - mint::Vector3::from(bounds.dimensions), - ))? - .into()) - }); + let return_value = BoundingBox { + center: mint::Vector3::from(bounds.center), + size: mint::Vector3::from(bounds.dimensions), + }; + Ok((return_value, Vec::new())) + } } - pub fn get_transform_flex( - node: &Node, - calling_client: Arc, - message: Message, - response: MethodResponseSender, - ) { - response.wrap_sync(move || { + fn get_relative_bounding_box( + node: Arc, + _calling_client: Arc, + _fds: Vec, + relative_to: Arc, + ) -> impl std::future::Future)>> + Send + 'static { + async move { let this_spatial = node .spatial .get() .ok_or_else(|| eyre!("Node doesn't have a spatial?"))?; - let relative_spatial = - find_reference_space(&calling_client, deserialize(message.as_ref())?)?; + let relative_spatial = get_spatial(&relative_to, "Relative node", "Spatial")?; + let center = + Spatial::space_to_space_matrix(Some(&this_spatial), Some(&relative_spatial)) + .transform_point3([0.0; 3].into()); + let bounds = Bounds { + center, + dimensions: [0.0; 3].into(), + }; + bounds_grow_to_fit_box( + bounds, + this_spatial.get_bounding_box(), + Some(Spatial::space_to_space_matrix( + Some(&this_spatial), + Some(&relative_spatial), + )), + ); + + let return_value = BoundingBox { + center: mint::Vector3::from(bounds.center), + size: mint::Vector3::from(bounds.dimensions), + }; + Ok((return_value, Vec::new())) + } + } + + fn get_transform( + node: Arc, + _calling_client: Arc, + _fds: Vec, + relative_to: Arc, + ) -> impl std::future::Future)>> + Send + 'static { + async move { + let this_spatial = node + .spatial + .get() + .ok_or_else(|| eyre!("Node doesn't have a spatial?"))?; + let relative_spatial = get_spatial(&relative_to, "Relative node", "Spatial")?; let (scale, rotation, position) = Spatial::space_to_space_matrix( Some(this_spatial.as_ref()), @@ -290,62 +319,83 @@ impl Spatial { ) .to_scale_rotation_translation(); - Ok(serialize(( - mint::Vector3::from(position), - mint::Quaternion::from(rotation), - mint::Vector3::from(scale), - ))? - .into()) - }); - } - pub fn set_transform_flex( - node: &Node, - calling_client: Arc, - message: Message, - ) -> Result<()> { - #[derive(Deserialize)] - struct TransformArgs<'a> { - reference_space_path: Option<&'a str>, - transform: Transform, + let return_value = Transform { + translation: Some(position.into()), + rotation: Some(rotation.into()), + scale: Some(scale.into()), + }; + Ok((return_value, Vec::new())) } - let transform_args: TransformArgs = deserialize(message.as_ref())?; - let reference_space_transform = transform_args - .reference_space_path - .map(|path| find_reference_space(&calling_client, path)) - .transpose()?; + } - node.spatial.get().unwrap().set_local_transform_components( - reference_space_transform.as_deref(), - transform_args.transform, - ); - Ok(()) - } - pub fn set_spatial_parent_flex( - node: &Node, - calling_client: Arc, - message: Message, - ) -> Result<()> { - let parent = find_spatial_parent(&calling_client, deserialize(message.as_ref())?)?; - node.spatial.get().unwrap().set_spatial_parent(Some(parent)) - } - pub fn set_spatial_parent_in_place_flex( - node: &Node, - calling_client: Arc, - message: Message, - ) -> Result<()> { - let parent = find_spatial_parent(&calling_client, deserialize(message.as_ref())?)?; - node.spatial - .get() - .unwrap() - .set_spatial_parent_in_place(Some(parent))?; - Ok(()) - } - pub fn set_zoneable_flex( - node: &Node, + fn set_local_transform( + node: Arc, _calling_client: Arc, - message: Message, + _fds: Vec, + transform: Transform, + ) -> Result<()> { + let this_spatial = node + .spatial + .get() + .ok_or_else(|| eyre!("Node doesn't have a spatial?"))?; + this_spatial.set_local_transform_components(None, transform); + Ok(()) + } + fn set_relative_transform( + node: Arc, + _calling_client: Arc, + _fds: Vec, + relative_to: Arc, + transform: Transform, + ) -> Result<()> { + let this_spatial = node + .spatial + .get() + .ok_or_else(|| eyre!("Node doesn't have a spatial?"))?; + let relative_spatial = get_spatial(&relative_to, "Relative node", "Spatial")?; + + this_spatial.set_local_transform_components(Some(&relative_spatial), transform); + Ok(()) + } + + fn set_spatial_parent( + node: Arc, + _calling_client: Arc, + _fds: Vec, + parent: Arc, + ) -> Result<()> { + let this_spatial = node + .spatial + .get() + .ok_or_else(|| eyre!("Node doesn't have a spatial?"))?; + let parent = get_spatial(&parent, "Parent", "Spatial")?; + + this_spatial.set_spatial_parent(Some(parent))?; + Ok(()) + } + + fn set_spatial_parent_in_place( + node: Arc, + _calling_client: Arc, + _fds: Vec, + parent: Arc, + ) -> Result<()> { + let this_spatial = node + .spatial + .get() + .ok_or_else(|| eyre!("Node doesn't have a spatial?"))?; + let parent = get_spatial(&parent, "Parent", "Spatial")?; + + this_spatial.set_spatial_parent_in_place(Some(parent))?; + Ok(()) + } + + fn set_zoneable( + node: Arc, + _calling_client: Arc, + _fds: Vec, + zoneable: bool, ) -> Result<()> { - let zoneable: bool = deserialize(message.as_ref())?; let spatial = node.spatial.get().unwrap(); if zoneable { ZONEABLE_REGISTRY.add_raw(spatial); @@ -355,94 +405,6 @@ impl Spatial { } Ok(()) } - - pub fn field_distance_flex( - node: &Node, - calling_client: Arc, - message: Message, - response: MethodResponseSender, - ) { - response.wrap_sync(move || { - let (point, fields): (Vector3, Vec>) = deserialize(message.as_ref())?; - let spatial = node.spatial.get().unwrap(); - - let output = fields - .into_iter() - .map(|f| { - calling_client - .get_node("Field", f?) - .ok()? - .get_aspect("Field", "field", |n| &n.field) - .ok() - .cloned() - }) - .map(|f| f.map(|f| f.distance(spatial, point.into()))) - .collect::>>(); - - Ok(serialize(output)?.into()) - }); - } - pub fn field_normal_flex( - node: &Node, - calling_client: Arc, - message: Message, - response: MethodResponseSender, - ) { - response.wrap_sync(move || { - let (point, fields): (Vector3, Vec>) = deserialize(message.as_ref())?; - let spatial = node.spatial.get().unwrap(); - - let output = fields - .into_iter() - .map(|f| { - calling_client - .get_node("Field", f?) - .ok()? - .get_aspect("Field", "field", |n| &n.field) - .ok() - .cloned() - }) - .map(|f| f.map(|f| Vector3::from(f.normal(spatial, point.into(), 0.001)))) - .collect::>(); - - Ok(serialize(output)?.into()) - }); - } - pub fn field_closest_point_flex( - node: &Node, - calling_client: Arc, - message: Message, - response: MethodResponseSender, - ) { - response.wrap_sync(move || { - let (point, fields): (Vector3, Vec>) = deserialize(message.as_ref())?; - let spatial = node.spatial.get().unwrap(); - - let output = fields - .into_iter() - .map(|f| { - calling_client - .get_node("Field", f?) - .ok()? - .get_aspect("Field", "field", |n| &n.field) - .ok() - .cloned() - }) - .map(|f| f.map(|f| Vector3::from(f.closest_point(spatial, point.into(), 0.001)))) - .collect::>(); - - Ok(serialize(output)?.into()) - }); - } - - pub(self) fn zone_distance(&self) -> f32 { - self.zone - .lock() - .upgrade() - .and_then(|zone| zone.field.upgrade()) - .map(|field| field.distance(self, vec3a(0.0, 0.0, 0.0))) - .unwrap_or(f32::MAX) - } } impl PartialEq for Spatial { fn eq(&self, other: &Self) -> bool { @@ -487,24 +449,22 @@ pub fn find_spatial( calling_client: &Arc, node_name: &'static str, node_path: &str, -) -> color_eyre::eyre::Result> { +) -> Result> { calling_client .get_node(node_name, node_path)? .get_aspect(node_name, "spatial", |n| &n.spatial) .cloned() } -pub fn find_spatial_parent( - calling_client: &Arc, - node_path: &str, -) -> color_eyre::eyre::Result> { +pub fn find_spatial_parent(calling_client: &Arc, node_path: &str) -> Result> { find_spatial(calling_client, "Spatial parent", node_path) } -pub fn find_reference_space( - calling_client: &Arc, - node_path: &str, -) -> color_eyre::eyre::Result> { +pub fn find_reference_space(calling_client: &Arc, node_path: &str) -> Result> { find_spatial(calling_client, "Reference space", node_path) } +pub fn get_spatial(node: &Arc, node_name: &str, aspect_name: &str) -> Result> { + node.get_aspect(node_name, aspect_name, |n| &n.spatial) + .cloned() +} pub fn create_interface(client: &Arc) -> Result<()> { let node = Node::create(client, "", "spatial", false); @@ -514,7 +474,7 @@ pub fn create_interface(client: &Arc) -> Result<()> { } pub fn create_spatial_flex( - _node: &Node, + _node: Arc, calling_client: Arc, message: Message, ) -> Result<()> { diff --git a/src/nodes/spatial/zone.rs b/src/nodes/spatial/zone.rs index f163a53..8dfafd2 100644 --- a/src/nodes/spatial/zone.rs +++ b/src/nodes/spatial/zone.rs @@ -73,20 +73,20 @@ impl Zone { let _ = node.zone.set(zone.clone()); zone } - fn capture_flex(node: &Node, calling_client: Arc, message: Message) -> Result<()> { + fn capture_flex(node: Arc, calling_client: Arc, message: Message) -> Result<()> { let zone = node.zone.get().unwrap(); let capture_path: &str = deserialize(message.as_ref())?; let spatial = find_spatial(&calling_client, "Spatial", capture_path)?; capture(&spatial, zone); Ok(()) } - fn release_flex(_node: &Node, calling_client: Arc, message: Message) -> Result<()> { + fn release_flex(_node: Arc, calling_client: Arc, message: Message) -> Result<()> { let capture_path: &str = deserialize(message.as_ref())?; let spatial = find_spatial(&calling_client, "Spatial", capture_path)?; release(&spatial); Ok(()) } - fn update(node: &Node, _calling_client: Arc, _message: Message) -> Result<()> { + fn update(node: Arc, _calling_client: Arc, _message: Message) -> Result<()> { let zone = node.zone.get().unwrap(); let Some(field) = zone.field.upgrade() else { return Err(color_eyre::eyre::eyre!("Zone's field has been destroyed")); @@ -160,7 +160,11 @@ impl Drop for Zone { } } -pub fn create_zone_flex(_node: &Node, calling_client: Arc, message: Message) -> Result<()> { +pub fn create_zone_flex( + _node: Arc, + calling_client: Arc, + message: Message, +) -> Result<()> { #[derive(Deserialize)] struct CreateZoneInfo<'a> { name: &'a str,