diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index 53a831ca..1ae02814 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -117,6 +117,10 @@ "DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors", "DEFAULT_OVERLAY_SCALE": "Default overlay size", "DEFAULT_OVERLAY_SCALE_HELP": "Spawn new overlays at this scale.", + "DEFAULT_CURVATURE": "Default overlay curvature", + "DEFAULT_OPACITY": "Default overlay opacity", + "DEFAULT_POSITIONING": "Default overlay positioning", + "DEFAULT_OVERLAY_DEFAULTS_HELP": "Only applies to new overlays", "ENABLED": "Enabled", "FEATURES": "Features", "FOCUS_FOLLOWS_MOUSE_MODE": "Mouse move on trigger touch", @@ -149,6 +153,12 @@ "NO_SKYMAPS_FOUND": "No skymaps found", "OPAQUE_BACKGROUND": "Opaque background", "OPTION": { + "ANCHORED": "Anchored", + "FLOATING": "Floating", + "STATIC": "Static", + "ANCHORED_HELP": "Moves with center marker. Recommended.", + "FLOATING_HELP": "Moves independently, recenters.\nEasy to misplace; not recommended.", + "STATIC_HELP": "Stays in place relative to world.", "AUTO": "Automatic", "AUTO_HELP": "ScreenCopy GPU if supported,\notherwise PipeWire GPU.", "EYE_ONLY": "Eye laser", diff --git a/dash-frontend/src/tab/settings/mod.rs b/dash-frontend/src/tab/settings/mod.rs index 64d1a866..4745cf71 100644 --- a/dash-frontend/src/tab/settings/mod.rs +++ b/dash-frontend/src/tab/settings/mod.rs @@ -311,6 +311,10 @@ pub(crate) enum SettingType { CaptureMethod, ClickFreezeTimeMs, Clock12h, + DefaultCurvature, + DefaultOpacity, + DefaultOverlayScale, + DefaultPositioning, DoubleCursorFix, EnableWatch, FocusFollowsMouseMode, @@ -330,7 +334,6 @@ pub(crate) enum SettingType { LongPressDuration, NotificationsEnabled, NotificationsSoundEnabled, - DefaultOverlayScale, OpaqueBackground, MouseAcceleration, PointerLerpFactor, @@ -405,6 +408,8 @@ impl SettingType { pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 { match self { + Self::DefaultCurvature => &mut config.default_curvature, + Self::DefaultOpacity => &mut config.default_opacity, Self::DefaultOverlayScale => &mut config.default_overlay_scale, Self::GridOpacity => &mut config.grid_opacity, Self::LongPressDuration => &mut config.long_press_duration, @@ -439,6 +444,10 @@ impl SettingType { Self::CaptureMethod => { config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!") } + Self::DefaultPositioning => { + config.default_positioning = + wlx_common::config::DefaultPositioning::from_str(value).expect("Invalid enum value!") + } Self::InputCaptureMethod => { config.wvr_input_capture = wlx_common::config::InputCaptureMethod::from_str(value).expect("Invalid enum value!") } @@ -466,6 +475,7 @@ impl SettingType { fn get_enum_title(self, config: &mut GeneralConfig) -> Translation { match self { Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method), + Self::DefaultPositioning => Self::get_enum_title_inner(config.default_positioning), Self::InputCaptureMethod => Self::get_enum_title_inner(config.wvr_input_capture), Self::InputEmulationMethod => Self::get_enum_title_inner(config.input_emulation_method), Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode), @@ -508,7 +518,10 @@ impl SettingType { Self::CaptureMethod => Ok("APP_SETTINGS.CAPTURE_METHOD"), Self::ClickFreezeTimeMs => Ok("APP_SETTINGS.CLICK_FREEZE_TIME_MS"), Self::Clock12h => Ok("APP_SETTINGS.CLOCK_12H"), + Self::DefaultCurvature => Ok("APP_SETTINGS.DEFAULT_CURVATURE"), + Self::DefaultOpacity => Ok("APP_SETTINGS.DEFAULT_OPACITY"), Self::DefaultOverlayScale => Ok("APP_SETTINGS.DEFAULT_OVERLAY_SCALE"), + Self::DefaultPositioning => Ok("APP_SETTINGS.DEFAULT_POSITIONING"), Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"), Self::FocusFollowsMouseMode => Ok("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE"), Self::GridOpacity => Ok("APP_SETTINGS.GRID_OPACITY"), @@ -565,7 +578,10 @@ impl SettingType { Self::BlockGameInputIgnoreWatch => Some("APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP"), Self::BlockPosesOnKbdInteraction => Some("APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP"), Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"), + Self::DefaultCurvature => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"), + Self::DefaultOpacity => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"), Self::DefaultOverlayScale => Some("APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP"), + Self::DefaultPositioning => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"), Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"), Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"), Self::HandsfreeAltTab => Some("APP_SETTINGS.HANDSFREE_ALT_TAB_HELP"), diff --git a/dash-frontend/src/tab/settings/tab_look_and_feel.rs b/dash-frontend/src/tab/settings/tab_look_and_feel.rs index bc264bb0..ca200997 100644 --- a/dash-frontend/src/tab/settings/tab_look_and_feel.rs +++ b/dash-frontend/src/tab/settings/tab_look_and_feel.rs @@ -67,7 +67,10 @@ impl State { options_checkbox(par.mp, c, SettingType::OpaqueBackground)?; options_checkbox(par.mp, c, SettingType::HideUsername)?; options_checkbox(par.mp, c, SettingType::HideGrabHelp)?; + options_slider_f32(par.mp, c, SettingType::DefaultCurvature, 0.0, 0.5, 0.05)?; // min, max, step + options_slider_f32(par.mp, c, SettingType::DefaultOpacity, 0.05, 1.0, 0.05)?; // min, max, step options_slider_f32(par.mp, c, SettingType::DefaultOverlayScale, 0.7, 1.5, 0.05)?; // min, max, step + options_dropdown::(par.mp, c, &SettingType::DefaultPositioning)?; 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)?; diff --git a/wayvr/src/assets/lang/de.json b/wayvr/src/assets/lang/de.json index 8a4ac873..cbf548e6 100644 --- a/wayvr/src/assets/lang/de.json +++ b/wayvr/src/assets/lang/de.json @@ -49,7 +49,6 @@ "OPACITY": "Undurchsichtigkeit", "POSITIONING": "Positionierung", "RESIZE_PRESS_AND_DRAG": "Größe ändern (gedrückt halten & ziehen)", - "POS_STATIC": "Statisch: Bleibt an Ort und Stelle und wird niemals neu zentriert.", "POS_ANCHORED": "Verankert: Bewegt sich zusammen mit dem Rest des Sets. Standard.", "POS_FLOATING": "Schwebend: Bleibt an Ort und Stelle, wird beim Anzeigen neu zentriert.", "POS_HMD": "Folge dem Headset.", @@ -153,4 +152,4 @@ "CLOSE": "Fokussierte App schließen", "MOUSE": "Echte Mausklicks & Scrollen werden auch auf den VR-Zeiger übertragen" } -} \ No newline at end of file +} diff --git a/wayvr/src/assets/lang/en.json b/wayvr/src/assets/lang/en.json index 1b440874..47ea1801 100644 --- a/wayvr/src/assets/lang/en.json +++ b/wayvr/src/assets/lang/en.json @@ -62,7 +62,7 @@ "POS_HAND_L": "Follow the left hand.", "POS_HAND_R": "Follow the right hand.", "POS_HMD": "Follow the HMD.", - "POS_STATIC": "Static: Not part of any set, no recenter.", + "POS_STATIC": "Static: Stays in place relative to world.", "POSITIONING": "Positioning", "RESIZE_PRESS_AND_DRAG": "Resize (press & drag)", "RESIZE_CORNER": "Drag to resize", diff --git a/wayvr/src/assets/lang/es.json b/wayvr/src/assets/lang/es.json index 8a714076..6261fcf3 100644 --- a/wayvr/src/assets/lang/es.json +++ b/wayvr/src/assets/lang/es.json @@ -49,7 +49,6 @@ "OPACITY": "Opacidad", "POSITIONING": "Posicionamiento", "RESIZE_PRESS_AND_DRAG": "Redimensionar (presionar y arrastrar)", - "POS_STATIC": "Estático: Permanece en su lugar y nunca se recentra.", "POS_ANCHORED": "Anclado: Se mueve junto con el resto del conjunto. Predeterminado.", "POS_FLOATING": "Flotante: Permanece en su lugar, se recentra cuando se muestra.", "POS_HMD": "Seguir el HMD.", @@ -153,4 +152,4 @@ "CLOSE": "Cerrar aplicación enfocada", "MOUSE": "Los clics y el desplazamiento del ratón real también se traducen al puntero de VR" } -} \ No newline at end of file +} diff --git a/wayvr/src/assets/lang/it.json b/wayvr/src/assets/lang/it.json index 837fffdf..246d5839 100644 --- a/wayvr/src/assets/lang/it.json +++ b/wayvr/src/assets/lang/it.json @@ -45,7 +45,6 @@ "POS_HAND_L": "Segui la mano sinistra.", "POS_HAND_R": "Segui la mano destra.", "POS_HMD": "Segui l'HMD.", - "POS_STATIC": "Statico: non fa parte di alcun set, senza recentratura.", "POSITIONING": "Posizionamento", "RESIZE_PRESS_AND_DRAG": "Ridimensiona (premi e trascina)", "STEREO_3D_MODE": { @@ -151,4 +150,4 @@ "CLOSE": "Chiudi l'app focalizzata", "MOUSE": "I clic e lo scorrimento del mouse reale vengono tradotti anche nel puntatore VR" } -} \ No newline at end of file +} diff --git a/wayvr/src/assets/lang/ja.json b/wayvr/src/assets/lang/ja.json index 6056f0a7..1adab398 100644 --- a/wayvr/src/assets/lang/ja.json +++ b/wayvr/src/assets/lang/ja.json @@ -49,7 +49,6 @@ "OPACITY": "不透明度", "POSITIONING": "位置付け", "RESIZE_PRESS_AND_DRAG": "サイズ変更(押してドラッグ)", - "POS_STATIC": "固定:置かれた場所に留まり、再センタリングされません。", "POS_ANCHORED": "アンカー:セット内の他のウィンドウと共に移動します。デフォルト。", "POS_FLOATING": "フローティング:置かれた場所に留まるが、表示される時に再センタリングされます。", "POS_HMD": "HMD に追従する。", @@ -151,4 +150,4 @@ "CLOSE": "フォーカス中のアプリを閉じる", "MOUSE": "実際のマウスのクリックとスクロールもVRポインターに反映されます" } -} \ No newline at end of file +} diff --git a/wayvr/src/assets/lang/pl.json b/wayvr/src/assets/lang/pl.json index dea58992..4f7f8ac4 100644 --- a/wayvr/src/assets/lang/pl.json +++ b/wayvr/src/assets/lang/pl.json @@ -50,7 +50,6 @@ "POSITIONING": "Pozycjonowanie", "BLOCK_INPUT": "Blokuj input z gry", "RESIZE_PRESS_AND_DRAG": "Zmień rozmiar (naciśnij i przeciągnij)", - "POS_STATIC": "Statyczne: Pozostaje w miejscu i nigdy nie jest ponownie wyśrodkowywane.", "POS_ANCHORED": "Zakotwiczone: Porusza się razem z resztą zestawu. Domyślne.", "POS_FLOATING": "Pływające: Pozostaje w miejscu, ponownie się wyśrodkowuje po pokazaniu.", "POS_HMD": "Podążaj za HMD.", @@ -151,4 +150,4 @@ "CLOSE": "Zamknij aktualną aplikację", "MOUSE": "Kliknięcia i przewijanie fizycznej myszy są również przeniesione na wskaźnik VR" } -} \ No newline at end of file +} diff --git a/wayvr/src/assets/lang/zh_CN.json b/wayvr/src/assets/lang/zh_CN.json index 7c872229..11e22088 100644 --- a/wayvr/src/assets/lang/zh_CN.json +++ b/wayvr/src/assets/lang/zh_CN.json @@ -45,7 +45,6 @@ "POS_HAND_L": "跟随左手。", "POS_HAND_R": "跟随右手。", "POS_HMD": "跟随头显 (HMD)。", - "POS_STATIC": "静态:不属于任何集合,不重新居中。", "POSITIONING": "定位", "RESIZE_PRESS_AND_DRAG": "调整大小 (按住并拖拽)", "STEREO_3D_MODE": { @@ -151,4 +150,4 @@ "CLOSE": "关闭当前焦点应用", "MOUSE": "真实鼠标的点击和滚动也将转换为 VR 指针" } -} \ No newline at end of file +} diff --git a/wayvr/src/backend/wayvr/mod.rs b/wayvr/src/backend/wayvr/mod.rs index 821ae7bd..93ffc509 100644 --- a/wayvr/src/backend/wayvr/mod.rs +++ b/wayvr/src/backend/wayvr/mod.rs @@ -58,7 +58,7 @@ use wgui::{gfx::WGfx, log::LogErr}; use wlx_capture::frame::Transform; use wlx_common::{ audio::{AudioSystem, SamplePlayer}, - config::{GeneralConfig, InputCaptureMethod}, + config::{DefaultPositioning, GeneralConfig, InputCaptureMethod}, desktop_finder::DesktopFinder, }; use xkbcommon::xkb; @@ -402,7 +402,11 @@ impl WvrServerState { } _ => ( Size::new(1920, 1080).clamp(min_size, max_size), - PositionMode::Float, + match app.session.config.default_positioning { + DefaultPositioning::Anchored => PositionMode::Anchor, + DefaultPositioning::Floating => PositionMode::Float, + DefaultPositioning::Static => PositionMode::Static, + }, None, None, false, diff --git a/wayvr/src/config.rs b/wayvr/src/config.rs index 15898d7d..8d9581e7 100644 --- a/wayvr/src/config.rs +++ b/wayvr/src/config.rs @@ -9,9 +9,9 @@ use wayvr_ipc::packet_client::WvrProcessLaunchParams; use wlx_common::{ astr_containers::AStrMap, config::{ - AltModifier, CaptureMethod, ChromaKeyParams, GeneralConfig, HandsfreeAltTab, - HandsfreePointer, InputCaptureMethod, InputEmulationMethod, PinnedApp, SerializedWindowSet, - SerializedWindowStates, + AltModifier, CaptureMethod, ChromaKeyParams, DefaultPositioning, GeneralConfig, + HandsfreeAltTab, HandsfreePointer, InputCaptureMethod, InputEmulationMethod, PinnedApp, + SerializedWindowSet, SerializedWindowStates, }, config_io, locale::Language, @@ -195,6 +195,9 @@ pub struct AutoSettings { pub wvr_mouse_acceleration: bool, pub wvr_mouse_speed: f32, pub wvr_input_capture: InputCaptureMethod, + pub default_curvature: f32, + pub default_opacity: f32, + pub default_positioning: DefaultPositioning, } fn get_settings_path() -> PathBuf { @@ -267,6 +270,9 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> { wvr_mouse_acceleration: config.wvr_mouse_acceleration, wvr_mouse_speed: config.wvr_mouse_speed, wvr_input_capture: config.wvr_input_capture, + default_curvature: config.default_curvature, + default_opacity: config.default_opacity, + default_positioning: config.default_positioning, }; let json = serde_json::to_string_pretty(&conf).unwrap(); // want panic @@ -306,3 +312,11 @@ pub fn save_state(config: &GeneralConfig) -> anyhow::Result<()> { log::info!("State was saved successfully."); Ok(()) } + +pub fn none_if_0(val: f32) -> Option { + if val.abs() < f32::EPSILON { + None + } else { + Some(val) + } +} diff --git a/wayvr/src/overlays/dashboard.rs b/wayvr/src/overlays/dashboard.rs index a228daf9..84577399 100644 --- a/wayvr/src/overlays/dashboard.rs +++ b/wayvr/src/overlays/dashboard.rs @@ -42,7 +42,7 @@ use crate::{ window::WindowHandle, }, }, - config::save_settings, + config::{none_if_0, save_settings}, ipc::ipc_server::{gen_args_vec, gen_env_vec}, state::AppState, subsystem::hid::WheelDelta, @@ -337,7 +337,7 @@ fn tutorial_spawn_effect(app: &mut AppState) -> anyhow::Result<()> { grabbable: true, interactable: true, positioning: Positioning::FollowHead { lerp: 0.01 }, - curvature: Some(0.15), + curvature: none_if_0(app.session.config.default_curvature), alpha: 0.1, ..Default::default() }); @@ -376,7 +376,7 @@ pub fn create_dash_frontend(app: &mut AppState) -> anyhow::Result anyhow::Result, app: &mut AppState) -> anyhow::Result Positioning::Anchored, PositionMode::Static => Positioning::Static, }, - curvature: Some(0.15 * curve_scale), + alpha: app.session.config.default_opacity, + curvature: none_if_0(app.session.config.default_curvature).map(|x| x * curve_scale), transform: Affine3A::from_scale_rotation_translation( Vec3::ONE * app.session.config.default_overlay_scale * scale, Quat::IDENTITY, diff --git a/wayvr/src/overlays/whisper.rs b/wayvr/src/overlays/whisper.rs index 2f0c85db..1591b2bb 100644 --- a/wayvr/src/overlays/whisper.rs +++ b/wayvr/src/overlays/whisper.rs @@ -17,6 +17,7 @@ use wlx_common::{ use crate::{ backend::task::{OverlayTask, TaskType, ToggleMode}, + config::none_if_0, gui::{ panel::{ GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, @@ -326,7 +327,8 @@ pub fn create_whisper(app: &mut AppState) -> anyhow::Result interactable: true, grabbable: true, transform, - positioning: Positioning::Anchored, + positioning: app.session.config.default_positioning.into(), + alpha: app.session.config.default_opacity, ..OverlayWindowState::default() }, category: OverlayCategory::BuiltInPanel, diff --git a/wlx-common/src/config.rs b/wlx-common/src/config.rs index eac2c0b7..f1ced2c4 100644 --- a/wlx-common/src/config.rs +++ b/wlx-common/src/config.rs @@ -92,6 +92,28 @@ pub enum InputCaptureMethod { None, } +#[derive(Default, Clone, Copy, Serialize, Deserialize, AsRefStr, EnumString, EnumProperty, VariantArray)] +pub enum DefaultPositioning { + #[default] + #[strum(props( + Translation = "APP_SETTINGS.OPTION.ANCHORED", + Tooltip = "APP_SETTINGS.OPTION.ANCHORED_HELP" + ))] + Anchored, + + #[strum(props( + Translation = "APP_SETTINGS.OPTION.FLOATING", + Tooltip = "APP_SETTINGS.OPTION.FLOATING_HELP", + ))] + Floating, + + #[strum(props( + Translation = "APP_SETTINGS.OPTION.STATIC", + Tooltip = "APP_SETTINGS.OPTION.STATIC_HELP" + ))] + Static, +} + #[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, AsRefStr, EnumString, EnumProperty, VariantArray)] pub enum AltModifier { #[default] @@ -270,6 +292,10 @@ const fn def_point3() -> f32 { 0.3 } +const fn def_point15() -> f32 { + 0.15 +} + const fn def_osc_port() -> u16 { 9000 } @@ -530,4 +556,13 @@ pub struct GeneralConfig { #[serde(default)] pub wvr_input_capture: InputCaptureMethod, + + #[serde(default)] + pub default_positioning: DefaultPositioning, + + #[serde(default = "def_one")] + pub default_opacity: f32, + + #[serde(default = "def_point15")] + pub default_curvature: f32, } diff --git a/wlx-common/src/windowing.rs b/wlx-common/src/windowing.rs index e41bd536..71959753 100644 --- a/wlx-common/src/windowing.rs +++ b/wlx-common/src/windowing.rs @@ -1,7 +1,7 @@ use glam::Affine3A; use serde::{Deserialize, Serialize}; -use crate::common::LeftRight; +use crate::{common::LeftRight, config::DefaultPositioning}; #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)] pub enum Positioning { @@ -25,6 +25,16 @@ pub enum Positioning { }, } +impl From for Positioning { + fn from(value: DefaultPositioning) -> Self { + match value { + DefaultPositioning::Anchored => Self::Anchored, + DefaultPositioning::Floating => Self::Floating, + DefaultPositioning::Static => Self::Static, + } + } +} + impl Positioning { pub const fn get_lerp(self) -> Option { match self {