mirror of https://github.com/wayvr-org/wayvr.git
ui for thresholds
This commit is contained in:
parent
8a8c41bd9e
commit
025c6a0998
|
|
@ -4,6 +4,11 @@
|
||||||
<!-- used at runtime [!!!] -->
|
<!-- used at runtime [!!!] -->
|
||||||
<include src="../t_dropdown_button.xml" />
|
<include src="../t_dropdown_button.xml" />
|
||||||
|
|
||||||
|
<!-- id, min, max, step, value, value2, tooltip -->
|
||||||
|
<template name="ThresholdSlider">
|
||||||
|
<Slider id="${id}" width="200" height="24" min_value="${min}" max_value="${max}" step="${step}" value="${value}" value2="${value2}" tooltip="${tooltip}" />
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- id, translation -->
|
<!-- id, translation -->
|
||||||
<template name="ActionRow">
|
<template name="ActionRow">
|
||||||
<rectangle macro="group_box" id="${id}">
|
<rectangle macro="group_box" id="${id}">
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,8 @@
|
||||||
"LEFT": "Left",
|
"LEFT": "Left",
|
||||||
"RIGHT": "Right",
|
"RIGHT": "Right",
|
||||||
"COMPONENT": "Actuation type",
|
"COMPONENT": "Actuation type",
|
||||||
"SUBPATH": "Actuating control"
|
"SUBPATH": "Actuating control",
|
||||||
|
"THRESHOLD": "Activate when above upper value\nDeactivate when below lower value"
|
||||||
},
|
},
|
||||||
"BROWSE_ONLINE_CATALOG": "Browse online catalog...",
|
"BROWSE_ONLINE_CATALOG": "Browse online catalog...",
|
||||||
"BROWSE_SKYMAPS": "Browse skymaps",
|
"BROWSE_SKYMAPS": "Browse skymaps",
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,8 @@ pub enum Component {
|
||||||
Touch,
|
Touch,
|
||||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.VALUE"))]
|
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.VALUE"))]
|
||||||
Value,
|
Value,
|
||||||
|
|
||||||
|
/// Not an actual component but monado uses this instead of X/Y
|
||||||
Position,
|
Position,
|
||||||
Pose,
|
Pose,
|
||||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.PROXIMITY"))]
|
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.PROXIMITY"))]
|
||||||
|
|
@ -166,16 +168,20 @@ pub enum Component {
|
||||||
Haptic,
|
Haptic,
|
||||||
|
|
||||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.X_AXIS"))]
|
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.X_AXIS"))]
|
||||||
/// Not an actual component, used to turn a 2D Position into a 1D Value
|
|
||||||
X,
|
X,
|
||||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.Y_AXIS"))]
|
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.Y_AXIS"))]
|
||||||
/// Not an actual component, used to turn a 2D Position into a 1D Value
|
|
||||||
Y,
|
Y,
|
||||||
|
|
||||||
#[serde(other)]
|
#[serde(other)]
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Component {
|
||||||
|
pub fn is_analog(&self) -> bool {
|
||||||
|
matches!(self, Component::Force | Component::Value | Component::X | Component::Y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BindingsDropdown for Component {
|
impl BindingsDropdown for Component {
|
||||||
fn translation(&self) -> Translation {
|
fn translation(&self) -> Translation {
|
||||||
self
|
self
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::{borrow::Cow, collections::HashMap, rc::Rc};
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
components::button::{ButtonClickEvent, ComponentButton},
|
components::{button::{ButtonClickEvent, ComponentButton}, slider::ComponentSlider},
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
|
|
@ -34,6 +34,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Params<'a> {
|
pub struct Params<'a> {
|
||||||
|
|
@ -83,14 +84,20 @@ impl ViewTrait for View {
|
||||||
blueprint: context_menu::Blueprint::Cells(cells),
|
blueprint: context_menu::Blueprint::Cells(cells),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Task::UpdateThreshold(action_name, lo, hi) => {
|
||||||
|
let cur_profile = &mut self.profiles[self.cur_profile_idx];
|
||||||
|
let action_mut = get_action_mut(cur_profile, &*action_name);
|
||||||
|
|
||||||
|
action_mut.threshold = Some([lo, hi]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dropdown handling
|
// Dropdown handling
|
||||||
if let TickResult::Action(name) = self.context_menu.tick(par.layout, &mut self.parser_state)?
|
if let TickResult::Action(name) = self.context_menu.tick(par.layout, &mut self.parser_state)?
|
||||||
&& let (Some(action), Some(_), Some(action_name), Some(side), Some(value)) = {
|
&& let (Some(action), Some(action_name), Some(side), Some(value)) = {
|
||||||
let mut s = name.splitn(5, ';');
|
let mut s = name.splitn(4, ';');
|
||||||
(s.next(), s.next(), s.next(), s.next(), s.next())
|
(s.next(), s.next(), s.next(), s.next())
|
||||||
} {
|
} {
|
||||||
let side = side.to_lowercase();
|
let side = side.to_lowercase();
|
||||||
let value = value.to_lowercase();
|
let value = value.to_lowercase();
|
||||||
|
|
@ -336,6 +343,7 @@ fn input_controls_for_action(
|
||||||
action.clone(),
|
action.clone(),
|
||||||
click_type,
|
click_type,
|
||||||
profile,
|
profile,
|
||||||
|
current.threshold,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let current_right = current.right.as_ref().map(|x| match x {
|
let current_right = current.right.as_ref().map(|x| match x {
|
||||||
|
|
@ -343,7 +351,7 @@ fn input_controls_for_action(
|
||||||
OneOrMany::Many(s) => s.first().unwrap().as_str(), // safe
|
OneOrMany::Many(s) => s.first().unwrap().as_str(), // safe
|
||||||
});
|
});
|
||||||
|
|
||||||
input_controls_for_hand(mp, parent, current_right, Side::Right, action, click_type, profile)
|
input_controls_for_hand(mp, parent, current_right, Side::Right, action, click_type, profile, current.threshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_controls_for_hand(
|
fn input_controls_for_hand(
|
||||||
|
|
@ -354,6 +362,7 @@ fn input_controls_for_hand(
|
||||||
action: Rc<str>,
|
action: Rc<str>,
|
||||||
click_type: ClickType,
|
click_type: ClickType,
|
||||||
profile: &Profile,
|
profile: &Profile,
|
||||||
|
threshold: Option<[f32; 2]>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let subaction_path = match side {
|
let subaction_path = match side {
|
||||||
Side::Left => "/user/hand/left",
|
Side::Left => "/user/hand/left",
|
||||||
|
|
@ -405,7 +414,11 @@ fn input_controls_for_hand(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
clicks_dropdown(mp, parent, action, click_type)?;
|
clicks_dropdown(mp, parent, action.clone(), click_type)?;
|
||||||
|
|
||||||
|
if let Some(component) = current.as_ref().map(|x| x.component) && component.is_analog() {
|
||||||
|
threshold_slider(mp, parent, action, threshold)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -478,6 +491,39 @@ fn clicks_dropdown(mp: &mut MacroParams, parent: WidgetID, action: Rc<str>, curr
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn threshold_slider(mp: &mut MacroParams, parent: WidgetID, action: Rc<str>, current: Option<[f32; 2]>) -> anyhow::Result<()> {
|
||||||
|
let id = mp.idx.to_string();
|
||||||
|
mp.idx += 1;
|
||||||
|
|
||||||
|
let current = current.unwrap_or([0.4, 0.6]);
|
||||||
|
|
||||||
|
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
|
||||||
|
params.insert(Rc::from("id"), Rc::from(id.as_ref()));
|
||||||
|
params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.THRESHOLD"));
|
||||||
|
params.insert(Rc::from("value"), Rc::from(format!("{:.2}", current[0])));
|
||||||
|
params.insert(Rc::from("value2"), Rc::from(format!("{:.2}", current[1])));
|
||||||
|
params.insert(Rc::from("min"), Rc::from("0.0"));
|
||||||
|
params.insert(Rc::from("max"), Rc::from("1.0"));
|
||||||
|
params.insert(Rc::from("step"), Rc::from("0.1"));
|
||||||
|
|
||||||
|
mp.parser_state
|
||||||
|
.instantiate_template(mp.doc_params, "ThresholdSlider", mp.layout, parent, params)?;
|
||||||
|
|
||||||
|
let slider = mp.parser_state.fetch_component_as::<ComponentSlider>(&id)?;
|
||||||
|
slider.on_value_changed(Box::new({
|
||||||
|
let tasks = mp.tasks.clone();
|
||||||
|
move |_common, e| {
|
||||||
|
if matches!(e.index, wgui::components::slider::ValueIndex::Primary) {
|
||||||
|
tasks.push(Task::UpdateThreshold(action.clone(), e.value, current[1]));
|
||||||
|
} else {
|
||||||
|
tasks.push(Task::UpdateThreshold(action.clone(), current[0], e.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn create_dropdown<B: 'static + BindingsDropdown>(mp: &mut MacroParams, parent: WidgetID, mut params: HashMap<Rc<str>, Rc<str>>, action: Rc<str>, side: Side, current_text: Translation, available: Rc<[B]>) -> anyhow::Result<()> {
|
fn create_dropdown<B: 'static + BindingsDropdown>(mp: &mut MacroParams, parent: WidgetID, mut params: HashMap<Rc<str>, Rc<str>>, action: Rc<str>, side: Side, current_text: Translation, available: Rc<[B]>) -> anyhow::Result<()> {
|
||||||
let id = mp.idx.to_string();
|
let id = mp.idx.to_string();
|
||||||
mp.idx += 1;
|
mp.idx += 1;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue