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 67f00070..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 */ } }, @@ -426,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 { @@ -466,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 { 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/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 874d8516..b96b0368 100644 --- a/wayvr/src/overlays/keyboard/builder.rs +++ b/wayvr/src/overlays/keyboard/builder.rs @@ -53,11 +53,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/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/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 57417808..e3d93dac 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/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);