Add accessibility pass: escalation meter and working HUD font scale
- Escalation cue now includes a shape meter and numeric level
("Escalation: Blocking [###--] L3/5") in addition to the colour and name, so it
reads in grayscale. Hud.escalation_meter(level) is pure and tested.
- HUD font scale from settings actually works: set_font_scale() resizes fonts via
theme overrides instead of Control.scale, which pushed the right-anchored clock
label off-screen. It now covers the top, log, target, hint, time, mode,
escalation, cooldown, and debug labels.
- Settings load before the HUD exists, so _ready() re-applies player settings after
_build_ui(); previously a saved font scale was ignored until the next apply.
Tests/docs
- Headless suite 134 -> 139 (test_accessibility.gd).
- Verified visually at 1.4x scale: no overflow, meter readable.
- README, TODO section moved to DONE, MEMORY. Version 0.2.9.
This commit is contained in:
1 parent
294ac17333
commit
3f4ac7e9aa
15 files changed
+115
-21
No files matched your search
+24
-9
@@ -49,6 +49,8 @@ var _debug_enabled := false
|
||||
var _log_lines: Array[String] = []
|
||||
var _cam_overlay: Control = null
|
||||
var _body_camera_on := false
|
||||
var _font_scale := 1.0
|
||||
var _base_font_sizes: Dictionary = {}
|
||||
|
||||
func _init() -> void:
|
||||
name = "HUD"
|
||||
@@ -300,16 +302,20 @@ func is_body_camera_on() -> bool:
|
||||
return _body_camera_on
|
||||
|
||||
## Scale the whole HUD text block (accessibility settings).
|
||||
## Resize HUD text by changing font sizes (not Control.scale, which overflows
|
||||
## anchored labels and breaks the right-aligned layout).
|
||||
func set_font_scale(scale: float) -> void:
|
||||
var clamped := clampf(scale, 0.75, 1.75)
|
||||
if top_label:
|
||||
top_label.scale = Vector2(clamped, clamped)
|
||||
if log_label:
|
||||
log_label.scale = Vector2(clamped, clamped)
|
||||
if target_label:
|
||||
target_label.scale = Vector2(clamped, clamped)
|
||||
if hint_label:
|
||||
hint_label.scale = Vector2(clamped, clamped)
|
||||
_font_scale = clamped
|
||||
var scaled: Array[Label] = [top_label, log_label, target_label, hint_label,
|
||||
time_label, mode_label, escalation_label, radio_cooldown_label, debug_label]
|
||||
for label in scaled:
|
||||
if label == null:
|
||||
continue
|
||||
if not _base_font_sizes.has(label):
|
||||
_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))))
|
||||
|
||||
func _make_icon(texture: Texture2D) -> TextureRect:
|
||||
var tr := TextureRect.new()
|
||||
@@ -353,9 +359,18 @@ func set_action_hint(text: String) -> void:
|
||||
|
||||
## Color-coded escalation feedback (PLAN.md: Polish and Accessibility).
|
||||
## Green → yellow → orange → red as the escalation level rises.
|
||||
## Grayscale-safe escalation meter: filled/empty blocks plus the level number, so
|
||||
## the cue does not rely on hue alone (accessibility).
|
||||
static func escalation_meter(level: int) -> String:
|
||||
var clamped := clampi(level, 0, 5)
|
||||
var filled := ""
|
||||
for i in 5:
|
||||
filled += "#" if i < clamped else "-"
|
||||
return "[%s] L%d/5" % [filled, clamped]
|
||||
|
||||
func set_escalation(level: int) -> void:
|
||||
var name: String = Rules.LEVEL_NAMES.get(level, "Observation")
|
||||
escalation_label.text = Strings.fmt("hud.escalation_prefix", [name])
|
||||
escalation_label.text = "%s %s" % [Strings.fmt("hud.escalation_prefix", [name]), escalation_meter(level)]
|
||||
var tint := Color(0.6, 0.9, 0.6)
|
||||
match level:
|
||||
Rules.Level.OBSERVATION, Rules.Level.SIMPLE_DETERRENCE:
|
||||
|
||||
Reference in new issue
Block a user