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 [!!!] -->
|
||||
<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 -->
|
||||
<template name="ActionRow">
|
||||
<rectangle macro="group_box" id="${id}">
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@
|
|||
"LEFT": "Left",
|
||||
"RIGHT": "Right",
|
||||
"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_SKYMAPS": "Browse skymaps",
|
||||
|
|
|
|||
|
|
@ -159,6 +159,8 @@ pub enum Component {
|
|||
Touch,
|
||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.VALUE"))]
|
||||
Value,
|
||||
|
||||
/// Not an actual component but monado uses this instead of X/Y
|
||||
Position,
|
||||
Pose,
|
||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.PROXIMITY"))]
|
||||
|
|
@ -166,16 +168,20 @@ pub enum Component {
|
|||
Haptic,
|
||||
|
||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.X_AXIS"))]
|
||||
/// Not an actual component, used to turn a 2D Position into a 1D Value
|
||||
X,
|
||||
#[strum(props(Translation = "APP_SETTINGS.BINDINGS.COMP.Y_AXIS"))]
|
||||
/// Not an actual component, used to turn a 2D Position into a 1D Value
|
||||
Y,
|
||||
|
||||
#[serde(other)]
|
||||
Other,
|
||||
}
|
||||
|
||||
impl Component {
|
||||
pub fn is_analog(&self) -> bool {
|
||||
matches!(self, Component::Force | Component::Value | Component::X | Component::Y)
|
||||
}
|
||||
}
|
||||
|
||||
impl BindingsDropdown for Component {
|
||||
fn translation(&self) -> Translation {
|
||||
self
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::{borrow::Cow, collections::HashMap, rc::Rc};
|
|||
use glam::Vec2;
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::button::{ButtonClickEvent, ComponentButton},
|
||||
components::{button::{ButtonClickEvent, ComponentButton}, slider::ComponentSlider},
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
|
|
@ -34,6 +34,7 @@ enum Task {
|
|||
Save,
|
||||
Cancel,
|
||||
OpenContextMenu(glam::Vec2, Vec<context_menu::Cell>),
|
||||
UpdateThreshold(Rc<str>, f32, f32)
|
||||
}
|
||||
|
||||
pub struct Params<'a> {
|
||||
|
|
@ -83,14 +84,20 @@ impl ViewTrait for View {
|
|||
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
|
||||
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 mut s = name.splitn(5, ';');
|
||||
(s.next(), s.next(), s.next(), s.next(), s.next())
|
||||
&& let (Some(action), Some(action_name), Some(side), Some(value)) = {
|
||||
let mut s = name.splitn(4, ';');
|
||||
(s.next(), s.next(), s.next(), s.next())
|
||||
} {
|
||||
let side = side.to_lowercase();
|
||||
let value = value.to_lowercase();
|
||||
|
|
@ -336,6 +343,7 @@ fn input_controls_for_action(
|
|||
action.clone(),
|
||||
click_type,
|
||||
profile,
|
||||
current.threshold,
|
||||
)?;
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
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(
|
||||
|
|
@ -354,6 +362,7 @@ fn input_controls_for_hand(
|
|||
action: Rc<str>,
|
||||
click_type: ClickType,
|
||||
profile: &Profile,
|
||||
threshold: Option<[f32; 2]>,
|
||||
) -> anyhow::Result<()> {
|
||||
let subaction_path = match side {
|
||||
Side::Left => "/user/hand/left",
|
||||
|
|
@ -405,7 +414,11 @@ fn input_controls_for_hand(
|
|||
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(())
|
||||
}
|
||||
|
|
@ -478,6 +491,39 @@ fn clicks_dropdown(mp: &mut MacroParams, parent: WidgetID, action: Rc<str>, curr
|
|||
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<()> {
|
||||
let id = mp.idx.to_string();
|
||||
mp.idx += 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue