wgui: separate globals and themes

This commit is contained in:
Aleksander 2026-03-05 19:28:42 +01:00
parent a83af3d833
commit cb899235b4
33 changed files with 257 additions and 317 deletions

View File

@ -12,6 +12,7 @@ use wgui::{
parser::{Fetchable, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentParams, ParserState},
renderer_vk::text::custom_glyph::CustomGlyphData, renderer_vk::text::custom_glyph::CustomGlyphData,
task::Tasks, task::Tasks,
theme::WguiTheme,
widget::{label::WidgetLabel, rectangle::WidgetRectangle, sprite::WidgetSprite}, widget::{label::WidgetLabel, rectangle::WidgetRectangle, sprite::WidgetSprite},
windowing::window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement}, windowing::window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra, WguiWindowPlacement},
}; };
@ -86,6 +87,7 @@ pub struct InitParams<'a, T> {
pub interface: BoxDashInterface<T>, pub interface: BoxDashInterface<T>,
pub lang_provider: &'a WayVRLangProvider, pub lang_provider: &'a WayVRLangProvider,
pub has_monado: bool, pub has_monado: bool,
pub theme: Rc<WguiTheme>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -106,12 +108,11 @@ pub enum FrontendTask {
RecenterPlayspace, RecenterPlayspace,
PushToast(Translation), PushToast(Translation),
PlaySound(SoundType), PlaySound(SoundType),
UpdateWguiDefaultsFromConfig,
HideDashboard, HideDashboard,
} }
impl<T: 'static> Frontend<T> { impl<T: 'static> Frontend<T> {
pub fn new(mut params: InitParams<T>, data: &mut T) -> anyhow::Result<Frontend<T>> { pub fn new(params: InitParams<T>) -> anyhow::Result<Frontend<T>> {
let mut assets = Box::new(assets::Asset {}); let mut assets = Box::new(assets::Asset {});
let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?; let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?;
@ -121,7 +122,6 @@ impl<T: 'static> Frontend<T> {
let globals = WguiGlobals::new( let globals = WguiGlobals::new(
assets, assets,
params.lang_provider, params.lang_provider,
wgui::globals::Defaults::default(),
&WguiFontConfig { &WguiFontConfig {
binaries: vec![&font_binary_regular, &font_binary_bold, &font_binary_light], binaries: vec![&font_binary_regular, &font_binary_bold, &font_binary_light],
family_name_sans_serif: "Quicksand", family_name_sans_serif: "Quicksand",
@ -131,15 +131,16 @@ impl<T: 'static> Frontend<T> {
PathBuf::new(), //FIXME: pass from somewhere else 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( let (layout, state) = wgui::parser::new_layout_from_assets(
&ParseDocumentParams { &ParseDocumentParams {
globals: globals.clone(), globals: globals.clone(),
path: AssetPath::BuiltIn("gui/dashboard.xml"), path: AssetPath::BuiltIn("gui/dashboard.xml"),
extra: Default::default(), 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")?; let id_popup_manager = state.get_widget_id("popup_manager")?;
@ -185,7 +186,6 @@ impl<T: 'static> Frontend<T> {
// init some things first // init some things first
frontend.tasks.push(FrontendTask::RefreshBackground); frontend.tasks.push(FrontendTask::RefreshBackground);
frontend.tasks.push(FrontendTask::RefreshClock); frontend.tasks.push(FrontendTask::RefreshClock);
frontend.tasks.push(FrontendTask::UpdateWguiDefaultsFromConfig);
Frontend::register_widgets(&mut frontend)?; Frontend::register_widgets(&mut frontend)?;
@ -196,16 +196,6 @@ impl<T: 'static> Frontend<T> {
self.sounds_to_play.push(sound_type); self.sounds_to_play.push(sound_type);
} }
fn update_defaults_from_config(globals: &WguiGlobals, interface: &mut BoxDashInterface<T>, 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<()> { fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> {
let mut assets = self.globals.assets_builtin(); let mut assets = self.globals.assets_builtin();
@ -273,7 +263,7 @@ impl<T: 'static> Frontend<T> {
{ {
// always 30 times per second // always 30 times per second
while self.timestep.on_tick() { 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<T: 'static> Frontend<T> {
FrontendTask::PushToast(content) => self.toast_manager.push(content), FrontendTask::PushToast(content) => self.toast_manager.push(content),
FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type), FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type),
FrontendTask::HideDashboard => self.action_hide_dashboard(params.data), FrontendTask::HideDashboard => self.action_hide_dashboard(params.data),
FrontendTask::UpdateWguiDefaultsFromConfig => {
Frontend::update_defaults_from_config(&self.globals, &mut self.interface, params.data)
}
}; };
Ok(()) Ok(())
} }

View File

@ -163,7 +163,7 @@ impl<T> Tab<T> for TabSettings<T> {
} }
Task::SettingUpdated(setting) => match setting { Task::SettingUpdated(setting) => match setting {
SettingType::UiAnimationSpeed | SettingType::UiGradientIntensity | SettingType::UiRoundMultiplier => { 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 */ } _ => { /* do nothing */ }
}, },
@ -426,16 +426,17 @@ impl SettingType {
} }
fn requires_restart(self) -> bool { fn requires_restart(self) -> bool {
match self { matches!(
self,
Self::UiAnimationSpeed Self::UiAnimationSpeed
| Self::UiRoundMultiplier | Self::UiRoundMultiplier
| Self::UprightScreenFix | Self::UiGradientIntensity
| Self::DoubleCursorFix | Self::UprightScreenFix
| Self::ScreenRenderDown | Self::DoubleCursorFix
| Self::Language | Self::ScreenRenderDown
| Self::CaptureMethod => true, | Self::Language
_ => false, | Self::CaptureMethod
} )
} }
fn get_frontend_task(self) -> Option<FrontendTask> { fn get_frontend_task(self) -> Option<FrontendTask> {
@ -466,7 +467,7 @@ fn horiz_cell(layout: &mut Layout, parent: WidgetID) -> anyhow::Result<WidgetID>
fn mount_requires_restart(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 content = Translation::from_translation_key("APP_SETTINGS.REQUIRES_RESTART");
let label = WidgetLabel::create( let label = WidgetLabel::create(
&mut layout.state.globals.get(), &mut layout.state,
WidgetLabelParams { WidgetLabelParams {
content, content,
style: TextStyle { style: TextStyle {

View File

@ -5,7 +5,6 @@ use wgui::{
animation::{Animation, AnimationEasing}, animation::{Animation, AnimationEasing},
components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR}, components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR},
drawing::Color, drawing::Color,
globals::WguiGlobals,
i18n::Translation, i18n::Translation,
layout::{Layout, LayoutTask, LayoutTasks, WidgetID}, layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
renderer_vk::{ renderer_vk::{
@ -61,15 +60,7 @@ impl ToastManager {
} }
} }
fn mount_toast( fn mount_toast(&self, layout: &mut Layout, state: &mut State, content: Translation) -> anyhow::Result<()> {
&self,
globals: &WguiGlobals,
layout: &mut Layout,
state: &mut State,
content: Translation,
) -> anyhow::Result<()> {
let mut globals = globals.get();
let (root, _) = layout.add_topmost_child( let (root, _) = layout.add_topmost_child(
WidgetDiv::create(), WidgetDiv::create(),
taffy::Style { taffy::Style {
@ -110,27 +101,24 @@ impl ToastManager {
}, },
)?; )?;
let (label, _) = layout.add_child( let label = WidgetLabel::create(
rect.id, &mut layout.state,
WidgetLabel::create( WidgetLabelParams {
&mut globals, content,
WidgetLabelParams { style: TextStyle {
content, weight: Some(FontWeight::Bold),
style: TextStyle { align: Some(HorizontalAlign::Center),
weight: Some(FontWeight::Bold), wrap: true,
align: Some(HorizontalAlign::Center), ..Default::default()
wrap: true,
..Default::default()
},
}, },
), },
taffy::Style { ..Default::default() }, );
)?; let (label, _) = layout.add_child(rect.id, label, taffy::Style { ..Default::default() })?;
// show-up animation // show-up animation
layout.animations.add(Animation::new( layout.animations.add(Animation::new(
rect.id, 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, AnimationEasing::Linear,
Box::new(move |common, data| { Box::new(move |common, data| {
let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0)); let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0));
@ -161,7 +149,7 @@ impl ToastManager {
Ok(()) 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(); let mut state = self.state.borrow_mut();
if state.timeout > 0 { if state.timeout > 0 {
state.timeout -= 1; state.timeout -= 1;
@ -176,7 +164,7 @@ impl ToastManager {
state.timeout = TOAST_DURATION_TICKS; state.timeout = TOAST_DURATION_TICKS;
// mount next // mount next
if let Some(content) = state.queue.pop_front() { if let Some(content) = state.queue.pop_front() {
self.mount_toast(globals, layout, &mut state, content)?; self.mount_toast(layout, &mut state, content)?;
} }
} }

View File

@ -8,7 +8,7 @@ use wgui::{
#[allow(dead_code)] #[allow(dead_code)]
pub fn create_label(layout: &mut Layout, parent: WidgetID, content: Translation) -> anyhow::Result<()> { pub fn create_label(layout: &mut Layout, parent: WidgetID, content: Translation) -> anyhow::Result<()> {
let label = WidgetLabel::create( let label = WidgetLabel::create(
&mut layout.state.globals.get(), &mut layout.state,
WidgetLabelParams { WidgetLabelParams {
content, content,
style: TextStyle { style: TextStyle {

View File

@ -110,8 +110,7 @@ struct MultiSelectorParams<'a> {
} }
fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> { fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> {
let globals = params.ess.layout.state.globals.clone(); let accent_color = params.ess.layout.state.theme.accent_color;
let accent_color = globals.defaults().accent_color;
for cell in params.cells { for cell in params.cells {
let highlighted = cell.key == params.def_cell; let highlighted = cell.key == params.def_cell;
@ -654,8 +653,6 @@ impl View {
} }
fn update_button_highlights(&self, layout: &mut Layout) -> anyhow::Result<()> { fn update_button_highlights(&self, layout: &mut Layout) -> anyhow::Result<()> {
let defaults = self.globals.defaults();
let mut c = layout.start_common(); let mut c = layout.start_common();
let mut common = c.common(); let mut common = c.common();
@ -667,14 +664,12 @@ impl View {
}; };
let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| { let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| {
btn.set_color( let color = if num == btn_num {
&mut common, common.state.theme.accent_color
if num == btn_num { } else {
defaults.accent_color common.state.theme.button_color
} else { };
defaults.button_color btn.set_color(&mut common, color);
},
);
}; };
perform(0, &self.btn_sinks); perform(0, &self.btn_sinks);

View File

@ -98,15 +98,9 @@ impl View {
Ok(()) Ok(())
} }
fn mount_placeholder_text( fn mount_placeholder_text(&self, layout: &mut Layout, parent: WidgetID, text: &str) -> anyhow::Result<()> {
&self,
globals: &WguiGlobals,
layout: &mut Layout,
parent: WidgetID,
text: &str,
) -> anyhow::Result<()> {
let label = WidgetLabel::create( let label = WidgetLabel::create(
&mut globals.get(), &mut layout.state,
WidgetLabelParams { WidgetLabelParams {
content: Translation::from_raw_text(text), content: Translation::from_raw_text(text),
style: TextStyle { style: TextStyle {
@ -153,7 +147,7 @@ impl View {
// mount placeholder // mount placeholder
let img = view_common.get_placeholder_image()?.clone(); let img = view_common.get_placeholder_image()?.clone();
self.mount_image(layout, &img)?; 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 { } else {
// mount image // mount image
let path = format!("app:{:?}", self.app_id); let path = format!("app:{:?}", self.app_id);

View File

@ -256,17 +256,14 @@ impl View {
)?; )?;
if let Some(text) = text.take() { if let Some(text) = text.take() {
layout.add_child( let label = WidgetLabel::create(
self.id_list_parent, &mut layout.state,
WidgetLabel::create( WidgetLabelParams {
&mut self.globals.get(), content: text,
WidgetLabelParams { ..Default::default()
content: text, },
..Default::default() );
}, layout.add_child(self.id_list_parent, label, Default::default())?;
),
Default::default(),
)?;
} }
Ok(()) Ok(())

View File

@ -34,7 +34,6 @@ impl TestbedAny {
let globals = WguiGlobals::new( let globals = WguiGlobals::new(
assets, assets,
&lang_provider, &lang_provider,
wgui::globals::Defaults::default(),
&WguiFontConfig::default(), &WguiFontConfig::default(),
PathBuf::new(), // cwd PathBuf::new(), // cwd
)?; )?;
@ -45,7 +44,7 @@ impl TestbedAny {
path, path,
extra: Default::default(), extra: Default::default(),
}, },
&LayoutParams::default(), LayoutParams::default(),
)?; )?;
Ok(Self { layout, state }) Ok(Self { layout, state })
} }

View File

@ -1,6 +1,8 @@
use std::rc::Rc;
use crate::testbed::{Testbed, TestbedUpdateParams}; use crate::testbed::{Testbed, TestbedUpdateParams};
use dash_frontend::frontend::{self, FrontendUpdateParams}; 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}; use wlx_common::{dash_interface_emulated::DashInterfaceEmulated, locale::WayVRLangProvider};
pub struct TestbedDashboard { pub struct TestbedDashboard {
@ -12,14 +14,12 @@ impl TestbedDashboard {
let interface = DashInterfaceEmulated::new(); let interface = DashInterfaceEmulated::new();
let lang_provider = WayVRLangProvider::default(); let lang_provider = WayVRLangProvider::default();
let frontend = frontend::Frontend::new( let frontend = frontend::Frontend::new(frontend::InitParams {
frontend::InitParams { interface: Box::new(interface),
interface: Box::new(interface), has_monado: true,
has_monado: true, lang_provider: &lang_provider,
lang_provider: &lang_provider, theme: Rc::new(WguiTheme::default()),
}, })?;
&mut (),
)?;
Ok(Self { frontend }) Ok(Self { frontend })
} }
} }

View File

@ -21,6 +21,7 @@ use wgui::{
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState},
taffy::{self, prelude::length}, taffy::{self, prelude::length},
task::Tasks, task::Tasks,
theme::WguiTheme,
widget::{div::WidgetDiv, label::WidgetLabel, rectangle::WidgetRectangle}, widget::{div::WidgetDiv, label::WidgetLabel, rectangle::WidgetRectangle},
windowing::{ windowing::{
context_menu::{self, TickResult}, context_menu::{self, TickResult},
@ -91,7 +92,6 @@ impl TestbedGeneric {
let globals = WguiGlobals::new( let globals = WguiGlobals::new(
assets, assets,
&lang_provider, &lang_provider,
wgui::globals::Defaults::default(),
&WguiFontConfig::default(), &WguiFontConfig::default(),
PathBuf::new(), // cwd PathBuf::new(), // cwd
)?; )?;
@ -125,8 +125,9 @@ impl TestbedGeneric {
let (layout, parser_state) = wgui::parser::new_layout_from_assets( let (layout, parser_state) = wgui::parser::new_layout_from_assets(
&TestbedGeneric::doc_params(&globals, extra), &TestbedGeneric::doc_params(&globals, extra),
&LayoutParams { LayoutParams {
resize_to_parent: true, resize_to_parent: true,
theme: Rc::new(WguiTheme::default()),
}, },
)?; )?;

View File

@ -147,8 +147,9 @@ impl<S: 'static> GuiPanel<S> {
let (mut layout, mut parser_state) = wgui::parser::new_layout_from_assets( let (mut layout, mut parser_state) = wgui::parser::new_layout_from_assets(
&doc_params, &doc_params,
&LayoutParams { LayoutParams {
resize_to_parent: params.resize_to_parent, resize_to_parent: params.resize_to_parent,
theme: app.wgui_theme.clone(),
}, },
)?; )?;

View File

@ -77,14 +77,12 @@ impl DashFrontend {
let _ = interface.process_launch(app, false, p)?; let _ = interface.process_launch(app, false, p)?;
} }
let frontend = frontend::Frontend::new( let frontend = frontend::Frontend::new(frontend::InitParams {
frontend::InitParams { interface: Box::new(interface),
interface: Box::new(interface), lang_provider: &WayVRLangProvider::from_config(&app.session.config),
lang_provider: &WayVRLangProvider::from_config(&app.session.config), has_monado: matches!(app.xr_backend, XrBackend::OpenXR),
has_monado: matches!(app.xr_backend, XrBackend::OpenXR), theme: app.wgui_theme.clone(),
}, })?;
app,
)?;
frontend frontend
.tasks .tasks

View File

@ -11,7 +11,7 @@ use wgui::{
widget::rectangle::WidgetRectangle, widget::rectangle::WidgetRectangle,
}; };
use crate::{backend::task::ModifyOverlayTask, overlays::edit::EditModeWrapPanel, state::AppState}; use crate::{backend::task::ModifyOverlayTask, overlays::edit::EditModeWrapPanel};
#[derive(Default)] #[derive(Default)]
pub(super) struct InteractLockHandler { pub(super) struct InteractLockHandler {
@ -53,21 +53,18 @@ impl InteractLockHandler {
button.set_sticky_state(common, !interactable); button.set_sticky_state(common, !interactable);
} }
let globals = common.state.globals.get();
if interactable { 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 { } 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( pub fn toggle(
&mut self, &mut self,
common: &mut CallbackDataCommon, common: &mut CallbackDataCommon,
app: &mut AppState,
anim_mult: f32, anim_mult: f32,
) -> Box<ModifyOverlayTask> { ) -> Box<ModifyOverlayTask> {
let defaults = app.wgui_globals.defaults().clone();
let rect_color = self.color; let rect_color = self.color;
self.interactable = !self.interactable; self.interactable = !self.interactable;
@ -86,7 +83,7 @@ impl InteractLockHandler {
rect, rect,
0.2 - (data.pos * 0.2), 0.2 - (data.pos * 0.2),
rect_color, rect_color,
defaults.danger_color, common.state.theme.danger_color,
); );
common.alterables.mark_redraw(); common.alterables.mark_redraw();
}), }),
@ -98,7 +95,12 @@ impl InteractLockHandler {
AnimationEasing::OutBack, AnimationEasing::OutBack,
Box::new(move |common, data| { Box::new(move |common, data| {
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap(); let rect = data.obj.get_as_mut::<WidgetRectangle>().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(); common.alterables.mark_redraw();
}), }),
) )

View File

@ -272,7 +272,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
mouse: SpriteTabHandler::default(), 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 on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, parser, attribs, _app| {
let Ok(button) = let Ok(button) =
@ -302,7 +302,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
} }
let sel = OverlaySelector::Id(*state.id.borrow()); 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 app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task))); .enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed) Ok(EventResult::Consumed)

View File

@ -53,11 +53,9 @@ pub(super) fn create_keyboard_panel(
let doc_params = new_doc_params(&mut panel); let doc_params = new_doc_params(&mut panel);
let globals = app.wgui_globals.clone();
let (accent_color, anim_mult) = { let (accent_color, anim_mult) = {
let def = globals.defaults(); let theme = &app.wgui_theme;
(def.accent_color, def.animation_mult) (theme.accent_color, theme.animation_mult)
}; };
let root = panel let root = panel

View File

@ -1,8 +1,10 @@
use glam::Affine3A; use glam::Affine3A;
use idmap::IdMap; use idmap::IdMap;
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use wgui::log::LogErr; use wgui::log::LogErr;
use wgui::theme::WguiTheme;
use wgui::{ use wgui::{
drawing, font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals, parser::parse_color_hex, drawing, font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals, parser::parse_color_hex,
renderer_vk::context::SharedContext as WSharedContext, renderer_vk::context::SharedContext as WSharedContext,
@ -48,6 +50,7 @@ pub struct AppState {
pub anchor_grabbed: bool, pub anchor_grabbed: bool,
pub wgui_globals: WguiGlobals, pub wgui_globals: WguiGlobals,
pub wgui_theme: Rc<WguiTheme>,
pub dbus: DbusConnector, pub dbus: DbusConnector,
@ -90,7 +93,7 @@ impl AppState {
let osc_sender = crate::subsystem::osc::OscSender::new(session.config.osc_out_port).ok(); let osc_sender = crate::subsystem::osc::OscSender::new(session.config.osc_out_port).ok();
let wgui_shared = WSharedContext::new(gfx.clone())?; 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(); let mut audio_sample_player = audio::SamplePlayer::new();
audio_sample_player.register_sample( audio_sample_player.register_sample(
@ -112,7 +115,7 @@ impl AppState {
let mut assets = Box::new(gui::asset::GuiAsset {}); let mut assets = Box::new(gui::asset::GuiAsset {});
audio_sample_player.register_wgui_samples(assets.as_mut())?; 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)] #[allow(clippy::ref_option)]
@ -122,15 +125,15 @@ impl AppState {
} }
} }
apply_color(&mut defaults.text_color, &session.config.color_text); apply_color(&mut theme.text_color, &session.config.color_text);
apply_color(&mut defaults.accent_color, &session.config.color_accent); apply_color(&mut theme.accent_color, &session.config.color_accent);
apply_color(&mut defaults.danger_color, &session.config.color_danger); apply_color(&mut theme.danger_color, &session.config.color_danger);
apply_color(&mut defaults.faded_color, &session.config.color_faded); apply_color(&mut theme.faded_color, &session.config.color_faded);
apply_color(&mut defaults.bg_color, &session.config.color_background); apply_color(&mut theme.bg_color, &session.config.color_background);
} }
defaults.animation_mult = 1. / session.config.ui_animation_speed; theme.animation_mult = 1. / session.config.ui_animation_speed;
defaults.rounding_mult = session.config.ui_round_multiplier; theme.rounding_mult = session.config.ui_round_multiplier;
let dbus = DbusConnector::default(); let dbus = DbusConnector::default();
@ -157,10 +160,10 @@ impl AppState {
wgui_globals: WguiGlobals::new( wgui_globals: WguiGlobals::new(
assets, assets,
&lang_provider, &lang_provider,
defaults,
&WguiFontConfig::default(), &WguiFontConfig::default(),
get_config_file_path(&theme), get_config_file_path(&theme_path),
)?, )?,
wgui_theme: Rc::new(theme),
dbus, dbus,
xr_backend, xr_backend,
ipc_server, ipc_server,

View File

@ -157,7 +157,7 @@ impl ComponentButton {
} }
pub fn set_color(&self, common: &mut CallbackDataCommon, color: Color) { 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::<WidgetRectangle>(self.data.id_rect) else { let Some(mut rect) = common.state.widgets.get_as::<WidgetRectangle>(self.data.id_rect) else {
return; return;
@ -194,8 +194,8 @@ impl ComponentButton {
} }
let (anim_mult, gradient_intensity) = { let (anim_mult, gradient_intensity) = {
let defaults = common.state.globals.defaults(); let theme = &common.state.theme;
(defaults.animation_mult, defaults.gradient_intensity) (theme.animation_mult, theme.gradient_intensity)
}; };
let anim_ticks = if sticky_down { 5. } else { 10. }; 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 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); //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<ComponentButton>)> { pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Result<(WidgetPair, Rc<ComponentButton>)> {
let globals = ess.layout.state.globals.clone();
let mut style = params.style; let mut style = params.style;
let theme = &ess.layout.state.theme;
// force-override style // force-override style
style.align_items = Some(AlignItems::Center); 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 { let color = if let Some(color) = params.color {
color color
} else { } else {
globals.defaults().button_color theme.button_color
}; };
let border_color = if let Some(border_color) = params.border_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) 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( let (root, _) = ess.layout.add_child(
ess.parent, ess.parent,
@ -469,15 +474,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
let id_rect = root.id; 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 { let default_margin = taffy::Rect {
top: length(4.0), top: length(4.0),
bottom: 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 { if let Some(sprite_path) = params.sprite_src {
let sprite = WidgetSprite::create(WidgetSpriteParams { 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() ..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 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( let (label, _node_label) = ess.layout.add_child(
id_rect, id_rect,
WidgetLabel::create( widget_label,
&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
},
},
),
taffy::Style { taffy::Style {
margin: default_margin, margin: default_margin,
..Default::default() ..Default::default()
@ -558,7 +556,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
id: root.id, id: root.id,
lhandles: { lhandles: {
let listeners = &mut root.widget.state().event_listeners; 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![ vec![
register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip, anim_mult), register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip, anim_mult),
register_event_mouse_leave(state.clone(), listeners, anim_mult), register_event_mouse_leave(state.clone(), listeners, anim_mult),

View File

@ -343,8 +343,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
(WLength::Units(5.0), WLength::Units(8.0)) (WLength::Units(5.0), WLength::Units(8.0))
}; };
let globals = ess.layout.state.globals.clone();
let (root, _) = ess.layout.add_child( let (root, _) = ess.layout.add_child(
ess.parent, ess.parent,
WidgetRectangle::create(WidgetRectangleParams { 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( let widget_label = WidgetLabel::create(
id_container, &mut ess.layout.state,
WidgetLabel::create( WidgetLabelParams {
&mut globals.get(), content: params.text,
WidgetLabelParams { style: TextStyle {
content: params.text, weight: Some(FontWeight::Bold),
style: TextStyle { ..Default::default()
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 { let data = Rc::new(Data {
id_container, id_container,
@ -433,7 +428,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
id: root.id, id: root.id,
lhandles: { lhandles: {
let listeners = &mut root.widget.state().event_listeners; 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![ vec![
register_event_mouse_enter(state.clone(), listeners, params.tooltip, anim_mult), register_event_mouse_enter(state.clone(), listeners, params.tooltip, anim_mult),
register_event_mouse_leave(state.clone(), listeners, anim_mult), register_event_mouse_leave(state.clone(), listeners, anim_mult),

View File

@ -99,11 +99,10 @@ fn anim_bottom_rect(
} }
fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State) -> Option<()> { fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State) -> Option<()> {
let defaults = common.defaults(); let theme = &common.state.theme;
let editbox_color = defaults.editbox_color; let editbox_color = theme.editbox_color;
let anim_mult = defaults.animation_mult; let anim_mult = theme.animation_mult;
let accent_color = defaults.accent_color; let accent_color = theme.accent_color;
drop(defaults);
let (rect_color, border_color) = if state.focused { let (rect_color, border_color) = if state.focused {
(editbox_color.add_rgb(0.15), editbox_color.add_rgb(0.15 + 0.25)) (editbox_color.add_rgb(0.15), editbox_color.add_rgb(0.15 + 0.25))
@ -279,10 +278,7 @@ pub fn construct(
ess: &mut ConstructEssentials, ess: &mut ConstructEssentials,
mut params: Params, mut params: Params,
) -> anyhow::Result<(WidgetPair, Rc<ComponentEditBox>)> { ) -> anyhow::Result<(WidgetPair, Rc<ComponentEditBox>)> {
let globals = ess.layout.state.globals.clone(); let text_color = ess.layout.state.theme.text_color;
let defaults = globals.defaults();
let text_color = defaults.text_color;
drop(defaults);
if params.style.size.width.is_auto() { if params.style.size.width.is_auto() {
params.style.size.width = length(128.0); 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(&params.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( let (label, _node_label) = ess.layout.add_child(
label_parent.id, label_parent.id,
WidgetLabel::create( widget_label,
&mut globals.get(),
WidgetLabelParams {
content: Translation::from_raw_text(&params.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()
},
},
),
taffy::Style { taffy::Style {
position: taffy::Position::Relative, position: taffy::Position::Relative,
..Default::default() ..Default::default()

View File

@ -498,26 +498,20 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
active_tooltip: None, active_tooltip: None,
}; };
let globals = ess.layout.state.globals.clone();
let slider_text: Option<(WidgetPair, taffy::NodeId)> = if params.show_value { let slider_text: Option<(WidgetPair, taffy::NodeId)> = if params.show_value {
let pair = ess.layout.add_child( let label = WidgetLabel::create(
slider_handle.id, &mut ess.layout.state,
WidgetLabel::create( WidgetLabelParams {
&mut globals.get(), content: Translation::default(),
WidgetLabelParams { style: TextStyle {
content: Translation::default(), color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0)), // always black
style: TextStyle { weight: Some(FontWeight::Bold),
color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0)), // always black align: Some(HorizontalAlign::Center),
weight: Some(FontWeight::Bold), ..Default::default()
align: Some(HorizontalAlign::Center),
..Default::default()
},
}, },
), },
Default::default(), );
)?; Some(ess.layout.add_child(slider_handle.id, label, Default::default())?)
Some(pair)
} else { } else {
None None
}; };
@ -535,7 +529,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
id: root.id, id: root.id,
lhandles: { lhandles: {
let listeners = &mut root.widget.state().event_listeners; 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![ vec![
register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip, anim_mult), register_event_mouse_enter(data.clone(), state.clone(), listeners, params.tooltip, anim_mult),
register_event_mouse_leave(data.clone(), state.clone(), listeners, anim_mult), register_event_mouse_leave(data.clone(), state.clone(), listeners, anim_mult),

View File

@ -67,8 +67,8 @@ impl ComponentTrait for ComponentTabs {
impl State { impl State {
fn select_entry(&mut self, common: &mut CallbackDataCommon, name: &Rc<str>) { fn select_entry(&mut self, common: &mut CallbackDataCommon, name: &Rc<str>) {
let (color_accent, color_button) = { let (color_accent, color_button) = {
let def = common.state.globals.defaults(); let theme = &common.state.theme;
(def.accent_color, def.button_color) (theme.accent_color, theme.button_color)
}; };
for entry in &self.mounted_entries { for entry in &self.mounted_entries {

View File

@ -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( let (div, _) = ess.layout.add_child(
ess.parent, ess.parent,
WidgetDiv::create(), WidgetDiv::create(),
@ -211,20 +209,17 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
}, },
)?; )?;
let (label, _) = ess.layout.add_child( let label = WidgetLabel::create(
rect.id, &mut ess.layout.state,
WidgetLabel::create( WidgetLabelParams {
&mut globals.get(), content: params.info.text,
WidgetLabelParams { style: TextStyle {
content: params.info.text, weight: Some(FontWeight::Bold),
style: TextStyle { ..Default::default()
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 }); 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), 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( ess.layout.animations.add(Animation::new(
rect.id, rect.id,
(10.0 * anim_mult) as u32, (10.0 * anim_mult) as u32,

View File

@ -1,6 +1,6 @@
use std::{ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
cell::{Ref, RefMut}, cell::RefMut,
collections::HashSet, collections::HashSet,
rc::{Rc, Weak}, rc::{Rc, Weak},
}; };
@ -181,10 +181,6 @@ impl CallbackDataCommon<'_> {
pub fn globals(&self) -> RefMut<'_, globals::Globals> { pub fn globals(&self) -> RefMut<'_, globals::Globals> {
self.state.globals.get() self.state.globals.get()
} }
pub fn defaults(&self) -> Ref<'_, globals::Defaults> {
self.state.globals.defaults()
}
} }
pub struct CallbackData<'a> { pub struct CallbackData<'a> {

View File

@ -1,5 +1,5 @@
use std::{ use std::{
cell::{Ref, RefCell, RefMut}, cell::{RefCell, RefMut},
io::Read, io::Read,
path::PathBuf, path::PathBuf,
rc::Rc, rc::Rc,
@ -11,53 +11,17 @@ use regex::Regex;
use crate::{ use crate::{
assets::{AssetPath, AssetProvider, LangProvider}, assets::{AssetPath, AssetProvider, LangProvider},
assets_internal, drawing, assets_internal,
font_config::{WguiFontConfig, WguiFontSystem}, font_config::{WguiFontConfig, WguiFontSystem},
i18n::I18n, i18n::I18n,
renderer_vk::text::custom_glyph::CustomGlyphCache, 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 struct Globals {
pub assets_internal: Box<dyn AssetProvider>, pub assets_internal: Box<dyn AssetProvider>,
pub assets_builtin: Box<dyn AssetProvider>, pub assets_builtin: Box<dyn AssetProvider>,
pub asset_folder: PathBuf, pub asset_folder: PathBuf,
pub i18n_builtin: I18n, pub i18n_builtin: I18n,
pub defaults: Defaults,
pub font_system: WguiFontSystem, pub font_system: WguiFontSystem,
pub custom_glyph_cache: CustomGlyphCache, pub custom_glyph_cache: CustomGlyphCache,
} }
@ -69,7 +33,6 @@ impl WguiGlobals {
pub fn new( pub fn new(
mut assets_builtin: Box<dyn AssetProvider>, mut assets_builtin: Box<dyn AssetProvider>,
lang_provider: &dyn LangProvider, lang_provider: &dyn LangProvider,
defaults: Defaults,
font_config: &WguiFontConfig, font_config: &WguiFontConfig,
asset_folder: PathBuf, asset_folder: PathBuf,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
@ -79,7 +42,6 @@ impl WguiGlobals {
Ok(Self(Rc::new(RefCell::new(Globals { Ok(Self(Rc::new(RefCell::new(Globals {
assets_internal, assets_internal,
assets_builtin, assets_builtin,
defaults,
asset_folder, asset_folder,
font_system: WguiFontSystem::new(font_config, i18n_builtin.get_locale()), font_system: WguiFontSystem::new(font_config, i18n_builtin.get_locale()),
i18n_builtin, i18n_builtin,
@ -128,10 +90,6 @@ impl WguiGlobals {
RefMut::map(self.0.borrow_mut(), |x| &mut x.i18n_builtin) 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<dyn AssetProvider>> { pub fn assets_internal(&self) -> RefMut<'_, Box<dyn AssetProvider>> {
RefMut::map(self.0.borrow_mut(), |x| &mut x.assets_internal) RefMut::map(self.0.borrow_mut(), |x| &mut x.assets_internal)
} }

View File

@ -15,6 +15,7 @@ use crate::{
globals::WguiGlobals, globals::WguiGlobals,
sound::WguiSoundType, sound::WguiSoundType,
task::Tasks, task::Tasks,
theme::WguiTheme,
widget::{self, EventParams, EventResult, WidgetObj, WidgetState, WidgetStateFlags, div::WidgetDiv}, widget::{self, EventParams, EventResult, WidgetObj, WidgetState, WidgetStateFlags, div::WidgetDiv},
}; };
@ -118,6 +119,7 @@ impl WidgetMap {
pub struct LayoutState { pub struct LayoutState {
pub globals: WguiGlobals, pub globals: WguiGlobals,
pub theme: Rc<WguiTheme>,
pub widgets: WidgetMap, pub widgets: WidgetMap,
pub nodes: WidgetNodeMap, pub nodes: WidgetNodeMap,
pub tree: taffy::tree::TaffyTree<WidgetID>, pub tree: taffy::tree::TaffyTree<WidgetID>,
@ -185,6 +187,7 @@ pub struct Layout {
#[derive(Default)] #[derive(Default)]
pub struct LayoutParams { pub struct LayoutParams {
pub resize_to_parent: bool, pub resize_to_parent: bool,
pub theme: Rc<WguiTheme>,
} }
fn add_child_internal( fn add_child_internal(
@ -526,12 +529,13 @@ impl Layout {
Ok(event_result) Ok(event_result)
} }
pub fn new(globals: WguiGlobals, params: &LayoutParams) -> anyhow::Result<Self> { pub fn new(globals: WguiGlobals, params: LayoutParams) -> anyhow::Result<Self> {
let mut state = LayoutState { let mut state = LayoutState {
tree: TaffyTree::new(), tree: TaffyTree::new(),
widgets: WidgetMap::new(), widgets: WidgetMap::new(),
nodes: WidgetNodeMap::default(), nodes: WidgetNodeMap::default(),
globals, globals,
theme: params.theme,
}; };
let size = if params.resize_to_parent { let size = if params.resize_to_parent {

View File

@ -40,6 +40,7 @@ pub mod renderer_vk;
pub mod sound; pub mod sound;
pub mod stack; pub mod stack;
pub mod task; pub mod task;
pub mod theme;
pub mod widget; pub mod widget;
pub mod windowing; pub mod windowing;

View File

@ -57,7 +57,7 @@ pub fn parse_component_button<'a>(
key, key,
value, value,
&mut round, &mut round,
ctx.doc_params.globals.defaults().rounding_mult, ctx.layout.state.theme.rounding_mult,
); );
} }
"color" => { "color" => {

View File

@ -462,7 +462,7 @@ impl ParserContext<'_> {
} }
fn populate_theme_variables(&mut self) { 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 { macro_rules! insert_color_vars {
($self:expr, $name:literal, $field:expr, $alpha:expr) => { ($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, "text", theme.text_color, theme.translucent_alpha);
insert_color_vars!(self, "accent", def.accent_color, def.translucent_alpha); insert_color_vars!(self, "accent", theme.accent_color, theme.translucent_alpha);
insert_color_vars!(self, "danger", def.danger_color, def.translucent_alpha); insert_color_vars!(self, "danger", theme.danger_color, theme.translucent_alpha);
insert_color_vars!(self, "faded", def.faded_color, def.translucent_alpha); insert_color_vars!(self, "faded", theme.faded_color, theme.translucent_alpha);
insert_color_vars!(self, "bg", def.bg_color, def.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) { 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( pub fn new_layout_from_assets(
doc_params: &ParseDocumentParams, doc_params: &ParseDocumentParams,
layout_params: &LayoutParams, layout_params: LayoutParams,
) -> anyhow::Result<(Layout, ParserState)> { ) -> anyhow::Result<(Layout, ParserState)> {
let mut layout = Layout::new(doc_params.globals.clone(), layout_params)?; let mut layout = Layout::new(doc_params.globals.clone(), layout_params)?;
let widget = layout.content_root_widget; let widget = layout.content_root_widget;

View File

@ -42,7 +42,7 @@ pub fn parse_widget_image<'a>(
key, key,
value, value,
&mut params.round, &mut params.round,
ctx.doc_params.globals.defaults().rounding_mult, ctx.layout.state.theme.rounding_mult,
); );
} }
"border" => { "border" => {

View File

@ -45,11 +45,8 @@ pub fn parse_widget_label<'a>(
} }
} }
let globals = ctx.layout.state.globals.clone(); let label = WidgetLabel::create(&mut ctx.layout.state, params);
let (widget, _) = ctx.layout.add_child(parent_id, label, style)?;
let (widget, _) = ctx
.layout
.add_child(parent_id, WidgetLabel::create(&mut globals.get(), params), style)?;
parse_widget_universal(ctx, &widget, attribs, tag_name); parse_widget_universal(ctx, &widget, attribs, tag_name);
parse_children(file, ctx, node, widget.id)?; parse_children(file, ctx, node, widget.id)?;

View File

@ -47,7 +47,7 @@ pub fn parse_widget_rectangle<'a>(
key, key,
value, value,
&mut params.round, &mut params.round,
ctx.doc_params.globals.defaults().rounding_mult, ctx.layout.state.theme.rounding_mult,
); );
} }
"border" => { "border" => {

36
wgui/src/theme.rs Normal file
View File

@ -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,
}
}
}

View File

@ -9,8 +9,9 @@ use crate::{
event::CallbackDataCommon, event::CallbackDataCommon,
globals::Globals, globals::Globals,
i18n::Translation, i18n::Translation,
layout::WidgetID, layout::{LayoutState, WidgetID},
renderer_vk::text::TextStyle, renderer_vk::text::TextStyle,
theme::WguiTheme,
widget::WidgetStateFlags, widget::WidgetStateFlags,
}; };
@ -31,9 +32,13 @@ pub struct WidgetLabel {
} }
impl 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() { 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(&params.style); let metrics = Metrics::from(&params.style);