feat(input): new system
This commit is contained in:
@@ -6,31 +6,31 @@ use std::{
|
|||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
|
|
||||||
// #[derive(Default)]
|
#[derive(Default)]
|
||||||
// pub struct LifeLinkedNodeList {
|
pub struct LifeLinkedNodeList {
|
||||||
// nodes: Mutex<Vec<Weak<Node>>>,
|
nodes: Mutex<Vec<Weak<Node>>>,
|
||||||
// }
|
}
|
||||||
// impl LifeLinkedNodeList {
|
impl LifeLinkedNodeList {
|
||||||
// pub fn add(&self, node: Weak<Node>) {
|
pub fn add(&self, node: Weak<Node>) {
|
||||||
// self.nodes.lock().push(node);
|
self.nodes.lock().push(node);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
// self.nodes
|
self.nodes
|
||||||
// .lock()
|
.lock()
|
||||||
// .iter()
|
.iter()
|
||||||
// .filter_map(|node| node.upgrade())
|
.filter_map(|node| node.upgrade())
|
||||||
// .for_each(|node| {
|
.for_each(|node| {
|
||||||
// node.destroy();
|
node.destroy();
|
||||||
// });
|
});
|
||||||
// self.nodes.lock().clear();
|
self.nodes.lock().clear();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// impl Drop for LifeLinkedNodeList {
|
impl Drop for LifeLinkedNodeList {
|
||||||
// fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// self.clear();
|
self.clear();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LifeLinkedNodeMap<K: Hash + Eq> {
|
pub struct LifeLinkedNodeMap<K: Hash + Eq> {
|
||||||
|
|||||||
@@ -7,23 +7,21 @@ use self::pointer::Pointer;
|
|||||||
use self::tip::Tip;
|
use self::tip::Tip;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
alias::{Alias, AliasInfo},
|
||||||
fields::{find_field, Field},
|
fields::{find_field, Field},
|
||||||
spatial::{find_spatial_parent, parse_transform, Spatial},
|
spatial::{find_spatial_parent, parse_transform, Spatial},
|
||||||
Node,
|
Node,
|
||||||
};
|
};
|
||||||
use crate::core::registry::Registry;
|
use crate::core::client::Client;
|
||||||
use crate::core::{client::Client, task};
|
use crate::core::eventloop::FRAME;
|
||||||
use crate::core::{eventloop::FRAME, node_collections::LifeLinkedNodeMap};
|
use crate::core::{node_collections::LifeLinkedNodeList, registry::Registry};
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::{ensure, Result};
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use portable_atomic::AtomicBool;
|
use portable_atomic::AtomicBool;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use stardust_xr::schemas::flat::{Datamap, InputDataType};
|
||||||
use stardust_xr::schemas::{flat::InputData, flex::deserialize};
|
use stardust_xr::schemas::{flat::InputData, flex::deserialize};
|
||||||
use stardust_xr::schemas::{
|
|
||||||
flat::{Datamap, InputDataType},
|
|
||||||
flex::flexbuffers,
|
|
||||||
};
|
|
||||||
use stardust_xr::values::Transform;
|
use stardust_xr::values::Transform;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
@@ -60,11 +58,11 @@ impl Deref for InputType {
|
|||||||
|
|
||||||
pub struct InputMethod {
|
pub struct InputMethod {
|
||||||
node: Weak<Node>,
|
node: Weak<Node>,
|
||||||
pub uid: String,
|
uid: String,
|
||||||
pub enabled: Mutex<bool>,
|
pub enabled: Mutex<bool>,
|
||||||
pub spatial: Arc<Spatial>,
|
pub spatial: Arc<Spatial>,
|
||||||
pub specialization: Mutex<InputType>,
|
pub specialization: Mutex<InputType>,
|
||||||
pub captures: Registry<InputHandler>,
|
captures: Registry<InputHandler>,
|
||||||
pub datamap: Mutex<Option<Datamap>>,
|
pub datamap: Mutex<Option<Datamap>>,
|
||||||
}
|
}
|
||||||
impl InputMethod {
|
impl InputMethod {
|
||||||
@@ -79,7 +77,8 @@ impl InputMethod {
|
|||||||
"Internal: Node does not have a spatial attached!"
|
"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 {
|
let method = InputMethod {
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
@@ -95,13 +94,18 @@ impl InputMethod {
|
|||||||
Ok(method)
|
Ok(method)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_datamap(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
fn capture_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
|
||||||
node.input_method
|
let method = node.get_aspect("Input Method", "input method", |n| &n.input_method)?;
|
||||||
.get()
|
let handler_node = calling_client.get_node("Input Handler", deserialize(data)?)?;
|
||||||
.unwrap()
|
let handler =
|
||||||
.datamap
|
handler_node.get_aspect("Input Handler", "input handler", |n| &n.input_handler)?;
|
||||||
.lock()
|
|
||||||
.replace(Datamap::new(data.to_vec())?);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,17 +125,30 @@ impl Drop for InputMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct DistanceLink {
|
pub struct DistanceLink {
|
||||||
pub distance: f32,
|
distance: f32,
|
||||||
pub method: Arc<InputMethod>,
|
method: Arc<InputMethod>,
|
||||||
pub handler: Arc<InputHandler>,
|
handler: Arc<InputHandler>,
|
||||||
}
|
}
|
||||||
impl DistanceLink {
|
impl DistanceLink {
|
||||||
fn from(method: Arc<InputMethod>, handler: Arc<InputHandler>) -> Self {
|
fn from(method: Arc<InputMethod>, handler: Arc<InputHandler>) -> Option<Self> {
|
||||||
DistanceLink {
|
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),
|
distance: method.compare_distance(&handler.field),
|
||||||
method,
|
method,
|
||||||
handler,
|
handler,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_input(&self, frame: u64, datamap: Datamap) {
|
fn send_input(&self, frame: u64, datamap: Datamap) {
|
||||||
@@ -158,8 +175,8 @@ pub struct InputHandler {
|
|||||||
enabled: Arc<AtomicBool>,
|
enabled: Arc<AtomicBool>,
|
||||||
node: Weak<Node>,
|
node: Weak<Node>,
|
||||||
spatial: Arc<Spatial>,
|
spatial: Arc<Spatial>,
|
||||||
pub field: Arc<Field>,
|
field: Arc<Field>,
|
||||||
method_aliases: LifeLinkedNodeMap<String>,
|
method_aliases: LifeLinkedNodeList,
|
||||||
}
|
}
|
||||||
impl InputHandler {
|
impl InputHandler {
|
||||||
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
|
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
|
||||||
@@ -173,7 +190,7 @@ impl InputHandler {
|
|||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
spatial: node.spatial.get().unwrap().clone(),
|
spatial: node.spatial.get().unwrap().clone(),
|
||||||
field: field.clone(),
|
field: field.clone(),
|
||||||
method_aliases: LifeLinkedNodeMap::default(),
|
method_aliases: LifeLinkedNodeList::default(),
|
||||||
};
|
};
|
||||||
let handler = INPUT_HANDLER_REGISTRY.add(handler);
|
let handler = INPUT_HANDLER_REGISTRY.add(handler);
|
||||||
let _ = node.input_handler.set(handler);
|
let _ = node.input_handler.set(handler);
|
||||||
@@ -182,30 +199,8 @@ impl InputHandler {
|
|||||||
|
|
||||||
#[instrument(level = "debug", skip(self, distance_link))]
|
#[instrument(level = "debug", skip(self, distance_link))]
|
||||||
fn send_input(&self, frame: u64, distance_link: &DistanceLink, datamap: Datamap) {
|
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 Some(node) = self.node.upgrade() else {return};
|
||||||
let method = Arc::downgrade(&distance_link.method);
|
let _ = node.send_remote_signal("input", &distance_link.serialize(datamap));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl PartialEq for InputHandler {
|
impl PartialEq for InputHandler {
|
||||||
@@ -259,18 +254,19 @@ pub fn process_input() {
|
|||||||
.filter(|method| *method.enabled.lock())
|
.filter(|method| *method.enabled.lock())
|
||||||
.filter(|method| method.datamap.lock().is_some())
|
.filter(|method| method.datamap.lock().is_some())
|
||||||
});
|
});
|
||||||
let handlers = INPUT_HANDLER_REGISTRY
|
let handlers = INPUT_HANDLER_REGISTRY.get_valid_contents();
|
||||||
.get_valid_contents()
|
for handler in &handlers {
|
||||||
.into_iter()
|
handler.method_aliases.clear();
|
||||||
.filter(|handler| handler.enabled.load(Ordering::Relaxed));
|
}
|
||||||
for method in methods {
|
for method in methods {
|
||||||
debug_span!("Process input method").in_scope(|| {
|
debug_span!("Process input method").in_scope(|| {
|
||||||
// Get all valid input handlers and convert them to DistanceLink objects
|
// Get all valid input handlers and convert them to DistanceLink objects
|
||||||
let mut distance_links: Vec<DistanceLink> = debug_span!("Generate distance links")
|
let mut distance_links: Vec<DistanceLink> = debug_span!("Generate distance links")
|
||||||
.in_scope(|| {
|
.in_scope(|| {
|
||||||
handlers
|
handlers
|
||||||
.clone()
|
.iter()
|
||||||
.map(|handler| DistanceLink::from(method.clone(), handler))
|
.filter(|handler| handler.enabled.load(Ordering::Relaxed))
|
||||||
|
.filter_map(|handler| DistanceLink::from(method.clone(), handler.clone()))
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ use stardust_xr::messenger::MessageSenderHandle;
|
|||||||
use stardust_xr::scenegraph::ScenegraphError;
|
use stardust_xr::scenegraph::ScenegraphError;
|
||||||
use stardust_xr::schemas::flex::deserialize;
|
use stardust_xr::schemas::flex::deserialize;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::future::Future;
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
use tracing::{debug_span, instrument};
|
use tracing::{debug_span, instrument};
|
||||||
@@ -249,21 +248,21 @@ impl Node {
|
|||||||
.transpose()?;
|
.transpose()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[instrument(level = "debug", skip_all)]
|
// #[instrument(level = "debug", skip_all)]
|
||||||
pub fn execute_remote_method(
|
// pub fn execute_remote_method(
|
||||||
&self,
|
// &self,
|
||||||
method: &str,
|
// method: &str,
|
||||||
data: Vec<u8>,
|
// data: Vec<u8>,
|
||||||
) -> Result<impl Future<Output = Result<Vec<u8>>>> {
|
// ) -> Result<impl Future<Output = Result<Vec<u8>>>> {
|
||||||
let message_sender_handle = self
|
// let message_sender_handle = self
|
||||||
.message_sender_handle
|
// .message_sender_handle
|
||||||
.as_ref()
|
// .as_ref()
|
||||||
.ok_or(eyre!("Messenger does not exist for this node"))?;
|
// .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 {
|
impl Debug for Node {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
|||||||
Reference in New Issue
Block a user