Harden UI layout for font scale and long strings
Full build / Import + headless tests (push) Successful in 36s
Full build / Full desktop build + optional release (push) Skipped

- Measure and cap the HUD target chip after each font-scale change; clip HUD top labels.
- Ellipsize long action-button labels so panels cannot grow past the viewport.
- Add accessibility/button layout assertions and refresh the gallery captures.
- Record the font/layout pass in TODO, docs, changelog and memory.
This commit is contained in:
Gig Line Dev committed 2026-11-02 16:23:46 +01:00
1 parent 26e6dd6413
commit f6aa26e6ca
20 files changed
+69 -7

No files matched your search

+17
View File
@@ -82,9 +82,11 @@ func _init() -> void:
top_label = Label.new()
top_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
top_label.clip_text = true
top.add_child(top_label)
time_label = Label.new()
time_label.clip_text = true
top.add_child(time_label)
var spacer := Control.new()
@@ -122,6 +124,7 @@ func _init() -> void:
target_label = Label.new()
target_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
target_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
target_label.clip_text = true
target_label.add_theme_font_size_override("font_size", 17)
_target_chip.add_child(target_label)
@@ -394,6 +397,17 @@ func set_target_label(text: String) -> void:
target_label.text = text
if _target_chip:
_target_chip.visible = text.strip_edges() != ""
# The chip is fixed around the crosshair; widen it for long names and
# larger HUD font scales instead of letting the text spill over the world.
var font := target_label.get_theme_font("font")
var font_size := target_label.get_theme_font_size("font_size")
var text_width := font.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1.0, font_size).x
var chip_width := clampf(text_width + 32.0, 180.0, 420.0)
_target_chip.offset_left = -chip_width * 0.5
_target_chip.offset_right = chip_width * 0.5
var chip_height := maxf(40.0, font.get_height(font_size) + 16.0)
_target_chip.offset_top = 38.0
_target_chip.offset_bottom = 38.0 + chip_height
## How many people the aim-free ring (Tab / mouse wheel) can cycle through.
func set_nearby_hint(count: int) -> void:
@@ -447,6 +461,9 @@ func set_font_scale(scale: float) -> void:
_base_font_sizes[label] = label.get_theme_font_size("font_size")
var base: int = int(_base_font_sizes[label])
label.add_theme_font_size_override("font_size", maxi(8, int(round(float(base) * clamped))))
# Recompute the target chip after its font size changed.
if target_label:
set_target_label(target_label.text)
func _make_icon(texture: Texture2D) -> TextureRect:
var tr := TextureRect.new()
+4
View File
@@ -21,6 +21,10 @@ static func apply_button(button: Button, font_size: int = 0, compact: bool = fal
return
if font_size > 0:
button.add_theme_font_size_override("font_size", font_size)
# Long localized labels must not push a panel past the viewport. The
# buttons keep their existing minimum width and ellipsize if needed.
button.clip_text = true
button.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
var margin_h := 12 if compact else 18
var margin_v := 7 if compact else 10
var normal := _box(SURFACE, margin_h, margin_v)
+11 -1
View File
@@ -49,8 +49,18 @@ func test_font_scale_applies_to_core_labels() -> bool:
hud.set_font_scale(9.0)
var capped: int = hud.top_label.get_theme_font_size("font_size")
var f := TestUtils.check(capped <= int(round(float(base_top) * 1.75)) + 1, "scale clamps at 1.75")
# The target chip must widen with the scaled font instead of spilling over
# the world; an extreme name is capped rather than pushing off-screen.
hud.set_font_scale(1.75)
hud.set_target_label("Intoxicated Pedestrian")
var chip = hud.get("_target_chip")
var chip_width: float = float(chip.offset_right) - float(chip.offset_left)
var g := TestUtils.check(chip_width > 300.0, "target chip widens at max font scale")
hud.set_target_label("An Extraordinarily Long Display Name For A Visitor In A Pseudo Locale")
var long_width: float = float(chip.offset_right) - float(chip.offset_left)
var h := TestUtils.check(long_width <= 420.5, "target chip caps an extreme name")
hud.free()
return a and b and c and d and e and f
return a and b and c and d and e and f and g and h
func test_settings_font_scale_is_applied_after_ui_exists() -> bool:
## The HUD is created after settings load, so the manager must re-apply.
+5 -1
View File
@@ -23,8 +23,12 @@ func test_shared_button_states_are_complete() -> bool:
var c := TestUtils.check(disabled != null and normal != null
and disabled.bg_color != normal.bg_color,
"the disabled state is visually distinct from normal")
button.text = "A very long localized action label that must not push the panel beyond the viewport"
var d := TestUtils.check(button.clip_text
and button.get_combined_minimum_size().x < 100.0,
"long action labels ellipsize instead of forcing a wide panel")
button.free()
return a and b and c
return a and b and c and d
func test_focus_helper_skips_hidden_and_disabled_controls() -> bool:
var hidden := Button.new()