Align the HUD target chip and escalation meter with the mockups

Move the target name out of the top-left stack into a boxed chip under the
crosshair, keep the log/hints left and shift status right, and add a five-segment
escalation bar under the existing color-coded label. Empty targets hide the
chip. Headless 226/226 verified in a clean HEAD worktree.
This commit is contained in:
zwitschi committed 2026-11-01 16:36:06 +01:00
1 parent cb65a5a601
commit 3030c60ae1
2 files changed
+48 -3

No files matched your search

+1 -1
View File
@@ -55,7 +55,7 @@ and scene visuals with those mockups — verified with
### Align in-game visuals
- [x] Make the venue selection screen match the `start_menu` mockup (layout, palette, background).
- [ ] Make the HUD match the `targeting_npc` / `escalation_hud` mockups (focus ring, escalation meter, log, hints).
- [x] Make the HUD match the `targeting_npc` / `escalation_hud` mockups (focus ring, escalation meter, log, hints).
- [x] Align the pause, settings, and shift-review panels to their mockups.
- [x] Align the radio and wand panels to their mockups.
- [x] Align the body-camera timeline to its mockup.
+47 -2
View File
@@ -47,6 +47,8 @@ var wand_text: Label
var wand_meta: Label
var escalation_label: Label
var precision_label: Label
var _target_chip: PanelContainer = null
var _escalation_segments: Array[ColorRect] = []
var _controls_label: Label
var _debug_enabled := false
@@ -87,9 +89,39 @@ func _init() -> void:
spacer.custom_minimum_size = Vector2(0, 6)
vbox.add_child(spacer)
# Target name sits in a small boxed chip just below the crosshair, matching
# the targeting mockup rather than pushing the whole HUD column down.
_target_chip = PanelContainer.new()
_target_chip.name = "TargetChip"
_target_chip.set_anchors_preset(Control.PRESET_CENTER)
_target_chip.offset_left = -150
_target_chip.offset_right = 150
_target_chip.offset_top = 38
_target_chip.offset_bottom = 78
_target_chip.mouse_filter = Control.MOUSE_FILTER_IGNORE
_target_chip.visible = false
var chip_style := StyleBoxFlat.new()
chip_style.bg_color = Color(0.06, 0.075, 0.09, 0.82)
chip_style.border_color = Color(0.82, 0.84, 0.86, 0.3)
chip_style.border_width_left = 1
chip_style.border_width_top = 1
chip_style.border_width_right = 1
chip_style.border_width_bottom = 1
chip_style.corner_radius_top_left = 8
chip_style.corner_radius_top_right = 8
chip_style.corner_radius_bottom_left = 8
chip_style.corner_radius_bottom_right = 8
chip_style.content_margin_left = 12
chip_style.content_margin_right = 12
chip_style.content_margin_top = 6
chip_style.content_margin_bottom = 6
_target_chip.add_theme_stylebox_override("panel", chip_style)
add_child(_target_chip)
target_label = Label.new()
target_label.add_theme_font_size_override("font_size", 16)
vbox.add_child(target_label)
target_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
target_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
target_label.add_theme_font_size_override("font_size", 17)
_target_chip.add_child(target_label)
nearby_label = Label.new()
nearby_label.add_theme_font_size_override("font_size", 12)
@@ -154,6 +186,15 @@ func _init() -> void:
escalation_label.add_theme_font_size_override("font_size", 13)
escalation_label.modulate = Color(0.6, 0.9, 0.6)
vbox.add_child(escalation_label)
var esc_row := HBoxContainer.new()
esc_row.add_theme_constant_override("separation", 4)
vbox.add_child(esc_row)
for i in 5:
var segment := ColorRect.new()
segment.custom_minimum_size = Vector2(26, 7)
segment.color = Color(0.2, 0.22, 0.26, 0.8)
esc_row.add_child(segment)
_escalation_segments.append(segment)
# --- escalation vignette (screen-space tint) ---
vignette_rect = TextureRect.new()
@@ -313,6 +354,8 @@ func _update_radio_cooldown(coordinator: Object) -> void:
func set_target_label(text: String) -> void:
target_label.text = text
if _target_chip:
_target_chip.visible = text.strip_edges() != ""
## How many people the aim-free ring (Tab / mouse wheel) can cycle through.
func set_nearby_hint(count: int) -> void:
@@ -446,6 +489,8 @@ func set_escalation(level: int) -> void:
Rules.Level.RADIO_ASSIST, Rules.Level.EMERGENCY:
tint = Color(1.0, 0.35, 0.3)
escalation_label.modulate = tint
for i in _escalation_segments.size():
_escalation_segments[i].color = tint if i < clampi(level, 0, 5) else Color(0.2, 0.22, 0.26, 0.8)
# Screen-space vignette follows the escalation color.
if vignette_rect:
vignette_rect.modulate = Color(tint.r, tint.g, tint.b, 0.05 + 0.2 * float(level) / 5.0)