Skip to content

Commit

Permalink
refactor(input): switch to manual handler order
Browse files Browse the repository at this point in the history
  • Loading branch information
technobaboo committed Apr 16, 2024
1 parent 226554f commit be2f5b8
Show file tree
Hide file tree
Showing 14 changed files with 415 additions and 151 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ fn main() {
.unwrap();
let mut hands = (!cli_args.flatscreen)
.then(|| {
let left = SkHand::new(Handed::Left).ok();
let right = SkHand::new(Handed::Right).ok();
let left = SkHand::new(Handed::Left, &sk).ok();
let right = SkHand::new(Handed::Right, &sk).ok();
left.zip(right)
})
.flatten();
Expand Down
13 changes: 5 additions & 8 deletions src/nodes/input/hand.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{DistanceLink, Finger, Hand, InputDataTrait, Joint, Thumb};
use super::{Finger, Hand, InputDataTrait, InputLink, Joint, Thumb};
use crate::nodes::fields::Field;
use crate::nodes::spatial::Spatial;
use glam::{vec3a, Mat4, Quat};
Expand Down Expand Up @@ -52,10 +52,7 @@ impl Default for Hand {
}

impl InputDataTrait for Hand {
fn compare_distance(&self, space: &Arc<Spatial>, field: &Field) -> f32 {
self.true_distance(space, field).abs()
}
fn true_distance(&self, space: &Arc<Spatial>, field: &Field) -> f32 {
fn distance(&self, space: &Arc<Spatial>, field: &Field) -> f32 {
let mut min_distance = f32::MAX;

for tip in [
Expand All @@ -70,7 +67,7 @@ impl InputDataTrait for Hand {

min_distance
}
fn update_to(&mut self, distance_link: &DistanceLink, local_to_handler_matrix: Mat4) {
fn update_to(&mut self, input_link: &InputLink, local_to_handler_matrix: Mat4) {
let mut joints: Vec<&mut Joint> = Vec::new();

joints.extend([&mut self.palm, &mut self.wrist]);
Expand Down Expand Up @@ -104,10 +101,10 @@ impl InputDataTrait for Hand {
let (_, rotation, position) = joint_matrix.to_scale_rotation_translation();
joint.position = position.into();
joint.rotation = rotation.into();
joint.distance = distance_link
joint.distance = input_link
.handler
.field
.distance(&distance_link.handler.spatial, position.into());
.distance(&input_link.handler.spatial, position.into());
}
}
}
15 changes: 6 additions & 9 deletions src/nodes/input/handler.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use super::{
input_handler_client, DistanceLink, InputHandlerAspect, INPUT_HANDLER_REGISTRY,
input_handler_client, InputHandlerAspect, InputLink, INPUT_HANDLER_REGISTRY,
INPUT_METHOD_REGISTRY,
};
use crate::{
core::node_collections::LifeLinkedNodeMap,
nodes::{fields::Field, spatial::Spatial, Aspect, Node},
};
use color_eyre::eyre::Result;
use portable_atomic::AtomicBool;
use stardust_xr::values::Datamap;
use std::sync::{Arc, Weak};
use tracing::instrument;

pub struct InputHandler {
pub enabled: Arc<AtomicBool>,
pub uid: String,
pub node: Weak<Node>,
pub spatial: Arc<Spatial>,
Expand All @@ -23,7 +21,6 @@ pub struct InputHandler {
impl InputHandler {
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
let handler = InputHandler {
enabled: node.enabled.clone(),
uid: node.uid.clone(),
node: Arc::downgrade(node),
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
Expand All @@ -39,28 +36,28 @@ impl InputHandler {
Ok(())
}

#[instrument(level = "debug", skip(self, distance_link))]
#[instrument(level = "debug", skip(self, input_link))]
pub(super) fn send_input(
&self,
order: u32,
captured: bool,
distance_link: &DistanceLink,
input_link: &InputLink,
datamap: Datamap,
) {
let Some(node) = self.node.upgrade() else {
return;
};
let Some(method_alias) = distance_link
let Some(method_alias) = input_link
.handler
.method_aliases
.get(&(Arc::as_ptr(&distance_link.method) as usize))
.get(&(Arc::as_ptr(&input_link.method) as usize))
else {
return;
};
let _ = input_handler_client::input(
&node,
&method_alias,
&distance_link.serialize(order, captured, datamap),
&input_link.serialize(order, captured, datamap),
);
}
}
Expand Down
38 changes: 17 additions & 21 deletions src/nodes/input/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ pub struct InputMethod {
pub data: Mutex<InputDataType>,
pub datamap: Mutex<Datamap>,

pub(super) captures: Registry<InputHandler>,
pub captures: Registry<InputHandler>,
pub(super) handler_aliases: LifeLinkedNodeMap<String>,
pub(super) handler_order: Mutex<Option<Vec<Weak<InputHandler>>>>,
pub(super) handler_order: Mutex<Vec<Weak<InputHandler>>>,
}
impl InputMethod {
pub fn add_to(
Expand All @@ -44,7 +44,7 @@ impl InputMethod {
captures: Registry::new(),
datamap: Mutex::new(datamap),
handler_aliases: LifeLinkedNodeMap::default(),
handler_order: Mutex::new(None),
handler_order: Mutex::new(Vec::new()),
};
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
method.handle_new_handler(&handler);
Expand Down Expand Up @@ -84,16 +84,12 @@ impl InputMethod {
.add(self as *const InputMethod as usize, &method_alias);
}

pub fn compare_distance(&self, to: &InputHandler) -> f32 {
let distance = self.data.lock().compare_distance(&self.spatial, &to.field);
if self.captures.contains(to) {
distance * 0.5
} else {
distance
}
pub fn distance(&self, to: &Field) -> f32 {
self.data.lock().distance(&self.spatial, to)
}
pub fn true_distance(&self, to: &Field) -> f32 {
self.data.lock().true_distance(&self.spatial, to)

pub fn set_handler_order<'a>(&self, handlers: impl Iterator<Item = &'a Arc<InputHandler>>) {
*self.handler_order.lock() = handlers.map(Arc::downgrade).collect();
}

pub(super) fn handle_new_handler(&self, handler: &InputHandler) {
Expand Down Expand Up @@ -137,7 +133,7 @@ impl InputMethod {
.add(handler.uid.clone() + "-field", &rx_field_alias);
}

let _ = input_method_client::new_handler(&method_node, &handler.uid, &handler_node);
let _ = input_method_client::create_handler(&method_node, &handler.uid, &handler_node);
}
pub(super) fn handle_drop_handler(&self, handler: &InputHandler) {
let uid = handler.uid.as_str();
Expand All @@ -147,7 +143,7 @@ impl InputMethod {
return;
};

let _ = input_method_client::drop_handler(&tx_node, &uid);
let _ = input_method_client::destroy_handler(&tx_node, &uid);
}
}
impl Aspect for InputMethod {
Expand Down Expand Up @@ -176,25 +172,25 @@ impl InputMethodAspect for InputMethod {
fn set_handler_order(
node: Arc<Node>,
_calling_client: Arc<Client>,
handlers: Option<Vec<Arc<Node>>>,
handlers: Vec<Arc<Node>>,
) -> Result<()> {
let input_method = node.get_aspect::<InputMethod>()?;
let Some(handlers) = handlers else {
*input_method.handler_order.lock() = None;
return Ok(());
};
let handlers = handlers
.into_iter()
.filter_map(|p| p.get_aspect::<InputHandler>().ok())
.map(|i| Arc::downgrade(&i))
.collect::<Vec<_>>();

*input_method.handler_order.lock() = Some(handlers);
*input_method.handler_order.lock() = handlers;
Ok(())
}

#[doc = "Have the input handler that this method reference came from capture the method for the next frame."]
fn capture(node: Arc<Node>, _calling_client: Arc<Client>, handler: Arc<Node>) -> Result<()> {
fn request_capture(
node: Arc<Node>,
_calling_client: Arc<Client>,
handler: Arc<Node>,
) -> Result<()> {
let input_method = node.get_aspect::<InputMethod>()?;
let input_handler = handler.get_aspect::<InputHandler>()?;

Expand Down
114 changes: 38 additions & 76 deletions src/nodes/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,17 @@ use std::sync::{Arc, Weak};
use tracing::{debug_span, instrument};

static INPUT_METHOD_REGISTRY: Registry<InputMethod> = Registry::new();
static INPUT_HANDLER_REGISTRY: Registry<InputHandler> = Registry::new();
pub static INPUT_HANDLER_REGISTRY: Registry<InputHandler> = Registry::new();

stardust_xr_server_codegen::codegen_input_protocol!();

pub struct DistanceLink {
distance: f32,
pub struct InputLink {
method: Arc<InputMethod>,
handler: Arc<InputHandler>,
}
impl DistanceLink {
impl InputLink {
fn from(method: Arc<InputMethod>, handler: Arc<InputHandler>) -> Self {
DistanceLink {
distance: method.compare_distance(&handler),
method,
handler,
}
InputLink { method, handler }
}

fn send_input(&self, order: u32, captured: bool, datamap: Datamap) {
Expand All @@ -53,40 +48,31 @@ impl DistanceLink {
InputData {
uid: self.method.uid.clone(),
input,
distance: self.method.true_distance(&self.handler.field),
distance: self.method.distance(&self.handler.field),
datamap,
order,
captured,
}
}
}
pub trait InputDataTrait {
fn compare_distance(&self, space: &Arc<Spatial>, field: &Field) -> f32;
fn true_distance(&self, space: &Arc<Spatial>, field: &Field) -> f32;
fn update_to(&mut self, distance_link: &DistanceLink, local_to_handler_matrix: Mat4);
fn distance(&self, space: &Arc<Spatial>, field: &Field) -> f32;
fn update_to(&mut self, input_link: &InputLink, local_to_handler_matrix: Mat4);
}
impl InputDataTrait for InputDataType {
fn compare_distance(&self, space: &Arc<Spatial>, field: &Field) -> f32 {
match self {
InputDataType::Pointer(i) => i.compare_distance(space, field),
InputDataType::Hand(i) => i.compare_distance(space, field),
InputDataType::Tip(i) => i.compare_distance(space, field),
}
}

fn true_distance(&self, space: &Arc<Spatial>, field: &Field) -> f32 {
fn distance(&self, space: &Arc<Spatial>, field: &Field) -> f32 {
match self {
InputDataType::Pointer(i) => i.true_distance(space, field),
InputDataType::Hand(i) => i.true_distance(space, field),
InputDataType::Tip(i) => i.true_distance(space, field),
InputDataType::Pointer(i) => i.distance(space, field),
InputDataType::Hand(i) => i.distance(space, field),
InputDataType::Tip(i) => i.distance(space, field),
}
}

fn update_to(&mut self, distance_link: &DistanceLink, local_to_handler_matrix: Mat4) {
fn update_to(&mut self, input_link: &InputLink, local_to_handler_matrix: Mat4) {
match self {
InputDataType::Pointer(i) => i.update_to(distance_link, local_to_handler_matrix),
InputDataType::Hand(i) => i.update_to(distance_link, local_to_handler_matrix),
InputDataType::Tip(i) => i.update_to(distance_link, local_to_handler_matrix),
InputDataType::Pointer(i) => i.update_to(input_link, local_to_handler_matrix),
InputDataType::Hand(i) => i.update_to(input_link, local_to_handler_matrix),
InputDataType::Tip(i) => i.update_to(input_link, local_to_handler_matrix),
}
}
}
Expand Down Expand Up @@ -144,66 +130,42 @@ pub fn process_input() {
.into_iter()
.filter(|method| *method.enabled.lock())
});
let handlers = INPUT_HANDLER_REGISTRY.get_valid_contents();
const LIMIT: usize = 50;
// const LIMIT: usize = 50;
for method in methods {
for alias in method.node.upgrade().unwrap().aliases.get_valid_contents() {
alias.enabled.store(false, Ordering::Release);
}

debug_span!("Process input method").in_scope(|| {
// Get all valid input handlers and convert them to DistanceLink objects
let distance_links: Vec<DistanceLink> = debug_span!("Generate distance links")
.in_scope(|| {
if let Some(handler_order) = &*method.handler_order.lock() {
handler_order
.iter()
.filter_map(Weak::upgrade)
.filter(|handler| handler.enabled.load(Ordering::Relaxed))
.map(|handler| DistanceLink::from(method.clone(), handler))
.collect()
} else {
let mut distance_links: Vec<_> = handlers
.iter()
.filter(|handler| handler.enabled.load(Ordering::Relaxed))
.map(|handler| {
debug_span!("Create distance link").in_scope(|| {
DistanceLink::from(method.clone(), handler.clone())
})
})
.collect();

// Sort the distance links by their distance in ascending order
debug_span!("Sort distance links").in_scope(|| {
distance_links.sort_unstable_by(|a, b| {
a.distance.abs().partial_cmp(&b.distance.abs()).unwrap()
});
});

distance_links.truncate(LIMIT);
distance_links
}
});

let captures = method.captures.take_valid_contents();
// Get all valid input handlers and convert them to InputLink objects
let input_links: Vec<InputLink> = debug_span!("Generate input links").in_scope(|| {
method
.handler_order
.lock()
.iter()
.filter_map(Weak::upgrade)
.filter(|handler| {
let Some(node) = handler.node.upgrade() else {
return false;
};
node.enabled()
})
.map(|handler| InputLink::from(method.clone(), handler))
.collect()
});

method.captures.clear();
// Iterate over the distance links and send input to them
for (i, distance_link) in distance_links.into_iter().enumerate() {
if let Some(method_alias) = distance_link
for (i, input_link) in input_links.into_iter().enumerate() {
if let Some(method_alias) = input_link
.handler
.method_aliases
.get(&(Arc::as_ptr(&distance_link.method) as usize))
.get(&(Arc::as_ptr(&input_link.method) as usize))
.and_then(|a| a.get_aspect::<Alias>().ok())
{
method_alias.enabled.store(true, Ordering::Release);
}
let captured = captures.contains(&distance_link.handler);
distance_link.send_input(i as u32, captured, method.datamap.lock().clone());

// If the current distance link is in the list of captured input handlers,
// break out of the loop to avoid sending input to the remaining distance links
if captured {
break;
}
input_link.send_input(i as u32, true, method.datamap.lock().clone());
}
});
}
Expand Down
Loading

0 comments on commit be2f5b8

Please sign in to comment.