diff --git a/client/ui/hud.gd b/client/ui/hud.gd index a7ae0c239..9456ed4e6 100644 --- a/client/ui/hud.gd +++ b/client/ui/hud.gd @@ -1,35 +1,59 @@ extends Control -# HUD — displays player health, perception mode, time, etc. +## HUD — implant-styled status panel (D-169, D-170). +## Displays health, perception mode, time in an ImplantPanel. -@onready var health_label: Label = $MarginContainer/VBoxContainer/HealthLabel -@onready var perception_label: Label = $MarginContainer/VBoxContainer/PerceptionLabel -@onready var time_label: Label = $MarginContainer/VBoxContainer/TimeLabel +var _panel: ImplantPanel +var _health_row: ImplantDataRow +var _perception_row: ImplantDataRow +var _time_row: ImplantDataRow +var _theme: ImplantTheme func _ready() -> void: + # Remove the old raw MarginContainer/labels if present + var old := get_node_or_null("MarginContainer") + if old: + old.queue_free() + + _theme = load("res://ui/implant/default_implant.tres") as ImplantTheme + + _panel = ImplantPanel.new() + _panel.name = "StatusPanel" + _panel.theme_resource = _theme + _panel.custom_minimum_size.x = 200.0 + _panel.size.x = 200.0 + _panel.mouse_filter = Control.MOUSE_FILTER_IGNORE + _panel.position = Vector2(16, 16) + add_child(_panel) + _panel.move_child(_panel.get_node("Content"), 0) # ensure content is first + + _health_row = ImplantDataRow.new("Health: 100") + _perception_row = ImplantDataRow.new("Mode: Baseline") + _time_row = ImplantDataRow.new("Time: 08:00") + + _panel.add_component(_health_row) + _panel.add_component(_perception_row) + _panel.add_component(_time_row) + print("HUD: Initialized") -# Update HUD from snapshot data func update_from_hud_data(data: Dictionary) -> void: - # Update perception mode display if data.has("perception_mode"): var prefix := UIStrings.get_text("hud.perception_mode_prefix") if prefix.is_empty(): - perception_label.text = data.perception_mode.capitalize() + _perception_row.text = data.perception_mode.capitalize() else: - perception_label.text = prefix + ": " + data.perception_mode.capitalize() + _perception_row.text = prefix + ": " + data.perception_mode.capitalize() - # Update time display (per D-031) if data.has("time"): var prefix := UIStrings.get_text("hud.time_prefix") if prefix.is_empty(): - time_label.text = data.time + _time_row.text = data.time else: - time_label.text = prefix + ": " + data.time + _time_row.text = prefix + ": " + data.time -# Update player health (from player data, not hud_data) func update_health(health: int) -> void: - health_label.text = UIStrings.get_text("hud.health") + ": " + str(health) + _health_row.text = UIStrings.get_text("hud.health") + ": " + str(health) diff --git a/client/ui/interaction_prompt.gd b/client/ui/interaction_prompt.gd index 10d36f8fb..7ef4fdf21 100644 --- a/client/ui/interaction_prompt.gd +++ b/client/ui/interaction_prompt.gd @@ -24,6 +24,17 @@ func _ready() -> void: modulate.a = 0.0 visible = false _is_showing = false + # D-169: Apply implant theme + var t := load("res://ui/implant/default_implant.tres") as ImplantTheme + if t: + var style := StyleBoxFlat.new() + style.bg_color = t.panel_bg + style.border_color = t.separator + style.set_border_width_all(int(t.border_width)) + style.set_content_margin_all(t.padding) + add_theme_stylebox_override("panel", style) + prompt_label.add_theme_color_override("font_color", t.text_primary) + prompt_label.add_theme_font_size_override("font_size", t.font_body) func _process(_delta: float) -> void: diff --git a/client/ui/stance_indicator.gd b/client/ui/stance_indicator.gd index 29a3c8472..a144037e0 100644 --- a/client/ui/stance_indicator.gd +++ b/client/ui/stance_indicator.gd @@ -1,8 +1,7 @@ extends Control -## D-053: Stance indicator — shows current movement stance on HUD. +## D-053: Stance indicator — implant-styled badge (D-169). ## Sprint/Walk/Careful/Crouch. Color-coded for quick read. -## Lives on UILayer (z-layer 7). const STANCE_COLORS := { "Sprint": Color("#d45d5d"), # Red — fast, loud, dangerous @@ -11,16 +10,23 @@ const STANCE_COLORS := { "Crouch": Color("#e8c547"), # Amber — very quiet, slow } -const STANCE_DEFAULT_COLOR := Color("#c8d0e0") -const BG_COLOR := Color(0.05, 0.05, 0.08, 0.5) -const FONT_SIZE := 13 -const PADDING := Vector2(10, 6) - var _current_stance: String = "Walk" +var _panel: ImplantPanel +var _row: ImplantDataRow func _ready() -> void: mouse_filter = Control.MOUSE_FILTER_IGNORE + var theme_res := load("res://ui/implant/default_implant.tres") as ImplantTheme + + _panel = ImplantPanel.new() + _panel.name = "StancePanel" + _panel.theme_resource = theme_res + _panel.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(_panel) + + _row = ImplantDataRow.new("Walk", STANCE_COLORS["Walk"]) + _panel.add_component(_row) func update_from_state() -> void: @@ -28,32 +34,8 @@ func update_from_state() -> void: if stance == _current_stance: return _current_stance = stance - queue_redraw() - - -func _draw() -> void: - var font := ThemeDB.fallback_font - var text := _current_stance - var text_size := font.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE) - var box_size := text_size + PADDING * 2 - - # Background - draw_rect(Rect2(Vector2.ZERO, box_size), BG_COLOR) - - # Stance text - var color: Color = STANCE_COLORS.get(_current_stance, STANCE_DEFAULT_COLOR) - draw_string( - font, - PADDING + Vector2(0, text_size.y), - text, - HORIZONTAL_ALIGNMENT_LEFT, - -1, - FONT_SIZE, - color - ) - - -# -- Public API --------------------------------------------------------------- + var color: Color = STANCE_COLORS.get(stance, Color("#c8d0e0")) + _row.set_content(stance, color) func get_current_stance() -> String: