watch rework
This commit is contained in:
@@ -16,7 +16,6 @@
|
|||||||
"HIDE_GRAB_HELP": "Greif-Hilfe ausblenden",
|
"HIDE_GRAB_HELP": "Greif-Hilfe ausblenden",
|
||||||
"ANIMATION_SPEED": "UI-Animationsgeschwindigkeit",
|
"ANIMATION_SPEED": "UI-Animationsgeschwindigkeit",
|
||||||
"ROUND_MULTIPLIER": "UI-Kantenrundung",
|
"ROUND_MULTIPLIER": "UI-Kantenrundung",
|
||||||
"SINGLE_SET_MODE": "Einzelnes Modus",
|
|
||||||
"USE_SKYBOX": "Skybox aktivieren",
|
"USE_SKYBOX": "Skybox aktivieren",
|
||||||
"USE_PASSTHROUGH": "Passthrough aktivieren",
|
"USE_PASSTHROUGH": "Passthrough aktivieren",
|
||||||
"CLOCK_12H": "12-Stunden-Uhr",
|
"CLOCK_12H": "12-Stunden-Uhr",
|
||||||
@@ -48,7 +47,6 @@
|
|||||||
"SCREEN_RENDER_DOWN": "Bildschirm bei niedrigerer Auflösung rendern",
|
"SCREEN_RENDER_DOWN": "Bildschirm bei niedrigerer Auflösung rendern",
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Behebt hochstehende Bildschirme auf einigen Desktops",
|
"UPRIGHT_SCREEN_FIX_HELP": "Behebt hochstehende Bildschirme auf einigen Desktops",
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Aktivieren Sie dies, wenn Sie 2 Cursor sehen",
|
"DOUBLE_CURSOR_FIX_HELP": "Aktivieren Sie dies, wenn Sie 2 Cursor sehen",
|
||||||
"SINGLE_SET_MODE_HELP": "Optimieren Sie die Anzeige für die Arbeit mit einem einzelnen Monitor",
|
|
||||||
"XR_CLICK_SENSITIVITY_HELP": "Analoge Trigger-Empfindlichkeit",
|
"XR_CLICK_SENSITIVITY_HELP": "Analoge Trigger-Empfindlichkeit",
|
||||||
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "Muss niedriger als Klick sein",
|
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "Muss niedriger als Klick sein",
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "Hilft bei der Präzision von Doppelklicks",
|
"CLICK_FREEZE_TIME_MS_HELP": "Hilft bei der Präzision von Doppelklicks",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"HIDE_GRAB_HELP": "Hide grab help",
|
"HIDE_GRAB_HELP": "Hide grab help",
|
||||||
"ANIMATION_SPEED": "UI Animation speed",
|
"ANIMATION_SPEED": "UI Animation speed",
|
||||||
"ROUND_MULTIPLIER": "UI Edge roundness",
|
"ROUND_MULTIPLIER": "UI Edge roundness",
|
||||||
"SINGLE_SET_MODE": "Single set mode",
|
"SETS_ON_WATCH": "Sets on watch",
|
||||||
"USE_SKYBOX": "Enable skybox",
|
"USE_SKYBOX": "Enable skybox",
|
||||||
"USE_PASSTHROUGH": "Enable passthrough",
|
"USE_PASSTHROUGH": "Enable passthrough",
|
||||||
"CLOCK_12H": "12-hour clock",
|
"CLOCK_12H": "12-hour clock",
|
||||||
@@ -49,7 +49,6 @@
|
|||||||
|
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Fixes upright screens on some desktops",
|
"UPRIGHT_SCREEN_FIX_HELP": "Fixes upright screens on some desktops",
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors",
|
"DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors",
|
||||||
"SINGLE_SET_MODE_HELP": "Optimize the watch for working with a single set",
|
|
||||||
"XR_CLICK_SENSITIVITY_HELP": "Analog trigger sensitivity",
|
"XR_CLICK_SENSITIVITY_HELP": "Analog trigger sensitivity",
|
||||||
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "Must be lower than click",
|
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "Must be lower than click",
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "Helps with double-click precision",
|
"CLICK_FREEZE_TIME_MS_HELP": "Helps with double-click precision",
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
"HIDE_GRAB_HELP": "掴み操作のヘルプを非表示にする",
|
"HIDE_GRAB_HELP": "掴み操作のヘルプを非表示にする",
|
||||||
"ANIMATION_SPEED": "UIアニメーション速度",
|
"ANIMATION_SPEED": "UIアニメーション速度",
|
||||||
"ROUND_MULTIPLIER": "UI エッジの丸み",
|
"ROUND_MULTIPLIER": "UI エッジの丸み",
|
||||||
"SINGLE_SET_MODE": "単一設定モード",
|
|
||||||
"USE_SKYBOX": "スカイボックスを有効にする",
|
"USE_SKYBOX": "スカイボックスを有効にする",
|
||||||
"USE_PASSTHROUGH": "パススルーを有効にする",
|
"USE_PASSTHROUGH": "パススルーを有効にする",
|
||||||
"CLOCK_12H": "12時間制",
|
"CLOCK_12H": "12時間制",
|
||||||
@@ -48,7 +47,6 @@
|
|||||||
"SCREEN_RENDER_DOWN": "低い解像度で画面をレンダリングする",
|
"SCREEN_RENDER_DOWN": "低い解像度で画面をレンダリングする",
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "一部のデスクトップで縦向きの画面を修正",
|
"UPRIGHT_SCREEN_FIX_HELP": "一部のデスクトップで縦向きの画面を修正",
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "2つのカーソルが表示される場合は、これを有効にします",
|
"DOUBLE_CURSOR_FIX_HELP": "2つのカーソルが表示される場合は、これを有効にします",
|
||||||
"SINGLE_SET_MODE_HELP": "シングルセットでの作業用に最適化",
|
|
||||||
"XR_CLICK_SENSITIVITY_HELP": "アナログトリガの感度",
|
"XR_CLICK_SENSITIVITY_HELP": "アナログトリガの感度",
|
||||||
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "クリックより低くする必要があります",
|
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "クリックより低くする必要があります",
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "ダブルクリックの精度向上に役立ちます",
|
"CLICK_FREEZE_TIME_MS_HELP": "ダブルクリックの精度向上に役立ちます",
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
"HIDE_GRAB_HELP": "Ukryj pomoc dotyczącą chwytania",
|
"HIDE_GRAB_HELP": "Ukryj pomoc dotyczącą chwytania",
|
||||||
"ANIMATION_SPEED": "Prędkość animacji UI",
|
"ANIMATION_SPEED": "Prędkość animacji UI",
|
||||||
"ROUND_MULTIPLIER": "Zaokrąglenie krawędzi UI",
|
"ROUND_MULTIPLIER": "Zaokrąglenie krawędzi UI",
|
||||||
"SINGLE_SET_MODE": "Tryb pojedynczego zestawu",
|
|
||||||
"USE_SKYBOX": "Włącz niebo",
|
"USE_SKYBOX": "Włącz niebo",
|
||||||
"USE_PASSTHROUGH": "Włącz passthrough",
|
"USE_PASSTHROUGH": "Włącz passthrough",
|
||||||
"CLOCK_12H": "Zegar 12-godzinny",
|
"CLOCK_12H": "Zegar 12-godzinny",
|
||||||
@@ -42,7 +41,6 @@
|
|||||||
"SCREEN_RENDER_DOWN": "Renderuj ekran w niższej rozdzielczości",
|
"SCREEN_RENDER_DOWN": "Renderuj ekran w niższej rozdzielczości",
|
||||||
"UPRIGHT_SCREEN_FIX_HELP": "Naprawia pionowe ekrany na niektórych komputerach",
|
"UPRIGHT_SCREEN_FIX_HELP": "Naprawia pionowe ekrany na niektórych komputerach",
|
||||||
"DOUBLE_CURSOR_FIX_HELP": "Włącz to, jeśli widzisz 2 kursory",
|
"DOUBLE_CURSOR_FIX_HELP": "Włącz to, jeśli widzisz 2 kursory",
|
||||||
"SINGLE_SET_MODE_HELP": "Zoptymalizuj oglądanie dla pracy z jednym zestawem",
|
|
||||||
"XR_CLICK_SENSITIVITY_HELP": "Czułość analogowego spustu",
|
"XR_CLICK_SENSITIVITY_HELP": "Czułość analogowego spustu",
|
||||||
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "Musi być niższa niż kliknięcie",
|
"XR_CLICK_SENSITIVITY_RELEASE_HELP": "Musi być niższa niż kliknięcie",
|
||||||
"CLICK_FREEZE_TIME_MS_HELP": "Pomaga w precyzji podwójnego kliknięcia",
|
"CLICK_FREEZE_TIME_MS_HELP": "Pomaga w precyzji podwójnego kliknięcia",
|
||||||
|
|||||||
@@ -36,22 +36,29 @@ impl<T> Tab<T> for TabSettings<T> {
|
|||||||
|
|
||||||
fn update(&mut self, frontend: &mut Frontend<T>, data: &mut T) -> anyhow::Result<()> {
|
fn update(&mut self, frontend: &mut Frontend<T>, data: &mut T) -> anyhow::Result<()> {
|
||||||
let config = frontend.interface.general_config(data);
|
let config = frontend.interface.general_config(data);
|
||||||
|
let mut changed = false;
|
||||||
for task in self.tasks.drain() {
|
for task in self.tasks.drain() {
|
||||||
match task {
|
match task {
|
||||||
Task::UpdateBool(setting, n) => {
|
Task::UpdateBool(setting, n) => {
|
||||||
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
||||||
*setting.mut_bool(config) = n;
|
*setting.mut_bool(config) = n;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
Task::UpdateFloat(setting, n) => {
|
Task::UpdateFloat(setting, n) => {
|
||||||
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
||||||
*setting.mut_f32(config) = n;
|
*setting.mut_f32(config) = n;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
Task::UpdateInt(setting, n) => {
|
Task::UpdateInt(setting, n) => {
|
||||||
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
setting.get_frontend_task().map(|task| frontend.tasks.push(task));
|
||||||
*setting.mut_i32(config) = n;
|
*setting.mut_i32(config) = n;
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if changed {
|
||||||
|
frontend.interface.config_changed(data);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +77,7 @@ enum SettingType {
|
|||||||
KeyboardSoundEnabled,
|
KeyboardSoundEnabled,
|
||||||
UprightScreenFix,
|
UprightScreenFix,
|
||||||
DoubleCursorFix,
|
DoubleCursorFix,
|
||||||
SingleSetMode,
|
SetsOnWatch,
|
||||||
HideGrabHelp,
|
HideGrabHelp,
|
||||||
XrClickSensitivity,
|
XrClickSensitivity,
|
||||||
XrClickSensitivityRelease,
|
XrClickSensitivityRelease,
|
||||||
@@ -103,7 +110,7 @@ impl SettingType {
|
|||||||
Self::KeyboardSoundEnabled => &mut config.keyboard_sound_enabled,
|
Self::KeyboardSoundEnabled => &mut config.keyboard_sound_enabled,
|
||||||
Self::UprightScreenFix => &mut config.upright_screen_fix,
|
Self::UprightScreenFix => &mut config.upright_screen_fix,
|
||||||
Self::DoubleCursorFix => &mut config.double_cursor_fix,
|
Self::DoubleCursorFix => &mut config.double_cursor_fix,
|
||||||
Self::SingleSetMode => &mut config.single_set_mode,
|
Self::SetsOnWatch => &mut config.sets_on_watch,
|
||||||
Self::HideGrabHelp => &mut config.hide_grab_help,
|
Self::HideGrabHelp => &mut config.hide_grab_help,
|
||||||
Self::AllowSliding => &mut config.allow_sliding,
|
Self::AllowSliding => &mut config.allow_sliding,
|
||||||
Self::FocusFollowsMouseMode => &mut config.focus_follows_mouse_mode,
|
Self::FocusFollowsMouseMode => &mut config.focus_follows_mouse_mode,
|
||||||
@@ -158,7 +165,7 @@ impl SettingType {
|
|||||||
Self::KeyboardSoundEnabled => Ok("APP_SETTINGS.KEYBOARD_SOUND_ENABLED"),
|
Self::KeyboardSoundEnabled => Ok("APP_SETTINGS.KEYBOARD_SOUND_ENABLED"),
|
||||||
Self::UprightScreenFix => Ok("APP_SETTINGS.UPRIGHT_SCREEN_FIX"),
|
Self::UprightScreenFix => Ok("APP_SETTINGS.UPRIGHT_SCREEN_FIX"),
|
||||||
Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"),
|
Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"),
|
||||||
Self::SingleSetMode => Ok("APP_SETTINGS.SINGLE_SET_MODE"),
|
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
|
||||||
Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"),
|
Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"),
|
||||||
Self::XrClickSensitivity => Ok("APP_SETTINGS.XR_CLICK_SENSITIVITY"),
|
Self::XrClickSensitivity => Ok("APP_SETTINGS.XR_CLICK_SENSITIVITY"),
|
||||||
Self::XrClickSensitivityRelease => Ok("APP_SETTINGS.XR_CLICK_SENSITIVITY_RELEASE"),
|
Self::XrClickSensitivityRelease => Ok("APP_SETTINGS.XR_CLICK_SENSITIVITY_RELEASE"),
|
||||||
@@ -186,7 +193,6 @@ impl SettingType {
|
|||||||
match self {
|
match self {
|
||||||
Self::UprightScreenFix => Some("APP_SETTINGS.UPRIGHT_SCREEN_FIX_HELP"),
|
Self::UprightScreenFix => Some("APP_SETTINGS.UPRIGHT_SCREEN_FIX_HELP"),
|
||||||
Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"),
|
Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"),
|
||||||
Self::SingleSetMode => Some("APP_SETTINGS.SINGLE_SET_MODE_HELP"),
|
|
||||||
Self::XrClickSensitivity => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_HELP"),
|
Self::XrClickSensitivity => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_HELP"),
|
||||||
Self::XrClickSensitivityRelease => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_RELEASE_HELP"),
|
Self::XrClickSensitivityRelease => Some("APP_SETTINGS.XR_CLICK_SENSITIVITY_RELEASE_HELP"),
|
||||||
Self::FocusFollowsMouseMode => Some("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE_HELP"),
|
Self::FocusFollowsMouseMode => Some("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE_HELP"),
|
||||||
@@ -207,7 +213,7 @@ impl SettingType {
|
|||||||
| Self::RoundMultiplier
|
| Self::RoundMultiplier
|
||||||
| Self::UprightScreenFix
|
| Self::UprightScreenFix
|
||||||
| Self::DoubleCursorFix
|
| Self::DoubleCursorFix
|
||||||
| Self::SingleSetMode
|
| Self::SetsOnWatch
|
||||||
| Self::UseSkybox
|
| Self::UseSkybox
|
||||||
| Self::UsePassthrough
|
| Self::UsePassthrough
|
||||||
| Self::ScreenRenderDown => true,
|
| Self::ScreenRenderDown => true,
|
||||||
@@ -388,7 +394,7 @@ impl<T> TabSettings<T> {
|
|||||||
checkbox!(mp, c, SettingType::HideGrabHelp);
|
checkbox!(mp, c, SettingType::HideGrabHelp);
|
||||||
slider_f32!(mp, c, SettingType::AnimationSpeed, 0.5, 5.0, 0.1); // min, max, step
|
slider_f32!(mp, c, SettingType::AnimationSpeed, 0.5, 5.0, 0.1); // min, max, step
|
||||||
slider_f32!(mp, c, SettingType::RoundMultiplier, 0.5, 5.0, 0.1);
|
slider_f32!(mp, c, SettingType::RoundMultiplier, 0.5, 5.0, 0.1);
|
||||||
checkbox!(mp, c, SettingType::SingleSetMode);
|
checkbox!(mp, c, SettingType::SetsOnWatch);
|
||||||
checkbox!(mp, c, SettingType::UseSkybox);
|
checkbox!(mp, c, SettingType::UseSkybox);
|
||||||
checkbox!(mp, c, SettingType::UsePassthrough);
|
checkbox!(mp, c, SettingType::UsePassthrough);
|
||||||
checkbox!(mp, c, SettingType::Clock12h);
|
checkbox!(mp, c, SettingType::Clock12h);
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ pub struct GeneralConfig {
|
|||||||
pub double_cursor_fix: bool,
|
pub double_cursor_fix: bool,
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
#[serde(default = "def_false")]
|
||||||
pub single_set_mode: bool,
|
pub sets_on_watch: bool,
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
#[serde(default = "def_false")]
|
||||||
pub hide_grab_help: bool,
|
pub hide_grab_help: bool,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub trait DashInterface<T> {
|
|||||||
fn recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()>;
|
fn recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()>;
|
||||||
fn desktop_finder<'a>(&'a mut self, data: &'a mut T) -> &'a mut DesktopFinder;
|
fn desktop_finder<'a>(&'a mut self, data: &'a mut T) -> &'a mut DesktopFinder;
|
||||||
fn general_config<'a>(&'a mut self, data: &'a mut T) -> &'a mut GeneralConfig;
|
fn general_config<'a>(&'a mut self, data: &'a mut T) -> &'a mut GeneralConfig;
|
||||||
|
fn config_changed(&mut self, data: &mut T);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type BoxDashInterface<T> = Box<dyn DashInterface<T>>;
|
pub type BoxDashInterface<T> = Box<dyn DashInterface<T>>;
|
||||||
|
|||||||
@@ -178,4 +178,6 @@ impl DashInterface<()> for DashInterfaceEmulated {
|
|||||||
fn general_config<'a>(&'a mut self, _: &'a mut ()) -> &'a mut crate::config::GeneralConfig {
|
fn general_config<'a>(&'a mut self, _: &'a mut ()) -> &'a mut crate::config::GeneralConfig {
|
||||||
&mut self.general_config
|
&mut self.general_config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn config_changed(&mut self, _: &mut ()) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,133 +0,0 @@
|
|||||||
<!--
|
|
||||||
Variant of the watch with no sets.
|
|
||||||
All overlays are listed on bottom row.
|
|
||||||
-->
|
|
||||||
<layout>
|
|
||||||
<theme>
|
|
||||||
<var key="set_color" value="#cad3f5" />
|
|
||||||
<var key="bgcolor" value="#010206d5" />
|
|
||||||
|
|
||||||
<var key="clock0_color" value="#cad3f5" />
|
|
||||||
<var key="clock0_size" value="46" />
|
|
||||||
<var key="clock0_date_size" value="16" />
|
|
||||||
<var key="clock0_dow_size" value="16" />
|
|
||||||
<var key="clock_alt1_color" value="#8bd5ca" />
|
|
||||||
<var key="clock_alt2_color" value="#b7bdf8" />
|
|
||||||
<var key="clock_alt_size" value="24" />
|
|
||||||
<var key="clock_alt_tz_size" value="14" />
|
|
||||||
</theme>
|
|
||||||
|
|
||||||
<macro name="decorative_rect"
|
|
||||||
padding="8" color="~bgcolor"
|
|
||||||
border="2" border_color="~color_accent" round="8" />
|
|
||||||
|
|
||||||
<macro name="button_style"
|
|
||||||
padding="8"
|
|
||||||
border_color="~color_accent_translucent" border="2" round="8" color="~color_accent_5" color2="~color_accent_1" gradient="vertical"
|
|
||||||
align_items="center" justify_content="center" />
|
|
||||||
|
|
||||||
<template name="Device">
|
|
||||||
<rectangle id="dev_${idx}" macro="decorative_rect" padding_top="4" padding_bottom="4" display="none" align_items="center" gap="8">
|
|
||||||
<sprite id="dev_${idx}_sprite" width="32" height="32" src_builtin="${src}" />
|
|
||||||
<label _source="battery" _device="${idx}" size="24" weight="bold" />
|
|
||||||
</rectangle>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template name="Overlay">
|
|
||||||
<Button macro="button_style" id="overlay_${idx}"
|
|
||||||
tooltip="WATCH.TOGGLE_FOR_CURRENT_SET" _press="::OverlayToggle ${idx}" _long_release="::SingleSetOverlayReset ${idx}"
|
|
||||||
align_items="center"
|
|
||||||
height="40">
|
|
||||||
<sprite id="overlay_${idx}_sprite" src_builtin="${src}" width="32" height="32" />
|
|
||||||
<label id="overlay_${idx}_label" text="WLX-${idx}" size="18" />
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
[!!!!!!!!] Disclaimer [!!!!!!!!]
|
|
||||||
Elements with id="norm_*" show in normal mode.
|
|
||||||
Elements with id="edit_*" show in edit mode.
|
|
||||||
-->
|
|
||||||
<elements>
|
|
||||||
<!-- padding="32" is required there (to make room for tooltips) -->
|
|
||||||
<div
|
|
||||||
padding="32" interactable="0"
|
|
||||||
flex_direction="column" gap="8">
|
|
||||||
<!-- Top elements (device battery levels) -->
|
|
||||||
<div id="devices" interactable="0" gap="6" width="100%" max_width="400" flex_direction="row" flex_wrap="wrap">
|
|
||||||
<!-- Src here may be changed, but maintain `TrackedDeviceRole` order: HMD, Left, Right, Tracker -->
|
|
||||||
<Device src="watch/hmd.svg" idx="0" />
|
|
||||||
<Device src="watch/controller_l.svg" idx="1" />
|
|
||||||
<Device src="watch/controller_r.svg" idx="2" />
|
|
||||||
<Device src="watch/track.svg" idx="3" />
|
|
||||||
<!-- Will populate additional <Device> tags at runtime -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- All other elements inside the container -->
|
|
||||||
<div flex_direction="column" gap="8">
|
|
||||||
<rectangle macro="decorative_rect" flex_direction="row" gap="8">
|
|
||||||
<!-- Clock, date and various timezones -->
|
|
||||||
<div gap="8">
|
|
||||||
<div flex_direction="column">
|
|
||||||
<label text="23:59" _source="clock" _display="time" color="~clock0_color" size="~clock0_size" weight="bold" />
|
|
||||||
<div padding="2" gap="2" flex_direction="column">
|
|
||||||
<label text="22/2/2022" _source="clock" _display="date" color="~clock0_color" size="~clock0_date_size" weight="bold" />
|
|
||||||
<label text="Tuesday" _source="clock" _display="dow" color="~clock0_color" size="~clock0_dow_size" weight="bold" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div flex_direction="column" gap="8">
|
|
||||||
<!-- Timezone names here are only placeholders. Set your timezones via ~/.config/wlxoverlay/conf.d -->
|
|
||||||
<div flex_direction="column">
|
|
||||||
<label text="Paris" _source="clock" _display="name" _timezone="0" color="~clock_alt1_color" size="~clock_alt_tz_size" weight="bold" />
|
|
||||||
<label text="23:59" _source="clock" _display="time" _timezone="0" color="~clock_alt1_color" size="~clock_alt_size" weight="bold" />
|
|
||||||
</div>
|
|
||||||
<div flex_direction="column">
|
|
||||||
<label text="New York" _source="clock" _display="name" _timezone="1" color="~clock_alt2_color" size="~clock_alt_tz_size" weight="bold" />
|
|
||||||
<label text="23:59" _source="clock" _display="time" _timezone="1" color="~clock_alt2_color" size="~clock_alt_size" weight="bold" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Four buttons -->
|
|
||||||
<div flex_direction="column" gap="8">
|
|
||||||
<div gap="8">
|
|
||||||
<Button macro="button_style" _press="::NewMirror" tooltip="WATCH.MIRROR" tooltip_side="left">
|
|
||||||
<sprite width="40" height="40" color="~set_color" src="edit/mirror.svg" />
|
|
||||||
</Button>
|
|
||||||
<Button macro="button_style" _press="::CleanupMirrors" tooltip="WATCH.CLEANUP_MIRRORS" tooltip_side="left">
|
|
||||||
<sprite width="40" height="40" color="~set_color" src="watch/mirror-off.svg" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div gap="8">
|
|
||||||
<Button macro="button_style" _press="::PlayspaceRecenter" tooltip="WATCH.RECENTER" tooltip_side="left">
|
|
||||||
<sprite width="40" height="40" color="~set_color" src="watch/recenter.svg" />
|
|
||||||
</Button>
|
|
||||||
<Button macro="button_style" _press="::PlayspaceFixFloor" tooltip="WATCH.FIX_FLOOR" tooltip_side="left">
|
|
||||||
<sprite width="40" height="40" color="~set_color" src="watch/fix-floor.svg" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rectangle>
|
|
||||||
|
|
||||||
<!-- Bottom buttons -->
|
|
||||||
<div id="toolbox-condensed" gap="6" width="100%" max_width="400" flex_direction="row" flex_wrap="wrap">
|
|
||||||
<Button id="btn_dashboard" height="40" macro="button_style" _press="::DashToggle" tooltip="WATCH.DASHBOARD" tooltip_side="top" >
|
|
||||||
<sprite color="~set_color" width="32" height="32" src="watch/wayvr_dashboard_mono.svg" />
|
|
||||||
</Button>
|
|
||||||
<Button id="btn_edit_mode" height="40" macro="button_style" _press="::EditToggle" tooltip="WATCH.EDIT_MODE" tooltip_side="top">
|
|
||||||
<sprite color="~set_color" width="32" height="32" src="watch/edit.svg" />
|
|
||||||
</Button>
|
|
||||||
<Button id="btn_keyboard" height="40" macro="button_style" tooltip="WATCH.TOGGLE_FOR_CURRENT_SET" _press="::OverlayToggle kbd" >
|
|
||||||
<sprite src_builtin="watch/keyboard.svg" width="32" height="32" />
|
|
||||||
</Button>
|
|
||||||
<!-- Src here may be changed, but maintain `OverlayCategory` order: Panel, Screen, Mirror, WayVR -->
|
|
||||||
<Overlay src="edit/panel.svg" idx="0" />
|
|
||||||
<Overlay src="edit/screen.svg" idx="1" />
|
|
||||||
<Overlay src="edit/mirror.svg" idx="2" />
|
|
||||||
<Overlay src="edit/wayvr.svg" idx="3" />
|
|
||||||
<!-- Will populate additional <Overlay> tags at runtime -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</elements>
|
|
||||||
</layout>
|
|
||||||
@@ -19,19 +19,49 @@
|
|||||||
align_items="center" justify_content="center" />
|
align_items="center" justify_content="center" />
|
||||||
|
|
||||||
<template name="Device">
|
<template name="Device">
|
||||||
<rectangle id="dev_${idx}" macro="decorative_rect" padding_top="4" padding_bottom="4" display="none" align_items="center" gap="8">
|
<rectangle macro="decorative_rect" padding_top="4" padding_bottom="4" align_items="center" gap="8">
|
||||||
<sprite id="dev_${idx}_sprite" width="32" height="32" src_builtin="${src}" />
|
<sprite width="32" height="32" src_builtin="${src}" />
|
||||||
<label _source="battery" _device="${idx}" size="24" weight="bold" />
|
<label _source="battery" _device="${idx}" size="24" weight="bold" />
|
||||||
</rectangle>
|
</rectangle>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="Overlay">
|
<template name="Hmd">
|
||||||
<Button macro="button_style" id="overlay_${idx}"
|
<Device idx="${idx}" src="watch/hmd.svg" />
|
||||||
tooltip="WATCH.TOGGLE_FOR_CURRENT_SET" _press="::EditModeOverlayToggle ${idx}"
|
</template>
|
||||||
align_items="center"
|
<template name="LeftHand">
|
||||||
height="40">
|
<Device idx="${idx}" src="watch/controller_l.svg" />
|
||||||
<sprite id="overlay_${idx}_sprite" src_builtin="${src}" width="32" height="32" />
|
</template>
|
||||||
<label id="overlay_${idx}_label" text="WLX-${idx}" size="18" />
|
<template name="RightHand">
|
||||||
|
<Device idx="${idx}" src="watch/controller_r.svg" />
|
||||||
|
</template>
|
||||||
|
<template name="Tracker">
|
||||||
|
<Device idx="${idx}" src="watch/track.svg" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="Screen">
|
||||||
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::OverlayToggle ${name}">
|
||||||
|
<sprite width="38" height="38" color="~text_color" src_builtin="edit/screen.svg" />
|
||||||
|
<div position="absolute" margin_top="-7" margin_left="-1">
|
||||||
|
<label text="${display}" size="18" color="~color_faded_20" weight="bold" />
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
<template name="Panel">
|
||||||
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::OverlayToggle ${name}">
|
||||||
|
<sprite width="38" height="38" color="~text_color" src_builtin="edit/panel.svg" />
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
<template name="Mirror">
|
||||||
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::OverlayToggle ${name}">
|
||||||
|
<sprite width="38" height="38" color="~text_color" src_builtin="edit/mirror.svg" />
|
||||||
|
<div position="absolute" margin_top="5" margin_left="13">
|
||||||
|
<label text="${display}" size="20" color="~color_faded_20" weight="bold" />
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
<template name="App">
|
||||||
|
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::OverlayToggle ${name}">
|
||||||
|
<sprite width="38" height="38" color="~text_color" src_ext="${icon}" />
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -44,63 +74,64 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="Clock">
|
||||||
|
<div gap="12" flex_direction="column" padding="4">
|
||||||
|
<div flex_direction="column" >
|
||||||
|
<label text="11:22 PM" _source="clock" _display="time" color="~text_color" size="~clock0_size" weight="bold" align="center" />
|
||||||
|
<div padding_left="2" gap="16" flex_direction="row" justify_content="center">
|
||||||
|
<label text="Tue" _source="clock" _display="dow_short" color="~clock0_color" size="~clock0_dow_size" weight="bold" />
|
||||||
|
<label text="22/2/2022" _source="clock" _display="date" color="~clock0_color" size="~clock0_date_size" weight="bold" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div flex_direction="row" gap="8" justify_content="space_around">
|
||||||
|
<!-- Timezone names here are only placeholders. Set your timezones via ~/.config/wlxoverlay/conf.d -->
|
||||||
|
<div flex_direction="column">
|
||||||
|
<label text="Paris" _source="clock" _display="name" _timezone="0" color="~clock_alt1_color" size="~clock_alt_tz_size" weight="bold" align="center" />
|
||||||
|
<label text="23:59" _source="clock" _display="time" _timezone="0" color="~clock_alt1_color" size="~clock_alt_size" weight="bold" align="center" />
|
||||||
|
</div>
|
||||||
|
<div flex_direction="column">
|
||||||
|
<label text="New York" _source="clock" _display="name" _timezone="1" color="~clock_alt2_color" size="~clock_alt_tz_size" weight="bold" align="center" />
|
||||||
|
<label text="23:59" _source="clock" _display="time" _timezone="1" color="~clock_alt2_color" size="~clock_alt_size" weight="bold" align="center" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template name="VerticalSeparator">
|
<template name="VerticalSeparator">
|
||||||
<rectangle width="2" height="100%" color="~color_accent" />
|
<rectangle width="2" height="100%" color="~color_accent" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!--
|
|
||||||
[!!!!!!!!] Disclaimer [!!!!!!!!]
|
|
||||||
Elements with id="norm_*" show in normal mode.
|
|
||||||
Elements with id="edit_*" show in edit mode.
|
|
||||||
-->
|
|
||||||
<elements>
|
<elements>
|
||||||
<!-- padding="32" is required there (to make room for tooltips) -->
|
<!-- padding="32" is required there (to make room for tooltips) -->
|
||||||
<div
|
<div
|
||||||
padding="32" interactable="0"
|
padding="32" interactable="0"
|
||||||
flex_direction="column" gap="8">
|
flex_direction="column" gap="8">
|
||||||
<!-- Top elements (device battery levels) -->
|
<!-- Top elements (device battery levels) -->
|
||||||
<div id="devices" interactable="0" gap="6" width="100%" max_width="400" flex_direction="row" flex_wrap="wrap">
|
<div id="devices_root" interactable="0" gap="6" width="100%" max_width="400" flex_direction="row" flex_wrap="wrap">
|
||||||
<!-- Src here may be changed, but maintain `TrackedDeviceRole` order: HMD, Left, Right, Tracker -->
|
<!-- Will populate tags at runtime -->
|
||||||
<Device src="watch/hmd.svg" idx="0" />
|
<!-- These are examples for uidev -->
|
||||||
<Device src="watch/controller_l.svg" idx="1" />
|
<Hmd idx="0" />
|
||||||
<Device src="watch/controller_r.svg" idx="2" />
|
<LeftHand idx="1" />
|
||||||
<Device src="watch/track.svg" idx="3" />
|
<RightHand idx="2" />
|
||||||
<!-- Will populate additional <Device> tags at runtime -->
|
<Track idx="3" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- All other elements inside the container -->
|
<!-- All other elements inside the container -->
|
||||||
<div flex_direction="column" gap="8">
|
<div flex_direction="column" gap="8" min_width="300">
|
||||||
<rectangle macro="decorative_rect" flex_direction="row" id="norm_pane" gap="8">
|
<rectangle macro="decorative_rect" flex_direction="row" gap="8" justify_content="space_evenly">
|
||||||
<!-- Clock, date and various timezones -->
|
<!-- Clock, date and various timezones -->
|
||||||
<div gap="8">
|
<div id="clock_root">
|
||||||
<div flex_direction="column">
|
<Clock />
|
||||||
<label text="23:59" _source="clock" _display="time" color="~text_color" size="~clock0_size" weight="bold" />
|
|
||||||
<div padding="2" gap="2" flex_direction="column">
|
|
||||||
<label text="22/2/2022" _source="clock" _display="date" color="~clock0_color" size="~clock0_date_size" weight="bold" />
|
|
||||||
<label text="Tuesday" _source="clock" _display="dow" color="~clock0_color" size="~clock0_dow_size" weight="bold" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div flex_direction="column" gap="8">
|
|
||||||
<!-- Timezone names here are only placeholders. Set your timezones via ~/.config/wlxoverlay/conf.d -->
|
|
||||||
<div flex_direction="column">
|
|
||||||
<label text="Paris" _source="clock" _display="name" _timezone="0" color="~clock_alt1_color" size="~clock_alt_tz_size" weight="bold" />
|
|
||||||
<label text="23:59" _source="clock" _display="time" _timezone="0" color="~clock_alt1_color" size="~clock_alt_size" weight="bold" />
|
|
||||||
</div>
|
|
||||||
<div flex_direction="column">
|
|
||||||
<label text="New York" _source="clock" _display="name" _timezone="1" color="~clock_alt2_color" size="~clock_alt_tz_size" weight="bold" />
|
|
||||||
<label text="23:59" _source="clock" _display="time" _timezone="1" color="~clock_alt2_color" size="~clock_alt_size" weight="bold" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Four buttons -->
|
<!-- Four buttons -->
|
||||||
<div flex_direction="column" gap="8">
|
<div flex_direction="column" gap="8">
|
||||||
<div gap="8">
|
<div gap="8">
|
||||||
<Button macro="button_style" _press="::NewMirror" tooltip="WATCH.MIRROR" tooltip_side="left">
|
<Button id="btn_keyboard" macro="button_style" _press="::OverlayToggle kbd" tooltip="EDIT_MODE.KEYBOARD" tooltip_side="left">
|
||||||
<sprite width="40" height="40" color="~text_color" src="edit/mirror.svg" />
|
<sprite src_builtin="watch/keyboard.svg" width="40" height="40" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button macro="button_style" _press="::CleanupMirrors" tooltip="WATCH.CLEANUP_MIRRORS" tooltip_side="left">
|
<Button id="btn_edit_mode" macro="button_style" _press="::EditToggle" tooltip="WATCH.EDIT_MODE" tooltip_side="left">
|
||||||
<sprite width="40" height="40" color="~text_color" src="watch/mirror-off.svg" />
|
<sprite color="~text_color" width="40" height="40" src="watch/edit.svg" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div gap="8">
|
<div gap="8">
|
||||||
@@ -114,50 +145,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</rectangle>
|
</rectangle>
|
||||||
|
|
||||||
<rectangle macro="decorative_rect" flex_direction="column" id="edit_pane" display="none" gap="8">
|
|
||||||
<div flex_direction="column" padding="4" align_items="center" justify_content="center">
|
|
||||||
<label translation="WATCH.EDIT_MODE_EXPLANATION" align="center" />
|
|
||||||
</div>
|
|
||||||
<div flex_direction="column" align_items="center" justify_content="center">
|
|
||||||
<div id="toolbox" gap="8" width="100%" max_width="400" flex_direction="row" flex_wrap="wrap">
|
|
||||||
<Button id="btn_keyboard" height="40" macro="button_style" tooltip="WATCH.TOGGLE_FOR_CURRENT_SET" _press="::OverlayToggle kbd">
|
|
||||||
<sprite src_builtin="watch/keyboard.svg" width="32" height="32" />
|
|
||||||
<label translation="EDIT_MODE.KEYBOARD" size="18" />
|
|
||||||
</Button>
|
|
||||||
<!-- Src here may be changed, but maintain `OverlayCategory` order: Panel, Screen, Mirror, WayVR -->
|
|
||||||
<Overlay src="edit/panel.svg" idx="0" />
|
|
||||||
<Overlay src="edit/screen.svg" idx="1" />
|
|
||||||
<Overlay src="edit/mirror.svg" idx="2" />
|
|
||||||
<Overlay src="edit/wayvr.svg" idx="3" />
|
|
||||||
<!-- Will populate additional <Overlay> tags at runtime -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rectangle>
|
|
||||||
|
|
||||||
<!-- Bottom buttons -->
|
<!-- Bottom buttons -->
|
||||||
<div flex_direction="row" gap="8">
|
<div flex_direction="row" gap="8">
|
||||||
<div gap="4">
|
<div gap="4">
|
||||||
<Button id="btn_dashboard" macro="button_style" _press="::DashToggle" tooltip="WATCH.DASHBOARD" tooltip_side="top">
|
<Button id="btn_dashboard" macro="button_style" _press="::DashToggle" tooltip="WATCH.DASHBOARD" tooltip_side="top">
|
||||||
<sprite color="~text_color" width="40" height="40" src="watch/wayvr_dashboard_mono.svg" />
|
<sprite color="~text_color" width="40" height="40" src="watch/wayvr_dashboard_mono.svg" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button id="btn_edit_mode" macro="button_style" _press="::EditToggle" tooltip="WATCH.EDIT_MODE" tooltip_side="top">
|
|
||||||
<sprite color="~text_color" width="40" height="40" src="watch/edit.svg" />
|
|
||||||
</Button>
|
|
||||||
<div id="edit_delete" display="none">
|
|
||||||
<Button macro="button_style" _long_release="::EditModeDeleteSet" tooltip="WATCH.LONG_PRESS_TO_DELETE_SET" tooltip_side="top" border_color="~color_danger_translucent" color="~color_danger_40" color2="~color_danger_10">
|
|
||||||
<sprite color="~text_color" width="40" height="40" src="edit/delete.svg" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div id="edit_add" display="none">
|
|
||||||
<Button macro="button_style" _press="::EditModeAddSet" tooltip="WATCH.ADD_NEW_SET" tooltip_side="top">
|
|
||||||
<sprite color="~text_color" width="40" height="40" src="edit/add.svg" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<VerticalSeparator />
|
<VerticalSeparator />
|
||||||
<div id="sets" gap="4">
|
<div id="sets_root" gap="4">
|
||||||
|
<!-- Will populate tags at runtime -->
|
||||||
|
<!-- These are examples for uidev -->
|
||||||
<Set idx="0" display="1" />
|
<Set idx="0" display="1" />
|
||||||
<!-- Will populate additional <Set> tags at runtime -->
|
<Set idx="1" display="2" />
|
||||||
|
</div>
|
||||||
|
<div id="panels_root" gap="4" display="none">
|
||||||
|
<!-- Will populate tags at runtime -->
|
||||||
|
<!-- These are examples for uidev -->
|
||||||
|
<Screen idx="0" display="H1" />
|
||||||
|
<Screen idx="1" display="D2" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles};
|
|||||||
|
|
||||||
use idmap_derive::IntegerId;
|
use idmap_derive::IntegerId;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
|
use strum::AsRefStr;
|
||||||
use wlx_common::common::LeftRight;
|
use wlx_common::common::LeftRight;
|
||||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ pub struct TrackedDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntegerId)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntegerId, AsRefStr)]
|
||||||
pub enum TrackedDeviceRole {
|
pub enum TrackedDeviceRole {
|
||||||
None,
|
None,
|
||||||
Hmd,
|
Hmd,
|
||||||
|
|||||||
@@ -76,18 +76,26 @@ pub struct ModifyPanelTask {
|
|||||||
pub command: ModifyPanelCommand,
|
pub command: ModifyPanelCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ToggleMode {
|
||||||
|
EnsureOn,
|
||||||
|
EnsureOff,
|
||||||
|
Toggle,
|
||||||
|
}
|
||||||
|
|
||||||
pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send;
|
pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send;
|
||||||
pub type CreateOverlayTask = dyn FnOnce(&mut AppState) -> Option<OverlayWindowConfig> + Send;
|
pub type CreateOverlayTask = dyn FnOnce(&mut AppState) -> Option<OverlayWindowConfig> + Send;
|
||||||
pub enum OverlayTask {
|
pub enum OverlayTask {
|
||||||
AddSet,
|
AddSet,
|
||||||
ToggleSet(usize),
|
ToggleSet(usize),
|
||||||
SwitchSet(Option<usize>),
|
SwitchSet(Option<usize>),
|
||||||
ToggleOverlay(OverlaySelector),
|
ToggleOverlay(OverlaySelector, ToggleMode),
|
||||||
|
ResetOverlay(OverlaySelector),
|
||||||
DeleteActiveSet,
|
DeleteActiveSet,
|
||||||
ToggleEditMode,
|
ToggleEditMode,
|
||||||
ToggleDashboard,
|
ToggleDashboard,
|
||||||
ShowHide,
|
ShowHide,
|
||||||
CleanupMirrors,
|
CleanupMirrors,
|
||||||
|
SettingsChanged,
|
||||||
Modify(OverlaySelector, Box<ModifyOverlayTask>),
|
Modify(OverlaySelector, Box<ModifyOverlayTask>),
|
||||||
Create(OverlaySelector, Box<CreateOverlayTask>),
|
Create(OverlaySelector, Box<CreateOverlayTask>),
|
||||||
ModifyPanel(ModifyPanelTask),
|
ModifyPanel(ModifyPanelTask),
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ use crate::{
|
|||||||
RUNNING,
|
RUNNING,
|
||||||
backend::{
|
backend::{
|
||||||
XrBackend,
|
XrBackend,
|
||||||
task::{OverlayTask, PlayspaceTask, TaskType},
|
task::{OverlayTask, PlayspaceTask, TaskType, ToggleMode},
|
||||||
wayvr::process::KillSignal,
|
wayvr::process::KillSignal,
|
||||||
},
|
},
|
||||||
overlays::{custom::create_custom, toast::Toast, wayvr::WvrCommand},
|
overlays::{custom::create_custom, toast::Toast, wayvr::WvrCommand},
|
||||||
@@ -337,11 +337,9 @@ pub(super) fn setup_custom_button<S: 'static>(
|
|||||||
return Ok(EventResult::Pass);
|
return Ok(EventResult::Pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
app.tasks
|
||||||
|
.enqueue(TaskType::Overlay(OverlayTask::ResetOverlay(
|
||||||
OverlaySelector::Name(arg.clone()),
|
OverlaySelector::Name(arg.clone()),
|
||||||
Box::new(move |app, owc| {
|
|
||||||
owc.activate(app);
|
|
||||||
}),
|
|
||||||
)));
|
)));
|
||||||
Ok(EventResult::Consumed)
|
Ok(EventResult::Consumed)
|
||||||
})
|
})
|
||||||
@@ -361,6 +359,7 @@ pub(super) fn setup_custom_button<S: 'static>(
|
|||||||
app.tasks
|
app.tasks
|
||||||
.enqueue(TaskType::Overlay(OverlayTask::ToggleOverlay(
|
.enqueue(TaskType::Overlay(OverlayTask::ToggleOverlay(
|
||||||
OverlaySelector::Name(arg.clone()),
|
OverlaySelector::Name(arg.clone()),
|
||||||
|
ToggleMode::Toggle,
|
||||||
)));
|
)));
|
||||||
Ok(EventResult::Consumed)
|
Ok(EventResult::Consumed)
|
||||||
})
|
})
|
||||||
@@ -384,6 +383,23 @@ pub(super) fn setup_custom_button<S: 'static>(
|
|||||||
Ok(EventResult::Consumed)
|
Ok(EventResult::Consumed)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
"::DeleteSet" => Box::new(move |_common, data, app, _state| {
|
||||||
|
if !test_button(data) || !test_duration(&button, app) {
|
||||||
|
return Ok(EventResult::Pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
app.tasks
|
||||||
|
.enqueue(TaskType::Overlay(OverlayTask::DeleteActiveSet));
|
||||||
|
Ok(EventResult::Consumed)
|
||||||
|
}),
|
||||||
|
"::AddSet" => Box::new(move |_common, data, app, _state| {
|
||||||
|
if !test_button(data) || !test_duration(&button, app) {
|
||||||
|
return Ok(EventResult::Pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
app.tasks.enqueue(TaskType::Overlay(OverlayTask::AddSet));
|
||||||
|
Ok(EventResult::Consumed)
|
||||||
|
}),
|
||||||
"::CustomOverlayReload" => {
|
"::CustomOverlayReload" => {
|
||||||
let arg: Arc<str> = args.collect::<Vec<_>>().join(" ").into();
|
let arg: Arc<str> = args.collect::<Vec<_>>().join(" ").into();
|
||||||
if arg.len() < 1 {
|
if arg.len() < 1 {
|
||||||
|
|||||||
67
wlx-overlay-s/src/gui/panel/device_list.rs
Normal file
67
wlx-overlay-s/src/gui/panel/device_list.rs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use slotmap::Key;
|
||||||
|
use wgui::{
|
||||||
|
layout::Layout,
|
||||||
|
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
backend::input::TrackedDeviceRole, state::AppState, windowing::backend::OverlayEventData,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
/// Helper for managing a list of overlays
|
||||||
|
/// Populates `id="devices_root"` with `<Hmd>`, `<LeftHand>`, `<RightHand>`, `<Tracker>` templates
|
||||||
|
pub struct DeviceList;
|
||||||
|
|
||||||
|
impl DeviceList {
|
||||||
|
pub fn on_notify(
|
||||||
|
&mut self,
|
||||||
|
app: &AppState,
|
||||||
|
layout: &mut Layout,
|
||||||
|
parser_state: &mut ParserState,
|
||||||
|
event_data: &OverlayEventData,
|
||||||
|
doc_params: &ParseDocumentParams,
|
||||||
|
) -> anyhow::Result<bool> {
|
||||||
|
let mut elements_changed = false;
|
||||||
|
match event_data {
|
||||||
|
OverlayEventData::DevicesChanged => {
|
||||||
|
let devices_root = parser_state
|
||||||
|
.get_widget_id("devices_root")
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
if devices_root.is_null() {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
layout.remove_children(devices_root);
|
||||||
|
|
||||||
|
for (i, device) in app.input_state.devices.iter().enumerate() {
|
||||||
|
let mut params = HashMap::new();
|
||||||
|
|
||||||
|
if matches!(device.role, TrackedDeviceRole::None) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let template = device.role.as_ref();
|
||||||
|
|
||||||
|
log::warn!("creating {template} tag for {i}");
|
||||||
|
|
||||||
|
params.insert("idx".into(), i.to_string().into());
|
||||||
|
parser_state.instantiate_template(
|
||||||
|
&doc_params,
|
||||||
|
template,
|
||||||
|
layout,
|
||||||
|
devices_root,
|
||||||
|
params,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
elements_changed = true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(elements_changed)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -89,6 +89,7 @@ pub(super) fn setup_custom_label<S: 'static>(
|
|||||||
}
|
}
|
||||||
"date" => "%x",
|
"date" => "%x",
|
||||||
"dow" => "%A",
|
"dow" => "%A",
|
||||||
|
"dow_short" => "%a",
|
||||||
"time" => {
|
"time" => {
|
||||||
if app.session.config.clock_12h {
|
if app.session.config.clock_12h {
|
||||||
"%I:%M %p"
|
"%I:%M %p"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ use crate::{
|
|||||||
use super::timer::GuiTimer;
|
use super::timer::GuiTimer;
|
||||||
|
|
||||||
pub mod button;
|
pub mod button;
|
||||||
|
pub mod device_list;
|
||||||
mod label;
|
mod label;
|
||||||
pub mod overlay_list;
|
pub mod overlay_list;
|
||||||
pub mod set_list;
|
pub mod set_list;
|
||||||
|
|||||||
@@ -75,9 +75,18 @@ impl OverlayList {
|
|||||||
);
|
);
|
||||||
("App", apps_root)
|
("App", apps_root)
|
||||||
}
|
}
|
||||||
OverlayCategory::Dashboard => {
|
OverlayCategory::Dashboard | OverlayCategory::Keyboard => {
|
||||||
let overlay_button = parser_state
|
let key = if matches!(meta.category, OverlayCategory::Dashboard) {
|
||||||
.fetch_component_as::<ComponentButton>("btn_dashboard")?;
|
"btn_dashboard"
|
||||||
|
} else {
|
||||||
|
"btn_keyboard"
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(overlay_button) =
|
||||||
|
parser_state.fetch_component_as::<ComponentButton>(key)
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
if meta.visible {
|
if meta.visible {
|
||||||
let mut com = CallbackDataCommon {
|
let mut com = CallbackDataCommon {
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ pub struct SetList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SetList {
|
impl SetList {
|
||||||
|
pub fn num_sets(&self) -> usize {
|
||||||
|
self.set_buttons.len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_notify(
|
pub fn on_notify(
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: &mut Layout,
|
layout: &mut Layout,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use wlx_common::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
input::{Haptics, HoverResult, PointerHit, PointerMode},
|
input::{Haptics, HoverResult, PointerHit, PointerMode},
|
||||||
task::{OverlayTask, PlayspaceTask, TaskType},
|
task::{OverlayTask, PlayspaceTask, TaskType, ToggleMode},
|
||||||
wayvr::{
|
wayvr::{
|
||||||
process::{KillSignal, ProcessHandle},
|
process::{KillSignal, ProcessHandle},
|
||||||
window::WindowHandle,
|
window::WindowHandle,
|
||||||
@@ -383,15 +383,13 @@ impl DashInterface<AppState> for DashInterfaceLive {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
app.tasks
|
||||||
|
.enqueue(TaskType::Overlay(OverlayTask::ToggleOverlay(
|
||||||
OverlaySelector::Id(oid),
|
OverlaySelector::Id(oid),
|
||||||
Box::new(move |app, owc| {
|
match visible {
|
||||||
if visible && !owc.is_active() {
|
true => ToggleMode::EnsureOn,
|
||||||
owc.activate(app);
|
false => ToggleMode::EnsureOff,
|
||||||
} else if !visible && owc.is_active() {
|
},
|
||||||
owc.deactivate();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)));
|
)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -415,4 +413,9 @@ impl DashInterface<AppState> for DashInterfaceLive {
|
|||||||
) -> &'a mut wlx_common::config::GeneralConfig {
|
) -> &'a mut wlx_common::config::GeneralConfig {
|
||||||
&mut data.session.config
|
&mut data.session.config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn config_changed(&mut self, data: &mut AppState) {
|
||||||
|
data.tasks
|
||||||
|
.enqueue(TaskType::Overlay(OverlayTask::SettingsChanged));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use wlx_common::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
input::{HoverResult, PointerHit},
|
input::{HoverResult, PointerHit},
|
||||||
task::{OverlayTask, TaskType},
|
task::{OverlayTask, TaskType, ToggleMode},
|
||||||
},
|
},
|
||||||
overlays::screen::capture::{MainThreadWlxCapture, new_wlx_capture},
|
overlays::screen::capture::{MainThreadWlxCapture, new_wlx_capture},
|
||||||
state::{AppSession, AppState},
|
state::{AppSession, AppState},
|
||||||
@@ -96,11 +96,10 @@ impl OverlayBackend for MirrorBackend {
|
|||||||
app.xr_backend,
|
app.xr_backend,
|
||||||
capture,
|
capture,
|
||||||
));
|
));
|
||||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
app.tasks
|
||||||
|
.enqueue(TaskType::Overlay(OverlayTask::ToggleOverlay(
|
||||||
OverlaySelector::Name(self.name.clone()),
|
OverlaySelector::Name(self.name.clone()),
|
||||||
Box::new(|app, o| {
|
ToggleMode::EnsureOn,
|
||||||
o.activate(app);
|
|
||||||
}),
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
use std::{collections::HashMap, rc::Rc, time::Duration};
|
use std::{rc::Rc, time::Duration};
|
||||||
|
|
||||||
use glam::{Affine3A, Quat, Vec3, Vec3A, vec3};
|
use glam::{Affine3A, Quat, Vec3, Vec3A, vec3};
|
||||||
use idmap::DirectIdMap;
|
|
||||||
use slotmap::SecondaryMap;
|
|
||||||
use wgui::{
|
use wgui::{
|
||||||
|
assets::AssetPath,
|
||||||
components::button::ComponentButton,
|
components::button::ComponentButton,
|
||||||
event::{CallbackDataCommon, EventAlterables, EventCallback, StyleSetRequest},
|
event::{CallbackDataCommon, EventAlterables, StyleSetRequest},
|
||||||
i18n::Translation,
|
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
parser::Fetchable,
|
parser::{Fetchable, ParseDocumentParams},
|
||||||
renderer_vk::text::custom_glyph::CustomGlyphData,
|
|
||||||
taffy,
|
taffy,
|
||||||
widget::{EventResult, label::WidgetLabel, sprite::WidgetSprite},
|
|
||||||
};
|
};
|
||||||
use wlx_common::{
|
use wlx_common::{
|
||||||
common::LeftRight,
|
common::LeftRight,
|
||||||
@@ -19,20 +15,18 @@ use wlx_common::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
|
||||||
input::TrackedDeviceRole,
|
|
||||||
task::{OverlayTask, TaskType},
|
|
||||||
},
|
|
||||||
gui::{
|
gui::{
|
||||||
panel::{GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, button::BUTTON_EVENTS},
|
panel::{
|
||||||
|
GuiPanel, NewGuiPanelParams, device_list::DeviceList, overlay_list::OverlayList,
|
||||||
|
set_list::SetList,
|
||||||
|
},
|
||||||
timer::GuiTimer,
|
timer::GuiTimer,
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::{
|
windowing::{
|
||||||
OverlayID, OverlaySelector, Z_ORDER_WATCH,
|
Z_ORDER_WATCH,
|
||||||
backend::{OverlayEventData, OverlayMeta},
|
backend::OverlayEventData,
|
||||||
manager::MAX_OVERLAY_SETS,
|
window::{OverlayWindowConfig, OverlayWindowData},
|
||||||
window::{OverlayCategory, OverlayWindowConfig, OverlayWindowData},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,462 +46,121 @@ struct OverlayButton {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct WatchState {
|
struct WatchState {
|
||||||
current_set: Option<usize>,
|
|
||||||
set_buttons: Vec<Rc<ComponentButton>>,
|
|
||||||
overlay_buttons: Vec<OverlayButton>,
|
|
||||||
overlay_metas: Vec<OverlayMeta>,
|
|
||||||
overlay_indices: SecondaryMap<OverlayID, usize>,
|
|
||||||
edit_mode_widgets: Vec<(WidgetID, bool)>,
|
edit_mode_widgets: Vec<(WidgetID, bool)>,
|
||||||
edit_add_widget: WidgetID,
|
edit_add_widget: WidgetID,
|
||||||
device_role_icons: DirectIdMap<TrackedDeviceRole, CustomGlyphData>,
|
device_list: DeviceList,
|
||||||
overlay_cat_icons: DirectIdMap<OverlayCategory, CustomGlyphData>,
|
overlay_list: OverlayList,
|
||||||
devices: Vec<(WidgetID, WidgetID)>,
|
set_list: SetList,
|
||||||
keyboard_oid: OverlayID,
|
clock_12h: bool,
|
||||||
dashboard_oid: OverlayID,
|
|
||||||
num_sets: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::significant_drop_tightening)]
|
#[allow(clippy::significant_drop_tightening)]
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||||
let state = WatchState::default();
|
let state = WatchState {
|
||||||
|
clock_12h: app.session.config.clock_12h,
|
||||||
let on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, parser, attribs, _app| {
|
|
||||||
let Ok(button) =
|
|
||||||
parser.fetch_component_from_widget_id_as::<ComponentButton>(attribs.widget_id)
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (name, kind, test_button, test_duration) in &BUTTON_EVENTS {
|
|
||||||
let Some(action) = attribs.get_value(name) else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut args = action.split_whitespace();
|
|
||||||
let Some(command) = args.next() else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let button = button.clone();
|
|
||||||
|
|
||||||
let callback: EventCallback<AppState, WatchState> = match command {
|
|
||||||
"::EditModeDeleteSet" => Box::new(move |_common, data, app, _state| {
|
|
||||||
if !test_button(data) || !test_duration(&button, app) {
|
|
||||||
return Ok(EventResult::Pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
app.tasks
|
|
||||||
.enqueue(TaskType::Overlay(OverlayTask::DeleteActiveSet));
|
|
||||||
Ok(EventResult::Consumed)
|
|
||||||
}),
|
|
||||||
"::EditModeAddSet" => Box::new(move |_common, data, app, _state| {
|
|
||||||
if !test_button(data) || !test_duration(&button, app) {
|
|
||||||
return Ok(EventResult::Pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::AddSet));
|
|
||||||
Ok(EventResult::Consumed)
|
|
||||||
}),
|
|
||||||
"::EditModeOverlayToggle" => {
|
|
||||||
let arg = args.next().unwrap_or_default();
|
|
||||||
let Ok(idx) = arg.parse::<usize>() else {
|
|
||||||
log::error!("{command} has invalid argument: \"{arg}\"");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
Box::new(move |_common, data, app, state| {
|
|
||||||
if !test_button(data) || !test_duration(&button, app) {
|
|
||||||
return Ok(EventResult::Pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(overlay) = state.overlay_metas.get(idx) else {
|
|
||||||
log::error!("No overlay at index {idx}.");
|
|
||||||
return Ok(EventResult::Consumed);
|
|
||||||
};
|
|
||||||
|
|
||||||
app.tasks
|
|
||||||
.enqueue(TaskType::Overlay(OverlayTask::ToggleOverlay(
|
|
||||||
OverlaySelector::Id(overlay.id),
|
|
||||||
)));
|
|
||||||
Ok(EventResult::Consumed)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"::SingleSetOverlayReset" => {
|
|
||||||
let arg = args.next().unwrap_or_default();
|
|
||||||
let Ok(idx) = arg.parse::<usize>() else {
|
|
||||||
log::error!("{command} has invalid argument: \"{arg}\"");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
Box::new(move |_common, data, app, state| {
|
|
||||||
if !test_button(data) || !test_duration(&button, app) {
|
|
||||||
return Ok(EventResult::Pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(overlay) = state.overlay_metas.get(idx) else {
|
|
||||||
log::error!("No overlay at index {idx}.");
|
|
||||||
return Ok(EventResult::Consumed);
|
|
||||||
};
|
|
||||||
|
|
||||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
|
||||||
OverlaySelector::Id(overlay.id),
|
|
||||||
Box::new(|app, owc| owc.activate(app)),
|
|
||||||
)));
|
|
||||||
Ok(EventResult::Consumed)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let id = layout.add_event_listener(attribs.widget_id, *kind, callback);
|
|
||||||
log::debug!("Registered {action} on {:?} as {id:?}", attribs.widget_id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let watch_xml = if app.session.config.single_set_mode {
|
|
||||||
"gui/watch-noset.xml"
|
|
||||||
} else {
|
|
||||||
"gui/watch.xml"
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut panel = GuiPanel::new_from_template(
|
|
||||||
app,
|
|
||||||
watch_xml,
|
|
||||||
state,
|
|
||||||
NewGuiPanelParams {
|
|
||||||
on_custom_id: Some(Box::new(
|
|
||||||
move |id, widget, doc_params, layout, parser_state, state| {
|
|
||||||
if id.starts_with("norm_") {
|
|
||||||
state.edit_mode_widgets.push((widget, false));
|
|
||||||
} else if &*id == "edit_add" {
|
|
||||||
state.edit_add_widget = widget;
|
|
||||||
} else if id.starts_with("edit_") {
|
|
||||||
state.edit_mode_widgets.push((widget, true));
|
|
||||||
} else if &*id == "sets" {
|
|
||||||
let node = layout.state.nodes[widget];
|
|
||||||
let num_children = layout.state.tree.children(node).iter().len();
|
|
||||||
|
|
||||||
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" || &*id == "toolbox-condensed" {
|
|
||||||
for idx in 0..MAX_TOOLBOX_BUTTONS {
|
|
||||||
let id_str = format!("overlay_{idx}");
|
|
||||||
|
|
||||||
let button = if let Ok(button) =
|
|
||||||
parser_state.fetch_component_as::<ComponentButton>(&id_str)
|
|
||||||
{
|
|
||||||
button
|
|
||||||
} else {
|
|
||||||
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,
|
|
||||||
)?;
|
|
||||||
parser_state.fetch_component_as::<ComponentButton>(&id_str)?
|
|
||||||
};
|
|
||||||
|
|
||||||
state.overlay_buttons.push(OverlayButton {
|
|
||||||
button,
|
|
||||||
label: parser_state
|
|
||||||
.get_widget_id(&format!("overlay_{idx}_label"))
|
|
||||||
.inspect_err(|e| log::warn!("{e:?}"))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
sprite: parser_state
|
|
||||||
.get_widget_id(&format!("overlay_{idx}_sprite"))
|
|
||||||
.inspect_err(|e| log::warn!("{e:?}"))
|
|
||||||
.unwrap_or_default(),
|
|
||||||
condensed: id.ends_with("-condensed"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if id.starts_with("overlay_") && id.ends_with("_sprite") {
|
|
||||||
// store device icons from xml
|
|
||||||
let id_n = id
|
|
||||||
.replace("overlay_", "")
|
|
||||||
.replace("_sprite", "")
|
|
||||||
.parse::<u64>()?;
|
|
||||||
|
|
||||||
let category = match id_n {
|
|
||||||
0 => OverlayCategory::Panel,
|
|
||||||
1 => OverlayCategory::Screen,
|
|
||||||
2 => OverlayCategory::Mirror,
|
|
||||||
3 => OverlayCategory::WayVR,
|
|
||||||
_ => 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.get_content().ok_or_else(|| {
|
|
||||||
anyhow::anyhow!("{id} is expected to have a src, but it doesn't.")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
state.overlay_cat_icons.insert(category, src);
|
|
||||||
} 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.get_content().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(), String::new().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(())
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
on_custom_attrib: Some(on_custom_attrib),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
};
|
||||||
)?;
|
let watch_xml = "gui/watch.xml";
|
||||||
|
|
||||||
let btn_edit_mode = panel
|
let mut panel =
|
||||||
.parser_state
|
GuiPanel::new_from_template(app, watch_xml, state, NewGuiPanelParams::default())?;
|
||||||
.fetch_component_as::<ComponentButton>("btn_edit_mode")
|
|
||||||
.ok();
|
let doc_params = ParseDocumentParams {
|
||||||
let btn_keyboard = panel
|
globals: panel.layout.state.globals.clone(),
|
||||||
.parser_state
|
path: AssetPath::FileOrBuiltIn(watch_xml),
|
||||||
.fetch_component_as::<ComponentButton>("btn_keyboard")
|
extra: panel.doc_extra.take().unwrap_or_default(),
|
||||||
.ok();
|
};
|
||||||
let btn_dashboard = panel
|
|
||||||
.parser_state
|
|
||||||
.fetch_component_as::<ComponentButton>("btn_dashboard")
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
panel.on_notify = Some(Box::new(move |panel, app, event_data| {
|
panel.on_notify = Some(Box::new(move |panel, app, event_data| {
|
||||||
let mut alterables = EventAlterables::default();
|
let mut alterables = EventAlterables::default();
|
||||||
|
|
||||||
|
let mut elems_changed = panel.state.overlay_list.on_notify(
|
||||||
|
&mut panel.layout,
|
||||||
|
&mut panel.parser_state,
|
||||||
|
&event_data,
|
||||||
|
&mut alterables,
|
||||||
|
&doc_params,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
elems_changed |= panel.state.set_list.on_notify(
|
||||||
|
&mut panel.layout,
|
||||||
|
&mut panel.parser_state,
|
||||||
|
&event_data,
|
||||||
|
&mut alterables,
|
||||||
|
&doc_params,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
elems_changed |= panel.state.device_list.on_notify(
|
||||||
|
app,
|
||||||
|
&mut panel.layout,
|
||||||
|
&mut panel.parser_state,
|
||||||
|
&event_data,
|
||||||
|
&doc_params,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
match event_data {
|
||||||
|
OverlayEventData::EditModeChanged(edit_mode) => {
|
||||||
|
if let Ok(btn_edit_mode) = panel
|
||||||
|
.parser_state
|
||||||
|
.fetch_component_as::<ComponentButton>("btn_edit_mode")
|
||||||
|
{
|
||||||
let mut com = CallbackDataCommon {
|
let mut com = CallbackDataCommon {
|
||||||
alterables: &mut alterables,
|
alterables: &mut alterables,
|
||||||
state: &panel.layout.state,
|
state: &panel.layout.state,
|
||||||
};
|
};
|
||||||
|
btn_edit_mode.set_sticky_state(&mut com, edit_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OverlayEventData::SettingsChanged => {
|
||||||
|
panel.layout.mark_redraw();
|
||||||
|
|
||||||
match event_data {
|
let display = if app.session.config.sets_on_watch {
|
||||||
OverlayEventData::ActiveSetChanged(current_set) => {
|
[taffy::Display::Flex, taffy::Display::None]
|
||||||
if let Some(old_set) = panel.state.current_set.take()
|
|
||||||
&& let Some(old_set) = panel.state.set_buttons.get_mut(old_set)
|
|
||||||
{
|
|
||||||
old_set.set_sticky_state(&mut com, false);
|
|
||||||
}
|
|
||||||
if let Some(new_set) = current_set
|
|
||||||
&& let Some(new_set) = panel.state.set_buttons.get_mut(new_set)
|
|
||||||
{
|
|
||||||
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, comp) in panel.state.set_buttons.iter().enumerate() {
|
|
||||||
let rect_id = comp.get_rect();
|
|
||||||
let display = if i < num_sets {
|
|
||||||
taffy::Display::Flex
|
|
||||||
} else {
|
} else {
|
||||||
taffy::Display::None
|
[taffy::Display::None, taffy::Display::Flex]
|
||||||
};
|
|
||||||
com.alterables
|
|
||||||
.set_style(rect_id, StyleSetRequest::Display(display));
|
|
||||||
}
|
|
||||||
let display = if num_sets < 7 {
|
|
||||||
taffy::Display::Flex
|
|
||||||
} else {
|
|
||||||
taffy::Display::None
|
|
||||||
};
|
|
||||||
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 {
|
|
||||||
let display = if *e == edit_mode {
|
|
||||||
taffy::Display::Flex
|
|
||||||
} else {
|
|
||||||
taffy::Display::None
|
|
||||||
};
|
|
||||||
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
|
|
||||||
};
|
|
||||||
com.alterables.set_style(
|
|
||||||
panel.state.edit_add_widget,
|
|
||||||
StyleSetRequest::Display(display),
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(btn) = btn_edit_mode.as_ref() {
|
|
||||||
btn.set_sticky_state(&mut com, edit_mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OverlayEventData::OverlaysChanged(metas) => {
|
|
||||||
panel.state.overlay_metas.clear();
|
|
||||||
for meta in &*metas {
|
|
||||||
match meta.category {
|
|
||||||
OverlayCategory::Keyboard => {
|
|
||||||
panel.state.keyboard_oid = meta.id;
|
|
||||||
if let Some(btn_keyboard) = btn_keyboard.as_ref() {
|
|
||||||
btn_keyboard.set_sticky_state(&mut com, meta.visible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OverlayCategory::Dashboard => {
|
|
||||||
if let Some(btn_dashboard) = btn_dashboard.as_ref() {
|
|
||||||
btn_dashboard.set_sticky_state(&mut com, meta.visible);
|
|
||||||
}
|
|
||||||
panel.state.dashboard_oid = meta.id;
|
|
||||||
}
|
|
||||||
OverlayCategory::Internal => {}
|
|
||||||
_ => panel.state.overlay_metas.push(meta.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.state.overlay_indices.clear();
|
|
||||||
for (idx, meta) in panel.state.overlay_metas.iter().enumerate() {
|
|
||||||
panel.state.overlay_indices.insert(meta.id, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (idx, btn) in panel.state.overlay_buttons.iter().enumerate() {
|
|
||||||
let display = if let Some(meta) = panel.state.overlay_metas.get(idx) {
|
|
||||||
let name = if btn.condensed {
|
|
||||||
condense_overlay_name(&meta.name)
|
|
||||||
} else {
|
|
||||||
sanitize_overlay_name(&meta.name)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(mut label) =
|
let widget = [
|
||||||
panel.layout.state.widgets.get_as::<WidgetLabel>(btn.label)
|
panel
|
||||||
{
|
.parser_state
|
||||||
label.set_text(&mut com, Translation::from_raw_text_rc(name));
|
.get_widget_id("panels_root")
|
||||||
} else {
|
.unwrap_or_default(),
|
||||||
btn.button
|
panel
|
||||||
.set_text(&mut com, Translation::from_raw_text_rc(name));
|
.parser_state
|
||||||
|
.get_widget_id("sets_root")
|
||||||
|
.unwrap_or_default(),
|
||||||
|
];
|
||||||
|
|
||||||
|
for i in 0..2 {
|
||||||
|
alterables.set_style(widget[i], StyleSetRequest::Display(display[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut sprite) = panel
|
if app.session.config.clock_12h != panel.state.clock_12h {
|
||||||
.layout
|
panel.state.clock_12h = app.session.config.clock_12h;
|
||||||
.state
|
|
||||||
.widgets
|
|
||||||
.get_as::<WidgetSprite>(btn.sprite)
|
|
||||||
&& let Some(glyph) = panel.state.overlay_cat_icons.get(meta.category)
|
|
||||||
{
|
|
||||||
sprite.set_content(&mut com, Some(glyph.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
btn.button.set_sticky_state(&mut com, meta.visible);
|
let clock_root = panel.parser_state.get_widget_id("clock_root")?;
|
||||||
|
panel.layout.remove_children(clock_root);
|
||||||
|
|
||||||
taffy::Display::Flex
|
panel.parser_state.instantiate_template(
|
||||||
} else {
|
&doc_params,
|
||||||
taffy::Display::None
|
"Clock",
|
||||||
};
|
&mut panel.layout,
|
||||||
com.alterables
|
clock_root,
|
||||||
.set_style(btn.button.get_rect(), StyleSetRequest::Display(display));
|
Default::default(),
|
||||||
}
|
)?;
|
||||||
}
|
|
||||||
OverlayEventData::VisibleOverlaysChanged(overlays) => {
|
|
||||||
for meta in &mut panel.state.overlay_metas {
|
|
||||||
meta.visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut keyboard_visible = false;
|
elems_changed = true;
|
||||||
let mut dashboard_visible = false;
|
|
||||||
|
|
||||||
for visible in &*overlays {
|
|
||||||
if let Some(idx) = panel.state.overlay_indices.get(*visible)
|
|
||||||
&& let Some(o) = panel.state.overlay_metas.get_mut(*idx)
|
|
||||||
{
|
|
||||||
o.visible = true;
|
|
||||||
} else if panel.state.keyboard_oid == *visible {
|
|
||||||
keyboard_visible = true;
|
|
||||||
} else if panel.state.dashboard_oid == *visible {
|
|
||||||
dashboard_visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (idx, btn) in panel.state.overlay_buttons.iter().enumerate() {
|
|
||||||
let Some(meta) = panel.state.overlay_metas.get(idx) else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
btn.button.set_sticky_state(&mut com, meta.visible);
|
|
||||||
}
|
|
||||||
if let Some(btn_keyboard) = btn_keyboard.as_ref() {
|
|
||||||
btn_keyboard.set_sticky_state(&mut com, keyboard_visible);
|
|
||||||
}
|
|
||||||
if let Some(btn_dashboard) = btn_dashboard.as_ref() {
|
|
||||||
btn_dashboard.set_sticky_state(&mut com, dashboard_visible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OverlayEventData::DevicesChanged => {
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
s.set_content(&mut com, Some(glyph.clone()));
|
|
||||||
com.alterables
|
|
||||||
.set_style(*div, StyleSetRequest::Display(taffy::Display::Flex));
|
|
||||||
} else {
|
|
||||||
com.alterables
|
|
||||||
.set_style(*div, StyleSetRequest::Display(taffy::Display::None));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if elems_changed {
|
||||||
|
panel.process_custom_elems(app);
|
||||||
|
}
|
||||||
|
|
||||||
panel.layout.process_alterables(alterables)?;
|
panel.layout.process_alterables(alterables)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
@@ -557,16 +210,3 @@ pub fn watch_fade<D>(app: &mut AppState, watch: &mut OverlayWindowData<D>) {
|
|||||||
state.alpha += 0.1;
|
state.alpha += 0.1;
|
||||||
state.alpha = state.alpha.clamp(0., 1.);
|
state.alpha = state.alpha.clamp(0., 1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sanitize_overlay_name(str: &str) -> Rc<str> {
|
|
||||||
str.replace("-wvr", "").into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn condense_overlay_name(str: &str) -> Rc<str> {
|
|
||||||
str.replace("DP-", "D")
|
|
||||||
.replace("HDMI-A-", "H")
|
|
||||||
.replace("WVR-wvr_", "W")
|
|
||||||
.replace("WVR-wvr", "W0")
|
|
||||||
.replace("Keyboard", "")
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
|
|
||||||
################ EXPERIENCE ################
|
################ EXPERIENCE ################
|
||||||
|
|
||||||
## When enabled, sets functionality will be disabled and
|
## The bottom of the watch will list sets instead of overlays.
|
||||||
## the bottom of the watch will list overlays instead of sets.
|
#sets_on_watch: false
|
||||||
#single_set_mode: false
|
|
||||||
|
|
||||||
## Force an alternative method for Wayland desktop capture.
|
## Force an alternative method for Wayland desktop capture.
|
||||||
## `auto`: default
|
## `auto`: default
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ pub enum OverlayEventData {
|
|||||||
OverlaysChanged(Rc<[OverlayMeta]>),
|
OverlaysChanged(Rc<[OverlayMeta]>),
|
||||||
VisibleOverlaysChanged(Rc<[OverlayID]>),
|
VisibleOverlaysChanged(Rc<[OverlayID]>),
|
||||||
DevicesChanged,
|
DevicesChanged,
|
||||||
|
SettingsChanged,
|
||||||
OverlayGrabbed {
|
OverlayGrabbed {
|
||||||
name: Arc<str>,
|
name: Arc<str>,
|
||||||
pos: Positioning,
|
pos: Positioning,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use wlx_common::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FRAME_COUNTER,
|
FRAME_COUNTER,
|
||||||
backend::task::OverlayTask,
|
backend::task::{OverlayTask, ToggleMode},
|
||||||
config::save_state,
|
config::save_state,
|
||||||
overlays::{
|
overlays::{
|
||||||
anchor::{create_anchor, create_grab_help},
|
anchor::{create_anchor, create_grab_help},
|
||||||
@@ -172,13 +172,29 @@ where
|
|||||||
OverlayTask::SwitchSet(maybe_set) => {
|
OverlayTask::SwitchSet(maybe_set) => {
|
||||||
self.switch_to_set(app, maybe_set, false);
|
self.switch_to_set(app, maybe_set, false);
|
||||||
}
|
}
|
||||||
OverlayTask::ToggleOverlay(sel) => {
|
OverlayTask::ResetOverlay(sel) => {
|
||||||
|
if let Some(o) = self.mut_by_selector(&sel) {
|
||||||
|
let was_active = o.config.is_active();
|
||||||
|
o.config.activate(app);
|
||||||
|
if !was_active {
|
||||||
|
self.visible_overlays_changed(app)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OverlayTask::ToggleOverlay(sel, mode) => {
|
||||||
let Some(id) = self.id_by_selector(&sel) else {
|
let Some(id) = self.id_by_selector(&sel) else {
|
||||||
log::warn!("Overlay not found for task: {sel:?}");
|
log::warn!("Overlay not found for task: {sel:?}");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let o = &mut self.overlays[id];
|
let o = &mut self.overlays[id];
|
||||||
|
|
||||||
|
match mode {
|
||||||
|
ToggleMode::EnsureOn if o.config.is_active() => return Ok(()),
|
||||||
|
ToggleMode::EnsureOff if !o.config.is_active() => return Ok(()),
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(active_state) = o.config.active_state.take() {
|
if let Some(active_state) = o.config.active_state.take() {
|
||||||
log::debug!("{}: toggle off", o.config.name);
|
log::debug!("{}: toggle off", o.config.name);
|
||||||
|
|
||||||
@@ -214,6 +230,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
overlay.config.deactivate();
|
overlay.config.deactivate();
|
||||||
}
|
}
|
||||||
|
self.visible_overlays_changed(app)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OverlayTask::AddSet => {
|
OverlayTask::AddSet => {
|
||||||
@@ -267,6 +284,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
OverlayTask::SettingsChanged => {
|
||||||
|
for o in self.overlays.values_mut() {
|
||||||
|
let _ = o
|
||||||
|
.config
|
||||||
|
.backend
|
||||||
|
.notify(app, OverlayEventData::SettingsChanged)
|
||||||
|
.log_err("Could not notify SettingsChanged");
|
||||||
|
}
|
||||||
|
}
|
||||||
OverlayTask::CleanupMirrors => {
|
OverlayTask::CleanupMirrors => {
|
||||||
let mut ids_to_remove = vec![];
|
let mut ids_to_remove = vec![];
|
||||||
for (oid, o) in &self.overlays {
|
for (oid, o) in &self.overlays {
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ impl OverlayWindowConfig {
|
|||||||
self.active_state.is_some()
|
self.active_state.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// only call this directly for `OverlayCategory::Internal`
|
||||||
|
/// for anything else, use `OverlayTask::ToggleOverlay` instead
|
||||||
pub fn activate(&mut self, app: &mut AppState) {
|
pub fn activate(&mut self, app: &mut AppState) {
|
||||||
log::debug!("activate {}", self.name.as_ref());
|
log::debug!("activate {}", self.name.as_ref());
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
@@ -120,19 +122,13 @@ impl OverlayWindowConfig {
|
|||||||
self.reset(app, true);
|
self.reset(app, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// only call this directly for `OverlayCategory::Internal`
|
||||||
|
/// for anything else, use `OverlayTask::ToggleOverlay` instead
|
||||||
pub fn deactivate(&mut self) {
|
pub fn deactivate(&mut self) {
|
||||||
log::debug!("deactivate {}", self.name.as_ref());
|
log::debug!("deactivate {}", self.name.as_ref());
|
||||||
self.active_state = None;
|
self.active_state = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle(&mut self, app: &mut AppState) {
|
|
||||||
if self.active_state.take().is_none() {
|
|
||||||
self.activate(app);
|
|
||||||
} else {
|
|
||||||
log::debug!("deactivate {} (toggle)", self.name.as_ref());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn auto_movement(&mut self, app: &mut AppState) {
|
pub fn auto_movement(&mut self, app: &mut AppState) {
|
||||||
if self.pause_movement {
|
if self.pause_movement {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user