feat(spatial): use codegen
This commit is contained in:
@@ -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<H: #aspect_handler_name>(self, handler: H) -> NodeResult<crate::HandlerWrapper<Self, H>> {
|
||||
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<H: #aspect_handler_name>(self, handler: std::sync::Arc<parking_lot::Mutex<H>>) -> NodeResult<crate::HandlerWrapper<Self, H>> {
|
||||
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<crate::client::Client>)
|
||||
let first_args = if member.side == Side::Server {
|
||||
quote!(_node: std::sync::Arc<crate::nodes::Node>, _calling_client: std::sync::Arc<crate::core::client::Client>, _fds: Vec<std::os::fd::OwnedFd>)
|
||||
} 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<Output = color_eyre::eyre::Result<(#return_type, Vec<std::os::fd::OwnedFd>)>> + 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<crate::nodes::Node>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Message, ScenegraphError>) {
|
||||
let _ = self.0.send(t.map(|m| (m.data, m.fds)));
|
||||
}
|
||||
// pub fn send_method_return<T: Serialize>(
|
||||
// self,
|
||||
// result: color_eyre::eyre::Result<(T, Vec<OwnedFd>)>,
|
||||
// ) {
|
||||
// let _ = self.0.send(map_method_return(result));
|
||||
// }
|
||||
pub fn wrap_sync<F: FnOnce() -> color_eyre::eyre::Result<Message>>(self, f: F) {
|
||||
self.send(f().map_err(|e| ScenegraphError::MethodError {
|
||||
error: e.to_string(),
|
||||
}))
|
||||
}
|
||||
pub fn wrap_async<T: Serialize>(
|
||||
self,
|
||||
f: impl Future<Output = color_eyre::eyre::Result<(T, Vec<OwnedFd>)>> + Send + 'static,
|
||||
) {
|
||||
tokio::task::spawn(async move { self.0.send(map_method_return(f.await)) });
|
||||
}
|
||||
}
|
||||
fn map_method_return<T: Serialize>(
|
||||
result: color_eyre::eyre::Result<(T, Vec<OwnedFd>)>,
|
||||
) -> Result<(Vec<u8>, Vec<OwnedFd>), 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(
|
||||
|
||||
@@ -83,13 +83,17 @@ impl Sound {
|
||||
}
|
||||
}
|
||||
|
||||
fn play_flex(node: &Node, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
|
||||
fn play_flex(node: Arc<Node>, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
|
||||
let sound = node.sound.get().unwrap();
|
||||
sound.play.lock().replace(());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stop_flex(node: &Node, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
|
||||
pub fn stop_flex(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_message: Message,
|
||||
) -> Result<()> {
|
||||
let sound = node.sound.get().unwrap();
|
||||
sound.stop.lock().replace(());
|
||||
Ok(())
|
||||
@@ -108,7 +112,7 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
|
||||
node.add_to_scenegraph().map(|_| ())
|
||||
}
|
||||
|
||||
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
pub fn create_flex(_node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct CreateSoundInfo<'a> {
|
||||
name: &'a str,
|
||||
|
||||
@@ -188,7 +188,11 @@ impl PulseSender {
|
||||
let _ = tx_node.send_remote_signal("drop_receiver", data);
|
||||
}
|
||||
|
||||
fn send_data_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
fn send_data_flex(
|
||||
node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
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<Client>) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn create_pulse_sender_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -297,7 +301,7 @@ pub fn create_pulse_sender_flex(
|
||||
}
|
||||
|
||||
pub fn create_pulse_receiver_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -324,7 +328,7 @@ pub fn create_pulse_receiver_flex(
|
||||
}
|
||||
|
||||
pub fn register_keymap_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
@@ -348,7 +352,7 @@ pub fn register_keymap_flex(
|
||||
});
|
||||
}
|
||||
pub fn get_keymap_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
|
||||
@@ -119,7 +119,7 @@ impl Lines {
|
||||
}
|
||||
|
||||
pub fn set_lines_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -149,7 +149,7 @@ pub fn draw_all(draw_ctx: &impl StereoKitDraw) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
pub fn create_flex(_node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct CreateLinesInfo<'a> {
|
||||
name: &'a str,
|
||||
|
||||
@@ -56,7 +56,11 @@ pub fn draw(sk: &impl StereoKitDraw) {
|
||||
static QUEUED_SKYLIGHT: Mutex<Option<PathBuf>> = Mutex::new(None);
|
||||
static QUEUED_SKYTEX: Mutex<Option<PathBuf>> = Mutex::new(None);
|
||||
|
||||
fn set_sky_file_flex(_node: &Node, _calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
fn set_sky_file_flex(
|
||||
_node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct SkyFileInfo {
|
||||
path: PathBuf,
|
||||
|
||||
@@ -244,7 +244,7 @@ impl ModelPart {
|
||||
}
|
||||
|
||||
fn apply_holdout_material_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -256,7 +256,7 @@ impl ModelPart {
|
||||
}
|
||||
|
||||
fn set_material_parameter_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -403,7 +403,7 @@ pub fn draw_all(sk: &impl StereoKitDraw) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
pub fn create_flex(_node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct CreateModelInfo<'a> {
|
||||
name: &'a str,
|
||||
|
||||
@@ -146,7 +146,7 @@ impl Text {
|
||||
}
|
||||
|
||||
pub fn set_character_height_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -159,7 +159,7 @@ impl Text {
|
||||
}
|
||||
|
||||
pub fn set_text_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -188,7 +188,7 @@ pub fn draw_all(sk: &impl StereoKitDraw) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
pub fn create_flex(_node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct CreateTextInfo<'a> {
|
||||
name: &'a str,
|
||||
|
||||
@@ -42,7 +42,7 @@ impl BoxField {
|
||||
}
|
||||
|
||||
pub fn set_size_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -72,7 +72,7 @@ impl FieldTrait for BoxField {
|
||||
}
|
||||
|
||||
pub fn create_box_field_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -44,7 +44,7 @@ impl CylinderField {
|
||||
}
|
||||
|
||||
pub fn set_size_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -71,7 +71,7 @@ impl FieldTrait for CylinderField {
|
||||
}
|
||||
|
||||
pub fn create_cylinder_field_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -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<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
@@ -160,7 +160,7 @@ fn field_distance_flex(
|
||||
});
|
||||
}
|
||||
fn field_normal_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
@@ -183,7 +183,7 @@ fn field_normal_flex(
|
||||
});
|
||||
}
|
||||
fn field_closest_point_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
@@ -206,7 +206,7 @@ fn field_closest_point_flex(
|
||||
});
|
||||
}
|
||||
fn field_ray_march_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
|
||||
@@ -41,11 +41,13 @@ impl SphereField {
|
||||
}
|
||||
|
||||
pub fn set_radius_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
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<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -44,7 +44,7 @@ impl TorusField {
|
||||
}
|
||||
|
||||
pub fn set_size_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -71,7 +71,7 @@ impl FieldTrait for TorusField {
|
||||
}
|
||||
|
||||
pub fn create_torus_field_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -109,23 +109,31 @@ impl InputMethod {
|
||||
.cloned()
|
||||
}
|
||||
|
||||
fn capture_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
let method = InputMethod::get(node)?;
|
||||
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, 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<Client>, message: Message) -> Result<()> {
|
||||
let method = InputMethod::get(node)?;
|
||||
fn set_datamap_flex(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
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<Client>, message: Message) -> Result<()> {
|
||||
let method = InputMethod::get(node)?;
|
||||
fn set_handlers_flex(
|
||||
node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
let method = InputMethod::get(&node)?;
|
||||
let handler_paths: Vec<&str> = deserialize(message.as_ref())?;
|
||||
let handlers: Vec<Weak<InputHandler>> = handler_paths
|
||||
.into_iter()
|
||||
@@ -352,7 +360,7 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn create_input_handler_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -66,7 +66,7 @@ impl InputSpecialization for Pointer {
|
||||
}
|
||||
|
||||
pub fn create_pointer_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> color_eyre::eyre::Result<()> {
|
||||
|
||||
@@ -18,7 +18,7 @@ pub struct Tip {
|
||||
pub radius: f32,
|
||||
}
|
||||
impl Tip {
|
||||
fn set_radius(node: &Node, _calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
fn set_radius(node: Arc<Node>, _calling_client: Arc<Client>, 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<Client>, message: Message) -> Result<()> {
|
||||
pub fn create_tip_flex(
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct CreateTipInfo<'a> {
|
||||
name: &'a str,
|
||||
|
||||
@@ -77,7 +77,7 @@ impl CameraItem {
|
||||
}
|
||||
|
||||
fn frame_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_message: Message,
|
||||
response: MethodResponseSender,
|
||||
@@ -91,7 +91,7 @@ impl CameraItem {
|
||||
}
|
||||
|
||||
fn apply_preview_material_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -164,7 +164,7 @@ pub fn update(sk: &impl StereoKitDraw) {
|
||||
}
|
||||
|
||||
pub(super) fn create_camera_item_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -45,7 +45,7 @@ impl EnvironmentItem {
|
||||
}
|
||||
|
||||
fn get_path_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_message: Message,
|
||||
response: MethodResponseSender,
|
||||
@@ -65,7 +65,7 @@ impl EnvironmentItem {
|
||||
}
|
||||
|
||||
pub(super) fn create_environment_item_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -156,7 +156,11 @@ impl Item {
|
||||
self.make_alias_named(client, parent, &self.uid)
|
||||
}
|
||||
|
||||
fn release_flex(node: &Node, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
|
||||
fn release_flex(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_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<Client>, message: Message) -> Result<()> {
|
||||
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, 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<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -460,7 +464,7 @@ pub fn register_item_ui_flex(
|
||||
}
|
||||
|
||||
fn create_item_acceptor_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -95,8 +95,8 @@ impl<'de> Visitor<'de> for SurfaceIDVisitor {
|
||||
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||
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<Arc<dyn PanelItemTrait>> {
|
||||
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<B: Backend + ?Sized> PanelItem<B> {
|
||||
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<B: Backend + ?Sized> PanelItem<B> {
|
||||
// Remote signals
|
||||
impl<B: Backend + ?Sized> PanelItem<B> {
|
||||
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::<u8>::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<u32>) {
|
||||
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<Geometry>) {
|
||||
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<Client>, _message: Message) -> Result<()> {
|
||||
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
|
||||
fn $fn_name(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_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<Client>, message: Message) -> Result<()> {
|
||||
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
|
||||
fn $fn_name(node: Arc<Node>, _calling_client: Arc<Client>, 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<B: Backend + ?Sized> PanelItem<B> {
|
||||
fn apply_surface_material_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
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<B: Backend + ?Sized> PanelItem<B> {
|
||||
.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<B: Backend + ?Sized> PanelItem<B> {
|
||||
flex_deserialize!(set_toplevel_size_changed_flex, set_toplevel_size);
|
||||
|
||||
fn pointer_motion_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
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<f32>) = deserialize(message.as_ref())?;
|
||||
debug!(?surface_id, ?position, "Pointer deactivate");
|
||||
@@ -393,11 +433,13 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
||||
Ok(())
|
||||
}
|
||||
fn pointer_button_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
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<B: Backend + ?Sized> PanelItem<B> {
|
||||
Ok(())
|
||||
}
|
||||
fn pointer_scroll_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
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<B: Backend + ?Sized> PanelItem<B> {
|
||||
}
|
||||
|
||||
fn keyboard_keys_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
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<i32>) =
|
||||
deserialize(message.as_ref())?;
|
||||
debug!(?keys, "Set keyboard key state");
|
||||
@@ -441,14 +487,22 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
||||
Ok(())
|
||||
}
|
||||
pub fn grab_keyboard(&self, sid: Option<SurfaceID>) {
|
||||
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<Client>, message: Message) -> Result<()> {
|
||||
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
|
||||
fn touch_down_flex(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = panel_item_from_node(&node) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let (surface_id, id, position): (SurfaceID, u32, Vector2<f32>) =
|
||||
deserialize(message.as_ref())?;
|
||||
@@ -458,8 +512,14 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn touch_move_flex(node: &Node, _calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
|
||||
fn touch_move_flex(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
let Some(panel_item) = panel_item_from_node(&node) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let (id, position): (u32, Vector2<f32>) = deserialize(message.as_ref())?;
|
||||
debug!(?position, "Touch move");
|
||||
|
||||
@@ -57,8 +57,8 @@ impl AsRef<[u8]> for Message {
|
||||
}
|
||||
}
|
||||
|
||||
pub type Signal = fn(&Node, Arc<Client>, Message) -> Result<()>;
|
||||
pub type Method = fn(&Node, Arc<Client>, Message, MethodResponseSender);
|
||||
pub type Signal = fn(Arc<Node>, Arc<Client>, Message) -> Result<()>;
|
||||
pub type Method = fn(Arc<Node>, Arc<Client>, Message, MethodResponseSender);
|
||||
|
||||
pub struct Node {
|
||||
pub enabled: Arc<AtomicBool>,
|
||||
@@ -158,7 +158,7 @@ impl Node {
|
||||
}
|
||||
|
||||
pub fn set_enabled_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
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<Node>,
|
||||
// _calling_client: Arc<Client>,
|
||||
// _message: Message,
|
||||
// ) -> Result<Message> {
|
||||
@@ -180,7 +180,7 @@ impl Node {
|
||||
// Ok(serialize(pid)?.into())
|
||||
// }
|
||||
pub fn destroy_flex(
|
||||
node: &Node,
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -197,12 +197,7 @@ impl Node {
|
||||
self.local_methods.lock().insert(name.to_string(), method);
|
||||
}
|
||||
|
||||
pub fn get_aspect<F, T>(
|
||||
&self,
|
||||
node_name: &'static str,
|
||||
aspect_type: &'static str,
|
||||
aspect_fn: F,
|
||||
) -> Result<&T>
|
||||
pub fn get_aspect<F, T>(&self, node_name: &str, aspect_type: &str, aspect_fn: F) -> Result<&T>
|
||||
where
|
||||
F: FnOnce(&Node) -> &OnceCell<T>,
|
||||
{
|
||||
@@ -212,7 +207,7 @@ impl Node {
|
||||
}
|
||||
|
||||
pub fn send_local_signal(
|
||||
&self,
|
||||
self: Arc<Self>,
|
||||
calling_client: Arc<Client>,
|
||||
method: &str,
|
||||
message: Message,
|
||||
@@ -239,7 +234,7 @@ impl Node {
|
||||
}
|
||||
}
|
||||
pub fn execute_local_method(
|
||||
&self,
|
||||
self: Arc<Self>,
|
||||
calling_client: Arc<Client>,
|
||||
method: &str,
|
||||
message: Message,
|
||||
|
||||
@@ -45,7 +45,7 @@ impl Root {
|
||||
}
|
||||
|
||||
fn subscribe_frame_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
_message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -70,7 +70,7 @@ impl Root {
|
||||
}
|
||||
|
||||
fn set_base_prefixes_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
@@ -79,7 +79,7 @@ impl Root {
|
||||
}
|
||||
|
||||
fn state_token_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
@@ -116,7 +116,7 @@ macro_rules! var_env_insert {
|
||||
};
|
||||
}
|
||||
pub fn get_connection_environment_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_message: Message,
|
||||
response: MethodResponseSender,
|
||||
|
||||
@@ -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<Spatial> = 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);
|
||||
<Spatial as SpatialAspect>::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<Arc<Spatial>>) -> 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<Client>,
|
||||
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<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_fds: Vec<OwnedFd>,
|
||||
) -> impl std::future::Future<Output = Result<(BoundingBox, Vec<OwnedFd>)>> + 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<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
) {
|
||||
response.wrap_sync(move || {
|
||||
fn get_relative_bounding_box(
|
||||
node: Arc<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_fds: Vec<OwnedFd>,
|
||||
relative_to: Arc<Node>,
|
||||
) -> impl std::future::Future<Output = Result<(BoundingBox, Vec<OwnedFd>)>> + 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<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_fds: Vec<OwnedFd>,
|
||||
relative_to: Arc<Node>,
|
||||
) -> impl std::future::Future<Output = Result<(Transform, Vec<OwnedFd>)>> + 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<Client>,
|
||||
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<Client>,
|
||||
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<Client>,
|
||||
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<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
_fds: Vec<OwnedFd>,
|
||||
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<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_fds: Vec<OwnedFd>,
|
||||
relative_to: Arc<Node>,
|
||||
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<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_fds: Vec<OwnedFd>,
|
||||
parent: Arc<Node>,
|
||||
) -> 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<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_fds: Vec<OwnedFd>,
|
||||
parent: Arc<Node>,
|
||||
) -> 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<Node>,
|
||||
_calling_client: Arc<Client>,
|
||||
_fds: Vec<OwnedFd>,
|
||||
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<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
) {
|
||||
response.wrap_sync(move || {
|
||||
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = 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::<Vec<Option<f32>>>();
|
||||
|
||||
Ok(serialize(output)?.into())
|
||||
});
|
||||
}
|
||||
pub fn field_normal_flex(
|
||||
node: &Node,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
) {
|
||||
response.wrap_sync(move || {
|
||||
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = 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::<Vec<_>>();
|
||||
|
||||
Ok(serialize(output)?.into())
|
||||
});
|
||||
}
|
||||
pub fn field_closest_point_flex(
|
||||
node: &Node,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
response: MethodResponseSender,
|
||||
) {
|
||||
response.wrap_sync(move || {
|
||||
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = 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::<Vec<_>>();
|
||||
|
||||
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<Client>,
|
||||
node_name: &'static str,
|
||||
node_path: &str,
|
||||
) -> color_eyre::eyre::Result<Arc<Spatial>> {
|
||||
) -> Result<Arc<Spatial>> {
|
||||
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<Client>,
|
||||
node_path: &str,
|
||||
) -> color_eyre::eyre::Result<Arc<Spatial>> {
|
||||
pub fn find_spatial_parent(calling_client: &Arc<Client>, node_path: &str) -> Result<Arc<Spatial>> {
|
||||
find_spatial(calling_client, "Spatial parent", node_path)
|
||||
}
|
||||
pub fn find_reference_space(
|
||||
calling_client: &Arc<Client>,
|
||||
node_path: &str,
|
||||
) -> color_eyre::eyre::Result<Arc<Spatial>> {
|
||||
pub fn find_reference_space(calling_client: &Arc<Client>, node_path: &str) -> Result<Arc<Spatial>> {
|
||||
find_spatial(calling_client, "Reference space", node_path)
|
||||
}
|
||||
pub fn get_spatial(node: &Arc<Node>, node_name: &str, aspect_name: &str) -> Result<Arc<Spatial>> {
|
||||
node.get_aspect(node_name, aspect_name, |n| &n.spatial)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn create_interface(client: &Arc<Client>) -> Result<()> {
|
||||
let node = Node::create(client, "", "spatial", false);
|
||||
@@ -514,7 +474,7 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn create_spatial_flex(
|
||||
_node: &Node,
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
|
||||
@@ -73,20 +73,20 @@ impl Zone {
|
||||
let _ = node.zone.set(zone.clone());
|
||||
zone
|
||||
}
|
||||
fn capture_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
||||
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, 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<Client>, message: Message) -> Result<()> {
|
||||
fn release_flex(_node: Arc<Node>, calling_client: Arc<Client>, 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<Client>, _message: Message) -> Result<()> {
|
||||
fn update(node: Arc<Node>, _calling_client: Arc<Client>, _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<Client>, message: Message) -> Result<()> {
|
||||
pub fn create_zone_flex(
|
||||
_node: Arc<Node>,
|
||||
calling_client: Arc<Client>,
|
||||
message: Message,
|
||||
) -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
struct CreateZoneInfo<'a> {
|
||||
name: &'a str,
|
||||
|
||||
Reference in New Issue
Block a user