From 40768f3b0a58c372ac876c29d8f57513d93fb78d Mon Sep 17 00:00:00 2001 From: funman300 Date: Tue, 19 May 2026 14:45:49 -0700 Subject: [PATCH] feat(engine): scale action-bar glyph font size dynamically on Android MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bottom bar's 7 icon buttons (≡ ← || ? ! M +) used TYPE_BODY = 14 px, a fixed size that is too small on phone screens. New behaviour: - `action_bar_font_size(window_width)` returns `(window_width / 40).clamp(16, 30)`, giving ~22 px on a 900 logical-px phone and ~16 px on narrow viewports. - `ActionButtonLabel` marker added to each button's text node (Android only). - `spawn_action_buttons` reads `Query<&Window>` at startup to apply the correct initial size before the first frame renders. - `resize_action_bar_labels` system re-runs whenever `LayoutResource` changes (window resize / orientation change) to keep glyphs in sync. Co-Authored-By: Claude Sonnet 4.6 --- solitaire_engine/src/hud_plugin.rs | 56 +++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/solitaire_engine/src/hud_plugin.rs b/solitaire_engine/src/hud_plugin.rs index 87b543e..32e420b 100644 --- a/solitaire_engine/src/hud_plugin.rs +++ b/solitaire_engine/src/hud_plugin.rs @@ -140,6 +140,12 @@ pub struct HudColumn; #[derive(Component, Debug)] pub struct HudActionBar; +/// Marker on the text node inside each action-bar button (Android only). +/// Used by `resize_action_bar_labels` to update font size on window resize. +#[cfg(target_os = "android")] +#[derive(Component, Debug)] +struct ActionButtonLabel; + /// Marker on the circular profile-picture button anchored to the /// top-right of the HUD band. Pressing it opens the Profile overlay. /// Shows the server avatar image when loaded; falls back to the player's @@ -489,6 +495,11 @@ impl Plugin for HudPlugin { .after(TouchDragSet::AfterStartDrag) .in_set(TouchDragSet::BeforeEndDrag), ); + app.add_systems( + Update, + resize_action_bar_labels + .run_if(resource_exists_and_changed::), + ); } } } @@ -843,11 +854,25 @@ fn handle_avatar_button( /// on its own visual edge. fn spawn_action_buttons( font_res: Option>, + windows: Query<&Window>, mut commands: Commands, ) { + // On Android the glyph labels must scale with the viewport so they remain + // legible on any screen density. Use the window width at startup; the + // resize_action_bar_labels system keeps this current on window changes. + #[cfg(target_os = "android")] + let action_font_size = { + let w = windows.iter().next().map_or(900.0, |win| win.width()); + action_bar_font_size(w) + }; + #[cfg(not(target_os = "android"))] + let action_font_size = TYPE_BODY; + #[cfg(not(target_os = "android"))] + let _windows = windows; + let font = TextFont { font: font_res.as_ref().map(|f| f.0.clone()).unwrap_or_default(), - font_size: TYPE_BODY, + font_size: action_font_size, ..default() }; @@ -992,6 +1017,9 @@ fn spawn_action_button( HighContrastBorder::with_default(BORDER_SUBTLE), )) .with_children(|b| { + #[cfg(target_os = "android")] + b.spawn((ActionButtonLabel, Text::new(label), font.clone(), TextColor(text_color))); + #[cfg(not(target_os = "android"))] b.spawn((Text::new(label), font.clone(), TextColor(text_color))); if let Some(key) = hotkey { // Hotkey hint rendered as a dim caption next to the label — @@ -2483,6 +2511,32 @@ fn restore_hud_on_modal( } } +/// Returns the action-bar glyph font size for a given logical window width. +/// Scales linearly so glyphs remain legible at any phone density. +#[cfg(target_os = "android")] +fn action_bar_font_size(window_width: f32) -> f32 { + // ~1/40 of the window width gives ~22 px on a 900 logical-px phone. + // Clamped so it never goes too tiny on narrow viewports or too large + // on landscape tablets. + (window_width / 40.0).clamp(16.0, 30.0) +} + +/// Resizes the glyph text inside every [`ActionButtonLabel`] to match the +/// current viewport width whenever [`LayoutResource`] changes (orientation +/// change or window resize). +#[cfg(target_os = "android")] +fn resize_action_bar_labels( + layout: Res, + windows: Query<&Window>, + mut labels: Query<&mut TextFont, With>, +) { + let w = windows.iter().next().map_or(layout.0.card_size.x * 7.25, |win| win.width()); + let new_size = action_bar_font_size(w); + for mut font in &mut labels { + font.font_size = new_size; + } +} + #[cfg(target_os = "android")] fn toggle_hud_on_tap( mut touch_events: MessageReader,