add watch toggle setting

This commit is contained in:
art0007i 2026-05-31 23:10:01 +02:00
parent 1591466a8d
commit ae698bf111
9 changed files with 73 additions and 39 deletions

View File

@ -100,6 +100,7 @@
"SCREEN_RENDER_DOWN_HELP": "Helps with aliasing on high-res screens",
"SCROLL_SPEED": "Scroll speed",
"SELECT_VARIANT": "Select variant",
"ENABLE_WATCH": "Enable watch",
"SETS_ON_WATCH": "Sets on watch",
"SKYBOX": "Skybox",
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",

View File

@ -44,6 +44,7 @@
"USE_SKYBOX_HELP": "Wyświetlaj niebo, jeśli nie ma aplikacji sceny lub passthrough",
"USE_PASSTHROUGH_HELP": "Pozwól na passthrough, jeśli runtime XR to obsługuje",
"SCREEN_RENDER_DOWN_HELP": "Pomaga redukować aliasing na ekranach o wysokiej rozdzielczości",
"ENABLE_WATCH": "Włącz zegarek",
"SETS_ON_WATCH": "Lista zestawów na zegarku",
"TROUBLESHOOTING": "Rozwiązywanie problemów",
"CLEAR_SAVED_STATE": "Wyczyść zapisany stan",

View File

@ -274,6 +274,7 @@ enum SettingType {
PointerLerpFactor,
ScreenRenderDown,
ScrollSpeed,
EnableWatch,
SetsOnWatch,
SpaceDragMultiplier,
SpaceDragUnlocked,
@ -309,6 +310,7 @@ impl SettingType {
Self::KeyboardSoundEnabled => &mut config.keyboard_sound_enabled,
Self::UprightScreenFix => &mut config.upright_screen_fix,
Self::DoubleCursorFix => &mut config.double_cursor_fix,
Self::EnableWatch => &mut config.enable_watch,
Self::SetsOnWatch => &mut config.sets_on_watch,
Self::HideGrabHelp => &mut config.hide_grab_help,
Self::AllowSliding => &mut config.allow_sliding,
@ -435,6 +437,7 @@ impl SettingType {
Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"),
Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"),
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
Self::EnableWatch => Ok("APP_SETTINGS.ENABLE_WATCH"),
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"),
Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"),

View File

@ -22,6 +22,7 @@ impl State {
options_slider_f32(par.mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1)?; // min, max, step
options_slider_f32(par.mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05)?; // min, max, step
options_slider_f32(par.mp, c, SettingType::UiRoundMultiplier, 0.1, 5.0, 0.1)?;
options_checkbox(par.mp, c, SettingType::EnableWatch)?;
options_checkbox(par.mp, c, SettingType::SetsOnWatch)?;
options_checkbox(par.mp, c, SettingType::Clock12h)?;
Ok(State {})

View File

@ -141,7 +141,7 @@ pub fn openxr_run(
lines.allocate(&xr_state, &app)?,
];
let watch_id = overlays.lookup(WATCH_NAME).unwrap(); // want panic
let watch_id = overlays.lookup(WATCH_NAME);
let mut input_source = input::OpenXrInputSource::new(&xr_state)?;
@ -345,17 +345,19 @@ pub fn openxr_run(
app.hid_provider.inner.commit();
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
let watch_state = watch.config.active_state.as_mut().unwrap();
let watch_transform = watch_state.transform;
if watch_state.alpha < 0.05 {
//FIXME: Temporary workaround for Monado bug
watch_state.transform = Affine3A::from_scale(Vec3 {
x: 0.001,
y: 0.001,
z: 0.001,
});
watch_state.alpha = 0.02; // visible but not really. Monado freaks out if no layers are submitted.
let mut watch_transform = Affine3A::IDENTITY;
if let Some(watch) = watch_id.and_then(|id| overlays.mut_by_id(id)) {
let watch_state = watch.config.active_state.as_mut().unwrap();
watch_transform = watch_state.transform;
if watch_state.alpha < 0.05 {
//FIXME: Temporary workaround for Monado bug
watch_state.transform = Affine3A::from_scale(Vec3 {
x: 0.001,
y: 0.001,
z: 0.001,
});
watch_state.alpha = 0.02; // visible but not really. Monado freaks out if no layers are submitted.
}
}
if let Err(e) =
@ -509,8 +511,9 @@ pub fn openxr_run(
delete_queue.retain(|(_, frame)| *frame > cur_frame);
//FIXME: Temporary workaround for Monado bug
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
watch.config.active_state.as_mut().unwrap().transform = watch_transform;
if let Some(watch) = watch_id.and_then(|id| overlays.mut_by_id(id)) {
watch.config.active_state.as_mut().unwrap().transform = watch_transform;
}
} // main_loop
if let (Some(blocker), Some(monado)) = (blocker, app.monado_state.as_mut()) {

View File

@ -145,6 +145,7 @@ pub struct AutoSettings {
pub keyboard_sound_enabled: bool,
pub upright_screen_fix: bool,
pub double_cursor_fix: bool,
pub enable_watch: bool,
pub sets_on_watch: bool,
pub hide_grab_help: bool,
pub xr_click_sensitivity: f32,
@ -200,6 +201,7 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
keyboard_sound_enabled: config.keyboard_sound_enabled,
upright_screen_fix: config.upright_screen_fix,
double_cursor_fix: config.double_cursor_fix,
enable_watch: config.enable_watch,
sets_on_watch: config.sets_on_watch,
hide_grab_help: config.hide_grab_help,
xr_click_sensitivity: config.xr_click_sensitivity,

View File

@ -85,6 +85,9 @@
# The settings are here for reference only.
# Probably don't include them in your config file.
## The watch will be enabled
#enable_watch: true
## The bottom of the watch will list sets instead of overlays.
#sets_on_watch: false

View File

@ -51,7 +51,7 @@ pub struct OverlayWindowManager<T> {
/// Usually the same as current_set, except it keeps its value when current_set is hidden.
restore_set: usize,
anchor_local: Affine3A,
watch_id: OverlayID,
watch_id: Option<OverlayID>,
keyboard_id: OverlayID,
edit_mode: bool,
dropped_overlays: VecDeque<OverlayWindowData<T>>,
@ -71,7 +71,7 @@ where
sets: vec![OverlayWindowSet::default()],
global_set: OverlayWindowSet::default(),
anchor_local: Affine3A::from_translation(Vec3::NEG_Z),
watch_id: OverlayID::null(), // set down below
watch_id: None, // set down below
keyboard_id: OverlayID::null(), // set down below
edit_mode: false,
dropped_overlays: VecDeque::with_capacity(8),
@ -127,8 +127,10 @@ where
let anchor = OverlayWindowData::from_config(create_anchor(app)?);
me.add(anchor, app);
let watch = OverlayWindowData::from_config(create_watch(app)?);
me.watch_id = me.add(watch, app);
if app.session.config.enable_watch {
let watch = OverlayWindowData::from_config(create_watch(app)?);
me.watch_id = Some(me.add(watch, app));
}
let dash_frontend = OverlayWindowData::from_config(create_dash_frontend(app)?);
me.add(dash_frontend, app);
@ -149,7 +151,7 @@ where
me.restore_layout(app);
me.overlays_changed(app)?;
for id in [me.watch_id, me.keyboard_id] {
for id in [me.watch_id, Some(me.keyboard_id)].iter().filter_map(|x| *x) {
for ev in [
OverlayEventData::NumSetsChanged(me.sets.len()),
OverlayEventData::EditModeChanged(false),
@ -288,6 +290,15 @@ where
self.sets_changed(app);
}
OverlayTask::SettingsChanged => {
if app.session.config.enable_watch != self.watch_id.is_some() {
if let Some(watch_id) = self.watch_id.take() {
self.overlays.remove(watch_id);
} else {
let watch = OverlayWindowData::from_config(create_watch(app)?);
self.watch_id = Some(self.add(watch, app));
}
}
for o in self.overlays.values_mut() {
let _ = o
.config
@ -440,7 +451,8 @@ impl<T> OverlayWindowManager<T> {
}
// global overlays; watch, toast
for oid in &[self.watch_id] {
if let Some(watch_id) = self.watch_id {
for oid in &[watch_id] {
let Some(o) = self.get_by_id(*oid) else {
break;
};
@ -451,6 +463,7 @@ impl<T> OverlayWindowManager<T> {
.config
.global_set
.insert(o.config.name.clone(), state.clone());
}
}
// BackendAttrib
@ -587,16 +600,18 @@ impl<T> OverlayWindowManager<T> {
}
}
}
if changed && let Some(watch) = self.mut_by_id(self.watch_id) {
watch
.config
.active_state
.iter_mut()
.for_each(|f| f.grabbable = enabled);
watch
.config
.backend
.notify(app, OverlayEventData::EditModeChanged(enabled))?;
if let Some(watch_id) = self.watch_id {
if changed && let Some(watch) = self.mut_by_id(watch_id) {
watch
.config
.active_state
.iter_mut()
.for_each(|f| f.grabbable = enabled);
watch
.config
.backend
.notify(app, OverlayEventData::EditModeChanged(enabled))?;
}
}
Ok(())
}
@ -824,7 +839,7 @@ impl<T> OverlayWindowManager<T> {
}
self.current_set = new_set;
for id in [self.watch_id, self.keyboard_id] {
for id in [self.watch_id, Some(self.keyboard_id)].iter().filter_map(|x| *x) {
let _ = self.mut_by_id(id).context("Missing overlay").and_then(|o| {
o.config
.backend
@ -877,7 +892,7 @@ impl<T> OverlayWindowManager<T> {
}
let meta: Rc<[OverlayMeta]> = meta.into();
for id in [self.watch_id, self.keyboard_id] {
for id in [self.watch_id, Some(self.keyboard_id)].iter().filter_map(|x| *x) {
let _ = self.mut_by_id(id).context("Missing overlay").and_then(|o| {
o.config
.backend
@ -902,7 +917,7 @@ impl<T> OverlayWindowManager<T> {
}
let vis: Rc<[OverlayID]> = vis.into();
for id in [self.watch_id, self.keyboard_id] {
for id in [self.watch_id, Some(self.keyboard_id)].iter().filter_map(|x| *x) {
let _ = self.mut_by_id(id).context("Missing overlay").and_then(|o| {
o.config
.backend
@ -915,7 +930,7 @@ impl<T> OverlayWindowManager<T> {
fn sets_changed(&mut self, app: &mut AppState) {
let len = self.sets.len();
for id in [self.watch_id, self.keyboard_id] {
for id in [self.watch_id, Some(self.keyboard_id)].iter().filter_map(|x| *x) {
if let Some(o) = self.mut_by_id(id) {
let _ = o
.config
@ -928,11 +943,13 @@ impl<T> OverlayWindowManager<T> {
#[allow(clippy::unnecessary_wraps)]
pub fn devices_changed(&mut self, app: &mut AppState) -> anyhow::Result<()> {
if let Some(watch) = self.mut_by_id(self.watch_id) {
let _ = watch
.config
.backend
.notify(app, OverlayEventData::DevicesChanged);
if let Some(watch_id) = self.watch_id {
if let Some(watch) = self.mut_by_id(watch_id) {
let _ = watch
.config
.backend
.notify(app, OverlayEventData::DevicesChanged);
}
}
Ok(())

View File

@ -273,6 +273,9 @@ pub struct GeneralConfig {
#[serde(default = "def_false")]
pub double_cursor_fix: bool,
#[serde(default = "def_true")]
pub enable_watch: bool,
#[serde(default = "def_false")]
pub sets_on_watch: bool,