refactor(ui): convert HUD status + interaction prompt to implant (#786, #788)

HUD: merge TimeDisplay into ImplantPanel (time/health/perception in one
panel), remove dead tscn nodes, move HUD to InsertOverlay for D-051 bloom.
Interaction prompt: convert from PanelContainer+StyleBoxFlat to Control
with ImplantPanel+ImplantDataRow, fix panel height for 42px minimum.
Tests updated for new scene structure and public API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-06 12:51:58 +02:00
co-authored by Claude Opus 4.6
parent 3c7231e275
commit 283518d332
8 changed files with 76 additions and 97 deletions
+5 -11
View File
@@ -222,15 +222,9 @@ func test_interact_with_data_encodes_as_data_variant() -> void:
# -- Helpers --
func _make_prompt() -> PanelContainer:
func _make_prompt() -> Control:
var PromptScript = load("res://ui/interaction_prompt.gd")
var panel = PanelContainer.new()
panel.set_script(PromptScript)
var margin = MarginContainer.new()
margin.name = "MarginContainer"
panel.add_child(margin)
var label = Label.new()
label.name = "PromptLabel"
margin.add_child(label)
add_child(panel)
return panel
var ctrl = Control.new()
ctrl.set_script(PromptScript)
add_child(ctrl) # triggers _ready() which creates ImplantPanel + ImplantDataRow
return ctrl
+11 -11
View File
@@ -5,15 +5,15 @@
## D-031 (game time: 10 ticks = 1 game-minute, 1440 min/day, HH:MM display)
## D-051 (diegetic insert display)
##
## Implementation: client/ui/time_display.gd — draw-based Control at InsertOverlay/TimeDisplay.
## Implementation: client/ui/time_display.gd — draw-based Control (removed from main scene #786;
## time display merged into HUD ImplantPanel at UILayer/HUD, see test_hud_* tests below).
## Format function: Constants.format_game_time(time_of_day: int) -> String (extracted for
## testability from time_display.gd:46 inline Constants.format_game_time(tod)).
## testability from time_display.gd).
##
## Private state access: Tests read _time_str, _phase_str, _day_str, _has_data directly
## because time_display.gd is draw-based (no Label nodes to inspect). This is an accepted
## test pattern for draw-based UI — the private vars ARE the rendered output contract.
## If the rendering approach changes (e.g. to Label nodes), these tests should switch to
## reading Label.text via public node paths instead.
## Scene integration tests now check UILayer/HUD.get_time_text() instead.
class_name TestTimeDisplaySprint17
extends GdUnitTestSuite
@@ -273,18 +273,18 @@ func test_sim_bridge_day_phase_is_valid() -> void:
# -------------------------------------------------------------------------
# Scene: InsertClock node at InsertOverlay/TimeDisplay
# Scene: HUD panel at UILayer/HUD (time row merged in, TimeDisplay removed #786)
# -------------------------------------------------------------------------
func test_insert_clock_exists_in_ui_layer() -> void:
func test_hud_panel_exists_in_ui_layer() -> void:
var scene := MAIN_SCENE
var instance = scene.instantiate()
auto_free(instance)
add_child(instance)
assert_that(instance.get_node_or_null("InsertOverlay/TimeDisplay")).is_not_null()
assert_that(instance.get_node_or_null("UILayer/HUD")).is_not_null()
func test_insert_clock_time_str_updates_after_process() -> void:
func test_hud_time_row_updates_after_process() -> void:
var scene := MAIN_SCENE
var instance = scene.instantiate()
auto_free(instance)
@@ -296,9 +296,9 @@ func test_insert_clock_time_str_updates_after_process() -> void:
})
instance._process(0.016)
var clock = instance.get_node_or_null("InsertOverlay/TimeDisplay")
assert_that(clock).is_not_null()
assert_that(clock._time_str).is_equal("12:00")
var hud = instance.get_node_or_null("UILayer/HUD")
assert_that(hud).is_not_null()
assert_that(hud.get_time_text()).is_equal("12:00 · Afternoon · D1")
# -------------------------------------------------------------------------