From 7fc239293d6e9efe8ddea719df555b0cbf7a25a0 Mon Sep 17 00:00:00 2001 From: Nova Date: Thu, 16 Jun 2022 14:28:40 -0400 Subject: [PATCH] feat(data): pulse receiver --- src/core/client.rs | 2 + src/nodes/core.rs | 4 +- src/nodes/data.rs | 273 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 272 insertions(+), 7 deletions(-) diff --git a/src/core/client.rs b/src/core/client.rs index 7434bb6..d4ebea4 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -1,4 +1,5 @@ use super::scenegraph::Scenegraph; +use crate::nodes::data; use crate::nodes::field; use crate::nodes::root; use crate::nodes::spatial; @@ -21,6 +22,7 @@ impl Client { root::create_root(&client); spatial::create_interface(&client); field::create_interface(&client); + data::create_interface(&client); client } pub fn dispatch(&self) -> Result<(), std::io::Error> { diff --git a/src/nodes/core.rs b/src/nodes/core.rs index a7b7e0c..a750a2a 100644 --- a/src/nodes/core.rs +++ b/src/nodes/core.rs @@ -1,4 +1,4 @@ -use super::data::PulseSender; +use super::data::{PulseReceiver, PulseSender}; use super::field::Field; use super::spatial::Spatial; use crate::core::client::Client; @@ -30,6 +30,7 @@ pub struct Node { pub spatial: OnceCell>, pub field: OnceCell>, pub pulse_sender: OnceCell>, + pub pulse_receiver: OnceCell>, } impl Node { @@ -63,6 +64,7 @@ impl Node { spatial: OnceCell::new(), field: OnceCell::new(), pulse_sender: OnceCell::new(), + pulse_receiver: OnceCell::new(), }; node.add_local_signal("destroy", Node::destroy_flex); node diff --git a/src/nodes/data.rs b/src/nodes/data.rs index bb24d28..b8da068 100644 --- a/src/nodes/data.rs +++ b/src/nodes/data.rs @@ -1,15 +1,72 @@ -use super::core::Node; +use super::core::{Alias, Node}; +use super::field::Field; +use super::spatial::{get_spatial_parent_flex, get_transform_pose_flex, Spatial}; +use crate::core::client::Client; use crate::core::registry::Registry; -use anyhow::{ensure, Result}; +use anyhow::{anyhow, ensure, Result}; +use glam::{vec3a, Mat4}; use lazy_static::lazy_static; -use std::sync::Arc; +use libstardustxr::flex::flexbuffer_from_vector_arguments; +use libstardustxr::{flex_to_quat, flex_to_vec3}; +use parking_lot::{Mutex, RwLock}; +use std::sync::{Arc, Weak}; lazy_static! { static ref PULSE_SENDER_REGISTRY: Registry = Default::default(); + static ref PULSE_RECEIVER_REGISTRY: Registry = Default::default(); } -pub struct PulseSender {} +fn mask_matches(mask_map_lesser: &Mask, mask_map_greater: &Mask) -> bool { + (|| -> Result<_> { + for key in mask_map_lesser.get_mask()?.iter_keys() { + let lesser_key_type = mask_map_lesser.get_mask()?.index(key)?.flexbuffer_type(); + let greater_key_type = mask_map_greater.get_mask()?.index(key)?.flexbuffer_type(); + if lesser_key_type != greater_key_type { + return Err(flexbuffers::ReaderError::InvalidPackedType {}.into()); + } + } + Ok(()) + })() + .is_ok() +} +type MaskMapGetFn = fn(&[u8]) -> Result>; +pub struct Mask { + binary: Vec, + get_fn: MaskMapGetFn, +} +impl Mask { + pub fn get_mask(&self) -> Result> { + (self.get_fn)(self.binary.as_slice()) + } + pub fn set_mask(&mut self, binary: Vec, get_fn: MaskMapGetFn) { + self.binary = binary; + self.get_fn = get_fn; + } +} +impl Default for Mask { + fn default() -> Self { + Mask { + binary: Default::default(), + get_fn: mask_get_err, + } + } +} +fn mask_get_err(_binary: &[u8]) -> Result> { + Err(anyhow!("You need to call setMask to set the mask!")) +} +fn mask_get_map_at_root(binary: &[u8]) -> Result> { + flexbuffers::Reader::get_root(binary) + .map_err(|_| anyhow!("Mask is not a valid flexbuffer"))? + .get_map() + .map_err(|_| anyhow!("Mask is not a valid map")) +} + +#[derive(Default)] +pub struct PulseSender { + mask: RwLock, + aliases: Mutex>, +} impl PulseSender { pub fn add_to(node: &Arc) -> Result<()> { ensure!( @@ -17,15 +74,219 @@ impl PulseSender { "Internal: Node does not have a spatial attached!" ); - let sender = PulseSender {}; + let sender = Default::default(); let sender = PULSE_SENDER_REGISTRY.add(sender)?; let _ = node.pulse_sender.set(sender); + node.add_local_signal("setMask", PulseSender::set_mask_flex); + node.add_local_method("getReceivers", PulseSender::get_receivers_flex); Ok(()) } -} + pub fn set_mask_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + ensure!( + node.pulse_sender.get().is_some(), + "Internal: Node does not have a pulse sender aspect" + ); + node.pulse_sender + .get() + .unwrap() + .mask + .write() + .set_mask(data.to_vec(), mask_get_map_at_root); + Ok(()) + } + fn get_receivers_flex( + node: &Node, + calling_client: Arc, + _data: &[u8], + ) -> Result> { + let sender_spatial = node + .spatial + .get() + .ok_or_else(|| anyhow!("Node does not have a spatial aspect!"))?; + let sender = node + .pulse_sender + .get() + .ok_or_else(|| anyhow!("Node does not have a sender aspect!"))?; + let valid_receivers = PULSE_RECEIVER_REGISTRY.get_valid_contents(); + let mut distance_sorted_receivers: Vec<(f32, &PulseReceiver)> = valid_receivers + .iter() + .filter(|receiver| receiver.get_field().is_some()) + .filter(|receiver| mask_matches(&*sender.mask.read(), &*receiver.mask.read())) + .map(|receiver| { + ( + receiver + .get_field() + .unwrap() + .distance(sender_spatial, vec3a(0_f32, 0_f32, 0_f32)), + receiver.as_ref(), + ) + }) + .collect(); + distance_sorted_receivers.sort_by(|(d1, _), (d2, _)| d1.partial_cmp(d2).unwrap()); + Ok(flexbuffer_from_vector_arguments(move |fbb| { + let mut aliases = sender.aliases.lock(); + for alias in aliases.iter() { + node.get_client().unwrap().scenegraph.remove_node(alias); + } + *aliases = Vec::with_capacity(distance_sorted_receivers.len()); + for (i, (_, receiver)) in distance_sorted_receivers.iter().enumerate() { + let receiver_alias = Node::create(node.get_path(), receiver.uid.as_str(), false); + let receiver_alias = calling_client.scenegraph.add_node(receiver_alias); + Alias::add_to( + &receiver_alias, + receiver.node.upgrade().as_ref().unwrap(), + vec![], + vec!["sendData".to_owned()], + ); + aliases[i] = "".to_owned(); + fbb.push(receiver.uid.as_str()); + } + })) + } +} impl Drop for PulseSender { fn drop(&mut self) { let _ = PULSE_SENDER_REGISTRY.remove(self); } } + +pub struct PulseReceiver { + uid: String, + node: Weak, + pub mask: RwLock, + field: Weak, +} +impl<'a> PulseReceiver { + pub fn add_to(node: &Arc, field: Arc) -> Result<()> { + ensure!( + node.spatial.get().is_some(), + "Internal: Node does not have a spatial attached!" + ); + + let receiver = PulseReceiver { + uid: node.uid.clone(), + node: Arc::downgrade(node), + field: Arc::downgrade(&field), + mask: Default::default(), + }; + let receiver = PULSE_RECEIVER_REGISTRY.add(receiver)?; + let _ = node.pulse_receiver.set(receiver); + node.add_local_signal("setMask", PulseReceiver::set_mask_flex); + Ok(()) + } + fn get_field(&self) -> Option> { + self.field.upgrade() + } + fn send_data_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + ensure!( + node.pulse_receiver.get().is_some(), + "Internal: Node does not have a pulse receiver aspect" + ); + let receiver_mask = node.pulse_receiver.get().unwrap().mask.read(); + let data_mask = Mask { + binary: data.to_vec(), + get_fn: mask_get_map_at_root, + }; + if !mask_matches(&receiver_mask, &data_mask) { + return Err(anyhow!( + "Message does not contain the same keys as the receiver mask" + )); + } + drop(receiver_mask); + node.send_remote_signal("pulse", data)?; + Ok(()) + } + fn set_mask_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { + ensure!( + node.pulse_receiver.get().is_some(), + "Internal: Node does not have a pulse receiver aspect" + ); + node.pulse_receiver + .get() + .unwrap() + .mask + .write() + .set_mask(data.to_vec(), mask_get_map_at_root); + Ok(()) + } +} + +impl Drop for PulseReceiver { + fn drop(&mut self) { + let _ = PULSE_RECEIVER_REGISTRY.remove(self); + } +} + +pub fn create_interface(client: &Arc) { + let node = Node::create("", "data", false); + node.add_local_signal("createPulseSender", create_pulse_sender_flex); + node.add_local_signal("createPulseReceiver", create_pulse_receiver_flex); + client.scenegraph.add_node(node); +} + +// pub fn mask_get_map_pulse_sender_create_args(mask: &Mask) -> Result> { +// flexbuffers::Reader::get_root(mask.binary.as_slice()) +// .map_err(|_| anyhow!("Mask is not a valid flexbuffer"))? +// .get_vector()? +// .index(4)? +// .get_map() +// .map_err(|_| anyhow!("Mask is not a valid map")) +// } +pub fn create_pulse_sender_flex( + _node: &Node, + calling_client: Arc, + data: &[u8], +) -> Result<()> { + let root = flexbuffers::Reader::get_root(data)?; + let flex_vec = root.get_vector()?; + let node = Node::create("/data/sender", flex_vec.idx(0).get_str()?, true); + let parent = get_spatial_parent_flex(&calling_client, flex_vec.idx(1).get_str()?)?; + let transform = Mat4::from_rotation_translation( + flex_to_quat!(flex_vec.idx(3)) + .ok_or_else(|| anyhow!("Rotation not found"))? + .into(), + flex_to_vec3!(flex_vec.idx(2)) + .ok_or_else(|| anyhow!("Position not found"))? + .into(), + ); + let node_rc = calling_client.scenegraph.add_node(node); + Spatial::add_to(&node_rc, Some(parent), transform)?; + PulseSender::add_to(&node_rc)?; + Ok(()) +} + +// pub fn mask_get_map_pulse_receiver_create_args( +// mask: &Mask, +// ) -> Result> { +// flexbuffers::Reader::get_root(mask.binary.as_slice()) +// .map_err(|_| anyhow!("Mask is not a valid flexbuffer"))? +// .get_vector()? +// .index(5)? +// .get_map() +// .map_err(|_| anyhow!("Mask is not a valid map")) +// } +pub fn create_pulse_receiver_flex( + _node: &Node, + calling_client: Arc, + data: &[u8], +) -> Result<()> { + let root = flexbuffers::Reader::get_root(data)?; + let flex_vec = root.get_vector()?; + let node = Node::create("/data/receiver", flex_vec.idx(0).get_str()?, true); + let parent = get_spatial_parent_flex(&calling_client, flex_vec.idx(1).get_str()?)?; + let transform = get_transform_pose_flex(&flex_vec.idx(2), &flex_vec.idx(3))?; + let field = calling_client + .scenegraph + .get_node(flex_vec.idx(4).as_str()) + .ok_or_else(|| anyhow!("Field not found"))? + .field + .get() + .ok_or_else(|| anyhow!("Field node is not a field"))? + .clone(); + + let node_rc = calling_client.scenegraph.add_node(node); + Spatial::add_to(&node_rc, Some(parent), transform)?; + PulseReceiver::add_to(&node_rc, field)?; + Ok(()) +}