diff --git a/Cargo.lock b/Cargo.lock index ac9db9f..23b0d3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1651,6 +1651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" dependencies = [ "approx", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index fd0eb94..4e4c112 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ flexi_logger = "0.28.0" fontconfig-rs = "0.1.1" freetype-rs = "0.36.0" futures = "0.3.29" -glam = { version = "0.27.0", features = ["approx"] } +glam = { version = "0.27.0", features = ["approx", "serde"] } idmap = { version = "0.2.21", features = ["serde"] } idmap-derive = "0.1.2" input-linux = "0.6.0" diff --git a/src/backend/common.rs b/src/backend/common.rs index 4b7c1c6..2d9a9c8 100644 --- a/src/backend/common.rs +++ b/src/backend/common.rs @@ -10,10 +10,10 @@ use serde::Deserialize; use thiserror::Error; use crate::{ - config::{AStrMapExt, AStrSetExt}, + config::AStrSetExt, overlays::{ anchor::create_anchor, - keyboard::{create_keyboard, KEYBOARD_NAME}, + keyboard::create_keyboard, screen::WlxClientAlias, watch::{create_watch, WATCH_NAME}, }, @@ -82,12 +82,6 @@ where state.show_hide = true; state.want_visible = false; } - state.curvature = app - .session - .config - .curve_values - .arc_get(state.name.as_ref()) - .copied(); overlays.insert( state.id, OverlayData:: { @@ -109,12 +103,6 @@ where let mut keyboard = create_keyboard(app)?; keyboard.state.show_hide = true; keyboard.state.want_visible = false; - keyboard.state.curvature = app - .session - .config - .curve_values - .arc_get(KEYBOARD_NAME) - .copied(); overlays.insert(keyboard.state.id, keyboard); Ok(Self { overlays, wl }) diff --git a/src/backend/input.rs b/src/backend/input.rs index 0a99b09..b4bf674 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -535,7 +535,6 @@ impl Pointer { Some(snap_upright(*anchor, Vec3A::Y).inverse() * overlay.state.transform); if let Some(grab_data) = self.interaction.grabbed.as_ref() { - let mut state_dirty = false; if overlay.state.curvature != grab_data.old_curvature { if let Some(val) = overlay.state.curvature { config.curve_values.arc_ins(overlay.state.name.clone(), val); @@ -543,13 +542,14 @@ impl Pointer { let ref_name = overlay.state.name.as_ref(); config.curve_values.arc_rm(ref_name); } - state_dirty = true; } - if state_dirty { - match save_state(config) { - Ok(_) => log::debug!("Saved state"), - Err(e) => log::error!("Failed to save state: {:?}", e), - } + config.transform_values.arc_ins( + overlay.state.name.clone(), + overlay.state.saved_transform.unwrap(), + ); + match save_state(config) { + Ok(_) => log::debug!("Saved state"), + Err(e) => log::error!("Failed to save state: {:?}", e), } } diff --git a/src/backend/overlay.rs b/src/backend/overlay.rs index b99bdf3..a1bff02 100644 --- a/src/backend/overlay.rs +++ b/src/backend/overlay.rs @@ -10,7 +10,7 @@ use anyhow::Ok; use glam::{Affine2, Affine3A, Mat3A, Quat, Vec2, Vec3, Vec3A}; use vulkano::image::view::ImageView; -use crate::state::AppState; +use crate::{config::AStrMapExt, state::AppState}; use super::input::{DummyInteractionHandler, Haptics, InteractionHandler, PointerHit}; @@ -178,7 +178,26 @@ where T: Default, { pub fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> { - self.state.reset(app, true); + self.state.curvature = app + .session + .config + .curve_values + .arc_get(self.state.name.as_ref()) + .copied(); + + let hard_reset; + if let Some(transform) = app + .session + .config + .transform_values + .arc_get(self.state.name.as_ref()) + { + self.state.saved_transform = Some(*transform); + hard_reset = false; + } else { + hard_reset = true; + } + self.state.reset(app, hard_reset); self.backend.init(app) } pub fn render(&mut self, app: &mut AppState) -> anyhow::Result<()> { diff --git a/src/config.rs b/src/config.rs index 4126e1e..cba7ccc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,6 +11,10 @@ use crate::state::LeftRight; use anyhow::bail; use config::Config; use config::File; +use glam::vec3a; +use glam::Affine3A; +use glam::Quat; +use glam::Vec3A; use idmap::IdMap; use log::error; use serde::Deserialize; @@ -78,12 +82,12 @@ impl AStrSetExt for AStrSet { pub type PwTokenMap = AStrMap; -pub fn def_watch_pos() -> [f32; 3] { - [-0.03, -0.01, 0.125] +pub fn def_watch_pos() -> Vec3A { + vec3a(-0.03, -0.01, 0.125) } -pub fn def_watch_rot() -> [f32; 4] { - [-0.7071066, 0.0007963618, 0.7071066, 0.0] +pub fn def_watch_rot() -> Quat { + Quat::from_xyzw(-0.7071066, 0.0007963618, 0.7071066, 0.0) } pub fn def_left() -> LeftRight { @@ -130,6 +134,10 @@ fn def_curve_values() -> AStrMap { AStrMap::new() } +fn def_transforms() -> AStrMap { + AStrMap::new() +} + fn def_auto() -> Arc { "auto".into() } @@ -145,10 +153,10 @@ fn def_font() -> Arc { #[derive(Deserialize, Serialize)] pub struct GeneralConfig { #[serde(default = "def_watch_pos")] - pub watch_pos: [f32; 3], + pub watch_pos: Vec3A, #[serde(default = "def_watch_rot")] - pub watch_rot: [f32; 4], + pub watch_rot: Quat, #[serde(default = "def_left")] pub watch_hand: LeftRight, @@ -198,6 +206,9 @@ pub struct GeneralConfig { #[serde(default = "def_curve_values")] pub curve_values: AStrMap, + #[serde(default = "def_transforms")] + pub transform_values: AStrMap, + #[serde(default = "def_auto")] pub capture_method: Arc, @@ -355,8 +366,8 @@ pub fn load_general() -> GeneralConfig { #[derive(Serialize)] pub struct AutoSettings { - pub watch_pos: [f32; 3], - pub watch_rot: [f32; 4], + pub watch_pos: Vec3A, + pub watch_rot: Quat, pub watch_hand: LeftRight, pub watch_view_angle_min: f32, pub watch_view_angle_max: f32, @@ -396,6 +407,7 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> { pub struct AutoState { pub show_screens: AStrSet, pub curve_values: AStrMap, + pub transform_values: AStrMap, } fn get_state_path() -> PathBuf { @@ -403,10 +415,12 @@ fn get_state_path() -> PathBuf { path.push("zz-saved-state.json5"); path } + pub fn save_state(config: &GeneralConfig) -> anyhow::Result<()> { let conf = AutoState { show_screens: config.show_screens.clone(), curve_values: config.curve_values.clone(), + transform_values: config.transform_values.clone(), }; let json = serde_json::to_string_pretty(&conf).unwrap(); // want panic diff --git a/src/gui/modular/button.rs b/src/gui/modular/button.rs index b8978ce..9384e99 100644 --- a/src/gui/modular/button.rs +++ b/src/gui/modular/button.rs @@ -6,7 +6,7 @@ use std::{ time::{Duration, Instant}, }; -use glam::{Quat, Vec3A, Vec4}; +use glam::{Quat, Vec4}; use serde::Deserialize; use crate::{ @@ -486,15 +486,15 @@ fn run_watch(data: &WatchAction, app: &mut AppState) { Box::new(|app, o| { if let RelativeTo::Hand(0) = o.relative_to { o.relative_to = RelativeTo::Hand(1); - o.spawn_rotation = Quat::from_slice(&app.session.config.watch_rot) + o.spawn_rotation = app.session.config.watch_rot * Quat::from_rotation_x(PI) * Quat::from_rotation_z(PI); - o.spawn_point = Vec3A::from_slice(&app.session.config.watch_pos); + o.spawn_point = app.session.config.watch_pos; o.spawn_point.x *= -1.; } else { o.relative_to = RelativeTo::Hand(0); - o.spawn_rotation = Quat::from_slice(&app.session.config.watch_rot); - o.spawn_point = Vec3A::from_slice(&app.session.config.watch_pos); + o.spawn_rotation = app.session.config.watch_rot; + o.spawn_point = app.session.config.watch_pos; } o.dirty = true; Toast::new( diff --git a/src/overlays/toast.rs b/src/overlays/toast.rs index 1784595..1a2585b 100644 --- a/src/overlays/toast.rs +++ b/src/overlays/toast.rs @@ -1,6 +1,6 @@ use std::{f32::consts::PI, ops::Add, sync::Arc, time::Instant}; -use glam::{vec3a, Quat, Vec3A}; +use glam::{vec3a, Quat}; use idmap_derive::IntegerId; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; @@ -127,9 +127,8 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box return None, DisplayMethod::Center => (vec3a(0., -0.2, -0.5), Quat::IDENTITY, RelativeTo::Head), DisplayMethod::Watch => { - let mut watch_pos = - Vec3A::from_slice(&app.session.config.watch_pos) + vec3a(-0.005, -0.05, 0.02); - let mut watch_rot = Quat::from_slice(&app.session.config.watch_rot); + let mut watch_pos = app.session.config.watch_pos + vec3a(-0.005, -0.05, 0.02); + let mut watch_rot = app.session.config.watch_rot; let relative_to = match app.session.config.watch_hand { LeftRight::Left => RelativeTo::Hand(0), LeftRight::Right => { diff --git a/src/overlays/watch.rs b/src/overlays/watch.rs index 85ed668..4b542af 100644 --- a/src/overlays/watch.rs +++ b/src/overlays/watch.rs @@ -1,4 +1,4 @@ -use glam::{Quat, Vec3A}; +use glam::Vec3A; use crate::{ backend::overlay::{ui_transform, OverlayData, OverlayState, RelativeTo}, @@ -26,8 +26,8 @@ where want_visible: true, interactable: true, spawn_scale: config.width, - spawn_point: Vec3A::from_slice(&state.session.config.watch_pos), - spawn_rotation: Quat::from_slice(&state.session.config.watch_rot), + spawn_point: state.session.config.watch_pos, + spawn_rotation: state.session.config.watch_rot, interaction_transform: ui_transform(&config.size), relative_to, ..Default::default()