feat(input): new system

This commit is contained in:
Nova
2023-02-25 16:39:30 -05:00
parent b5fc321e36
commit 42782d0f87
3 changed files with 88 additions and 93 deletions

View File

@@ -6,31 +6,31 @@ use std::{
sync::{Arc, Weak},
};
// #[derive(Default)]
// pub struct LifeLinkedNodeList {
// nodes: Mutex<Vec<Weak<Node>>>,
// }
// impl LifeLinkedNodeList {
// pub fn add(&self, node: Weak<Node>) {
// self.nodes.lock().push(node);
// }
#[derive(Default)]
pub struct LifeLinkedNodeList {
nodes: Mutex<Vec<Weak<Node>>>,
}
impl LifeLinkedNodeList {
pub fn add(&self, node: Weak<Node>) {
self.nodes.lock().push(node);
}
// pub fn clear(&self) {
// self.nodes
// .lock()
// .iter()
// .filter_map(|node| node.upgrade())
// .for_each(|node| {
// node.destroy();
// });
// self.nodes.lock().clear();
// }
// }
// impl Drop for LifeLinkedNodeList {
// fn drop(&mut self) {
// self.clear();
// }
// }
pub fn clear(&self) {
self.nodes
.lock()
.iter()
.filter_map(|node| node.upgrade())
.for_each(|node| {
node.destroy();
});
self.nodes.lock().clear();
}
}
impl Drop for LifeLinkedNodeList {
fn drop(&mut self) {
self.clear();
}
}
#[derive(Default)]
pub struct LifeLinkedNodeMap<K: Hash + Eq> {

View File

@@ -7,23 +7,21 @@ use self::pointer::Pointer;
use self::tip::Tip;
use super::{
alias::{Alias, AliasInfo},
fields::{find_field, Field},
spatial::{find_spatial_parent, parse_transform, Spatial},
Node,
};
use crate::core::registry::Registry;
use crate::core::{client::Client, task};
use crate::core::{eventloop::FRAME, node_collections::LifeLinkedNodeMap};
use crate::core::client::Client;
use crate::core::eventloop::FRAME;
use crate::core::{node_collections::LifeLinkedNodeList, registry::Registry};
use color_eyre::eyre::{ensure, Result};
use glam::Mat4;
use parking_lot::Mutex;
use portable_atomic::AtomicBool;
use serde::Deserialize;
use stardust_xr::schemas::flat::{Datamap, InputDataType};
use stardust_xr::schemas::{flat::InputData, flex::deserialize};
use stardust_xr::schemas::{
flat::{Datamap, InputDataType},
flex::flexbuffers,
};
use stardust_xr::values::Transform;
use std::ops::Deref;
use std::sync::atomic::Ordering;
@@ -60,11 +58,11 @@ impl Deref for InputType {
pub struct InputMethod {
node: Weak<Node>,
pub uid: String,
uid: String,
pub enabled: Mutex<bool>,
pub spatial: Arc<Spatial>,
pub specialization: Mutex<InputType>,
pub captures: Registry<InputHandler>,
captures: Registry<InputHandler>,
pub datamap: Mutex<Option<Datamap>>,
}
impl InputMethod {
@@ -79,7 +77,8 @@ impl InputMethod {
"Internal: Node does not have a spatial attached!"
);
node.add_local_signal("set_datamap", InputMethod::set_datamap);
node.add_local_signal("capture", InputMethod::capture_flex);
node.add_local_signal("set_datamap", InputMethod::set_datamap_flex);
let method = InputMethod {
node: Arc::downgrade(node),
@@ -95,13 +94,18 @@ impl InputMethod {
Ok(method)
}
fn set_datamap(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
node.input_method
.get()
.unwrap()
.datamap
.lock()
.replace(Datamap::new(data.to_vec())?);
fn capture_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let method = node.get_aspect("Input Method", "input method", |n| &n.input_method)?;
let handler_node = calling_client.get_node("Input Handler", deserialize(data)?)?;
let handler =
handler_node.get_aspect("Input Handler", "input handler", |n| &n.input_handler)?;
method.captures.add_raw(&handler);
Ok(())
}
fn set_datamap_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let method = node.get_aspect("Input Method", "input method", |n| &n.input_method)?;
method.datamap.lock().replace(Datamap::new(data.to_vec())?);
Ok(())
}
@@ -121,17 +125,30 @@ impl Drop for InputMethod {
}
pub struct DistanceLink {
pub distance: f32,
pub method: Arc<InputMethod>,
pub handler: Arc<InputHandler>,
distance: f32,
method: Arc<InputMethod>,
handler: Arc<InputHandler>,
}
impl DistanceLink {
fn from(method: Arc<InputMethod>, handler: Arc<InputHandler>) -> Self {
DistanceLink {
fn from(method: Arc<InputMethod>, handler: Arc<InputHandler>) -> Option<Self> {
let handler_node = handler.node.upgrade()?;
let method_alias = Alias::create(
&handler_node.get_client()?,
handler_node.get_path(),
&method.uid,
&method.node.upgrade()?,
AliasInfo {
local_signals: vec!["capture"],
..Default::default()
},
)
.ok()?;
handler.method_aliases.add(Arc::downgrade(&method_alias));
Some(DistanceLink {
distance: method.compare_distance(&handler.field),
method,
handler,
}
})
}
fn send_input(&self, frame: u64, datamap: Datamap) {
@@ -158,8 +175,8 @@ pub struct InputHandler {
enabled: Arc<AtomicBool>,
node: Weak<Node>,
spatial: Arc<Spatial>,
pub field: Arc<Field>,
method_aliases: LifeLinkedNodeMap<String>,
field: Arc<Field>,
method_aliases: LifeLinkedNodeList,
}
impl InputHandler {
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
@@ -173,7 +190,7 @@ impl InputHandler {
node: Arc::downgrade(node),
spatial: node.spatial.get().unwrap().clone(),
field: field.clone(),
method_aliases: LifeLinkedNodeMap::default(),
method_aliases: LifeLinkedNodeList::default(),
};
let handler = INPUT_HANDLER_REGISTRY.add(handler);
let _ = node.input_handler.set(handler);
@@ -182,30 +199,8 @@ impl InputHandler {
#[instrument(level = "debug", skip(self, distance_link))]
fn send_input(&self, frame: u64, distance_link: &DistanceLink, datamap: Datamap) {
let data = distance_link.serialize(datamap);
let Some(node) = self.node.upgrade() else {return};
let method = Arc::downgrade(&distance_link.method);
let handler = Arc::downgrade(&distance_link.handler);
if let Ok(data) = node.execute_remote_method("input", data) {
let _ = task::new(|| "input capture", async move {
if let Ok(data) = data.await {
if frame == FRAME.load(Ordering::Relaxed) {
let capture = flexbuffers::Reader::get_root(data.as_slice())
.and_then(|data| data.get_bool())
.unwrap_or(false);
if capture {
if let Some(method) = method.upgrade() {
if let Some(handler) = handler.upgrade() {
method.captures.add_raw(&handler);
}
}
}
}
}
});
}
let _ = node.send_remote_signal("input", &distance_link.serialize(datamap));
}
}
impl PartialEq for InputHandler {
@@ -259,18 +254,19 @@ pub fn process_input() {
.filter(|method| *method.enabled.lock())
.filter(|method| method.datamap.lock().is_some())
});
let handlers = INPUT_HANDLER_REGISTRY
.get_valid_contents()
.into_iter()
.filter(|handler| handler.enabled.load(Ordering::Relaxed));
let handlers = INPUT_HANDLER_REGISTRY.get_valid_contents();
for handler in &handlers {
handler.method_aliases.clear();
}
for method in methods {
debug_span!("Process input method").in_scope(|| {
// Get all valid input handlers and convert them to DistanceLink objects
let mut distance_links: Vec<DistanceLink> = debug_span!("Generate distance links")
.in_scope(|| {
handlers
.clone()
.map(|handler| DistanceLink::from(method.clone(), handler))
.iter()
.filter(|handler| handler.enabled.load(Ordering::Relaxed))
.filter_map(|handler| DistanceLink::from(method.clone(), handler.clone()))
.collect()
});

View File

@@ -22,7 +22,6 @@ use stardust_xr::messenger::MessageSenderHandle;
use stardust_xr::scenegraph::ScenegraphError;
use stardust_xr::schemas::flex::deserialize;
use std::fmt::Debug;
use std::future::Future;
use std::sync::{Arc, Weak};
use std::vec::Vec;
use tracing::{debug_span, instrument};
@@ -249,21 +248,21 @@ impl Node {
.transpose()?;
Ok(())
}
#[instrument(level = "debug", skip_all)]
pub fn execute_remote_method(
&self,
method: &str,
data: Vec<u8>,
) -> Result<impl Future<Output = Result<Vec<u8>>>> {
let message_sender_handle = self
.message_sender_handle
.as_ref()
.ok_or(eyre!("Messenger does not exist for this node"))?;
// #[instrument(level = "debug", skip_all)]
// pub fn execute_remote_method(
// &self,
// method: &str,
// data: Vec<u8>,
// ) -> Result<impl Future<Output = Result<Vec<u8>>>> {
// let message_sender_handle = self
// .message_sender_handle
// .as_ref()
// .ok_or(eyre!("Messenger does not exist for this node"))?;
let future = message_sender_handle.method(self.path.as_str(), method, &data)?;
// let future = message_sender_handle.method(self.path.as_str(), method, &data)?;
Ok(async { future.await.map_err(|e| eyre!(e)) })
}
// Ok(async { future.await.map_err(|e| eyre!(e)) })
// }
}
impl Debug for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {