watch & edit to use theme.xml; device batteries

This commit is contained in:
galister
2025-11-30 18:01:52 +09:00
parent 363c2d533c
commit 6c5ab63bec
13 changed files with 304 additions and 116 deletions

View File

@@ -5,19 +5,24 @@ use std::{
};
use glam::{Affine3A, Vec3, Vec3A};
use idmap::DirectIdMap;
use wgui::{
components::button::ComponentButton,
event::{CallbackDataCommon, EventAlterables, EventCallback},
event::{CallbackDataCommon, EventAlterables, EventCallback, StyleSetRequest},
i18n::Translation,
layout::WidgetID,
parser::Fetchable,
renderer_vk::text::custom_glyph::CustomGlyphData,
taffy,
widget::EventResult,
widget::{sprite::WidgetSprite, EventResult},
};
use wlx_common::windowing::{OverlayWindowState, Positioning};
use crate::{
backend::task::{ManagerTask, TaskType},
backend::{
input::TrackedDeviceRole,
task::{ManagerTask, TaskType},
},
gui::{
panel::{button::BUTTON_EVENTS, GuiPanel, NewGuiPanelParams, OnCustomAttribFunc},
timer::GuiTimer,
@@ -34,6 +39,7 @@ use crate::{
pub const WATCH_NAME: &str = "watch";
const MAX_TOOLBOX_BUTTONS: usize = 16;
const MAX_DEVICES: usize = 9;
#[derive(Default)]
struct WatchState {
@@ -43,6 +49,8 @@ struct WatchState {
overlay_metas: Vec<OverlayMeta>,
edit_mode_widgets: Vec<(WidgetID, bool)>,
edit_add_widget: WidgetID,
device_role_icons: DirectIdMap<TrackedDeviceRole, CustomGlyphData>,
devices: Vec<(WidgetID, WidgetID)>,
num_sets: usize,
delete: LongPressButtonState,
}
@@ -127,30 +135,85 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
} else if id.starts_with("edit_") {
state.edit_mode_widgets.push((widget, true));
} else if &*id == "sets" {
for idx in 0..MAX_OVERLAY_SETS {
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert("display".into(), (idx + 1).to_string().into());
params.insert("handle".into(), idx.to_string().into());
parser_state
.instantiate_template(doc_params, "Set", layout, widget, params)?;
let node = layout.state.nodes[widget];
let num_children = layout.state.tree.children(node).iter().len();
let button_id = format!("set_{idx}");
let component =
parser_state.fetch_component_as::<ComponentButton>(&button_id)?;
state.set_buttons.push(component);
for idx in 0..MAX_OVERLAY_SETS {
if idx >= num_children {
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert("display".into(), (idx + 1).to_string().into());
params.insert("idx".into(), idx.to_string().into());
parser_state.instantiate_template(
doc_params, "Set", layout, widget, params,
)?;
}
let comp = parser_state
.fetch_component_as::<ComponentButton>(&format!("set_{idx}"))?;
state.set_buttons.push(comp);
}
} else if &*id == "toolbox" {
for idx in 0..MAX_TOOLBOX_BUTTONS {
let overlay_id = format!("overlay_{idx}");
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert("idx".into(), idx.to_string().into());
parser_state.instantiate_template(
doc_params, "Overlay", layout, widget, params,
)?;
let node = layout.state.nodes[widget];
let num_children = layout.state.tree.children(node).iter().len() - 1; // -1 for keyboard
let component =
parser_state.fetch_component_as::<ComponentButton>(&overlay_id)?;
state.overlay_buttons.push(component);
for idx in 0..MAX_TOOLBOX_BUTTONS {
if idx >= num_children {
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert("idx".into(), idx.to_string().into());
parser_state.instantiate_template(
doc_params, "Overlay", layout, widget, params,
)?;
}
let comp = parser_state
.fetch_component_as::<ComponentButton>(&format!("overlay_{idx}"))?;
state.overlay_buttons.push(comp);
}
} else if id.starts_with("dev_") && id.ends_with("_sprite") {
// store device icons from xml
let id_n = id
.replace("dev_", "")
.replace("_sprite", "")
.parse::<u64>()?;
let role = match id_n {
0 => TrackedDeviceRole::Hmd,
1 => TrackedDeviceRole::LeftHand,
2 => TrackedDeviceRole::RightHand,
3 => TrackedDeviceRole::Tracker,
_ => return Ok(()), // not parsing the first 4 elems
};
let sprite = layout
.state
.widgets
.get_as::<WidgetSprite>(widget)
.ok_or_else(|| {
anyhow::anyhow!("{id} is expected to be a sprite, but it isn't.")
})?;
let src = sprite.params.glyph_data.clone().ok_or_else(|| {
anyhow::anyhow!("{id} is expected to have a src, but it doesn't.")
})?;
state.device_role_icons.insert(role, src);
} else if &*id == "devices" {
let node = layout.state.nodes[widget];
let num_children = layout.state.tree.children(node).iter().len();
for idx in 0..MAX_DEVICES {
if idx >= num_children {
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert("idx".into(), idx.to_string().into());
params.insert("src".into(), "".to_string().into());
parser_state.instantiate_template(
doc_params, "Device", layout, widget, params,
)?;
}
let div = parser_state.get_widget_id(&format!("dev_{idx}"))?;
let spr = parser_state.get_widget_id(&format!("dev_{idx}_sprite"))?;
state.devices.push((div, spr));
}
}
Ok(())
@@ -161,9 +224,9 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
},
)?;
panel.on_notify = Some(Box::new(|panel, _app, event_data| {
panel.on_notify = Some(Box::new(|panel, app, event_data| {
let mut alterables = EventAlterables::default();
let mut common = CallbackDataCommon {
let mut com = CallbackDataCommon {
alterables: &mut alterables,
state: &panel.layout.state,
};
@@ -171,31 +234,34 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
match event_data {
OverlayEventData::ActiveSetChanged(current_set) => {
if let Some(old_set) = panel.state.current_set.take() {
panel.state.set_buttons[old_set].set_sticky_state(&mut common, false);
panel.state.set_buttons[old_set].set_sticky_state(&mut com, false);
}
if let Some(new_set) = current_set {
panel.state.set_buttons[new_set].set_sticky_state(&mut common, true);
panel.state.set_buttons[new_set].set_sticky_state(&mut com, true);
}
panel.state.current_set = current_set;
}
OverlayEventData::NumSetsChanged(num_sets) => {
panel.state.num_sets = num_sets;
for i in 0..MAX_OVERLAY_SETS {
let comp = panel.state.set_buttons[i].clone();
for (i, comp) in panel.state.set_buttons.iter().enumerate() {
let rect_id = comp.get_rect();
let display = if i < num_sets {
taffy::Display::Flex
} else {
taffy::Display::None
};
panel.widget_set_display(rect_id, display, common.alterables);
com.alterables
.set_style(rect_id, StyleSetRequest::Display(display));
}
let display = if num_sets < 7 {
taffy::Display::Flex
} else {
taffy::Display::None
};
panel.widget_set_display(panel.state.edit_add_widget, display, common.alterables);
com.alterables.set_style(
panel.state.edit_add_widget,
StyleSetRequest::Display(display),
);
}
OverlayEventData::EditModeChanged(edit_mode) => {
for (w, e) in &panel.state.edit_mode_widgets {
@@ -204,26 +270,49 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
} else {
taffy::Display::None
};
panel.widget_set_display(*w, display, common.alterables);
com.alterables
.set_style(*w, StyleSetRequest::Display(display));
}
let display = if edit_mode && panel.state.num_sets < 7 {
taffy::Display::Flex
} else {
taffy::Display::None
};
panel.widget_set_display(panel.state.edit_add_widget, display, common.alterables);
com.alterables.set_style(
panel.state.edit_add_widget,
StyleSetRequest::Display(display),
);
}
OverlayEventData::OverlaysChanged(metas) => {
panel.state.overlay_metas = metas;
for (idx, btn) in panel.state.overlay_buttons.iter().enumerate() {
let display = if let Some(meta) = panel.state.overlay_metas.get(idx) {
btn.set_text(&mut common, Translation::from_raw_text(&meta.name));
btn.set_text(&mut com, Translation::from_raw_text(&meta.name));
//TODO: add category icons
taffy::Display::Flex
} else {
taffy::Display::None
};
panel.widget_set_display(btn.get_rect(), display, common.alterables);
com.alterables
.set_style(btn.get_rect(), StyleSetRequest::Display(display));
}
}
OverlayEventData::DevicesChanged => {
log::info!("dev");
for (i, (div, s)) in panel.state.devices.iter().enumerate() {
if let Some(dev) = app.input_state.devices.get(i)
&& let Some(glyph) = panel.state.device_role_icons.get(dev.role)
&& let Some(mut s) = panel.layout.state.widgets.get_as::<WidgetSprite>(*s)
{
log::info!("dev {i} ok");
s.params.glyph_data = Some(glyph.clone());
com.alterables
.set_style(*div, StyleSetRequest::Display(taffy::Display::Flex));
} else {
log::info!("dev {i} nok");
com.alterables
.set_style(*div, StyleSetRequest::Display(taffy::Display::None));
};
}
}
}