feat(alias): add aliasing remote signals/methods

This commit is contained in:
Nova
2022-06-19 23:31:38 -04:00
parent 82140c09fa
commit cceda8f72d
6 changed files with 122 additions and 56 deletions

View File

@@ -7,15 +7,16 @@ use libstardustxr::messenger::Messenger;
use mio::net::UnixStream;
use std::sync::Arc;
#[derive(Default)]
pub struct Client {
pub messenger: Messenger,
pub messenger: Option<Messenger>,
pub scenegraph: Scenegraph,
}
impl Client {
pub fn from_connection(connection: UnixStream) -> Arc<Self> {
let client = Arc::new(Client {
messenger: Messenger::new(connection),
messenger: Some(Messenger::new(connection)),
scenegraph: Default::default(),
});
let _ = client.scenegraph.client.set(Arc::downgrade(&client));
@@ -26,6 +27,10 @@ impl Client {
client
}
pub fn dispatch(&self) -> Result<(), std::io::Error> {
self.messenger.dispatch(&self.scenegraph)
if let Some(messenger) = &self.messenger {
messenger.dispatch(&self.scenegraph)
} else {
Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
}
}
}

View File

@@ -2,6 +2,7 @@ use super::data::{PulseReceiver, PulseSender};
use super::field::Field;
use super::spatial::Spatial;
use crate::core::client::Client;
use crate::core::registry::Registry;
use anyhow::{anyhow, Result};
use libstardustxr::scenegraph::ScenegraphError;
use nanoid::nanoid;
@@ -26,7 +27,9 @@ pub struct Node {
local_methods: DashMap<String, Method, BuildHasherDefault<FxHasher>>,
destroyable: AtomicBool,
alias: OnceCell<Alias>,
alias: OnceCell<Arc<Alias>>,
aliases: Registry<Alias>,
pub spatial: OnceCell<Arc<Spatial>>,
pub field: OnceCell<Arc<Field>>,
pub pulse_sender: OnceCell<Arc<PulseSender>>,
@@ -34,8 +37,8 @@ pub struct Node {
}
impl Node {
pub fn get_client(&self) -> Option<Arc<Client>> {
self.client.clone().upgrade()
pub fn get_client(&self) -> Arc<Client> {
self.client.clone().upgrade().unwrap()
}
// pub fn get_name(&self) -> &str {
// &self.path[self.trailing_slash_pos + 1..]
@@ -47,13 +50,13 @@ impl Node {
self.destroyable.load(Ordering::Relaxed)
}
pub fn create(parent: &str, name: &str, destroyable: bool) -> Self {
pub fn create(client: &Arc<Client>, parent: &str, name: &str, destroyable: bool) -> Self {
let mut path = parent.to_string();
path.push('/');
path.push_str(name);
let node = Node {
uid: nanoid!(),
client: Weak::new(),
client: Arc::downgrade(client),
path,
// trailing_slash_pos: parent.len(),
local_signals: Default::default(),
@@ -61,6 +64,8 @@ impl Node {
destroyable: AtomicBool::from(destroyable),
alias: OnceCell::new(),
aliases: Default::default(),
spatial: OnceCell::new(),
field: OnceCell::new(),
pulse_sender: OnceCell::new(),
@@ -69,10 +74,11 @@ impl Node {
node.add_local_signal("destroy", Node::destroy_flex);
node
}
pub fn add_to_scenegraph(self) -> Arc<Node> {
self.get_client().scenegraph.add_node(self)
}
pub fn destroy(&self) {
if let Some(client) = self.get_client() {
let _ = client.scenegraph.remove_node(self.get_path());
}
let _ = self.get_client().scenegraph.remove_node(self.get_path());
}
pub fn destroy_flex(node: &Node, _calling_client: Arc<Client>, _data: &[u8]) -> Result<()> {
@@ -96,7 +102,7 @@ impl Node {
data: &[u8],
) -> Result<(), ScenegraphError> {
if let Some(alias) = self.alias.get().as_ref() {
if !alias.signals.iter().any(|e| e == &method) {
if !alias.local_signals.iter().any(|e| e == &method) {
return Err(ScenegraphError::SignalNotFound);
}
alias
@@ -120,7 +126,7 @@ impl Node {
data: &[u8],
) -> Result<Vec<u8>, ScenegraphError> {
if let Some(alias) = self.alias.get().as_ref() {
if !alias.methods.iter().any(|e| e == &method) {
if !alias.local_methods.iter().any(|e| e == &method) {
return Err(ScenegraphError::MethodNotFound);
}
alias
@@ -138,9 +144,21 @@ impl Node {
}
}
pub fn send_remote_signal(&self, method: &str, data: &[u8]) -> Result<()> {
self.aliases
.get_valid_contents()
.iter()
.filter(|alias| alias.remote_signals.iter().any(|e| e == &method))
.for_each(|alias| {
let _ = alias
.node
.upgrade()
.unwrap()
.send_remote_signal(method, data);
});
self.get_client()
.ok_or_else(|| anyhow!("Node has no client, can't send remote signal!"))?
.messenger
.as_ref()
.ok_or_else(|| anyhow!("Node's client has no messenger"))?
.send_remote_signal(self.path.as_str(), method, data)
.map_err(|_| anyhow!("Unable to write in messenger"))
}
@@ -150,31 +168,53 @@ impl Node {
// data: &[u8],
// callback: Box<dyn Fn(&[u8]) + 'a>,
// ) -> Result<()> {
// self.aliases
// .get_valid_contents()
// .iter()
// .filter(|alias| alias.remote_methods.iter().any(|e| e == &method))
// .for_each(|alias| {
// alias
// .node
// .upgrade()
// .unwrap()
// .execute_remote_method(method, data, callback);
// });
// self.get_client()
// .ok_or_else(|| anyhow!("Node has no client, can't send remote signal!"))?
// .messenger
// .as_ref()
// .ok_or_else(|| anyhow!("Node's client has no messenger"))?
// .execute_remote_method(self.path.as_str(), method, data, callback)
// .map_err(|_| anyhow!("Unable to write in messenger"))
// }
}
pub struct Alias {
node: Weak<Node>,
original: Weak<Node>,
signals: Vec<&'static str>,
methods: Vec<&'static str>,
local_signals: Vec<&'static str>,
local_methods: Vec<&'static str>,
remote_signals: Vec<&'static str>,
remote_methods: Vec<&'static str>,
}
impl Alias {
pub fn add_to(
node: &Arc<Node>,
original: &Arc<Node>,
signals: Vec<&'static str>,
methods: Vec<&'static str>,
local_signals: Vec<&'static str>,
local_methods: Vec<&'static str>,
remote_signals: Vec<&'static str>,
remote_methods: Vec<&'static str>,
) {
let _ = node.alias.set(Alias {
let alias = Alias {
node: Arc::downgrade(node),
original: Arc::downgrade(original),
signals,
methods,
});
local_signals,
local_methods,
remote_signals,
remote_methods,
};
let alias = original.aliases.add(alias);
let _ = node.alias.set(alias);
}
}

View File

@@ -128,13 +128,20 @@ impl PulseSender {
Ok(flexbuffer_from_vector_arguments(move |fbb| {
sender.aliases.clear();
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);
let receiver_alias = Node::create(
&calling_client,
node.get_path(),
receiver.uid.as_str(),
false,
)
.add_to_scenegraph();
Alias::add_to(
&receiver_alias,
receiver.node.upgrade().as_ref().unwrap(),
vec![],
vec!["sendData"],
vec![],
vec![],
);
sender.aliases.add(Arc::downgrade(&receiver_alias));
fbb.push(receiver.uid.as_str());
@@ -217,10 +224,10 @@ impl Drop for PulseReceiver {
}
pub fn create_interface(client: &Arc<Client>) {
let node = Node::create("", "data", false);
let node = Node::create(client, "", "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);
node.add_to_scenegraph();
}
// pub fn mask_get_map_pulse_sender_create_args(mask: &Mask) -> Result<flexbuffers::MapReader<&[u8]>> {
@@ -238,7 +245,12 @@ pub fn create_pulse_sender_flex(
) -> 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 node = Node::create(
&calling_client,
"/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))
@@ -248,9 +260,9 @@ pub fn create_pulse_sender_flex(
.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)?;
let node = node.add_to_scenegraph();
Spatial::add_to(&node, Some(parent), transform)?;
PulseSender::add_to(&node)?;
Ok(())
}
@@ -271,7 +283,12 @@ pub fn create_pulse_receiver_flex(
) -> 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 node = Node::create(
&calling_client,
"/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
@@ -283,8 +300,8 @@ pub fn create_pulse_receiver_flex(
.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)?;
let node = node.add_to_scenegraph();
Spatial::add_to(&node, Some(parent), transform)?;
PulseReceiver::add_to(&node, field)?;
Ok(())
}

View File

@@ -310,16 +310,16 @@ impl FieldTrait for SphereField {
}
pub fn create_interface(client: &Arc<Client>) {
let node = Node::create("", "field", false);
let node = Node::create(client, "", "field", false);
node.add_local_signal("createBoxField", create_box_field_flex);
node.add_local_signal("createCylinderField", create_cylinder_field_flex);
node.add_local_signal("createSphereField", create_sphere_field_flex);
client.scenegraph.add_node(node);
node.add_to_scenegraph();
}
pub fn create_box_field_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?;
let node = Node::create("/field", flex_vec.idx(0).get_str()?, true);
let node = Node::create(&calling_client, "/field", 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))
@@ -330,9 +330,9 @@ pub fn create_box_field_flex(_node: &Node, calling_client: Arc<Client>, data: &[
.into(),
);
let size = flex_to_vec3!(flex_vec.idx(4)).ok_or_else(|| anyhow!("Size invalid"))?;
let node_rc = calling_client.scenegraph.add_node(node);
Spatial::add_to(&node_rc, Some(parent), transform)?;
BoxField::add_to(&node_rc, size.into())?;
let node = node.add_to_scenegraph();
Spatial::add_to(&node, Some(parent), transform)?;
BoxField::add_to(&node, size.into())?;
Ok(())
}
@@ -342,7 +342,7 @@ pub fn create_cylinder_field_flex(
data: &[u8],
) -> Result<()> {
let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?;
let node = Node::create("/field", flex_vec.idx(0).get_str()?, true);
let node = Node::create(&calling_client, "/field", 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))
@@ -354,9 +354,9 @@ pub fn create_cylinder_field_flex(
);
let length = flex_vec.idx(0).as_f32();
let radius = flex_vec.idx(1).as_f32();
let node_rc = calling_client.scenegraph.add_node(node);
Spatial::add_to(&node_rc, Some(parent), transform)?;
CylinderField::add_to(&node_rc, length, radius)?;
let node = node.add_to_scenegraph();
Spatial::add_to(&node, Some(parent), transform)?;
CylinderField::add_to(&node, length, radius)?;
Ok(())
}
@@ -366,15 +366,15 @@ pub fn create_sphere_field_flex(
data: &[u8],
) -> Result<()> {
let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?;
let node = Node::create("/field", flex_vec.idx(0).get_str()?, true);
let node = Node::create(&calling_client, "/field", 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_translation(
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)?;
SphereField::add_to(&node_rc, flex_vec.idx(3).as_f32())?;
let node = node.add_to_scenegraph();
Spatial::add_to(&node, Some(parent), transform)?;
SphereField::add_to(&node, flex_vec.idx(3).as_f32())?;
Ok(())
}

View File

@@ -5,7 +5,6 @@ use glam::Mat4;
use std::sync::Arc;
pub fn create_root(client: &Arc<Client>) {
let node = Node::create("", "", false);
let node = client.scenegraph.add_node(node);
let node = Node::create(client, "", "", false).add_to_scenegraph();
let _ = Spatial::add_to(&node, None, Mat4::IDENTITY);
}

View File

@@ -177,14 +177,19 @@ pub fn get_transform_pose_flex<B: flexbuffers::Buffer>(
}
pub fn create_interface(client: &Arc<Client>) {
let node = Node::create("", "spatial", false);
let node = Node::create(client, "", "spatial", false);
node.add_local_signal("createSpatial", create_spatial_flex);
client.scenegraph.add_node(node);
node.add_to_scenegraph();
}
pub fn create_spatial_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let flex_vec = flexbuffers::Reader::get_root(data)?.get_vector()?;
let spatial = Node::create("/spatial/spatial", flex_vec.idx(0).get_str()?, true);
let node = Node::create(
&calling_client,
"/spatial/spatial",
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_scale_rotation_translation(
flex_to_vec3!(flex_vec.idx(4))
@@ -197,7 +202,7 @@ pub fn create_spatial_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8
.ok_or_else(|| anyhow!("Position not found"))?
.into(),
);
let spatial_rc = calling_client.scenegraph.add_node(spatial);
Spatial::add_to(&spatial_rc, Some(parent), transform)?;
let node = node.add_to_scenegraph();
Spatial::add_to(&node, Some(parent), transform)?;
Ok(())
}