diff --git a/Cargo.lock b/Cargo.lock index c7a1e2c..f7ea700 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1852,9 +1852,9 @@ checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -6278,6 +6278,7 @@ dependencies = [ "anyhow", "cosmic-text", "etagere", + "flate2", "glam", "image", "log", diff --git a/dash-frontend/assets/Quicksand-Bold.ttf.gz b/dash-frontend/assets/Quicksand-Bold.ttf.gz new file mode 100644 index 0000000..b0467a6 Binary files /dev/null and b/dash-frontend/assets/Quicksand-Bold.ttf.gz differ diff --git a/dash-frontend/assets/Quicksand-Light.ttf.gz b/dash-frontend/assets/Quicksand-Light.ttf.gz new file mode 100644 index 0000000..dbda8da Binary files /dev/null and b/dash-frontend/assets/Quicksand-Light.ttf.gz differ diff --git a/dash-frontend/assets/Quicksand-Regular.ttf.gz b/dash-frontend/assets/Quicksand-Regular.ttf.gz new file mode 100644 index 0000000..f31c5b6 Binary files /dev/null and b/dash-frontend/assets/Quicksand-Regular.ttf.gz differ diff --git a/dash-frontend/assets/gui/dashboard.xml b/dash-frontend/assets/gui/dashboard.xml index b4e804e..0aab48a 100644 --- a/dash-frontend/assets/gui/dashboard.xml +++ b/dash-frontend/assets/gui/dashboard.xml @@ -100,6 +100,8 @@
-
diff --git a/dash-frontend/src/frontend.rs b/dash-frontend/src/frontend.rs index 42db205..48cdb69 100644 --- a/dash-frontend/src/frontend.rs +++ b/dash-frontend/src/frontend.rs @@ -3,9 +3,9 @@ use std::{cell::RefCell, collections::VecDeque, rc::Rc}; use chrono::Timelike; use glam::Vec2; use wgui::{ - assets::AssetPath, + assets::{AssetPath, AssetProvider}, components::button::ComponentButton, - event::{CallbackDataCommon, EventAlterables}, + font_config::WguiFontConfig, globals::WguiGlobals, i18n::Translation, layout::{LayoutParams, RcLayout, WidgetID}, @@ -54,7 +54,22 @@ pub enum FrontendTask { impl Frontend { pub fn new(params: InitParams) -> anyhow::Result<(RcFrontend, RcLayout)> { - let globals = WguiGlobals::new(Box::new(assets::Asset {}), wgui::globals::Defaults::default())?; + let mut assets = Box::new(assets::Asset {}); + + let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?; + let font_binary_regular = assets.load_from_path_gzip("Quicksand-Regular.ttf.gz")?; + let font_binary_light = assets.load_from_path_gzip("Quicksand-Light.ttf.gz")?; + + let globals = WguiGlobals::new( + assets, + wgui::globals::Defaults::default(), + &WguiFontConfig { + binaries: vec![&font_binary_regular, &font_binary_bold, &font_binary_light], + family_name_sans_serif: "Quicksand", + family_name_serif: "Quicksand", + family_name_monospace: "", + }, + )?; let (layout, state) = wgui::parser::new_layout_from_assets( &ParseDocumentParams { diff --git a/dash-frontend/src/tab/home.rs b/dash-frontend/src/tab/home.rs index 7472a9c..2ea9df0 100644 --- a/dash-frontend/src/tab/home.rs +++ b/dash-frontend/src/tab/home.rs @@ -1,7 +1,9 @@ use wgui::{ assets::AssetPath, components::button::ComponentButton, + event::CallbackDataCommon, i18n::Translation, + layout::Widget, parser::{Fetchable, ParseDocumentParams, ParserState}, widget::label::WidgetLabel, }; @@ -23,7 +25,7 @@ impl Tab for TabHome { } } -fn configure_label_hello(label_hello: &mut WidgetLabel, i18n: &mut wgui::i18n::I18n, settings: &settings::Settings) { +fn configure_label_hello(common: &mut CallbackDataCommon, label_hello: Widget, settings: &settings::Settings) { let mut username = various::get_username(); // first character as uppercase if let Some(first) = username.chars().next() { @@ -32,12 +34,13 @@ fn configure_label_hello(label_hello: &mut WidgetLabel, i18n: &mut wgui::i18n::I } let translated = if !settings.home_screen.hide_username { - i18n.translate_and_replace("HELLO_USER", ("{USER}", &username)) + common.i18n().translate_and_replace("HELLO_USER", ("{USER}", &username)) } else { - i18n.translate("HELLO").to_string() + common.i18n().translate("HELLO").to_string() }; - label_hello.set_text_simple(i18n, Translation::from_raw_text(&translated)); + let mut label_hello = label_hello.get_as_mut::().unwrap(); + label_hello.set_text(common, Translation::from_raw_text(&translated)); } impl TabHome { @@ -52,8 +55,9 @@ impl TabHome { params.parent_id, )?; - let mut label_hello = state.fetch_widget_as::(¶ms.layout.state, "label_hello")?; - configure_label_hello(&mut label_hello, &mut params.globals.i18n(), params.settings); + let mut c = params.layout.start_common(); + let widget_label = state.fetch_widget(&c.layout.state, "label_hello")?.widget; + configure_label_hello(&mut c.common(), widget_label, params.settings); let btn_apps = state.fetch_component_as::("btn_apps")?; let btn_games = state.fetch_component_as::("btn_games")?; diff --git a/dash-frontend/src/tab/mod.rs b/dash-frontend/src/tab/mod.rs index d13c34f..9139ea7 100644 --- a/dash-frontend/src/tab/mod.rs +++ b/dash-frontend/src/tab/mod.rs @@ -2,7 +2,6 @@ use std::rc::Rc; use wgui::{ components::button::ComponentButton, - event::CallbackDataCommon, globals::WguiGlobals, layout::{Layout, WidgetID}, }; diff --git a/uidev/src/main.rs b/uidev/src/main.rs index 8e178b0..d627240 100644 --- a/uidev/src/main.rs +++ b/uidev/src/main.rs @@ -1,26 +1,26 @@ -use glam::{vec2, Vec2}; +use glam::{Vec2, vec2}; use std::sync::Arc; -use testbed::{testbed_any::TestbedAny, Testbed}; +use testbed::{Testbed, testbed_any::TestbedAny}; use timestep::Timestep; +use tracing_subscriber::EnvFilter; use tracing_subscriber::filter::LevelFilter; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::EnvFilter; use vulkan::init_window; use vulkano::{ + Validated, VulkanError, command_buffer::CommandBufferUsage, format::Format, - image::{view::ImageView, ImageUsage}, + image::{ImageUsage, view::ImageView}, swapchain::{ - acquire_next_image, CompositeAlpha, PresentMode, Surface, SurfaceInfo, Swapchain, - SwapchainCreateInfo, SwapchainPresentInfo, + CompositeAlpha, PresentMode, Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo, + SwapchainPresentInfo, acquire_next_image, }, sync::GpuFuture, - Validated, VulkanError, }; use wgui::{ event::{MouseButtonIndex, MouseDownEvent, MouseMotionEvent, MouseUpEvent, MouseWheelEvent}, - gfx::{cmd::WGfxClearMode, WGfx}, + gfx::{WGfx, cmd::WGfxClearMode}, renderer_vk::{self}, }; use winit::{ @@ -32,7 +32,7 @@ use winit::{ use crate::{ rate_limiter::RateLimiter, testbed::{ - testbed_dashboard::TestbedDashboard, testbed_generic::TestbedGeneric, TestbedUpdateParams, + TestbedUpdateParams, testbed_dashboard::TestbedDashboard, testbed_generic::TestbedGeneric, }, }; @@ -337,7 +337,11 @@ fn main() -> Result<(), Box> { .unwrap(); let mut layout = testbed.layout().borrow_mut(); + let globals = layout.state.globals.clone(); + let mut globals = globals.get(); + let mut draw_params = wgui::drawing::DrawParams { + globals: &mut globals, layout: &mut layout, debug_draw: debug_draw_enabled, alpha: timestep.alpha, @@ -347,7 +351,12 @@ fn main() -> Result<(), Box> { drop(layout); let draw_result = render_context - .draw(&mut shared_context, &mut cmd_buf, &primitives) + .draw( + &globals.font_system, + &mut shared_context, + &mut cmd_buf, + &primitives, + ) .unwrap(); if debug_draw_enabled { diff --git a/uidev/src/testbed/testbed_any.rs b/uidev/src/testbed/testbed_any.rs index 472714a..e453132 100644 --- a/uidev/src/testbed/testbed_any.rs +++ b/uidev/src/testbed/testbed_any.rs @@ -5,6 +5,7 @@ use crate::{ use glam::Vec2; use wgui::{ assets::AssetPath, + font_config::WguiFontConfig, globals::WguiGlobals, layout::{LayoutParams, RcLayout}, parser::{ParseDocumentParams, ParserState}, @@ -24,6 +25,7 @@ impl TestbedAny { let globals = WguiGlobals::new( Box::new(assets::Asset {}), wgui::globals::Defaults::default(), + &WguiFontConfig::default(), )?; let (layout, state) = wgui::parser::new_layout_from_assets( diff --git a/uidev/src/testbed/testbed_generic.rs b/uidev/src/testbed/testbed_generic.rs index c14fa7d..6e790fb 100644 --- a/uidev/src/testbed/testbed_generic.rs +++ b/uidev/src/testbed/testbed_generic.rs @@ -8,11 +8,12 @@ use glam::Vec2; use wgui::{ assets::AssetPath, components::{ + Component, button::{ButtonClickCallback, ComponentButton}, checkbox::ComponentCheckbox, - Component, }, drawing::Color, + font_config::WguiFontConfig, globals::WguiGlobals, i18n::Translation, layout::{Layout, LayoutParams, RcLayout, Widget}, @@ -76,6 +77,7 @@ impl TestbedGeneric { let globals = WguiGlobals::new( Box::new(assets::Asset {}), wgui::globals::Defaults::default(), + &WguiFontConfig::default(), )?; let extra = ParseDocumentExtra { diff --git a/wgui/Cargo.toml b/wgui/Cargo.toml index 4d7b251..d57feb3 100644 --- a/wgui/Cargo.toml +++ b/wgui/Cargo.toml @@ -30,3 +30,4 @@ taffy = "0.9.1" vulkano = { workspace = true } vulkano-shaders = { workspace = true } rust-embed = { workspace = true } +flate2 = "1.1.5" diff --git a/wgui/src/assets.rs b/wgui/src/assets.rs index b70d26c..cdceac1 100644 --- a/wgui/src/assets.rs +++ b/wgui/src/assets.rs @@ -1,3 +1,5 @@ +use flate2::read::GzDecoder; +use std::io::Read; use std::path::{Path, PathBuf}; #[derive(Clone, Copy)] @@ -74,6 +76,13 @@ impl Default for AssetPathOwned { pub trait AssetProvider { fn load_from_path(&mut self, path: &str) -> anyhow::Result>; + fn load_from_path_gzip(&mut self, path: &str) -> anyhow::Result> { + let compressed = self.load_from_path(path)?; + let mut gz = GzDecoder::new(&compressed[..]); + let mut out = Vec::new(); + gz.read_to_end(&mut out)?; + Ok(out) + } } // replace "./foo/bar/../file.txt" with "./foo/file.txt" diff --git a/wgui/src/components/checkbox.rs b/wgui/src/components/checkbox.rs index 63f7287..0138ccc 100644 --- a/wgui/src/components/checkbox.rs +++ b/wgui/src/components/checkbox.rs @@ -8,9 +8,9 @@ use crate::{ animation::{Animation, AnimationEasing}, components::{Component, ComponentBase, ComponentTrait, InitData}, drawing::Color, - event::{CallbackDataCommon, EventAlterables, EventListenerCollection, EventListenerID, EventListenerKind}, + event::{CallbackDataCommon, EventListenerCollection, EventListenerID, EventListenerKind}, i18n::Translation, - layout::{self, LayoutState, WidgetID, WidgetPair}, + layout::{self, WidgetID, WidgetPair}, renderer_vk::text::{FontWeight, TextStyle}, widget::{ ConstructEssentials, EventResult, @@ -53,6 +53,7 @@ struct State { #[allow(clippy::struct_field_names)] struct Data { + #[allow(dead_code)] id_container: WidgetID, // Rectangle, transparent if not hovered //id_outer_box: WidgetID, // Rectangle, parent of container diff --git a/wgui/src/components/mod.rs b/wgui/src/components/mod.rs index 2d24642..c659579 100644 --- a/wgui/src/components/mod.rs +++ b/wgui/src/components/mod.rs @@ -17,6 +17,7 @@ pub struct InitData<'a> { // common component data #[derive(Default)] pub struct ComponentBase { + #[allow(dead_code)] lhandles: Vec, } diff --git a/wgui/src/components/slider.rs b/wgui/src/components/slider.rs index 7768cc7..37e92f2 100644 --- a/wgui/src/components/slider.rs +++ b/wgui/src/components/slider.rs @@ -53,7 +53,8 @@ struct State { } struct Data { - body: WidgetID, // Div + #[allow(dead_code)] + body: WidgetID, // Div slider_handle_rect_id: WidgetID, // Rectangle slider_text_id: WidgetID, // Text slider_handle_node: taffy::NodeId, diff --git a/wgui/src/drawing.rs b/wgui/src/drawing.rs index 75b20f6..2a1ee56 100644 --- a/wgui/src/drawing.rs +++ b/wgui/src/drawing.rs @@ -7,6 +7,7 @@ use taffy::TraversePartialTree; use crate::{ drawing, event::EventAlterables, + globals::Globals, layout::Widget, renderer_vk::text::{TextShadow, custom_glyph::CustomGlyph}, stack::{self, ScissorBoundary, ScissorStack, TransformStack}, @@ -169,6 +170,7 @@ pub enum RenderPrimitive { } pub struct DrawParams<'a> { + pub globals: &'a Globals, pub layout: &'a mut Layout, pub debug_draw: bool, pub alpha: f32, // timestep alpha, 0.0 - 1.0, used for motion interpolation if rendering above tick rate: smoother animations or scrolling @@ -347,6 +349,7 @@ pub fn draw(params: &mut DrawParams) -> anyhow::Result> { let mut alterables = EventAlterables::default(); let mut state = DrawState { + globals: params.globals, primitives: &mut primitives, transform_stack: &mut transform_stack, scissor_stack: &mut scissor_stack, diff --git a/wgui/src/event.rs b/wgui/src/event.rs index beaef43..0b80ffa 100644 --- a/wgui/src/event.rs +++ b/wgui/src/event.rs @@ -2,7 +2,6 @@ use std::{ any::{Any, TypeId}, cell::RefMut, collections::HashSet, - ops::Deref, }; use glam::Vec2; diff --git a/wgui/src/font_config.rs b/wgui/src/font_config.rs new file mode 100644 index 0000000..d6278e7 --- /dev/null +++ b/wgui/src/font_config.rs @@ -0,0 +1,45 @@ +use parking_lot::Mutex; + +#[derive(Default)] +pub struct WguiFontConfig<'a> { + pub binaries: Vec<&'a [u8]>, + pub family_name_sans_serif: &'a str, + pub family_name_serif: &'a str, + pub family_name_monospace: &'a str, +} + +pub struct WguiFontSystem { + pub system: Mutex, +} + +impl WguiFontSystem { + pub fn new(config: &WguiFontConfig) -> Self { + let mut db = cosmic_text::fontdb::Database::new(); + + let system = if config.binaries.is_empty() { + cosmic_text::FontSystem::new() + } else { + for binary in &config.binaries { + // binary data is copied and preserved here + db.load_font_data(binary.to_vec()); + } + + if !config.family_name_sans_serif.is_empty() { + db.set_sans_serif_family(config.family_name_sans_serif); + } + + if !config.family_name_serif.is_empty() { + db.set_serif_family(config.family_name_serif); + } + + // we don't require anything special, at least for now + let locale = String::from("C"); + + cosmic_text::FontSystem::new_with_locale_and_db(locale, db) + }; + + Self { + system: Mutex::new(system), + } + } +} diff --git a/wgui/src/globals.rs b/wgui/src/globals.rs index d0219dc..5250d5a 100644 --- a/wgui/src/globals.rs +++ b/wgui/src/globals.rs @@ -7,6 +7,7 @@ use std::{ use crate::{ assets::{AssetPath, AssetProvider}, assets_internal, drawing, + font_config::{WguiFontConfig, WguiFontSystem}, i18n::I18n, }; @@ -31,13 +32,18 @@ pub struct Globals { pub assets_builtin: Box, pub i18n_builtin: I18n, pub defaults: Defaults, + pub font_system: WguiFontSystem, } #[derive(Clone)] pub struct WguiGlobals(Rc>); impl WguiGlobals { - pub fn new(mut assets_builtin: Box, defaults: Defaults) -> anyhow::Result { + pub fn new( + mut assets_builtin: Box, + defaults: Defaults, + font_config: &WguiFontConfig, + ) -> anyhow::Result { let i18n_builtin = I18n::new(&mut assets_builtin)?; let assets_internal = Box::new(assets_internal::AssetInternal {}); @@ -46,6 +52,7 @@ impl WguiGlobals { assets_builtin, i18n_builtin, defaults, + font_system: WguiFontSystem::new(font_config), })))) } @@ -81,4 +88,8 @@ impl WguiGlobals { pub fn assets_builtin(&self) -> RefMut<'_, Box> { RefMut::map(self.0.borrow_mut(), |x| &mut x.assets_builtin) } + + pub fn font_system(&self) -> RefMut<'_, WguiFontSystem> { + RefMut::map(self.0.borrow_mut(), |x| &mut x.font_system) + } } diff --git a/wgui/src/i18n.rs b/wgui/src/i18n.rs index 9fee6c5..5b5d432 100644 --- a/wgui/src/i18n.rs +++ b/wgui/src/i18n.rs @@ -75,7 +75,7 @@ impl I18n { log::info!("Guessed system language: {lang}"); match lang.as_str() { - "en" | "pl" | "it" | "ja" | "es" => {} + "en" | "pl" | "it" | "ja" | "es" | "de" => {} _ => { log::warn!("Unsupported language \"{}\", defaulting to \"en\".", lang.as_str()); diff --git a/wgui/src/layout.rs b/wgui/src/layout.rs index 5b647a4..285e3b1 100644 --- a/wgui/src/layout.rs +++ b/wgui/src/layout.rs @@ -198,7 +198,7 @@ fn add_child_internal( pub struct LayoutCommon<'a> { alterables: EventAlterables, - layout: &'a mut Layout, + pub layout: &'a mut Layout, } impl LayoutCommon<'_> { @@ -564,6 +564,8 @@ impl Layout { log::debug!("re-computing layout, size {}x{}", size.x, size.y); self.prev_size = size; + let globals = self.state.globals.get(); + self.state.tree.compute_layout_with_measure( self.tree_root_node, taffy::Size { @@ -583,7 +585,10 @@ impl Layout { None => taffy::Size::ZERO, Some(h) => { if let Some(w) = self.state.widgets.get(*h) { - w.0.borrow_mut().obj.measure(known_dimensions, available_space) + w.0 + .borrow_mut() + .obj + .measure(&globals, known_dimensions, available_space) } else { taffy::Size::ZERO } diff --git a/wgui/src/lib.rs b/wgui/src/lib.rs index 682dd71..2e4a45e 100644 --- a/wgui/src/lib.rs +++ b/wgui/src/lib.rs @@ -27,6 +27,7 @@ mod assets_internal; pub mod components; pub mod drawing; pub mod event; +pub mod font_config; pub mod gfx; pub mod globals; pub mod i18n; diff --git a/wgui/src/parser/mod.rs b/wgui/src/parser/mod.rs index 14c3e53..bdc96df 100644 --- a/wgui/src/parser/mod.rs +++ b/wgui/src/parser/mod.rs @@ -8,7 +8,7 @@ mod widget_rectangle; mod widget_sprite; use crate::{ - assets::{normalize_path, AssetPath, AssetPathOwned}, + assets::{AssetPath, AssetPathOwned, normalize_path}, components::{Component, ComponentWeak}, drawing::{self}, globals::WguiGlobals, @@ -624,7 +624,7 @@ pub fn replace_vars(input: &str, vars: &HashMap, Rc>) -> Rc { if let Some(replacement) = vars.get(input_var) { replacement.clone() } else { - log::warn!("failed to replace var named \"{input_var}\" (not found)"); + // failed to find var, return an empty string Rc::from("") } }); diff --git a/wgui/src/parser/style.rs b/wgui/src/parser/style.rs index a3f6094..9180099 100644 --- a/wgui/src/parser/style.rs +++ b/wgui/src/parser/style.rs @@ -65,6 +65,7 @@ pub fn parse_text_style(attribs: &[AttribPair]) -> TextStyle { } }, "weight" => match value { + "light" => style.weight = Some(FontWeight::Light), "normal" => style.weight = Some(FontWeight::Normal), "bold" => style.weight = Some(FontWeight::Bold), _ => { diff --git a/wgui/src/renderer_vk/context.rs b/wgui/src/renderer_vk/context.rs index 2a20aea..3f3247b 100644 --- a/wgui/src/renderer_vk/context.rs +++ b/wgui/src/renderer_vk/context.rs @@ -7,13 +7,14 @@ use vulkano::pipeline::graphics::viewport; use crate::{ drawing::{self}, + font_config, gfx::{WGfx, cmd::GfxCommandBuffer}, }; use super::{ rect::{RectPipeline, RectRenderer}, text::{ - DEFAULT_METRICS, FONT_SYSTEM, SWASH_CACHE, TextArea, TextBounds, + DEFAULT_METRICS, SWASH_CACHE, TextArea, TextBounds, text_atlas::{TextAtlas, TextPipeline}, text_renderer::TextRenderer, }, @@ -51,6 +52,7 @@ impl RendererPass<'_> { fn submit( &mut self, + font_system: &font_config::WguiFontSystem, gfx: &Arc, viewport: &mut Viewport, cmd_buf: &mut GfxCommandBuffer, @@ -90,7 +92,7 @@ impl RendererPass<'_> { self.rect_renderer.render(gfx, viewport, &vk_scissor, cmd_buf)?; { - let mut font_system = FONT_SYSTEM.lock(); + let mut font_system = font_system.system.lock(); let mut swash_cache = SWASH_CACHE.lock(); self.text_renderer.prepare( @@ -217,6 +219,7 @@ impl Context { pub fn draw( &mut self, + font_system: &font_config::WguiFontSystem, shared: &mut SharedContext, cmd_buf: &mut GfxCommandBuffer, primitives: &[drawing::RenderPrimitive], @@ -302,7 +305,13 @@ impl Context { }; for mut pass in passes { - pass.submit(&shared.gfx, &mut self.viewport, cmd_buf, &mut atlas.text_atlas)?; + pass.submit( + font_system, + &shared.gfx, + &mut self.viewport, + cmd_buf, + &mut atlas.text_atlas, + )?; } Ok(res) diff --git a/wgui/src/renderer_vk/text/mod.rs b/wgui/src/renderer_vk/text/mod.rs index 96b587c..8bb5463 100644 --- a/wgui/src/renderer_vk/text/mod.rs +++ b/wgui/src/renderer_vk/text/mod.rs @@ -13,7 +13,6 @@ use parking_lot::Mutex; use crate::drawing::{self}; -pub static FONT_SYSTEM: LazyLock> = LazyLock::new(|| Mutex::new(FontSystem::new())); pub static SWASH_CACHE: LazyLock> = LazyLock::new(|| Mutex::new(SwashCache::new())); /// Used in case no `font_size` is defined @@ -102,6 +101,7 @@ impl From for Style { #[derive(Default, Debug, Clone, Copy)] pub enum FontWeight { + Light, #[default] Normal, Bold, @@ -110,6 +110,7 @@ pub enum FontWeight { impl From for Weight { fn from(value: FontWeight) -> Self { match value { + FontWeight::Light => Self::LIGHT, FontWeight::Normal => Self::NORMAL, FontWeight::Bold => Self::BOLD, } diff --git a/wgui/src/widget/label.rs b/wgui/src/widget/label.rs index a22de38..ef73ecd 100644 --- a/wgui/src/widget/label.rs +++ b/wgui/src/widget/label.rs @@ -8,9 +8,9 @@ use crate::{ drawing::{self, Boundary, PrimitiveExtent}, event::CallbackDataCommon, globals::Globals, - i18n::{I18n, Translation}, + i18n::Translation, layout::WidgetID, - renderer_vk::text::{TextStyle, FONT_SYSTEM}, + renderer_vk::text::TextStyle, }; use super::{WidgetObj, WidgetState}; @@ -41,7 +41,7 @@ impl WidgetLabel { let mut buffer = Buffer::new_empty(metrics); { - let mut font_system = FONT_SYSTEM.lock(); + let mut font_system = globals.font_system.system.lock(); let mut buffer = buffer.borrow_with(&mut font_system); buffer.set_wrap(wrap); @@ -63,19 +63,19 @@ impl WidgetLabel { // set text without layout/re-render update. // Not recommended unless the widget wasn't rendered yet (first init). - pub fn set_text_simple(&mut self, i18n: &mut I18n, translation: Translation) -> bool { + pub fn set_text_simple(&mut self, globals: &mut Globals, translation: Translation) -> bool { if self.params.content == translation { return false; } self.params.content = translation; let attrs = Attrs::from(&self.params.style); - let mut font_system = FONT_SYSTEM.lock(); + let mut font_system = globals.font_system.system.lock(); let mut buffer = self.buffer.borrow_mut(); buffer.set_rich_text( &mut font_system, - [(self.params.content.generate(i18n).as_ref(), attrs)], + [(self.params.content.generate(&mut globals.i18n_builtin).as_ref(), attrs)], &Attrs::new(), Shaping::Advanced, self.params.style.align.map(Into::into), @@ -93,7 +93,9 @@ impl WidgetLabel { // set text and check if it needs to be re-rendered/re-layouted pub fn set_text(&mut self, common: &mut CallbackDataCommon, translation: Translation) { - if self.set_text_simple(&mut common.i18n(), translation) { + let mut globals = common.state.globals.get(); + + if self.set_text_simple(&mut globals, translation) { common.mark_widget_dirty(self.id); } } @@ -113,7 +115,7 @@ impl WidgetObj for WidgetLabel { if self.last_boundary != boundary { self.last_boundary = boundary; - let mut font_system = FONT_SYSTEM.lock(); + let mut font_system = state.globals.font_system.system.lock(); let mut buffer = self.buffer.borrow_mut(); buffer.set_size(&mut font_system, Some(boundary.size.x), Some(boundary.size.y)); } @@ -130,6 +132,7 @@ impl WidgetObj for WidgetLabel { fn measure( &mut self, + globals: &Globals, known_dimensions: taffy::Size>, available_space: taffy::Size, ) -> taffy::Size { @@ -140,7 +143,8 @@ impl WidgetObj for WidgetLabel { AvailableSpace::Definite(width) => Some(width), }); - let mut font_system = FONT_SYSTEM.lock(); + let wgui_font_system = &globals.font_system; + let mut font_system = wgui_font_system.system.lock(); let mut buffer = self.buffer.borrow_mut(); buffer.set_size(&mut font_system, width_constraint, None); diff --git a/wgui/src/widget/mod.rs b/wgui/src/widget/mod.rs index a69eefa..0b4b7c3 100644 --- a/wgui/src/widget/mod.rs +++ b/wgui/src/widget/mod.rs @@ -10,6 +10,7 @@ use crate::{ EventListenerKind::{self, InternalStateChange, MouseLeave}, MouseWheelEvent, }, + globals::Globals, layout::{Layout, LayoutState, WidgetID}, stack::{ScissorStack, TransformStack}, }; @@ -108,6 +109,7 @@ impl WidgetState { // global draw params pub struct DrawState<'a> { + pub globals: &'a Globals, pub layout: &'a Layout, pub primitives: &'a mut Vec, pub transform_stack: &'a mut TransformStack, @@ -151,6 +153,7 @@ pub trait WidgetObj: AnyTrait { fn measure( &mut self, + _globals: &Globals, _known_dimensions: taffy::Size>, _available_space: taffy::Size, ) -> taffy::Size { @@ -181,11 +184,7 @@ impl EventResult { #[must_use] pub fn merge(self, other: Self) -> Self { - if self > other { - self - } else { - other - } + if self > other { self } else { other } } } diff --git a/wgui/src/widget/sprite.rs b/wgui/src/widget/sprite.rs index 7bc9ec3..f1efce4 100644 --- a/wgui/src/widget/sprite.rs +++ b/wgui/src/widget/sprite.rs @@ -5,10 +5,11 @@ use slotmap::Key; use crate::{ drawing::{self, PrimitiveExtent}, + globals::Globals, layout::WidgetID, renderer_vk::text::{ + DEFAULT_METRICS, custom_glyph::{CustomGlyph, CustomGlyphData}, - DEFAULT_METRICS, FONT_SYSTEM, }, }; @@ -67,7 +68,7 @@ impl WidgetObj for WidgetSprite { let mut buffer = Buffer::new_empty(DEFAULT_METRICS); { - let mut font_system = FONT_SYSTEM.lock(); + let mut font_system = state.globals.font_system.system.lock(); let mut buffer = buffer.borrow_with(&mut font_system); let attrs = Attrs::new().color(Color::rgb(255, 0, 255)).weight(Weight::BOLD); @@ -88,6 +89,7 @@ impl WidgetObj for WidgetSprite { fn measure( &mut self, + _globals: &Globals, _known_dimensions: taffy::Size>, _available_space: taffy::Size, ) -> taffy::Size { diff --git a/wlx-overlay-s/src/gui/panel/label.rs b/wlx-overlay-s/src/gui/panel/label.rs index 23a392e..d812585 100644 --- a/wlx-overlay-s/src/gui/panel/label.rs +++ b/wlx-overlay-s/src/gui/panel/label.rs @@ -15,8 +15,8 @@ use wgui::{ event::{self, EventCallback}, i18n::Translation, layout::Layout, - parser::{parse_color_hex, CustomAttribsInfoOwned}, - widget::{label::WidgetLabel, EventResult}, + parser::{CustomAttribsInfoOwned, parse_color_hex}, + widget::{EventResult, label::WidgetLabel}, }; use crate::state::AppState; @@ -123,13 +123,13 @@ pub(super) fn setup_custom_label( let pretty_tz = maybe_pretty_tz.as_ref().map_or("Local", |x| x.as_str()); - let mut i18n = layout.state.globals.i18n(); + let mut globals = layout.state.globals.get(); layout .state .widgets .get_as::(attribs.widget_id) .unwrap() - .set_text_simple(&mut i18n, Translation::from_raw_text(pretty_tz)); + .set_text_simple(&mut globals, Translation::from_raw_text(pretty_tz)); // does not need to be dynamic return; diff --git a/wlx-overlay-s/src/gui/panel/mod.rs b/wlx-overlay-s/src/gui/panel/mod.rs index 954a2f3..43ab0fa 100644 --- a/wlx-overlay-s/src/gui/panel/mod.rs +++ b/wlx-overlay-s/src/gui/panel/mod.rs @@ -1,7 +1,7 @@ use std::{cell::RefCell, rc::Rc, sync::Arc}; use button::setup_custom_button; -use glam::{vec2, Affine2, Vec2}; +use glam::{Affine2, Vec2, vec2}; use label::setup_custom_label; use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView}; use wgui::{ @@ -15,14 +15,14 @@ use wgui::{ layout::{Layout, LayoutParams, WidgetID}, parser::ParserState, renderer_vk::context::Context as WguiContext, - widget::{label::WidgetLabel, rectangle::WidgetRectangle, EventResult}, + widget::{EventResult, label::WidgetLabel, rectangle::WidgetRectangle}, }; use crate::{ backend::input::{Haptics, HoverResult, PointerHit, PointerMode}, graphics::{CommandBuffers, ExtentExt}, state::AppState, - windowing::backend::{ui_transform, FrameMeta, OverlayBackend, ShouldRender}, + windowing::backend::{FrameMeta, OverlayBackend, ShouldRender, ui_transform}, }; use super::{timer::GuiTimer, timestep::Timestep}; @@ -237,13 +237,21 @@ impl OverlayBackend for GuiPanel { wgui::gfx::cmd::WGfxClearMode::Clear([0.0, 0.0, 0.0, 0.0]), )?; + let globals = self.layout.state.globals.clone(); // sorry + let mut globals = globals.get(); + let primitives = wgui::drawing::draw(&mut wgui::drawing::DrawParams { + globals: &mut globals, layout: &mut self.layout, debug_draw: false, alpha, })?; - self.context - .draw(&mut app.wgui_shared, &mut cmd_buf, &primitives)?; + self.context.draw( + &globals.font_system, + &mut app.wgui_shared, + &mut cmd_buf, + &primitives, + )?; cmd_buf.end_rendering()?; buf.push(cmd_buf.build()?); diff --git a/wlx-overlay-s/src/state.rs b/wlx-overlay-s/src/state.rs index c0511fb..ea9d23b 100644 --- a/wlx-overlay-s/src/state.rs +++ b/wlx-overlay-s/src/state.rs @@ -1,10 +1,11 @@ use glam::Affine3A; use idmap::IdMap; use serde::{Deserialize, Serialize}; -use smallvec::{smallvec, SmallVec}; +use smallvec::{SmallVec, smallvec}; use std::sync::Arc; use wgui::{ - gfx::WGfx, globals::WguiGlobals, renderer_vk::context::SharedContext as WSharedContext, + font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals, + renderer_vk::context::SharedContext as WSharedContext, }; #[cfg(feature = "wayvr")] @@ -97,6 +98,7 @@ impl AppState { wgui_globals: WguiGlobals::new( Box::new(gui::asset::GuiAsset {}), wgui::globals::Defaults::default(), + &WguiFontConfig::default(), )?, #[cfg(feature = "osc")]