mirror of https://github.com/wayvr-org/wayvr.git
per-action thresholds
This commit is contained in:
parent
638af5a608
commit
b906bc6656
|
|
@ -181,8 +181,6 @@
|
||||||
"WATCH_VIEW_ANGLE_HELP": "Control how the watch fades away",
|
"WATCH_VIEW_ANGLE_HELP": "Control how the watch fades away",
|
||||||
"GRID_OPACITY": "Floor grid opacity",
|
"GRID_OPACITY": "Floor grid opacity",
|
||||||
"GRID_OPACITY_HELP": "Opacity of the floor grid when the skybox is enabled",
|
"GRID_OPACITY_HELP": "Opacity of the floor grid when the skybox is enabled",
|
||||||
"XR_CLICK_SENSITIVITY": "XR trigger sensitivity",
|
|
||||||
"XR_CLICK_SENSITIVITY_HELP": "Press and release values for analog triggers",
|
|
||||||
"XWAYLAND_BY_DEFAULT": "Run apps in Compatibility mode by default",
|
"XWAYLAND_BY_DEFAULT": "Run apps in Compatibility mode by default",
|
||||||
"SAVE": "Save",
|
"SAVE": "Save",
|
||||||
"CANCEL": "Cancel"
|
"CANCEL": "Cancel"
|
||||||
|
|
|
||||||
|
|
@ -316,8 +316,6 @@ enum SettingType {
|
||||||
UseSkybox,
|
UseSkybox,
|
||||||
WatchViewAngleMax,
|
WatchViewAngleMax,
|
||||||
WatchViewAngleMin,
|
WatchViewAngleMin,
|
||||||
XrClickSensitivity,
|
|
||||||
XrClickSensitivityRelease,
|
|
||||||
XwaylandByDefault,
|
XwaylandByDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -378,8 +376,6 @@ impl SettingType {
|
||||||
Self::UiRoundMultiplier => &mut config.ui_round_multiplier,
|
Self::UiRoundMultiplier => &mut config.ui_round_multiplier,
|
||||||
Self::WatchViewAngleMax => &mut config.watch_view_angle_max,
|
Self::WatchViewAngleMax => &mut config.watch_view_angle_max,
|
||||||
Self::WatchViewAngleMin => &mut config.watch_view_angle_min,
|
Self::WatchViewAngleMin => &mut config.watch_view_angle_min,
|
||||||
Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
|
|
||||||
Self::XrClickSensitivityRelease => &mut config.xr_click_sensitivity_release,
|
|
||||||
_ => panic!("Requested f32 for non-f32 SettingType"),
|
_ => panic!("Requested f32 for non-f32 SettingType"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -490,8 +486,6 @@ impl SettingType {
|
||||||
Self::UseSkybox => Ok("APP_SETTINGS.USE_SKYBOX"),
|
Self::UseSkybox => Ok("APP_SETTINGS.USE_SKYBOX"),
|
||||||
Self::WatchViewAngleMax => Ok("APP_SETTINGS.WATCH_VIEW_ANGLE"),
|
Self::WatchViewAngleMax => Ok("APP_SETTINGS.WATCH_VIEW_ANGLE"),
|
||||||
Self::WatchViewAngleMin => Ok("APP_SETTINGS.WATCH_VIEW_ANGLE"),
|
Self::WatchViewAngleMin => Ok("APP_SETTINGS.WATCH_VIEW_ANGLE"),
|
||||||
Self::XrClickSensitivity => Ok("APP_SETTINGS.XR_CLICK_SENSITIVITY"),
|
|
||||||
Self::XrClickSensitivityRelease => Ok("APP_SETTINGS.XR_CLICK_SENSITIVITY"),
|
|
||||||
Self::XwaylandByDefault => Ok("APP_SETTINGS.XWAYLAND_BY_DEFAULT"),
|
Self::XwaylandByDefault => Ok("APP_SETTINGS.XWAYLAND_BY_DEFAULT"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -519,8 +513,6 @@ impl SettingType {
|
||||||
Self::UseSkybox => Some("APP_SETTINGS.USE_SKYBOX_HELP"),
|
Self::UseSkybox => Some("APP_SETTINGS.USE_SKYBOX_HELP"),
|
||||||
Self::WatchViewAngleMax => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
Self::WatchViewAngleMax => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
||||||
Self::WatchViewAngleMin => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
Self::WatchViewAngleMin => Some("APP_SETTINGS.WATCH_VIEW_ANGLE_HELP"),
|
||||||
Self::XrClickSensitivity => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_HELP"),
|
|
||||||
Self::XrClickSensitivityRelease => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_HELP"),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,7 @@ use crate::{
|
||||||
frontend::FrontendTasks,
|
frontend::FrontendTasks,
|
||||||
tab::settings::{
|
tab::settings::{
|
||||||
SettingType, SettingsMountParams, SettingsTab,
|
SettingType, SettingsMountParams, SettingsTab,
|
||||||
macros::{
|
macros::{options_category, options_checkbox, options_dropdown, options_slider_f32, options_slider_i32},
|
||||||
options_category, options_checkbox, options_dropdown, options_range_f32, options_slider_f32, options_slider_i32,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
views::{ViewUpdateParams, input_profiles},
|
views::{ViewUpdateParams, input_profiles},
|
||||||
};
|
};
|
||||||
|
|
@ -104,15 +102,6 @@ impl State {
|
||||||
|
|
||||||
if par.feats.openxr {
|
if par.feats.openxr {
|
||||||
options_slider_f32(par.mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1)?;
|
options_slider_f32(par.mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1)?;
|
||||||
options_range_f32(
|
|
||||||
par.mp,
|
|
||||||
c,
|
|
||||||
SettingType::XrClickSensitivityRelease,
|
|
||||||
SettingType::XrClickSensitivity,
|
|
||||||
0.1,
|
|
||||||
0.9,
|
|
||||||
0.1,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
|
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use anyhow::{bail, Context};
|
use anyhow::{Context, bail};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use strum::{AsRefStr, EnumProperty, EnumString};
|
use strum::{AsRefStr, EnumProperty, EnumString};
|
||||||
use wgui::i18n::Translation;
|
use wgui::i18n::Translation;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ enum Task {
|
||||||
Save,
|
Save,
|
||||||
Cancel,
|
Cancel,
|
||||||
OpenContextMenu(glam::Vec2, Vec<context_menu::Cell>),
|
OpenContextMenu(glam::Vec2, Vec<context_menu::Cell>),
|
||||||
UpdateThreshold(Rc<str>, f32, f32),
|
UpdateThreshold(Rc<str>, Side, f32, f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Params<'a> {
|
pub struct Params<'a> {
|
||||||
|
|
@ -89,11 +89,15 @@ impl ViewTrait for View {
|
||||||
blueprint: context_menu::Blueprint::Cells(cells),
|
blueprint: context_menu::Blueprint::Cells(cells),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Task::UpdateThreshold(action_name, lo, hi) => {
|
Task::UpdateThreshold(action_name, side, lo, hi) => {
|
||||||
let cur_profile = &mut self.profiles[self.cur_profile_idx];
|
let cur_profile = &mut self.profiles[self.cur_profile_idx];
|
||||||
let action_mut = get_action_mut(cur_profile, &*action_name);
|
let action_mut = get_action_mut(cur_profile, &*action_name);
|
||||||
|
|
||||||
action_mut.threshold = Some([lo, hi]);
|
if matches!(side, Side::Right) {
|
||||||
|
action_mut.threshold_right = Some([lo, hi]);
|
||||||
|
} else {
|
||||||
|
action_mut.threshold_left = Some([lo, hi]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +242,13 @@ impl View {
|
||||||
|
|
||||||
for action in action_names {
|
for action in action_names {
|
||||||
let current = get_action_mut(&mut self.profiles[self.cur_profile_idx], action);
|
let current = get_action_mut(&mut self.profiles[self.cur_profile_idx], action);
|
||||||
input_controls_for_action(&mut mp, self.list_parent, action.into(), &self.controller_profile, current)?;
|
input_controls_for_action(
|
||||||
|
&mut mp,
|
||||||
|
self.list_parent,
|
||||||
|
action.into(),
|
||||||
|
&self.controller_profile,
|
||||||
|
current,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -264,13 +274,17 @@ impl View {
|
||||||
|
|
||||||
let action = cur_profile.haptic.get_or_insert_default();
|
let action = cur_profile.haptic.get_or_insert_default();
|
||||||
|
|
||||||
let has_haptic = profile_left.map(|x| x.find_subpath(SubpathKind::Haptic).is_some()).unwrap_or_default();
|
let has_haptic = profile_left
|
||||||
|
.map(|x| x.find_subpath(SubpathKind::Haptic).is_some())
|
||||||
|
.unwrap_or_default();
|
||||||
if action.left.is_none() && has_haptic {
|
if action.left.is_none() && has_haptic {
|
||||||
let path = "/user/hand/left/output/haptic";
|
let path = "/user/hand/left/output/haptic";
|
||||||
action.left = Some(OneOrMany::One(path.into()));
|
action.left = Some(OneOrMany::One(path.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let has_haptic = profile_right.map(|x| x.find_subpath(SubpathKind::Haptic).is_some()).unwrap_or_default();
|
let has_haptic = profile_right
|
||||||
|
.map(|x| x.find_subpath(SubpathKind::Haptic).is_some())
|
||||||
|
.unwrap_or_default();
|
||||||
if action.right.is_none() && has_haptic {
|
if action.right.is_none() && has_haptic {
|
||||||
let path = "/user/hand/right/output/haptic";
|
let path = "/user/hand/right/output/haptic";
|
||||||
action.right = Some(OneOrMany::One(path.into()));
|
action.right = Some(OneOrMany::One(path.into()));
|
||||||
|
|
@ -381,7 +395,7 @@ fn input_controls_for_action(
|
||||||
action.clone(),
|
action.clone(),
|
||||||
click_type,
|
click_type,
|
||||||
profile,
|
profile,
|
||||||
current.threshold,
|
current.threshold_left,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let current_right = current.right.as_ref().map(|x| match x {
|
let current_right = current.right.as_ref().map(|x| match x {
|
||||||
|
|
@ -397,7 +411,7 @@ fn input_controls_for_action(
|
||||||
action,
|
action,
|
||||||
click_type,
|
click_type,
|
||||||
profile,
|
profile,
|
||||||
current.threshold,
|
current.threshold_right,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -423,9 +437,15 @@ fn input_controls_for_hand(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|par| user_path.find_subpath(par.subpath))
|
.and_then(|par| user_path.find_subpath(par.subpath))
|
||||||
.map(|subp| subp.components)
|
.map(|subp| subp.components)
|
||||||
.unwrap_or_default().into();
|
.unwrap_or_default()
|
||||||
|
.into();
|
||||||
|
|
||||||
let available_subpaths : Rc<[SubpathKind]> = user_path.paths.iter().filter(|x| !x.kind.get_bool("Hidden").unwrap_or_default()).map(|x| x.kind).collect();
|
let available_subpaths: Rc<[SubpathKind]> = user_path
|
||||||
|
.paths
|
||||||
|
.iter()
|
||||||
|
.filter(|x| !x.kind.get_bool("Hidden").unwrap_or_default())
|
||||||
|
.map(|x| x.kind)
|
||||||
|
.collect();
|
||||||
|
|
||||||
subpath_dropdown(
|
subpath_dropdown(
|
||||||
mp,
|
mp,
|
||||||
|
|
@ -452,7 +472,7 @@ fn input_controls_for_hand(
|
||||||
if let Some(component) = current.as_ref().map(|x| x.component)
|
if let Some(component) = current.as_ref().map(|x| x.component)
|
||||||
&& component.is_analog()
|
&& component.is_analog()
|
||||||
{
|
{
|
||||||
threshold_slider(mp, parent, action, threshold)?;
|
threshold_slider(mp, parent, action, side, threshold)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -530,6 +550,7 @@ fn threshold_slider(
|
||||||
mp: &mut MacroParams,
|
mp: &mut MacroParams,
|
||||||
parent: WidgetID,
|
parent: WidgetID,
|
||||||
action: Rc<str>,
|
action: Rc<str>,
|
||||||
|
side: Side,
|
||||||
current: Option<[f32; 2]>,
|
current: Option<[f32; 2]>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let id = mp.idx.to_string();
|
let id = mp.idx.to_string();
|
||||||
|
|
@ -554,9 +575,9 @@ fn threshold_slider(
|
||||||
let tasks = mp.tasks.clone();
|
let tasks = mp.tasks.clone();
|
||||||
move |_common, e| {
|
move |_common, e| {
|
||||||
if matches!(e.index, wgui::components::slider::ValueIndex::Primary) {
|
if matches!(e.index, wgui::components::slider::ValueIndex::Primary) {
|
||||||
tasks.push(Task::UpdateThreshold(action.clone(), e.value, current[1]));
|
tasks.push(Task::UpdateThreshold(action.clone(), side, e.value, current[1]));
|
||||||
} else {
|
} else {
|
||||||
tasks.push(Task::UpdateThreshold(action.clone(), current[0], e.value));
|
tasks.push(Task::UpdateThreshold(action.clone(), side, current[0], e.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
@ -626,7 +647,12 @@ fn create_dropdown<B: 'static + BindingsDropdown>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_subpath(side_mut: &mut Option<OneOrMany<String>>, side_str: &str, subpath_str: &str, profile: &ControllerProfile,) {
|
fn apply_subpath(
|
||||||
|
side_mut: &mut Option<OneOrMany<String>>,
|
||||||
|
side_str: &str,
|
||||||
|
subpath_str: &str,
|
||||||
|
profile: &ControllerProfile,
|
||||||
|
) {
|
||||||
let (Ok(side), Ok(subpath)) = (Side::try_from(side_str), SubpathKind::try_from(subpath_str)) else {
|
let (Ok(side), Ok(subpath)) = (Side::try_from(side_str), SubpathKind::try_from(subpath_str)) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -674,7 +700,5 @@ fn apply_comp(side_mut: &mut Option<OneOrMany<String>>, side: &str, comp: &str)
|
||||||
|
|
||||||
let subpath = parsed.subpath.as_ref().to_lowercase();
|
let subpath = parsed.subpath.as_ref().to_lowercase();
|
||||||
|
|
||||||
*side_mut = Some(OneOrMany::One(format!(
|
*side_mut = Some(OneOrMany::One(format!("/user/hand/{side}/input/{subpath}/{comp}")));
|
||||||
"/user/hand/{side}/input/{subpath}/{comp}"
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
||||||
openxr_controller_profiles::OPENXR_INPUT_PROFILES,
|
openxr_controller_profiles::OPENXR_INPUT_PROFILES,
|
||||||
popup_manager::{MountPopupOnceParams, PopupHolder},
|
popup_manager::{MountPopupOnceParams, PopupHolder},
|
||||||
},
|
},
|
||||||
views::{self, bindings, ViewTrait, ViewUpdateParams},
|
views::{self, ViewTrait, ViewUpdateParams, bindings},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ pub struct CustomClickAction {
|
||||||
single: MultiClickHandler<0>,
|
single: MultiClickHandler<0>,
|
||||||
double: MultiClickHandler<1>,
|
double: MultiClickHandler<1>,
|
||||||
triple: MultiClickHandler<2>,
|
triple: MultiClickHandler<2>,
|
||||||
|
threshold: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomClickAction {
|
impl CustomClickAction {
|
||||||
|
|
@ -127,18 +128,19 @@ impl CustomClickAction {
|
||||||
single,
|
single,
|
||||||
double,
|
double,
|
||||||
triple,
|
triple,
|
||||||
|
threshold: [0.5, 0.7],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn state(
|
|
||||||
&mut self,
|
pub fn set_threshold(&mut self, threshold: [f32; 2]) {
|
||||||
before: bool,
|
self.threshold = threshold;
|
||||||
state: &XrState,
|
}
|
||||||
session: &AppSession,
|
|
||||||
) -> anyhow::Result<bool> {
|
pub fn state(&mut self, before: bool, state: &XrState) -> anyhow::Result<bool> {
|
||||||
let threshold = if before {
|
let threshold = if before {
|
||||||
session.config.xr_click_sensitivity_release
|
self.threshold[1]
|
||||||
} else {
|
} else {
|
||||||
session.config.xr_click_sensitivity
|
self.threshold[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(self.single.check(&state.session, threshold)?
|
Ok(self.single.check(&state.session, threshold)?
|
||||||
|
|
@ -171,14 +173,13 @@ impl OpenXrInputSource {
|
||||||
.instance()
|
.instance()
|
||||||
.create_action_set("wayvr", "WayVR Actions", 0)?;
|
.create_action_set("wayvr", "WayVR Actions", 0)?;
|
||||||
|
|
||||||
let left_source = OpenXrHandSource::new(&mut action_set, "left")?;
|
let mut left_source = OpenXrHandSource::new(&mut action_set, "left")?;
|
||||||
let right_source = OpenXrHandSource::new(&mut action_set, "right")?;
|
let mut right_source = OpenXrHandSource::new(&mut action_set, "right")?;
|
||||||
let fallback_source = OpenXrHandSource::new(&mut action_set, "handsfree")?;
|
let mut fallback_source = OpenXrHandSource::new(&mut action_set, "handsfree")?;
|
||||||
|
|
||||||
suggest_bindings(
|
let mut hands: [&mut OpenXrHandSource; 3] =
|
||||||
&xr.instance,
|
[&mut left_source, &mut right_source, &mut fallback_source];
|
||||||
&[&left_source, &right_source, &fallback_source],
|
suggest_bindings(&xr.instance, &mut hands);
|
||||||
);
|
|
||||||
|
|
||||||
xr.session.attach_action_sets(&[&action_set])?;
|
xr.session.attach_action_sets(&[&action_set])?;
|
||||||
|
|
||||||
|
|
@ -381,7 +382,7 @@ impl OpenXrPointer {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pointer_load_actions(pointer, xr, session)?;
|
self.pointer_load_actions(pointer, xr)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -394,7 +395,7 @@ impl OpenXrPointer {
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
pointer.handsfree = false;
|
pointer.handsfree = false;
|
||||||
self.pointer_load_pose(pointer, xr, session.config.pointer_lerp_factor)?;
|
self.pointer_load_pose(pointer, xr, session.config.pointer_lerp_factor)?;
|
||||||
self.pointer_load_actions(pointer, xr, session)?;
|
self.pointer_load_actions(pointer, xr)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -431,15 +432,10 @@ impl OpenXrPointer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pointer_load_actions(
|
fn pointer_load_actions(&mut self, pointer: &mut Pointer, xr: &XrState) -> anyhow::Result<()> {
|
||||||
&mut self,
|
pointer.now.click = self.source.click.state(pointer.before.click, xr)?;
|
||||||
pointer: &mut Pointer,
|
|
||||||
xr: &XrState,
|
|
||||||
session: &AppSession,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
pointer.now.click = self.source.click.state(pointer.before.click, xr, session)?;
|
|
||||||
|
|
||||||
pointer.now.grab = self.source.grab.state(pointer.before.grab, xr, session)?;
|
pointer.now.grab = self.source.grab.state(pointer.before.grab, xr)?;
|
||||||
|
|
||||||
let scroll = self
|
let scroll = self
|
||||||
.source
|
.source
|
||||||
|
|
@ -450,50 +446,44 @@ impl OpenXrPointer {
|
||||||
pointer.now.scroll_x = scroll.x;
|
pointer.now.scroll_x = scroll.x;
|
||||||
pointer.now.scroll_y = scroll.y;
|
pointer.now.scroll_y = scroll.y;
|
||||||
|
|
||||||
pointer.now.alt_click =
|
pointer.now.alt_click = self.source.alt_click.state(pointer.before.alt_click, xr)?;
|
||||||
self.source
|
|
||||||
.alt_click
|
|
||||||
.state(pointer.before.alt_click, xr, session)?;
|
|
||||||
|
|
||||||
pointer.now.show_hide =
|
pointer.now.show_hide = self.source.show_hide.state(pointer.before.show_hide, xr)?;
|
||||||
self.source
|
|
||||||
.show_hide
|
|
||||||
.state(pointer.before.show_hide, xr, session)?;
|
|
||||||
|
|
||||||
pointer.now.click_modifier_right =
|
pointer.now.click_modifier_right = self
|
||||||
self.source
|
.source
|
||||||
.modifier_right
|
.modifier_right
|
||||||
.state(pointer.before.click_modifier_right, xr, session)?;
|
.state(pointer.before.click_modifier_right, xr)?;
|
||||||
|
|
||||||
pointer.now.toggle_dashboard =
|
pointer.now.toggle_dashboard = self
|
||||||
self.source
|
.source
|
||||||
.toggle_dashboard
|
.toggle_dashboard
|
||||||
.state(pointer.before.toggle_dashboard, xr, session)?;
|
.state(pointer.before.toggle_dashboard, xr)?;
|
||||||
|
|
||||||
pointer.now.click_modifier_middle =
|
pointer.now.click_modifier_middle = self
|
||||||
self.source
|
.source
|
||||||
.modifier_middle
|
.modifier_middle
|
||||||
.state(pointer.before.click_modifier_middle, xr, session)?;
|
.state(pointer.before.click_modifier_middle, xr)?;
|
||||||
|
|
||||||
pointer.now.move_mouse =
|
pointer.now.move_mouse = self
|
||||||
self.source
|
.source
|
||||||
.move_mouse
|
.move_mouse
|
||||||
.state(pointer.before.move_mouse, xr, session)?;
|
.state(pointer.before.move_mouse, xr)?;
|
||||||
|
|
||||||
pointer.now.space_drag =
|
pointer.now.space_drag = self
|
||||||
self.source
|
.source
|
||||||
.space_drag
|
.space_drag
|
||||||
.state(pointer.before.space_drag, xr, session)?;
|
.state(pointer.before.space_drag, xr)?;
|
||||||
|
|
||||||
pointer.now.space_rotate =
|
pointer.now.space_rotate = self
|
||||||
self.source
|
.source
|
||||||
.space_rotate
|
.space_rotate
|
||||||
.state(pointer.before.space_rotate, xr, session)?;
|
.state(pointer.before.space_rotate, xr)?;
|
||||||
|
|
||||||
pointer.now.space_reset =
|
pointer.now.space_reset = self
|
||||||
self.source
|
.source
|
||||||
.space_reset
|
.space_reset
|
||||||
.state(pointer.before.space_reset, xr, session)?;
|
.state(pointer.before.space_reset, xr)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -648,7 +638,20 @@ macro_rules! add_custom_lr {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
|
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
|
||||||
fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 3]) {
|
macro_rules! set_threshold_for {
|
||||||
|
($hands:expr, $profile_action:expr, $field:ident) => {
|
||||||
|
if let Some(ref profile_action) = $profile_action {
|
||||||
|
if let Some(threshold) = profile_action.threshold_left {
|
||||||
|
$hands[0].$field.set_threshold(threshold);
|
||||||
|
}
|
||||||
|
if let Some(threshold) = profile_action.threshold_right {
|
||||||
|
$hands[1].$field.set_threshold(threshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn suggest_bindings(instance: &xr::Instance, hands: &mut [&mut OpenXrHandSource; 3]) {
|
||||||
let profiles = load_xr_input_profiles();
|
let profiles = load_xr_input_profiles();
|
||||||
|
|
||||||
for profile in profiles {
|
for profile in profiles {
|
||||||
|
|
@ -659,6 +662,7 @@ fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 3]) {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{
|
||||||
let mut bindings: Vec<xr::Binding> = vec![];
|
let mut bindings: Vec<xr::Binding> = vec![];
|
||||||
|
|
||||||
add_custom_lr!(profile.pose, pose, hands, bindings, instance);
|
add_custom_lr!(profile.pose, pose, hands, bindings, instance);
|
||||||
|
|
@ -724,4 +728,17 @@ fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 3]) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_threshold_for!(hands, profile.click, click);
|
||||||
|
set_threshold_for!(hands, profile.alt_click, alt_click);
|
||||||
|
set_threshold_for!(hands, profile.grab, grab);
|
||||||
|
set_threshold_for!(hands, profile.show_hide, show_hide);
|
||||||
|
set_threshold_for!(hands, profile.toggle_dashboard, toggle_dashboard);
|
||||||
|
set_threshold_for!(hands, profile.space_drag, space_drag);
|
||||||
|
set_threshold_for!(hands, profile.space_rotate, space_rotate);
|
||||||
|
set_threshold_for!(hands, profile.space_reset, space_reset);
|
||||||
|
set_threshold_for!(hands, profile.click_modifier_right, modifier_right);
|
||||||
|
set_threshold_for!(hands, profile.click_modifier_middle, modifier_middle);
|
||||||
|
set_threshold_for!(hands, profile.move_mouse, move_mouse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,8 +148,6 @@ pub struct AutoSettings {
|
||||||
pub enable_watch: bool,
|
pub enable_watch: bool,
|
||||||
pub sets_on_watch: bool,
|
pub sets_on_watch: bool,
|
||||||
pub hide_grab_help: bool,
|
pub hide_grab_help: bool,
|
||||||
pub xr_click_sensitivity: f32,
|
|
||||||
pub xr_click_sensitivity_release: f32,
|
|
||||||
pub allow_sliding: bool,
|
pub allow_sliding: bool,
|
||||||
pub focus_follows_mouse_mode: bool,
|
pub focus_follows_mouse_mode: bool,
|
||||||
pub left_handed_mouse: bool,
|
pub left_handed_mouse: bool,
|
||||||
|
|
@ -210,8 +208,6 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
|
||||||
enable_watch: config.enable_watch,
|
enable_watch: config.enable_watch,
|
||||||
sets_on_watch: config.sets_on_watch,
|
sets_on_watch: config.sets_on_watch,
|
||||||
hide_grab_help: config.hide_grab_help,
|
hide_grab_help: config.hide_grab_help,
|
||||||
xr_click_sensitivity: config.xr_click_sensitivity,
|
|
||||||
xr_click_sensitivity_release: config.xr_click_sensitivity_release,
|
|
||||||
allow_sliding: config.allow_sliding,
|
allow_sliding: config.allow_sliding,
|
||||||
focus_follows_mouse_mode: config.focus_follows_mouse_mode,
|
focus_follows_mouse_mode: config.focus_follows_mouse_mode,
|
||||||
left_handed_mouse: config.left_handed_mouse,
|
left_handed_mouse: config.left_handed_mouse,
|
||||||
|
|
|
||||||
|
|
@ -194,11 +194,6 @@
|
||||||
#invert_scroll_direction_x: false
|
#invert_scroll_direction_x: false
|
||||||
#invert_scroll_direction_y: false
|
#invert_scroll_direction_y: false
|
||||||
|
|
||||||
## Press and release thresholds for grip & trigger
|
|
||||||
## when using OpenXR (WiVRn, Monado)
|
|
||||||
#xr_click_sensitivity: 0.7
|
|
||||||
#xr_click_sensitivity_release: 0.5
|
|
||||||
|
|
||||||
## How many seconds to buttons need to be held
|
## How many seconds to buttons need to be held
|
||||||
## before it's considered a long press
|
## before it's considered a long press
|
||||||
#long_press_duration: 1.0
|
#long_press_duration: 1.0
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,11 @@
|
||||||
move_mouse: {
|
move_mouse: {
|
||||||
left: "/user/hand/left/input/trigger/value",
|
left: "/user/hand/left/input/trigger/value",
|
||||||
right: "/user/hand/right/input/trigger/value",
|
right: "/user/hand/right/input/trigger/value",
|
||||||
threshold: [
|
threshold_left: [
|
||||||
|
0.1,
|
||||||
|
0.2
|
||||||
|
],
|
||||||
|
threshold_right: [
|
||||||
0.1,
|
0.1,
|
||||||
0.2
|
0.2
|
||||||
]
|
]
|
||||||
|
|
@ -282,7 +286,11 @@
|
||||||
move_mouse: {
|
move_mouse: {
|
||||||
left: "/user/hand/left/input/trigger/value",
|
left: "/user/hand/left/input/trigger/value",
|
||||||
right: "/user/hand/right/input/trigger/value",
|
right: "/user/hand/right/input/trigger/value",
|
||||||
threshold: [
|
threshold_left: [
|
||||||
|
0.1,
|
||||||
|
0.2
|
||||||
|
],
|
||||||
|
threshold_right: [
|
||||||
0.1,
|
0.1,
|
||||||
0.2
|
0.2
|
||||||
]
|
]
|
||||||
|
|
@ -326,7 +334,11 @@
|
||||||
move_mouse: {
|
move_mouse: {
|
||||||
left: "/user/hand/left/input/trigger/value",
|
left: "/user/hand/left/input/trigger/value",
|
||||||
right: "/user/hand/right/input/trigger/value",
|
right: "/user/hand/right/input/trigger/value",
|
||||||
threshold: [
|
threshold_left: [
|
||||||
|
0.1,
|
||||||
|
0.2
|
||||||
|
],
|
||||||
|
threshold_right: [
|
||||||
0.1,
|
0.1,
|
||||||
0.2
|
0.2
|
||||||
]
|
]
|
||||||
|
|
@ -361,7 +373,11 @@
|
||||||
move_mouse: {
|
move_mouse: {
|
||||||
left: "/user/hand/left/input/trigger/value",
|
left: "/user/hand/left/input/trigger/value",
|
||||||
right: "/user/hand/right/input/trigger/value",
|
right: "/user/hand/right/input/trigger/value",
|
||||||
threshold: [
|
threshold_left: [
|
||||||
|
0.1,
|
||||||
|
0.2
|
||||||
|
],
|
||||||
|
threshold_right: [
|
||||||
0.1,
|
0.1,
|
||||||
0.2
|
0.2
|
||||||
]
|
]
|
||||||
|
|
@ -408,7 +424,11 @@
|
||||||
move_mouse: {
|
move_mouse: {
|
||||||
left: "/user/hand/left/input/trigger/value",
|
left: "/user/hand/left/input/trigger/value",
|
||||||
right: "/user/hand/right/input/trigger/value",
|
right: "/user/hand/right/input/trigger/value",
|
||||||
threshold: [
|
threshold_left: [
|
||||||
|
0.1,
|
||||||
|
0.2
|
||||||
|
],
|
||||||
|
threshold_right: [
|
||||||
0.1,
|
0.1,
|
||||||
0.2
|
0.2
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -292,12 +292,6 @@ pub struct GeneralConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub capture_method: CaptureMethod,
|
pub capture_method: CaptureMethod,
|
||||||
|
|
||||||
#[serde(default = "def_point7")]
|
|
||||||
pub xr_click_sensitivity: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_half")]
|
|
||||||
pub xr_click_sensitivity_release: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
#[serde(default = "def_true")]
|
||||||
pub allow_sliding: bool,
|
pub allow_sliding: bool,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ pub struct OpenXrInputAction {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub handsfree: Option<OneOrMany<String>>,
|
pub handsfree: Option<OneOrMany<String>>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub threshold: Option<[f32; 2]>,
|
pub threshold_left: Option<[f32; 2]>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub threshold_right: Option<[f32; 2]>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub double_click: Option<bool>,
|
pub double_click: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue