From 60ff3404450d595f088c6a7690f2f1e0dc00d0c1 Mon Sep 17 00:00:00 2001 From: BOT Alex <44818698+MagicBOTAlex@users.noreply.github.com> Date: Thu, 11 Dec 2025 01:58:21 +0100 Subject: [PATCH] all bindings can have multiple bindings (#281) fixed right hand and improved code remove flake forgor forgor removed print statemnets Co-authored-by: BOTAlex --- wlx-overlay-s/src/backend/openxr/input.rs | 238 ++++++++++------------ 1 file changed, 111 insertions(+), 127 deletions(-) diff --git a/wlx-overlay-s/src/backend/openxr/input.rs b/wlx-overlay-s/src/backend/openxr/input.rs index dbffaba7..db7342d4 100644 --- a/wlx-overlay-s/src/backend/openxr/input.rs +++ b/wlx-overlay-s/src/backend/openxr/input.rs @@ -438,8 +438,8 @@ impl OpenXrHandSource { } } -fn to_path(maybe_path_str: Option<&String>, instance: &xr::Instance) -> Option { - maybe_path_str.as_ref().and_then(|s| { +fn to_paths(maybe_path_str: Option<&str>, instance: &xr::Instance) -> Option { + maybe_path_str.and_then(|s| { instance .string_to_path(s) .inspect_err(|_| { @@ -449,60 +449,102 @@ fn to_path(maybe_path_str: Option<&String>, instance: &xr::Instance) -> Option) -> bool { - maybe_type_str - .as_ref() - .unwrap() // want panic +fn is_bool(path_str: &str) -> bool { + path_str .split('/') .next_back() .is_some_and(|last| matches!(last, "click" | "touch") || last.starts_with("dpad_")) } macro_rules! add_custom { - ($action:expr, $left:expr, $right:expr, $bindings:expr, $instance:expr) => { + ($action:expr, $field:ident, $hands:expr, $bindings:expr, $instance:expr) => { if let Some(action) = $action.as_ref() { - if let Some(p) = to_path(action.left.as_ref(), $instance) { - if is_bool(action.left.as_ref()) { - if action.triple_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$left.triple.action_bool, p)); - } else if action.double_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$left.double.action_bool, p)); - } else { - $bindings.push(xr::Binding::new(&$left.single.action_bool, p)); - } + for i in 0..2 { + let spec = if i == 0 { + action.left.as_ref() } else { - if action.triple_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$left.triple.action_f32, p)); - } else if action.double_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$left.double.action_f32, p)); - } else { - $bindings.push(xr::Binding::new(&$left.single.action_f32, p)); + action.right.as_ref() + }; + + if let Some(spec) = spec { + let iter: Box> = match spec { + OneOrMany::One(s) => Box::new(std::iter::once(s)), + OneOrMany::Many(v) => Box::new(v.iter()), + }; + + for s in iter { + if let Some(p) = to_paths(Some(s.as_str()), $instance) { + if is_bool(s) { + if action.triple_click.unwrap_or(false) { + $bindings.push(xr::Binding::new( + &$hands[i].$field.triple.action_bool, + p, + )); + } else if action.double_click.unwrap_or(false) { + $bindings.push(xr::Binding::new( + &$hands[i].$field.double.action_bool, + p, + )); + } else { + $bindings.push(xr::Binding::new( + &$hands[i].$field.single.action_bool, + p, + )); + } + } else { + if action.triple_click.unwrap_or(false) { + $bindings.push(xr::Binding::new( + &$hands[i].$field.triple.action_f32, + p, + )); + } else if action.double_click.unwrap_or(false) { + $bindings.push(xr::Binding::new( + &$hands[i].$field.double.action_f32, + p, + )); + } else { + $bindings.push(xr::Binding::new( + &$hands[i].$field.single.action_f32, + p, + )); + } + } + }; } - } - } - if let Some(p) = to_path(action.right.as_ref(), $instance) { - if is_bool(action.right.as_ref()) { - if action.triple_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$right.triple.action_bool, p)); - } else if action.double_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$right.double.action_bool, p)); - } else { - $bindings.push(xr::Binding::new(&$right.single.action_bool, p)); - } - } else { - if action.triple_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$right.triple.action_f32, p)); - } else if action.double_click.unwrap_or(false) { - $bindings.push(xr::Binding::new(&$right.double.action_f32, p)); - } else { - $bindings.push(xr::Binding::new(&$right.single.action_f32, p)); - } - } + }; } } }; } +// TODO: rename this bad func name +macro_rules! add_custom_lr { + ($action:expr, $field:ident, $hands:expr, $bindings:expr, $instance:expr) => { + if let Some(action) = $action { + for i in 0..2 { + let spec = if i == 0 { + action.left.as_ref() + } else { + action.right.as_ref() + }; + + if let Some(spec) = spec { + let iter: Box> = match spec { + OneOrMany::One(s) => Box::new(std::iter::once(s)), + OneOrMany::Many(v) => Box::new(v.iter()), + }; + + for s in iter { + if let Some(p) = to_paths(Some(s.as_str()), $instance) { + $bindings.push(xr::Binding::new(&$hands[i].$field, p)); + } + } + }; + } + }; + }; +} + #[allow(clippy::too_many_lines, clippy::cognitive_complexity)] fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) { let profiles = load_action_profiles(); @@ -515,120 +557,55 @@ fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) { let mut bindings: Vec = vec![]; - if let Some(action) = profile.pose { - if let Some(p) = to_path(action.left.as_ref(), instance) { - bindings.push(xr::Binding::new(&hands[0].pose, p)); - } - if let Some(p) = to_path(action.right.as_ref(), instance) { - bindings.push(xr::Binding::new(&hands[1].pose, p)); - } - } + add_custom_lr!(profile.pose, pose, hands, bindings, instance); + add_custom_lr!(profile.haptic, haptics, hands, bindings, instance); + add_custom_lr!(profile.scroll, scroll, hands, bindings, instance); - if let Some(action) = profile.haptic { - if let Some(p) = to_path(action.left.as_ref(), instance) { - bindings.push(xr::Binding::new(&hands[0].haptics, p)); - } - if let Some(p) = to_path(action.right.as_ref(), instance) { - bindings.push(xr::Binding::new(&hands[1].haptics, p)); - } - } + add_custom!(profile.click, click, hands, bindings, instance); - if let Some(action) = profile.scroll { - if let Some(p) = to_path(action.left.as_ref(), instance) { - bindings.push(xr::Binding::new(&hands[0].scroll, p)); - } - if let Some(p) = to_path(action.right.as_ref(), instance) { - bindings.push(xr::Binding::new(&hands[1].scroll, p)); - } - } + add_custom!(profile.alt_click, alt_click, hands, bindings, instance); - add_custom!( - profile.click, - hands[0].click, - hands[1].click, - bindings, - instance - ); + add_custom!(profile.grab, grab, hands, bindings, instance); - add_custom!( - profile.alt_click, - &hands[0].alt_click, - &hands[1].alt_click, - bindings, - instance - ); - - add_custom!( - profile.grab, - &hands[0].grab, - &hands[1].grab, - bindings, - instance - ); - - add_custom!( - profile.show_hide, - &hands[0].show_hide, - &hands[1].show_hide, - bindings, - instance - ); + add_custom!(profile.show_hide, show_hide, hands, bindings, instance); add_custom!( profile.toggle_dashboard, - &hands[0].toggle_dashboard, - &hands[1].toggle_dashboard, + toggle_dashboard, + hands, bindings, instance ); - add_custom!( - profile.space_drag, - &hands[0].space_drag, - &hands[1].space_drag, - bindings, - instance - ); + add_custom!(profile.space_drag, space_drag, hands, bindings, instance); add_custom!( profile.space_rotate, - &hands[0].space_rotate, - &hands[1].space_rotate, + space_rotate, + hands, bindings, instance ); - add_custom!( - profile.space_reset, - &hands[0].space_reset, - &hands[1].space_reset, - bindings, - instance - ); + add_custom!(profile.space_reset, space_reset, hands, bindings, instance); add_custom!( profile.click_modifier_right, - &hands[0].modifier_right, - &hands[1].modifier_right, + modifier_right, + hands, bindings, instance ); add_custom!( profile.click_modifier_middle, - &hands[0].modifier_middle, - &hands[1].modifier_middle, + modifier_middle, + hands, bindings, instance ); - add_custom!( - profile.move_mouse, - &hands[0].move_mouse, - &hands[1].move_mouse, - bindings, - instance - ); + add_custom!(profile.move_mouse, move_mouse, hands, bindings, instance); if instance .suggest_interaction_profile_bindings(profile_path, &bindings) @@ -640,10 +617,17 @@ fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +enum OneOrMany { + One(T), + Many(Vec), +} + #[derive(Debug, Clone, Serialize, Deserialize)] struct OpenXrActionConfAction { - left: Option, - right: Option, + left: Option>, + right: Option>, threshold: Option<[f32; 2]>, double_click: Option, triple_click: Option,