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