diff --git a/TODO.md b/TODO.md index 502b16a..1ce02cc 100644 --- a/TODO.md +++ b/TODO.md @@ -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. diff --git a/src/game/ui/hud.gd b/src/game/ui/hud.gd index 928ddee..b4a546f 100644 --- a/src/game/ui/hud.gd +++ b/src/game/ui/hud.gd @@ -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)