diff --git a/Cargo.lock b/Cargo.lock index ad97adda..1a3a6c1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1033,6 +1033,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "pure-rust-locales", "wasm-bindgen", "windows-link 0.2.1", ] @@ -4878,6 +4879,12 @@ dependencies = [ "syn 2.0.113", ] +[[package]] +name = "pure-rust-locales" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "869675ad2d7541aea90c6d88c81f46a7f4ea9af8cd0395d38f11a95126998a0d" + [[package]] name = "pxfm" version = "0.1.27" @@ -7378,6 +7385,7 @@ dependencies = [ "mint", "openxr", "ovr_overlay", + "pure-rust-locales", "regex", "rosc", "rust-embed", diff --git a/README.md b/README.md index 5629c1a0..811068ff 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,10 @@ Typing - While using the ORANGE laser, all keystrokes will have SHIFT applied. - Purple laser is customizable via the settings, no modifier by default. -**Modifier Keys** are sticky. They will remain pressed until a non-modifier key is pressed, the modifier gets toggled off, or the keyboard gets hidden. +**Modifier Keys are sticky**. They will remain pressed until eiter: +- a non-modifier key is pressed +- the modifier is toggled off by clicking again +- the keyboard is hidden (including via show-hide) ### Default Bindings @@ -139,11 +142,23 @@ Typing ![Touch Controller Bindings](https://github.com/wlx-team/wayvr/blob/guide/wlx-oculus.png) -To customize bindings on OpenXR, refer to the [OpenXR Bindings wiki page](https://github.com/wlx-team/wayvr/wiki/OpenXR-Bindings). -If your bindings are not supported, please reach out. \ +### Changing Bindings + +SteamVR: Simply change the bindings from the SteamVR bindings section. If WayVR doesn't show up on the list, select any other title and then press back on the top left. (SteamVR is weird like that sometimes) + +OpenXR (Monado/WiVRn): See [Wiki: OpenXR Bindings](https://github.com/wlx-team/wayvr/wiki/OpenXR-Bindings) + +If your controllers are not supported, please reach out. \ We would like to work with you and include additional bindings. +## Customization + +See these relevant wiki pages: +- For all available config options, check [Wiki: Configuration](https://github.com/wlx-team/wayvr/wiki/Configuration) +- Looking to customize look & feel, or add functionality? See [Wiki: Customization](https://github.com/wlx-team/wayvr/wiki/Customization) +- Looking to change the OpenXR background? See [Wiki: OpenXR Skybox](https://github.com/wlx-team/wayvr/wiki/OpenXR-Skybox) + ## Troubleshooting When an error is detected, we often print tips for fixing it into the log file. diff --git a/dash-frontend/assets/lang/de.json b/dash-frontend/assets/lang/de.json index 149d849a..6310d031 100644 --- a/dash-frontend/assets/lang/de.json +++ b/dash-frontend/assets/lang/de.json @@ -90,7 +90,9 @@ "BLOCK_POSES_ON_KBD_INTERACTION": "Posen beim Interagieren mit der Tastatur blockieren", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Verhindert, dass das Spiel Posen empfängt, wenn die Tastatur angefahren wird und „Spieleingabe blockieren“ aktiviert ist", "LANGUAGE": "Sprache", - "REQUIRES_RESTART": "Erfordert Neustart" + "REQUIRES_RESTART": "Erfordert Neustart", + "GRID_OPACITY": "Bodenraster-Undurchsichtigkeit", + "GRID_OPACITY_HELP": "Undurchsichtigkeit des Bodenrasters, wenn der Skybox aktiviert ist" }, "HELLO": "Hallo!", "AUDIO": { diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index b2471032..c7b4f8ea 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -107,6 +107,8 @@ "USE_PASSTHROUGH_HELP": "Allow passthrough if the XR runtime supports it", "USE_SKYBOX": "Enable skybox", "USE_SKYBOX_HELP": "Show a skybox if there's no scene app or passthrough", + "GRID_OPACITY": "Floor grid opacity", + "GRID_OPACITY_HELP": "Opacity of the floor grid when the skybox is enabled", "XR_CLICK_SENSITIVITY": "XR click sensitivity", "XR_CLICK_SENSITIVITY_HELP": "Analog trigger sensitivity", "XR_CLICK_SENSITIVITY_RELEASE": "XR release sensitivity", diff --git a/dash-frontend/assets/lang/es.json b/dash-frontend/assets/lang/es.json index b8622030..a42b8b99 100644 --- a/dash-frontend/assets/lang/es.json +++ b/dash-frontend/assets/lang/es.json @@ -90,7 +90,9 @@ "BLOCK_POSES_ON_KBD_INTERACTION": "Bloquear poses al interactuar con el teclado", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Bloquea que el juego reciba poses cuando el teclado está sobre él y 'Bloquear entrada del juego' está habilitado", "LANGUAGE": "Idioma", - "REQUIRES_RESTART": "Requiere reinicio" + "REQUIRES_RESTART": "Requiere reinicio", + "GRID_OPACITY": "Opacidad de la cuadrícula del suelo", + "GRID_OPACITY_HELP": "Opacidad de la cuadrícula del suelo cuando el skybox está habilitado" }, "HELLO": "¡Hola!", "AUDIO": { diff --git a/dash-frontend/assets/lang/it.json b/dash-frontend/assets/lang/it.json index 51ab5c4e..7e154553 100644 --- a/dash-frontend/assets/lang/it.json +++ b/dash-frontend/assets/lang/it.json @@ -111,7 +111,9 @@ "BLOCK_POSES_ON_KBD_INTERACTION": "Blocca le pose durante l'interazione con la tastiera", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Impedisce al gioco di ricevere pose quando la tastiera è evidenziata e 'Blocca input di gioco' è abilitato", "LANGUAGE": "Lingua", - "REQUIRES_RESTART": "Richiede riavvio" + "REQUIRES_RESTART": "Richiede riavvio", + "GRID_OPACITY": "Opacità della griglia del pavimento", + "GRID_OPACITY_HELP": "Opacità della griglia del pavimento quando lo skybox è abilitato" }, "APPLICATION_LAUNCHER": "Lanciatore applicazioni", "APPLICATION_STARTED": "Applicazione avviata", diff --git a/dash-frontend/assets/lang/ja.json b/dash-frontend/assets/lang/ja.json index 15322fce..4569f6a6 100644 --- a/dash-frontend/assets/lang/ja.json +++ b/dash-frontend/assets/lang/ja.json @@ -90,7 +90,9 @@ "BLOCK_POSES_ON_KBD_INTERACTION": "キーボード操作時のポーズをブロック", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "キーボードがホバーされ、「ゲーム入力をブロック」が有効になっている場合、ゲームがポーズを受信することをブロックします", "LANGUAGE": "言語", - "REQUIRES_RESTART": "再起動が必要です" + "REQUIRES_RESTART": "再起動が必要です", + "GRID_OPACITY": "フロアグリッドの不透明度", + "GRID_OPACITY_HELP": "スカイボックスが有効なときの床グリッドの不透明度" }, "HELLO": "こんにちは!", "AUDIO": { diff --git a/dash-frontend/assets/lang/pl.json b/dash-frontend/assets/lang/pl.json index 9e86daaf..250c387f 100644 --- a/dash-frontend/assets/lang/pl.json +++ b/dash-frontend/assets/lang/pl.json @@ -85,7 +85,9 @@ "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blokuje odbieranie póz przez grę, gdy kursor myszy znajduje się nad klawiaturą i włączona jest opcja 'Blokuj dane wejściowe z gry'", "LANGUAGE": "Język", "REQUIRES_RESTART": "Wymaga restartu", - "MISC": "Różne" + "MISC": "Różne", + "GRID_OPACITY": "Przezroczystość siatki podłogowej", + "GRID_OPACITY_HELP": "Przezroczystość siatki podłogowej, gdy włączony jest skybox" }, "APPLICATION_LAUNCHER": "Uruchamiacz aplikacji", "APPLICATIONS": "Aplikacje", diff --git a/dash-frontend/assets/lang/zh_CN.json b/dash-frontend/assets/lang/zh_CN.json index 81f6b04e..bde60a4e 100644 --- a/dash-frontend/assets/lang/zh_CN.json +++ b/dash-frontend/assets/lang/zh_CN.json @@ -111,7 +111,9 @@ "BLOCK_POSES_ON_KBD_INTERACTION": "与键盘交互时阻止姿势", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "当键盘悬停且启用“阻止游戏输入”时,阻止游戏接收姿势", "LANGUAGE": "语言", - "REQUIRES_RESTART": "需要重启" + "REQUIRES_RESTART": "需要重启", + "GRID_OPACITY": "地面网格不透明度", + "GRID_OPACITY_HELP": "启用天空盒时地板网格的不透明度" }, "APPLICATION_LAUNCHER": "应用启动器", "APPLICATION_STARTED": "应用已启动", diff --git a/dash-frontend/src/frontend.rs b/dash-frontend/src/frontend.rs index 3c334356..ac2000f4 100644 --- a/dash-frontend/src/frontend.rs +++ b/dash-frontend/src/frontend.rs @@ -12,6 +12,7 @@ use wgui::{ parser::{Fetchable, ParseDocumentParams, ParserState}, renderer_vk::text::custom_glyph::CustomGlyphData, task::Tasks, + theme::WguiTheme, widget::{label::WidgetLabel, rectangle::WidgetRectangle, sprite::WidgetSprite}, windowing::window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement}, }; @@ -86,6 +87,7 @@ pub struct InitParams<'a, T> { pub interface: BoxDashInterface, pub lang_provider: &'a WayVRLangProvider, pub has_monado: bool, + pub theme: Rc, } #[derive(Clone)] @@ -106,12 +108,11 @@ pub enum FrontendTask { RecenterPlayspace, PushToast(Translation), PlaySound(SoundType), - UpdateWguiDefaultsFromConfig, HideDashboard, } impl Frontend { - pub fn new(mut params: InitParams, data: &mut T) -> anyhow::Result> { + pub fn new(params: InitParams) -> anyhow::Result> { let mut assets = Box::new(assets::Asset {}); let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?; @@ -121,7 +122,6 @@ impl Frontend { let globals = WguiGlobals::new( assets, params.lang_provider, - wgui::globals::Defaults::default(), &WguiFontConfig { binaries: vec![&font_binary_regular, &font_binary_bold, &font_binary_light], family_name_sans_serif: "Quicksand", @@ -131,15 +131,16 @@ impl Frontend { PathBuf::new(), //FIXME: pass from somewhere else )?; - Frontend::update_defaults_from_config(&globals, &mut params.interface, data); - let (layout, state) = wgui::parser::new_layout_from_assets( &ParseDocumentParams { globals: globals.clone(), path: AssetPath::BuiltIn("gui/dashboard.xml"), extra: Default::default(), }, - &LayoutParams { resize_to_parent: true }, + LayoutParams { + resize_to_parent: true, + theme: params.theme, + }, )?; let id_popup_manager = state.get_widget_id("popup_manager")?; @@ -185,7 +186,6 @@ impl Frontend { // init some things first frontend.tasks.push(FrontendTask::RefreshBackground); frontend.tasks.push(FrontendTask::RefreshClock); - frontend.tasks.push(FrontendTask::UpdateWguiDefaultsFromConfig); Frontend::register_widgets(&mut frontend)?; @@ -196,16 +196,6 @@ impl Frontend { self.sounds_to_play.push(sound_type); } - fn update_defaults_from_config(globals: &WguiGlobals, interface: &mut BoxDashInterface, data: &mut T) { - let config = interface.general_config(data); - - let mut globals = globals.get(); - let defaults = &mut globals.defaults; - - defaults.animation_mult = 1.0 / config.ui_animation_speed; - defaults.gradient_intensity = config.ui_gradient_intensity; - } - fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> { let mut assets = self.globals.assets_builtin(); @@ -273,7 +263,7 @@ impl Frontend { { // always 30 times per second while self.timestep.on_tick() { - self.toast_manager.tick(&self.globals, &mut self.layout)?; + self.toast_manager.tick(&mut self.layout)?; } } @@ -374,9 +364,6 @@ impl Frontend { FrontendTask::PushToast(content) => self.toast_manager.push(content), FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type), FrontendTask::HideDashboard => self.action_hide_dashboard(params.data), - FrontendTask::UpdateWguiDefaultsFromConfig => { - Frontend::update_defaults_from_config(&self.globals, &mut self.interface, params.data) - } }; Ok(()) } diff --git a/dash-frontend/src/tab/settings.rs b/dash-frontend/src/tab/settings.rs index cdb8e97d..32a1a2c4 100644 --- a/dash-frontend/src/tab/settings.rs +++ b/dash-frontend/src/tab/settings.rs @@ -163,7 +163,7 @@ impl Tab for TabSettings { } Task::SettingUpdated(setting) => match setting { SettingType::UiAnimationSpeed | SettingType::UiGradientIntensity | SettingType::UiRoundMultiplier => { - frontend.tasks.push(FrontendTask::UpdateWguiDefaultsFromConfig); + // todo: currently, wayvr restart is required to apply these changes (WguiTheme is Rc) } _ => { /* do nothing */ } }, @@ -247,6 +247,7 @@ enum SettingType { UprightScreenFix, UsePassthrough, UseSkybox, + GridOpacity, XrClickSensitivity, XrClickSensitivityRelease, XwaylandByDefault, @@ -294,6 +295,7 @@ impl SettingType { Self::XrClickSensitivityRelease => &mut config.xr_click_sensitivity_release, Self::SpaceDragMultiplier => &mut config.space_drag_multiplier, Self::PointerLerpFactor => &mut config.pointer_lerp_factor, + Self::GridOpacity => &mut config.grid_opacity, _ => panic!("Requested f32 for non-f32 SettingType"), } } @@ -368,6 +370,7 @@ impl SettingType { Self::Clock12h => Ok("APP_SETTINGS.CLOCK_12H"), Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"), Self::FocusFollowsMouseMode => Ok("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE"), + Self::GridOpacity => Ok("APP_SETTINGS.GRID_OPACITY"), Self::HandsfreePointer => Ok("APP_SETTINGS.HANDSFREE_POINTER"), Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"), Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"), @@ -408,6 +411,7 @@ impl SettingType { Self::BlockPosesOnKbdInteraction => Some("APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP"), Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"), Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"), + Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"), Self::HandsfreePointer => Some("APP_SETTINGS.HANDSFREE_POINTER_HELP"), Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"), Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"), @@ -422,16 +426,17 @@ impl SettingType { } fn requires_restart(self) -> bool { - match self { + matches!( + self, Self::UiAnimationSpeed - | Self::UiRoundMultiplier - | Self::UprightScreenFix - | Self::DoubleCursorFix - | Self::ScreenRenderDown - | Self::Language - | Self::CaptureMethod => true, - _ => false, - } + | Self::UiRoundMultiplier + | Self::UiGradientIntensity + | Self::UprightScreenFix + | Self::DoubleCursorFix + | Self::ScreenRenderDown + | Self::Language + | Self::CaptureMethod + ) } fn get_frontend_task(self) -> Option { @@ -462,7 +467,7 @@ fn horiz_cell(layout: &mut Layout, parent: WidgetID) -> anyhow::Result fn mount_requires_restart(layout: &mut Layout, parent: WidgetID) -> anyhow::Result<()> { let content = Translation::from_translation_key("APP_SETTINGS.REQUIRES_RESTART"); let label = WidgetLabel::create( - &mut layout.state.globals.get(), + &mut layout.state, WidgetLabelParams { content, style: TextStyle { @@ -795,6 +800,7 @@ impl TabSettings { slider_f32!(mp, c, SettingType::UiRoundMultiplier, 0.5, 5.0, 0.1); checkbox!(mp, c, SettingType::SetsOnWatch); checkbox!(mp, c, SettingType::UseSkybox); + slider_f32!(mp, c, SettingType::GridOpacity, 0.0, 1.0, 0.05); // min, max, step checkbox!(mp, c, SettingType::UsePassthrough); checkbox!(mp, c, SettingType::Clock12h); } diff --git a/dash-frontend/src/util/toast_manager.rs b/dash-frontend/src/util/toast_manager.rs index b2c0f035..b5128957 100644 --- a/dash-frontend/src/util/toast_manager.rs +++ b/dash-frontend/src/util/toast_manager.rs @@ -5,7 +5,6 @@ use wgui::{ animation::{Animation, AnimationEasing}, components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR}, drawing::Color, - globals::WguiGlobals, i18n::Translation, layout::{Layout, LayoutTask, LayoutTasks, WidgetID}, renderer_vk::{ @@ -61,15 +60,7 @@ impl ToastManager { } } - fn mount_toast( - &self, - globals: &WguiGlobals, - layout: &mut Layout, - state: &mut State, - content: Translation, - ) -> anyhow::Result<()> { - let mut globals = globals.get(); - + fn mount_toast(&self, layout: &mut Layout, state: &mut State, content: Translation) -> anyhow::Result<()> { let (root, _) = layout.add_topmost_child( WidgetDiv::create(), taffy::Style { @@ -110,27 +101,24 @@ impl ToastManager { }, )?; - let (label, _) = layout.add_child( - rect.id, - WidgetLabel::create( - &mut globals, - WidgetLabelParams { - content, - style: TextStyle { - weight: Some(FontWeight::Bold), - align: Some(HorizontalAlign::Center), - wrap: true, - ..Default::default() - }, + let label = WidgetLabel::create( + &mut layout.state, + WidgetLabelParams { + content, + style: TextStyle { + weight: Some(FontWeight::Bold), + align: Some(HorizontalAlign::Center), + wrap: true, + ..Default::default() }, - ), - taffy::Style { ..Default::default() }, - )?; + }, + ); + let (label, _) = layout.add_child(rect.id, label, taffy::Style { ..Default::default() })?; // show-up animation layout.animations.add(Animation::new( rect.id, - (TOAST_DURATION_TICKS as f32 * globals.defaults.animation_mult) as u32, + (TOAST_DURATION_TICKS as f32 * layout.state.theme.animation_mult) as u32, AnimationEasing::Linear, Box::new(move |common, data| { let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0)); @@ -161,7 +149,7 @@ impl ToastManager { Ok(()) } - pub fn tick(&mut self, globals: &WguiGlobals, layout: &mut Layout) -> anyhow::Result<()> { + pub fn tick(&mut self, layout: &mut Layout) -> anyhow::Result<()> { let mut state = self.state.borrow_mut(); if state.timeout > 0 { state.timeout -= 1; @@ -176,7 +164,7 @@ impl ToastManager { state.timeout = TOAST_DURATION_TICKS; // mount next if let Some(content) = state.queue.pop_front() { - self.mount_toast(globals, layout, &mut state, content)?; + self.mount_toast(layout, &mut state, content)?; } } diff --git a/dash-frontend/src/util/wgui_simple.rs b/dash-frontend/src/util/wgui_simple.rs index b689b194..44dad5ee 100644 --- a/dash-frontend/src/util/wgui_simple.rs +++ b/dash-frontend/src/util/wgui_simple.rs @@ -8,7 +8,7 @@ use wgui::{ #[allow(dead_code)] pub fn create_label(layout: &mut Layout, parent: WidgetID, content: Translation) -> anyhow::Result<()> { let label = WidgetLabel::create( - &mut layout.state.globals.get(), + &mut layout.state, WidgetLabelParams { content, style: TextStyle { diff --git a/dash-frontend/src/views/audio_settings.rs b/dash-frontend/src/views/audio_settings.rs index 5eaa489a..f2c43f45 100644 --- a/dash-frontend/src/views/audio_settings.rs +++ b/dash-frontend/src/views/audio_settings.rs @@ -110,8 +110,7 @@ struct MultiSelectorParams<'a> { } fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> { - let globals = params.ess.layout.state.globals.clone(); - let accent_color = globals.defaults().accent_color; + let accent_color = params.ess.layout.state.theme.accent_color; for cell in params.cells { let highlighted = cell.key == params.def_cell; @@ -654,8 +653,6 @@ impl View { } fn update_button_highlights(&self, layout: &mut Layout) -> anyhow::Result<()> { - let defaults = self.globals.defaults(); - let mut c = layout.start_common(); let mut common = c.common(); @@ -667,14 +664,12 @@ impl View { }; let mut perform = |btn_num: u8, btn: &Rc| { - btn.set_color( - &mut common, - if num == btn_num { - defaults.accent_color - } else { - defaults.button_color - }, - ); + let color = if num == btn_num { + common.state.theme.accent_color + } else { + common.state.theme.button_color + }; + btn.set_color(&mut common, color); }; perform(0, &self.btn_sinks); diff --git a/dash-frontend/src/views/game_cover.rs b/dash-frontend/src/views/game_cover.rs index 07fdc478..5221ea1d 100644 --- a/dash-frontend/src/views/game_cover.rs +++ b/dash-frontend/src/views/game_cover.rs @@ -98,15 +98,9 @@ impl View { Ok(()) } - fn mount_placeholder_text( - &self, - globals: &WguiGlobals, - layout: &mut Layout, - parent: WidgetID, - text: &str, - ) -> anyhow::Result<()> { + fn mount_placeholder_text(&self, layout: &mut Layout, parent: WidgetID, text: &str) -> anyhow::Result<()> { let label = WidgetLabel::create( - &mut globals.get(), + &mut layout.state, WidgetLabelParams { content: Translation::from_raw_text(text), style: TextStyle { @@ -153,7 +147,7 @@ impl View { // mount placeholder let img = view_common.get_placeholder_image()?.clone(); self.mount_image(layout, &img)?; - self.mount_placeholder_text(&view_common.globals, layout, self.id_image_parent, &self.app_name)?; + self.mount_placeholder_text(layout, self.id_image_parent, &self.app_name)?; } else { // mount image let path = format!("app:{:?}", self.app_id); diff --git a/dash-frontend/src/views/game_list.rs b/dash-frontend/src/views/game_list.rs index 56dcac36..9946bdf6 100644 --- a/dash-frontend/src/views/game_list.rs +++ b/dash-frontend/src/views/game_list.rs @@ -256,17 +256,14 @@ impl View { )?; if let Some(text) = text.take() { - layout.add_child( - self.id_list_parent, - WidgetLabel::create( - &mut self.globals.get(), - WidgetLabelParams { - content: text, - ..Default::default() - }, - ), - Default::default(), - )?; + let label = WidgetLabel::create( + &mut layout.state, + WidgetLabelParams { + content: text, + ..Default::default() + }, + ); + layout.add_child(self.id_list_parent, label, Default::default())?; } Ok(()) diff --git a/uidev/src/testbed/testbed_any.rs b/uidev/src/testbed/testbed_any.rs index fc3a02ef..04ba5663 100644 --- a/uidev/src/testbed/testbed_any.rs +++ b/uidev/src/testbed/testbed_any.rs @@ -34,7 +34,6 @@ impl TestbedAny { let globals = WguiGlobals::new( assets, &lang_provider, - wgui::globals::Defaults::default(), &WguiFontConfig::default(), PathBuf::new(), // cwd )?; @@ -45,7 +44,7 @@ impl TestbedAny { path, extra: Default::default(), }, - &LayoutParams::default(), + LayoutParams::default(), )?; Ok(Self { layout, state }) } diff --git a/uidev/src/testbed/testbed_dashboard.rs b/uidev/src/testbed/testbed_dashboard.rs index a051ad67..c6aaba5a 100644 --- a/uidev/src/testbed/testbed_dashboard.rs +++ b/uidev/src/testbed/testbed_dashboard.rs @@ -1,6 +1,8 @@ +use std::rc::Rc; + use crate::testbed::{Testbed, TestbedUpdateParams}; use dash_frontend::frontend::{self, FrontendUpdateParams}; -use wgui::layout::Layout; +use wgui::{layout::Layout, theme::WguiTheme}; use wlx_common::{dash_interface_emulated::DashInterfaceEmulated, locale::WayVRLangProvider}; pub struct TestbedDashboard { @@ -12,14 +14,12 @@ impl TestbedDashboard { let interface = DashInterfaceEmulated::new(); let lang_provider = WayVRLangProvider::default(); - let frontend = frontend::Frontend::new( - frontend::InitParams { - interface: Box::new(interface), - has_monado: true, - lang_provider: &lang_provider, - }, - &mut (), - )?; + let frontend = frontend::Frontend::new(frontend::InitParams { + interface: Box::new(interface), + has_monado: true, + lang_provider: &lang_provider, + theme: Rc::new(WguiTheme::default()), + })?; Ok(Self { frontend }) } } diff --git a/uidev/src/testbed/testbed_generic.rs b/uidev/src/testbed/testbed_generic.rs index 6388bf5d..6f8425c6 100644 --- a/uidev/src/testbed/testbed_generic.rs +++ b/uidev/src/testbed/testbed_generic.rs @@ -21,6 +21,7 @@ use wgui::{ parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState}, taffy::{self, prelude::length}, task::Tasks, + theme::WguiTheme, widget::{div::WidgetDiv, label::WidgetLabel, rectangle::WidgetRectangle}, windowing::{ context_menu::{self, TickResult}, @@ -91,7 +92,6 @@ impl TestbedGeneric { let globals = WguiGlobals::new( assets, &lang_provider, - wgui::globals::Defaults::default(), &WguiFontConfig::default(), PathBuf::new(), // cwd )?; @@ -125,8 +125,9 @@ impl TestbedGeneric { let (layout, parser_state) = wgui::parser::new_layout_from_assets( &TestbedGeneric::doc_params(&globals, extra), - &LayoutParams { + LayoutParams { resize_to_parent: true, + theme: Rc::new(WguiTheme::default()), }, )?; diff --git a/wayvr-ipc/README.md b/wayvr-ipc/README.md index 30d33c73..776c16bc 100644 --- a/wayvr-ipc/README.md +++ b/wayvr-ipc/README.md @@ -2,7 +2,7 @@ This repository contains the IPC specification and client implementation for the WayVR protocol. The primary purpose is to enable communication between applications and the WayVR server, offering a range of API functions. -[WayVR Server README](https://github.com/galister/wlx-overlay-s/tree/main/contrib/wayvr) +[WayVR Server README](https://github.com/wlx-team/wayvr/tree/main/wayvr/contrib/wayvr) ## Usage diff --git a/wayvr/Cargo.toml b/wayvr/Cargo.toml index b225972d..807528c9 100644 --- a/wayvr/Cargo.toml +++ b/wayvr/Cargo.toml @@ -44,7 +44,8 @@ xdg.workspace = true ash = "^0.38.0" # must match vulkano bytes = { version = "1.11.1" } -chrono = "0.4.42" +chrono = { version = "0.4.42", features = [ "unstable-locales"]} +pure-rust-locales = "0.8.2" chrono-tz = "0.10.4" config = "0.15.19" dbus = { version = "0.9.9" } diff --git a/wayvr/src/backend/openxr/helpers.rs b/wayvr/src/backend/openxr/helpers.rs index 722e25c8..48cd2054 100644 --- a/wayvr/src/backend/openxr/helpers.rs +++ b/wayvr/src/backend/openxr/helpers.rs @@ -3,6 +3,18 @@ use glam::{Affine3A, Quat, Vec3, Vec3A}; use openxr::{self as xr, SessionCreateFlags, Version, sys::Handle}; use xr::OverlaySessionCreateFlagsEXTX; +macro_rules! next_chain_insert { + ($layer:expr, $payload:expr) => {{ + let payload_ptr = $payload.as_mut() as *mut _ as *mut xr::sys::BaseInStructure; + let new_elem = payload_ptr.as_mut().unwrap(); + let mut raw = $layer.into_raw(); + new_elem.next = raw.next as _; + raw.next = payload_ptr as *const _; + raw + }}; +} +pub(crate) use next_chain_insert; + pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> { let entry = xr::Entry::linked(); diff --git a/wayvr/src/backend/openxr/openxr_actions.json5 b/wayvr/src/backend/openxr/openxr_actions.json5 index 30574e0a..53467d7c 100644 --- a/wayvr/src/backend/openxr/openxr_actions.json5 +++ b/wayvr/src/backend/openxr/openxr_actions.json5 @@ -214,8 +214,11 @@ left: "/user/hand/left/input/trackpad/x", right: "/user/hand/right/input/trackpad/x" }, + toggle_dashboard: { + right: "/user/hand/right/input/system/click", + }, show_hide: { - left: "/user/hand/left/input/menu/click", + left: "/user/hand/left/input/system/click", }, space_drag: { right: "/user/hand/right/input/menu/click", diff --git a/wayvr/src/backend/openxr/overlay.rs b/wayvr/src/backend/openxr/overlay.rs index ff02dad9..b4404e86 100644 --- a/wayvr/src/backend/openxr/overlay.rs +++ b/wayvr/src/backend/openxr/overlay.rs @@ -6,7 +6,10 @@ use xr::EyeVisibility; use super::{CompositionLayer, XrState, helpers, swapchain::WlxSwapchain}; use crate::{ - backend::openxr::swapchain::{SwapchainOpts, WlxSwapchainImage, create_swapchain}, + backend::openxr::{ + helpers::next_chain_insert, + swapchain::{SwapchainOpts, WlxSwapchainImage, create_swapchain}, + }, state::AppState, windowing::window::OverlayWindowData, }; @@ -20,17 +23,6 @@ pub struct OpenXrOverlayData { color_bias_khr: Option>, } -macro_rules! next_chain_insert { - ($layer:expr, $payload:expr) => {{ - let payload_ptr = $payload.as_mut() as *mut _ as *mut xr::sys::BaseInStructure; - let new_elem = payload_ptr.as_mut().unwrap(); - let mut raw = $layer.into_raw(); - new_elem.next = raw.next as _; - raw.next = payload_ptr as *const _; - raw - }}; -} - impl OverlayWindowData { pub(super) fn ensure_swapchain_acquire<'a>( &'a mut self, diff --git a/wayvr/src/backend/openxr/skybox.rs b/wayvr/src/backend/openxr/skybox.rs index 804a2ede..de010956 100644 --- a/wayvr/src/backend/openxr/skybox.rs +++ b/wayvr/src/backend/openxr/skybox.rs @@ -1,8 +1,4 @@ -use std::{ - f32::consts::PI, - fs::File, - sync::{Arc, LazyLock}, -}; +use std::{f32::consts::PI, fs::File, sync::Arc}; use glam::{Quat, Vec3A}; use openxr as xr; @@ -14,7 +10,10 @@ use wgui::gfx::{cmd::WGfxClearMode, pipeline::WPipelineCreateInfo}; use wlx_common::config_io; use crate::{ - backend::openxr::{helpers::translation_rotation_to_posef, swapchain::SwapchainOpts}, + backend::openxr::{ + helpers::{next_chain_insert, translation_rotation_to_posef}, + swapchain::SwapchainOpts, + }, graphics::{ExtentExt, GpuFutures, dds::WlxCommandBufferDds}, state::AppState, }; @@ -28,10 +27,12 @@ pub(super) struct Skybox { view: Arc, sky: Option, grid: Option, + grid_pose: xr::Posef, + grid_color_scale_bias_khr: Option>, } impl Skybox { - pub fn new(app: &AppState) -> anyhow::Result { + pub fn new(xr: &XrState, app: &AppState) -> anyhow::Result { let mut command_buffer = app .gfx .create_xfer_command_buffer(CommandBufferUsage::OneTimeSubmit)?; @@ -74,10 +75,30 @@ impl Skybox { let view = ImageView::new_default(maybe_image.unwrap())?; // safe unwrap + let grid_color_scale_bias_khr = xr + .instance + .exts() + .khr_composition_layer_color_scale_bias + .map(|_| { + Box::new(xr::sys::CompositionLayerColorScaleBiasKHR { + ty: xr::StructureType::COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR, + next: std::ptr::null(), + color_bias: Default::default(), + color_scale: xr::Color4f { + r: 1.0, + g: 1.0, + b: 1.0, + a: 1.0, + }, + }) + }); + Ok(Self { view, sky: None, grid: None, + grid_pose: translation_rotation_to_posef(Vec3A::ZERO, Quat::from_rotation_x(PI * -0.5)), + grid_color_scale_bias_khr: grid_color_scale_bias_khr, }) } @@ -205,10 +226,6 @@ impl Skybox { const HI_VERT_ANGLE: f32 = 0.5 * PI; const LO_VERT_ANGLE: f32 = -0.5 * PI; - static GRID_POSE: LazyLock = LazyLock::new(|| { - translation_rotation_to_posef(Vec3A::ZERO, Quat::from_rotation_x(PI * -0.5)) - }); - let pose = xr::Posef { orientation: xr::Quaternionf::IDENTITY, position: xr::Vector3f { @@ -232,9 +249,12 @@ impl Skybox { .lower_vertical_angle(LO_VERT_ANGLE); self.grid.as_mut().unwrap().ensure_image_released()?; - let grid = xr::CompositionLayerQuad::new() - .layer_flags(xr::CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA) - .pose(*GRID_POSE) + + let flags = xr::CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA + | xr::CompositionLayerFlags::UNPREMULTIPLIED_ALPHA; + let mut grid = xr::CompositionLayerQuad::new() + .layer_flags(flags) + .pose(self.grid_pose) .size(xr::Extent2Df { width: 10.0, height: 10.0, @@ -243,6 +263,15 @@ impl Skybox { .eye_visibility(xr::EyeVisibility::BOTH) .space(&xr.stage); + if let Some(grid_color_scale_bias_khr) = self.grid_color_scale_bias_khr.as_mut() { + let grid_opacity = app.session.config.grid_opacity; + grid_color_scale_bias_khr.color_scale.a = (grid_opacity * grid_opacity).clamp(0.0, 1.0); + unsafe { + let raw = next_chain_insert!(grid, grid_color_scale_bias_khr); + grid = xr::CompositionLayerQuad::from_raw(raw); + } + } + Ok(vec![ CompositionLayer::Equirect2(sky), CompositionLayer::Quad(grid), @@ -254,5 +283,5 @@ pub(super) fn create_skybox(xr: &XrState, app: &AppState) -> Option { xr.instance .exts() .khr_composition_layer_equirect2 - .and_then(|_| Skybox::new(app).ok()) + .and_then(|_| Skybox::new(xr, app).ok()) } diff --git a/wayvr/src/config.rs b/wayvr/src/config.rs index 2a797e1c..94b4d2e2 100644 --- a/wayvr/src/config.rs +++ b/wayvr/src/config.rs @@ -130,6 +130,7 @@ pub struct AutoSettings { pub block_poses_on_kbd_interaction: bool, pub space_drag_multiplier: f32, pub use_skybox: bool, + pub grid_opacity: f32, pub use_passthrough: bool, pub screen_render_down: bool, pub pointer_lerp_factor: f32, @@ -180,6 +181,7 @@ pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> { block_poses_on_kbd_interaction: config.block_poses_on_kbd_interaction, space_drag_multiplier: config.space_drag_multiplier, use_skybox: config.use_skybox, + grid_opacity: config.grid_opacity, use_passthrough: config.use_passthrough, screen_render_down: config.screen_render_down, pointer_lerp_factor: config.pointer_lerp_factor, diff --git a/wayvr/src/gui/panel/label.rs b/wayvr/src/gui/panel/label.rs index c281619e..dd785c52 100644 --- a/wayvr/src/gui/panel/label.rs +++ b/wayvr/src/gui/panel/label.rs @@ -130,6 +130,14 @@ pub(super) fn setup_custom_label( .ok() }), format: format.into(), + locale: { + let i18n = app.wgui_globals.i18n(); + let locale = i18n.get_locale(); + match pure_rust_locales::Locale::try_from(locale.to_string().as_str()) { + Ok(loc) => loc, + Err(_) => pure_rust_locales::Locale::en_US, + } + }, }; Box::new(move |common, data, _, _| { @@ -213,6 +221,7 @@ fn battery_on_tick( struct ClockLabelState { timezone: Option, format: Rc, + locale: chrono::Locale, } fn clock_on_tick( @@ -221,8 +230,20 @@ fn clock_on_tick( data: &mut event::CallbackData, ) { let date_time = state.timezone.as_ref().map_or_else( - || format!("{}", Local::now().format(&state.format)), - |tz| format!("{}", Local::now().with_timezone(tz).format(&state.format)), + || { + format!( + "{}", + Local::now().format_localized(&state.format, state.locale) + ) + }, + |tz| { + format!( + "{}", + Local::now() + .with_timezone(tz) + .format_localized(&state.format, state.locale) + ) + }, ); let label = data.obj.get_as_mut::().unwrap(); diff --git a/wayvr/src/gui/panel/mod.rs b/wayvr/src/gui/panel/mod.rs index 3bb15adf..dc170904 100644 --- a/wayvr/src/gui/panel/mod.rs +++ b/wayvr/src/gui/panel/mod.rs @@ -147,8 +147,9 @@ impl GuiPanel { let (mut layout, mut parser_state) = wgui::parser::new_layout_from_assets( &doc_params, - &LayoutParams { + LayoutParams { resize_to_parent: params.resize_to_parent, + theme: app.wgui_theme.clone(), }, )?; diff --git a/wayvr/src/overlays/dashboard.rs b/wayvr/src/overlays/dashboard.rs index 1fc4b4db..48e9ef07 100644 --- a/wayvr/src/overlays/dashboard.rs +++ b/wayvr/src/overlays/dashboard.rs @@ -77,14 +77,12 @@ impl DashFrontend { let _ = interface.process_launch(app, false, p)?; } - let frontend = frontend::Frontend::new( - frontend::InitParams { - interface: Box::new(interface), - lang_provider: &WayVRLangProvider::from_config(&app.session.config), - has_monado: matches!(app.xr_backend, XrBackend::OpenXR), - }, - app, - )?; + let frontend = frontend::Frontend::new(frontend::InitParams { + interface: Box::new(interface), + lang_provider: &WayVRLangProvider::from_config(&app.session.config), + has_monado: matches!(app.xr_backend, XrBackend::OpenXR), + theme: app.wgui_theme.clone(), + })?; frontend .tasks diff --git a/wayvr/src/overlays/edit/lock.rs b/wayvr/src/overlays/edit/lock.rs index 2732cbb0..3edfd528 100644 --- a/wayvr/src/overlays/edit/lock.rs +++ b/wayvr/src/overlays/edit/lock.rs @@ -11,7 +11,7 @@ use wgui::{ widget::rectangle::WidgetRectangle, }; -use crate::{backend::task::ModifyOverlayTask, overlays::edit::EditModeWrapPanel, state::AppState}; +use crate::{backend::task::ModifyOverlayTask, overlays::edit::EditModeWrapPanel}; #[derive(Default)] pub(super) struct InteractLockHandler { @@ -53,21 +53,18 @@ impl InteractLockHandler { button.set_sticky_state(common, !interactable); } - let globals = common.state.globals.get(); if interactable { - set_anim_color(&mut rect, 0.0, self.color, globals.defaults.danger_color); + set_anim_color(&mut rect, 0.0, self.color, common.state.theme.danger_color); } else { - set_anim_color(&mut rect, 0.2, self.color, globals.defaults.danger_color); + set_anim_color(&mut rect, 0.2, self.color, common.state.theme.danger_color); } } pub fn toggle( &mut self, common: &mut CallbackDataCommon, - app: &mut AppState, anim_mult: f32, ) -> Box { - let defaults = app.wgui_globals.defaults().clone(); let rect_color = self.color; self.interactable = !self.interactable; @@ -86,7 +83,7 @@ impl InteractLockHandler { rect, 0.2 - (data.pos * 0.2), rect_color, - defaults.danger_color, + common.state.theme.danger_color, ); common.alterables.mark_redraw(); }), @@ -98,7 +95,12 @@ impl InteractLockHandler { AnimationEasing::OutBack, Box::new(move |common, data| { let rect = data.obj.get_as_mut::().unwrap(); - set_anim_color(rect, data.pos * 0.2, rect_color, defaults.danger_color); + set_anim_color( + rect, + data.pos * 0.2, + rect_color, + common.state.theme.danger_color, + ); common.alterables.mark_redraw(); }), ) diff --git a/wayvr/src/overlays/edit/mod.rs b/wayvr/src/overlays/edit/mod.rs index 78db7089..7eddf592 100644 --- a/wayvr/src/overlays/edit/mod.rs +++ b/wayvr/src/overlays/edit/mod.rs @@ -272,7 +272,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result { mouse: SpriteTabHandler::default(), }; - let anim_mult = app.wgui_globals.defaults().animation_mult; + let anim_mult = app.wgui_theme.animation_mult; let on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, parser, attribs, _app| { let Ok(button) = @@ -302,7 +302,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result { } let sel = OverlaySelector::Id(*state.id.borrow()); - let task = state.lock.toggle(common, app, anim_mult); + let task = state.lock.toggle(common, anim_mult); app.tasks .enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task))); Ok(EventResult::Consumed) diff --git a/wayvr/src/overlays/keyboard/builder.rs b/wayvr/src/overlays/keyboard/builder.rs index 2094836c..fad16dca 100644 --- a/wayvr/src/overlays/keyboard/builder.rs +++ b/wayvr/src/overlays/keyboard/builder.rs @@ -51,11 +51,9 @@ pub(super) fn create_keyboard_panel( let doc_params = new_doc_params(&mut panel); - let globals = app.wgui_globals.clone(); - let (accent_color, anim_mult) = { - let def = globals.defaults(); - (def.accent_color, def.animation_mult) + let theme = &app.wgui_theme; + (theme.accent_color, theme.animation_mult) }; let root = panel diff --git a/wayvr/src/res/config.yaml b/wayvr/src/res/config.yaml index 76064afd..55747a09 100644 --- a/wayvr/src/res/config.yaml +++ b/wayvr/src/res/config.yaml @@ -125,6 +125,9 @@ ## If disabled, there will be no background rendered (solid black). #use_skybox: true +## Monado/WiVRn only. Opacity of the floor grid if use_skybox is enabled. +#grid_opacity: true + ## Hide the help popup that appears on your hand while grabbing an overlay #hide_grab_help: false diff --git a/wayvr/src/shaders/grid.frag b/wayvr/src/shaders/grid.frag index f2250645..467aec41 100644 --- a/wayvr/src/shaders/grid.frag +++ b/wayvr/src/shaders/grid.frag @@ -16,4 +16,3 @@ void main() } out_color = vec4(1.0, 1.0, 1.0, grid * fade); } - diff --git a/wayvr/src/state.rs b/wayvr/src/state.rs index 0547549e..59146f36 100644 --- a/wayvr/src/state.rs +++ b/wayvr/src/state.rs @@ -1,8 +1,10 @@ use glam::Affine3A; use idmap::IdMap; use smallvec::{SmallVec, smallvec}; +use std::rc::Rc; use std::sync::Arc; use wgui::log::LogErr; +use wgui::theme::WguiTheme; use wgui::{ drawing, font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals, parser::parse_color_hex, renderer_vk::context::SharedContext as WSharedContext, @@ -48,6 +50,7 @@ pub struct AppState { pub anchor_grabbed: bool, pub wgui_globals: WguiGlobals, + pub wgui_theme: Rc, pub dbus: DbusConnector, @@ -90,7 +93,7 @@ impl AppState { let osc_sender = crate::subsystem::osc::OscSender::new(session.config.osc_out_port).ok(); let wgui_shared = WSharedContext::new(gfx.clone())?; - let theme = session.config.theme_path.clone(); + let theme_path = session.config.theme_path.clone(); let mut audio_sample_player = audio::SamplePlayer::new(); audio_sample_player.register_sample( @@ -112,7 +115,7 @@ impl AppState { let mut assets = Box::new(gui::asset::GuiAsset {}); audio_sample_player.register_wgui_samples(assets.as_mut())?; - let mut defaults = wgui::globals::Defaults::default(); + let mut theme = WguiTheme::default(); { #[allow(clippy::ref_option)] @@ -122,15 +125,15 @@ impl AppState { } } - apply_color(&mut defaults.text_color, &session.config.color_text); - apply_color(&mut defaults.accent_color, &session.config.color_accent); - apply_color(&mut defaults.danger_color, &session.config.color_danger); - apply_color(&mut defaults.faded_color, &session.config.color_faded); - apply_color(&mut defaults.bg_color, &session.config.color_background); + apply_color(&mut theme.text_color, &session.config.color_text); + apply_color(&mut theme.accent_color, &session.config.color_accent); + apply_color(&mut theme.danger_color, &session.config.color_danger); + apply_color(&mut theme.faded_color, &session.config.color_faded); + apply_color(&mut theme.bg_color, &session.config.color_background); } - defaults.animation_mult = 1. / session.config.ui_animation_speed; - defaults.rounding_mult = session.config.ui_round_multiplier; + theme.animation_mult = 1. / session.config.ui_animation_speed; + theme.rounding_mult = session.config.ui_round_multiplier; let dbus = DbusConnector::default(); @@ -157,10 +160,10 @@ impl AppState { wgui_globals: WguiGlobals::new( assets, &lang_provider, - defaults, &WguiFontConfig::default(), - get_config_file_path(&theme), + get_config_file_path(&theme_path), )?, + wgui_theme: Rc::new(theme), dbus, xr_backend, ipc_server, diff --git a/wgui/doc/widgets.md b/wgui/doc/widgets.md index 655a047f..4878f2cc 100644 --- a/wgui/doc/widgets.md +++ b/wgui/doc/widgets.md @@ -60,7 +60,7 @@ _They can be used in any widget/component._ `width`, `height`: **float** | **percent** -### Advanced attributes +## Advanced attributes `interactable`: "1" | "0" @@ -74,6 +74,32 @@ _Used in case of overlapping pop-ups or windows, most notably applied to various _Set to 1 if you want to render overlapping pop-ups to properly render your widgets in order. Wgui renders with as few Vulkan drawcalls as possible, so this is your responsibility._ +## Default Colors + +_These colors can be defined by the user to control the color scheme. They always exists and can be used in any place a normal color could be used._ + +`~color_text`: default: white(#FFFFFF) +`~color_accent`: default: light blue(#21ADFF) +`~color_danger`: default: red(#E60000) +`~color_faded`: default: grey(#ABBDCC) +`~color_bg`: default: black(#00121ABF) (color_background in config) + +_Only the default colors can be changed with the following suffixes._ + +`_translucent` + +_Halves the alpha of the color._ + +`_10` +`_20` +`_30` +`_40` +`_50` + +_Darkens the color by multiplying it with a percentage. `~color_accent_50` Would be half of the normal brightness but the same alpha. You can't combine the suffixes_ + +### Color + # Widgets ## div widget diff --git a/wgui/src/components/button.rs b/wgui/src/components/button.rs index 0243c7e1..b782c280 100644 --- a/wgui/src/components/button.rs +++ b/wgui/src/components/button.rs @@ -157,7 +157,7 @@ impl ComponentButton { } pub fn set_color(&self, common: &mut CallbackDataCommon, color: Color) { - let gradient_intensity = common.defaults().gradient_intensity; + let gradient_intensity = common.state.theme.gradient_intensity; let Some(mut rect) = common.state.widgets.get_as::(self.data.id_rect) else { return; @@ -194,8 +194,8 @@ impl ComponentButton { } let (anim_mult, gradient_intensity) = { - let defaults = common.state.globals.defaults(); - (defaults.animation_mult, defaults.gradient_intensity) + let theme = &common.state.theme; + (theme.animation_mult, theme.gradient_intensity) }; let anim_ticks = if sticky_down { 5. } else { 10. }; @@ -247,7 +247,7 @@ fn anim_hover( let bgcolor = init_color.lerp(&colors.hover_color, mult); - let gradient_intensity = common.globals().defaults.gradient_intensity; + let gradient_intensity = common.state.theme.gradient_intensity; //let t = Mat4::from_scale(Vec3::splat(1.0 + pos * 0.5)) * Mat4::from_rotation_z(pos * 1.0); @@ -416,8 +416,8 @@ fn register_event_mouse_release( } pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Result<(WidgetPair, Rc)> { - let globals = ess.layout.state.globals.clone(); let mut style = params.style; + let theme = &ess.layout.state.theme; // force-override style style.align_items = Some(AlignItems::Center); @@ -431,7 +431,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul let color = if let Some(color) = params.color { color } else { - globals.defaults().button_color + theme.button_color }; let border_color = if let Some(border_color) = params.border_color { @@ -452,7 +452,12 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul Color::new(color.r + 0.5, color.g + 0.5, color.g + 0.5, color.a + 0.5) }; - let gradient_intensity = ess.layout.state.globals.defaults().gradient_intensity; + let gradient_intensity = theme.gradient_intensity; + + let light_text = { + let mult = if theme.dark_mode { color.a } else { 1.0 - color.a }; + (color.r + color.g + color.b) * mult < 1.5 + }; let (root, _) = ess.layout.add_child( ess.parent, @@ -469,15 +474,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul let id_rect = root.id; - let light_text = { - let mult = if globals.defaults().dark_mode { - color.a - } else { - 1.0 - color.a - }; - (color.r + color.g + color.b) * mult < 1.5 - }; - let default_margin = taffy::Rect { top: length(4.0), bottom: length(4.0), @@ -487,7 +483,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul if let Some(sprite_path) = params.sprite_src { let sprite = WidgetSprite::create(WidgetSpriteParams { - glyph_data: Some(CustomGlyphData::from_assets(&globals, sprite_path)?), + glyph_data: Some(CustomGlyphData::from_assets(&ess.layout.state.globals, sprite_path)?), ..Default::default() }); @@ -506,23 +502,25 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul } let id_label = if let Some(content) = params.text { + let widget_label = WidgetLabel::create( + &mut ess.layout.state, + WidgetLabelParams { + content, + style: TextStyle { + weight: Some(FontWeight::Bold), + color: Some(if light_text { + Color::new(1.0, 1.0, 1.0, 1.0) + } else { + Color::new(0.0, 0.0, 0.0, 1.0) + }), + ..params.text_style + }, + }, + ); + let (label, _node_label) = ess.layout.add_child( id_rect, - WidgetLabel::create( - &mut globals.get(), - WidgetLabelParams { - content, - style: TextStyle { - weight: Some(FontWeight::Bold), - color: Some(if light_text { - Color::new(1.0, 1.0, 1.0, 1.0) - } else { - Color::new(0.0, 0.0, 0.0, 1.0) - }), - ..params.text_style - }, - }, - ), + widget_label, taffy::Style { margin: default_margin, ..Default::default() @@ -558,7 +556,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul id: root.id, lhandles: { let listeners = &mut root.widget.state().event_listeners; - let anim_mult = ess.layout.state.globals.defaults().animation_mult; + let anim_mult = ess.layout.state.theme.animation_mult; vec![ register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip, anim_mult), register_event_mouse_leave(state.clone(), listeners, anim_mult), diff --git a/wgui/src/components/checkbox.rs b/wgui/src/components/checkbox.rs index 1d48167f..68dff648 100644 --- a/wgui/src/components/checkbox.rs +++ b/wgui/src/components/checkbox.rs @@ -343,8 +343,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul (WLength::Units(5.0), WLength::Units(8.0)) }; - let globals = ess.layout.state.globals.clone(); - let (root, _) = ess.layout.add_child( ess.parent, WidgetRectangle::create(WidgetRectangleParams { @@ -397,20 +395,17 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul }, )?; - let (label, _node_label) = ess.layout.add_child( - id_container, - WidgetLabel::create( - &mut globals.get(), - WidgetLabelParams { - content: params.text, - style: TextStyle { - weight: Some(FontWeight::Bold), - ..Default::default() - }, + let widget_label = WidgetLabel::create( + &mut ess.layout.state, + WidgetLabelParams { + content: params.text, + style: TextStyle { + weight: Some(FontWeight::Bold), + ..Default::default() }, - ), - Default::default(), - )?; + }, + ); + let (label, _node_label) = ess.layout.add_child(id_container, widget_label, Default::default())?; let data = Rc::new(Data { id_container, @@ -433,7 +428,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul id: root.id, lhandles: { let listeners = &mut root.widget.state().event_listeners; - let anim_mult = ess.layout.state.globals.defaults().animation_mult; + let anim_mult = ess.layout.state.theme.animation_mult; vec![ register_event_mouse_enter(state.clone(), listeners, params.tooltip, anim_mult), register_event_mouse_leave(state.clone(), listeners, anim_mult), diff --git a/wgui/src/components/editbox.rs b/wgui/src/components/editbox.rs index a1e5454e..7dff8cb5 100644 --- a/wgui/src/components/editbox.rs +++ b/wgui/src/components/editbox.rs @@ -99,11 +99,10 @@ fn anim_bottom_rect( } fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State) -> Option<()> { - let defaults = common.defaults(); - let editbox_color = defaults.editbox_color; - let anim_mult = defaults.animation_mult; - let accent_color = defaults.accent_color; - drop(defaults); + let theme = &common.state.theme; + let editbox_color = theme.editbox_color; + let anim_mult = theme.animation_mult; + let accent_color = theme.accent_color; let (rect_color, border_color) = if state.focused { (editbox_color.add_rgb(0.15), editbox_color.add_rgb(0.15 + 0.25)) @@ -279,10 +278,7 @@ pub fn construct( ess: &mut ConstructEssentials, mut params: Params, ) -> anyhow::Result<(WidgetPair, Rc)> { - let globals = ess.layout.state.globals.clone(); - let defaults = globals.defaults(); - let text_color = defaults.text_color; - drop(defaults); + let text_color = ess.layout.state.theme.text_color; if params.style.size.width.is_auto() { params.style.size.width = length(128.0); @@ -345,22 +341,23 @@ pub fn construct( }, )?; + let widget_label = WidgetLabel::create( + &mut ess.layout.state, + WidgetLabelParams { + content: Translation::from_raw_text(¶ms.initial_text), + style: TextStyle { + shadow: Some(TextShadow { + x: 1.0, + y: 1.0, + color: Color::new(0.0, 0.0, 0.0, 1.0), + }), + ..Default::default() + }, + }, + ); let (label, _node_label) = ess.layout.add_child( label_parent.id, - WidgetLabel::create( - &mut globals.get(), - WidgetLabelParams { - content: Translation::from_raw_text(¶ms.initial_text), - style: TextStyle { - shadow: Some(TextShadow { - x: 1.0, - y: 1.0, - color: Color::new(0.0, 0.0, 0.0, 1.0), - }), - ..Default::default() - }, - }, - ), + widget_label, taffy::Style { position: taffy::Position::Relative, ..Default::default() diff --git a/wgui/src/components/slider.rs b/wgui/src/components/slider.rs index 28d74e58..af94d3ec 100644 --- a/wgui/src/components/slider.rs +++ b/wgui/src/components/slider.rs @@ -498,26 +498,20 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul active_tooltip: None, }; - let globals = ess.layout.state.globals.clone(); - let slider_text: Option<(WidgetPair, taffy::NodeId)> = if params.show_value { - let pair = ess.layout.add_child( - slider_handle.id, - WidgetLabel::create( - &mut globals.get(), - WidgetLabelParams { - content: Translation::default(), - style: TextStyle { - color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0)), // always black - weight: Some(FontWeight::Bold), - align: Some(HorizontalAlign::Center), - ..Default::default() - }, + let label = WidgetLabel::create( + &mut ess.layout.state, + WidgetLabelParams { + content: Translation::default(), + style: TextStyle { + color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0)), // always black + weight: Some(FontWeight::Bold), + align: Some(HorizontalAlign::Center), + ..Default::default() }, - ), - Default::default(), - )?; - Some(pair) + }, + ); + Some(ess.layout.add_child(slider_handle.id, label, Default::default())?) } else { None }; @@ -535,7 +529,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul id: root.id, lhandles: { let listeners = &mut root.widget.state().event_listeners; - let anim_mult = ess.layout.state.globals.defaults().animation_mult; + let anim_mult = ess.layout.state.theme.animation_mult; vec![ register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip, anim_mult), register_event_mouse_leave(data.clone(), state.clone(), listeners, anim_mult), diff --git a/wgui/src/components/tabs.rs b/wgui/src/components/tabs.rs index b680d491..521fb842 100644 --- a/wgui/src/components/tabs.rs +++ b/wgui/src/components/tabs.rs @@ -67,8 +67,8 @@ impl ComponentTrait for ComponentTabs { impl State { fn select_entry(&mut self, common: &mut CallbackDataCommon, name: &Rc) { let (color_accent, color_button) = { - let def = common.state.globals.defaults(); - (def.accent_color, def.button_color) + let theme = &common.state.theme; + (theme.accent_color, theme.button_color) }; for entry in &self.mounted_entries { diff --git a/wgui/src/components/tooltip.rs b/wgui/src/components/tooltip.rs index 4f9b40f3..05648ae5 100644 --- a/wgui/src/components/tooltip.rs +++ b/wgui/src/components/tooltip.rs @@ -163,8 +163,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul ), }; - let globals = ess.layout.state.globals.clone(); - let (div, _) = ess.layout.add_child( ess.parent, WidgetDiv::create(), @@ -211,20 +209,17 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul }, )?; - let (label, _) = ess.layout.add_child( - rect.id, - WidgetLabel::create( - &mut globals.get(), - WidgetLabelParams { - content: params.info.text, - style: TextStyle { - weight: Some(FontWeight::Bold), - ..Default::default() - }, + let label = WidgetLabel::create( + &mut ess.layout.state, + WidgetLabelParams { + content: params.info.text, + style: TextStyle { + weight: Some(FontWeight::Bold), + ..Default::default() }, - ), - Default::default(), - )?; + }, + ); + let (label, _) = ess.layout.add_child(rect.id, label, Default::default())?; let data = Rc::new(Data { id_root: div.id }); @@ -246,7 +241,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul TooltipSide::Bottom => Vec2::new(0.0, 1.0), }; - let anim_mult = ess.layout.state.globals.defaults().animation_mult; + let anim_mult = ess.layout.state.theme.animation_mult; ess.layout.animations.add(Animation::new( rect.id, (10.0 * anim_mult) as u32, diff --git a/wgui/src/event.rs b/wgui/src/event.rs index 244471c8..83e2c921 100644 --- a/wgui/src/event.rs +++ b/wgui/src/event.rs @@ -1,6 +1,6 @@ use std::{ any::{Any, TypeId}, - cell::{Ref, RefMut}, + cell::RefMut, collections::HashSet, rc::{Rc, Weak}, }; @@ -181,10 +181,6 @@ impl CallbackDataCommon<'_> { pub fn globals(&self) -> RefMut<'_, globals::Globals> { self.state.globals.get() } - - pub fn defaults(&self) -> Ref<'_, globals::Defaults> { - self.state.globals.defaults() - } } pub struct CallbackData<'a> { diff --git a/wgui/src/globals.rs b/wgui/src/globals.rs index 47cb4325..e1a54333 100644 --- a/wgui/src/globals.rs +++ b/wgui/src/globals.rs @@ -1,5 +1,5 @@ use std::{ - cell::{Ref, RefCell, RefMut}, + cell::{RefCell, RefMut}, io::Read, path::PathBuf, rc::Rc, @@ -11,53 +11,17 @@ use regex::Regex; use crate::{ assets::{AssetPath, AssetProvider, LangProvider}, - assets_internal, drawing, + assets_internal, font_config::{WguiFontConfig, WguiFontSystem}, i18n::I18n, renderer_vk::text::custom_glyph::CustomGlyphCache, }; -#[derive(Clone)] -pub struct Defaults { - pub dark_mode: bool, - pub text_color: drawing::Color, - pub button_color: drawing::Color, - pub accent_color: drawing::Color, - pub danger_color: drawing::Color, - pub faded_color: drawing::Color, - pub bg_color: drawing::Color, - pub editbox_color: drawing::Color, - pub translucent_alpha: f32, - pub animation_mult: f32, - pub rounding_mult: f32, - pub gradient_intensity: f32, // currently used for buttons -} - -impl Default for Defaults { - fn default() -> Self { - Self { - dark_mode: true, - text_color: drawing::Color::new(1.0, 1.0, 1.0, 1.0), - button_color: drawing::Color::new(1.0, 1.0, 1.0, 0.02), - accent_color: drawing::Color::new(0.13, 0.68, 1.0, 1.0), - danger_color: drawing::Color::new(0.9, 0.0, 0.0, 1.0), - faded_color: drawing::Color::new(0.67, 0.74, 0.80, 1.0), - bg_color: drawing::Color::new(0.0, 0.07, 0.1, 0.75), - editbox_color: drawing::Color::new(0.15, 0.25, 0.35, 0.95), - translucent_alpha: 0.5, - animation_mult: 1.0, - rounding_mult: 1.0, - gradient_intensity: 0.3, - } - } -} - pub struct Globals { pub assets_internal: Box, pub assets_builtin: Box, pub asset_folder: PathBuf, pub i18n_builtin: I18n, - pub defaults: Defaults, pub font_system: WguiFontSystem, pub custom_glyph_cache: CustomGlyphCache, } @@ -69,7 +33,6 @@ impl WguiGlobals { pub fn new( mut assets_builtin: Box, lang_provider: &dyn LangProvider, - defaults: Defaults, font_config: &WguiFontConfig, asset_folder: PathBuf, ) -> anyhow::Result { @@ -79,7 +42,6 @@ impl WguiGlobals { Ok(Self(Rc::new(RefCell::new(Globals { assets_internal, assets_builtin, - defaults, asset_folder, font_system: WguiFontSystem::new(font_config, i18n_builtin.get_locale()), i18n_builtin, @@ -128,10 +90,6 @@ impl WguiGlobals { RefMut::map(self.0.borrow_mut(), |x| &mut x.i18n_builtin) } - pub fn defaults(&self) -> Ref<'_, Defaults> { - Ref::map(self.0.borrow(), |x| &x.defaults) - } - pub fn assets_internal(&self) -> RefMut<'_, Box> { RefMut::map(self.0.borrow_mut(), |x| &mut x.assets_internal) } diff --git a/wgui/src/i18n.rs b/wgui/src/i18n.rs index e2384bef..8fcad26b 100644 --- a/wgui/src/i18n.rs +++ b/wgui/src/i18n.rs @@ -123,13 +123,7 @@ impl Locale { // check if forced language is set if let Some(forced_lang) = lang_provider.forced_lang() { - let matched = - Self::match_locale(default_lang, forced_lang, None, lang_provider.langs_list().all_locale()).to_string(); - return Self { - lang: forced_lang.to_string(), - region: None, - matched, - }; + return Self::parse_str(lang_provider.langs_list(), forced_lang); } // fallback to environment variables diff --git a/wgui/src/layout.rs b/wgui/src/layout.rs index 8370e653..2efb3398 100644 --- a/wgui/src/layout.rs +++ b/wgui/src/layout.rs @@ -15,6 +15,7 @@ use crate::{ globals::WguiGlobals, sound::WguiSoundType, task::Tasks, + theme::WguiTheme, widget::{self, EventParams, EventResult, WidgetObj, WidgetState, WidgetStateFlags, div::WidgetDiv}, }; @@ -118,6 +119,7 @@ impl WidgetMap { pub struct LayoutState { pub globals: WguiGlobals, + pub theme: Rc, pub widgets: WidgetMap, pub nodes: WidgetNodeMap, pub tree: taffy::tree::TaffyTree, @@ -185,6 +187,7 @@ pub struct Layout { #[derive(Default)] pub struct LayoutParams { pub resize_to_parent: bool, + pub theme: Rc, } fn add_child_internal( @@ -526,12 +529,13 @@ impl Layout { Ok(event_result) } - pub fn new(globals: WguiGlobals, params: &LayoutParams) -> anyhow::Result { + pub fn new(globals: WguiGlobals, params: LayoutParams) -> anyhow::Result { let mut state = LayoutState { tree: TaffyTree::new(), widgets: WidgetMap::new(), nodes: WidgetNodeMap::default(), globals, + theme: params.theme, }; let size = if params.resize_to_parent { diff --git a/wgui/src/lib.rs b/wgui/src/lib.rs index f81e501b..d913f0bf 100644 --- a/wgui/src/lib.rs +++ b/wgui/src/lib.rs @@ -40,6 +40,7 @@ pub mod renderer_vk; pub mod sound; pub mod stack; pub mod task; +pub mod theme; pub mod widget; pub mod windowing; diff --git a/wgui/src/parser/component_button.rs b/wgui/src/parser/component_button.rs index 9a03657c..4e640c1c 100644 --- a/wgui/src/parser/component_button.rs +++ b/wgui/src/parser/component_button.rs @@ -57,7 +57,7 @@ pub fn parse_component_button<'a>( key, value, &mut round, - ctx.doc_params.globals.defaults().rounding_mult, + ctx.layout.state.theme.rounding_mult, ); } "color" => { diff --git a/wgui/src/parser/mod.rs b/wgui/src/parser/mod.rs index a97c80d4..2ed37d82 100644 --- a/wgui/src/parser/mod.rs +++ b/wgui/src/parser/mod.rs @@ -462,7 +462,7 @@ impl ParserContext<'_> { } fn populate_theme_variables(&mut self) { - let def = self.doc_params.globals.defaults(); + let theme = self.layout.state.theme.clone(); macro_rules! insert_color_vars { ($self:expr, $name:literal, $field:expr, $alpha:expr) => { @@ -479,11 +479,11 @@ impl ParserContext<'_> { }; } - insert_color_vars!(self, "text", def.text_color, def.translucent_alpha); - insert_color_vars!(self, "accent", def.accent_color, def.translucent_alpha); - insert_color_vars!(self, "danger", def.danger_color, def.translucent_alpha); - insert_color_vars!(self, "faded", def.faded_color, def.translucent_alpha); - insert_color_vars!(self, "bg", def.bg_color, def.translucent_alpha); + insert_color_vars!(self, "text", theme.text_color, theme.translucent_alpha); + insert_color_vars!(self, "accent", theme.accent_color, theme.translucent_alpha); + insert_color_vars!(self, "danger", theme.danger_color, theme.translucent_alpha); + insert_color_vars!(self, "faded", theme.faded_color, theme.translucent_alpha); + insert_color_vars!(self, "bg", theme.bg_color, theme.translucent_alpha); } fn print_invalid_attrib(&self, tag_name: &str, key: &str, value: &str) { @@ -1232,7 +1232,7 @@ pub fn parse_from_assets( pub fn new_layout_from_assets( doc_params: &ParseDocumentParams, - layout_params: &LayoutParams, + layout_params: LayoutParams, ) -> anyhow::Result<(Layout, ParserState)> { let mut layout = Layout::new(doc_params.globals.clone(), layout_params)?; let widget = layout.content_root_widget; diff --git a/wgui/src/parser/widget_image.rs b/wgui/src/parser/widget_image.rs index 90dc8770..6abdc8e1 100644 --- a/wgui/src/parser/widget_image.rs +++ b/wgui/src/parser/widget_image.rs @@ -42,7 +42,7 @@ pub fn parse_widget_image<'a>( key, value, &mut params.round, - ctx.doc_params.globals.defaults().rounding_mult, + ctx.layout.state.theme.rounding_mult, ); } "border" => { diff --git a/wgui/src/parser/widget_label.rs b/wgui/src/parser/widget_label.rs index 8c69292e..4ad72e19 100644 --- a/wgui/src/parser/widget_label.rs +++ b/wgui/src/parser/widget_label.rs @@ -45,11 +45,8 @@ pub fn parse_widget_label<'a>( } } - let globals = ctx.layout.state.globals.clone(); - - let (widget, _) = ctx - .layout - .add_child(parent_id, WidgetLabel::create(&mut globals.get(), params), style)?; + let label = WidgetLabel::create(&mut ctx.layout.state, params); + let (widget, _) = ctx.layout.add_child(parent_id, label, style)?; parse_widget_universal(ctx, &widget, attribs, tag_name); parse_children(file, ctx, node, widget.id)?; diff --git a/wgui/src/parser/widget_rectangle.rs b/wgui/src/parser/widget_rectangle.rs index 95305668..555c7380 100644 --- a/wgui/src/parser/widget_rectangle.rs +++ b/wgui/src/parser/widget_rectangle.rs @@ -47,7 +47,7 @@ pub fn parse_widget_rectangle<'a>( key, value, &mut params.round, - ctx.doc_params.globals.defaults().rounding_mult, + ctx.layout.state.theme.rounding_mult, ); } "border" => { diff --git a/wgui/src/theme.rs b/wgui/src/theme.rs new file mode 100644 index 00000000..6d9c530a --- /dev/null +++ b/wgui/src/theme.rs @@ -0,0 +1,36 @@ +use crate::drawing; + +#[derive(Clone)] +pub struct WguiTheme { + pub dark_mode: bool, + pub text_color: drawing::Color, + pub button_color: drawing::Color, + pub accent_color: drawing::Color, + pub danger_color: drawing::Color, + pub faded_color: drawing::Color, + pub bg_color: drawing::Color, + pub editbox_color: drawing::Color, + pub translucent_alpha: f32, + pub animation_mult: f32, + pub rounding_mult: f32, + pub gradient_intensity: f32, // currently used for buttons +} + +impl Default for WguiTheme { + fn default() -> Self { + Self { + dark_mode: true, + text_color: drawing::Color::new(1.0, 1.0, 1.0, 1.0), + button_color: drawing::Color::new(1.0, 1.0, 1.0, 0.02), + accent_color: drawing::Color::new(0.13, 0.68, 1.0, 1.0), + danger_color: drawing::Color::new(0.9, 0.0, 0.0, 1.0), + faded_color: drawing::Color::new(0.67, 0.74, 0.80, 1.0), + bg_color: drawing::Color::new(0.0, 0.07, 0.1, 0.75), + editbox_color: drawing::Color::new(0.15, 0.25, 0.35, 0.95), + translucent_alpha: 0.5, + animation_mult: 1.0, + rounding_mult: 1.0, + gradient_intensity: 0.3, + } + } +} diff --git a/wgui/src/widget/label.rs b/wgui/src/widget/label.rs index 89a17c9e..e83bb46f 100644 --- a/wgui/src/widget/label.rs +++ b/wgui/src/widget/label.rs @@ -9,8 +9,9 @@ use crate::{ event::CallbackDataCommon, globals::Globals, i18n::Translation, - layout::WidgetID, + layout::{LayoutState, WidgetID}, renderer_vk::text::TextStyle, + theme::WguiTheme, widget::WidgetStateFlags, }; @@ -31,9 +32,13 @@ pub struct WidgetLabel { } impl WidgetLabel { - pub fn create(globals: &mut Globals, mut params: WidgetLabelParams) -> WidgetState { + pub fn create(state: &mut LayoutState, params: WidgetLabelParams) -> WidgetState { + WidgetLabel::create_ex(&mut state.globals.get(), &state.theme, params) + } + + pub fn create_ex(globals: &mut Globals, theme: &WguiTheme, mut params: WidgetLabelParams) -> WidgetState { if params.style.color.is_none() { - params.style.color = Some(globals.defaults.text_color); + params.style.color = Some(theme.text_color); } let metrics = Metrics::from(¶ms.style); diff --git a/wlx-common/src/config.rs b/wlx-common/src/config.rs index 60864770..8ab23297 100644 --- a/wlx-common/src/config.rs +++ b/wlx-common/src/config.rs @@ -324,4 +324,7 @@ pub struct GeneralConfig { #[serde(default)] pub handsfree_pointer: HandsfreePointer, + + #[serde(default = "def_one")] + pub grid_opacity: f32, } diff --git a/wlx-common/src/locale.rs b/wlx-common/src/locale.rs index 7679c47b..78d814db 100644 --- a/wlx-common/src/locale.rs +++ b/wlx-common/src/locale.rs @@ -9,6 +9,8 @@ use crate::config::GeneralConfig; pub enum Language { #[strum(props(Text = "English"))] English, + #[strum(props(Text = "English(UK)"))] + British, #[strum(props(Text = "Polski"))] Polish, #[strum(props(Text = "日本語"))] @@ -26,13 +28,14 @@ pub enum Language { impl Language { pub const fn code(&self) -> &'static str { match self { - Language::English => "en", - Language::Polish => "pl", - Language::Japanese => "ja", - Language::German => "de", - Language::Italian => "it", + Language::English => "en_US", + Language::British => "en_GB", + Language::Polish => "pl_PL", + Language::Japanese => "ja_JP", + Language::German => "de_DE", + Language::Italian => "it_IT", Language::ChineseSimplified => "zh_CN", - Language::Spanish => "es", + Language::Spanish => "es_ES", } }