Record original-alignment implementation and traceability checkpoint
Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
This commit is contained in:
@@ -35,6 +35,40 @@ func _run() -> void:
|
||||
await process_frame
|
||||
await process_frame
|
||||
_preview = _main.find_child("WorldPreview", true, false) as WorldPreview
|
||||
# A deferred tick must retain its retry UI through the compact projection.
|
||||
var previous_deferred: int = _runtime.get("_operations_deferred_runtime_minute")
|
||||
_runtime.set("_operations_deferred_runtime_minute", _clock.absolute_minute)
|
||||
_main.call("_update_pause_and_speed")
|
||||
_expect((_main.get("pause_button") as Button).text == "運営再試行", "compact projection preserves deferred tick retry button")
|
||||
_expect((_main.get("phase_label") as Label).text == "要確認", "compact projection preserves deferred tick warning")
|
||||
_runtime.set("_operations_deferred_runtime_minute", previous_deferred)
|
||||
_main.call("_update_pause_and_speed")
|
||||
_expect((_main.get("pause_button") as Button).text == "再開", "cleared deferred tick restores paused resume button")
|
||||
var before_weather: Dictionary = _runtime.create_snapshot()
|
||||
_expect(_runtime.weather.schedule(&"storm", _clock.absolute_minute + 1)[&"ok"], "schedule storm for visible weather boundary")
|
||||
_clock.advance_minutes(1)
|
||||
_main.call("_refresh_dashboard")
|
||||
_expect((_main.get("weather_label") as Label).text == "嵐", "HUD shows actual Runtime storm")
|
||||
if OS.get_environment("THE_TREE_WEATHER_CAPTURE") == "1":
|
||||
await process_frame
|
||||
await RenderingServer.frame_post_draw
|
||||
_expect(root.get_texture().get_image().save_png(ProjectSettings.globalize_path("res://artifacts/weather-2026-09-29/storm-hud.png")) == OK, "capture rendered storm HUD")
|
||||
_expect(_runtime.restore_snapshot(before_weather), "restore weather before UI drill")
|
||||
_main.call("_refresh_dashboard")
|
||||
_expect((_main.get("weather_label") as Label).text == "晴れ", "HUD follows restored weather state")
|
||||
var mana_label := (_main.get("resource_labels") as Dictionary)[&"mana"] as Label
|
||||
var original_mana_color := mana_label.get_theme_color("font_color")
|
||||
var original_mana: int = _state.get_resource(&"mana")
|
||||
_state.set_resource(&"mana", 0)
|
||||
_expect("停止" in mana_label.text and "0" in mana_label.text, "resource signal visibly identifies zero-reserve outage")
|
||||
_expect("残量と配電" in mana_label.tooltip_text and "休止は解除されません" in mana_label.tooltip_text, "mana HUD explains recovery without promising suspension reset")
|
||||
if OS.get_environment("THE_TREE_MANA_CAPTURE") == "1":
|
||||
await process_frame
|
||||
await RenderingServer.frame_post_draw
|
||||
var capture := ProjectSettings.globalize_path("res://artifacts/mana-2026-09-29/outage-hud.png")
|
||||
_expect(root.get_texture().get_image().save_png(capture) == OK, "capture rendered outage HUD")
|
||||
_state.set_resource(&"mana", original_mana)
|
||||
_expect(not "停止" in mana_label.text and mana_label.get_theme_color("font_color") == original_mana_color, "resource recovery clears outage label and alert color")
|
||||
|
||||
_expect(_preview != null, "dashboard creates the live world preview")
|
||||
var visual_theme := _main.get("visual_theme") as VisualThemeProfile
|
||||
@@ -49,7 +83,7 @@ func _run() -> void:
|
||||
"world preview consumes the scene theme instead of hard-coded asset paths"
|
||||
)
|
||||
_expect(
|
||||
visual_theme.facility_icons.size() == 18
|
||||
visual_theme.facility_icons.size() == 23
|
||||
and visual_theme.navigation_icons.size() == 6
|
||||
and visual_theme.resource_icons.size() == 4
|
||||
and visual_theme.control_icons.size() == 6,
|
||||
@@ -88,16 +122,36 @@ func _run() -> void:
|
||||
_expect(bool(operations.get(&"enabled", false)), "dashboard enables the production Operations loop")
|
||||
var summary := _main.get("dashboard_summary_label") as Label
|
||||
_expect(
|
||||
summary != null and "行動点" in summary.text and "未払給与" in summary.text,
|
||||
summary != null and "行動点" in summary.text and "未払経費" in summary.text,
|
||||
"dashboard exposes action points and payroll arrears"
|
||||
)
|
||||
await _test_defense_notice()
|
||||
var palette := _main.find_child("BuildPalette", true, false) as GridContainer
|
||||
_expect(palette.get_child_count() == 18, "all sixteen MVP facilities and two stairs appear in the build palette")
|
||||
_expect(palette.get_child_count() == 23, "all23 facilities including the cleaning room appear in the build palette")
|
||||
var iconized_build_buttons := 0
|
||||
for build_button_value: Variant in (_main.get("build_buttons") as Dictionary).values():
|
||||
if (build_button_value as Button).icon != null:
|
||||
iconized_build_buttons += 1
|
||||
_expect(iconized_build_buttons == 18, "all facility catalog buttons consume theme-provided icons")
|
||||
_expect(iconized_build_buttons == 23, "all facility catalog buttons consume theme-provided icons")
|
||||
var premium_button: Button = (_main.get("build_buttons") as Dictionary)[&"premium_room"]
|
||||
_main.call("_set_build_palette_open", true)
|
||||
premium_button.button_pressed = true
|
||||
_expect(_main.get("_selected_definition_id") == &"premium_room" and _main.get("_selected_definition").footprint == Vector2i(4,1), "premium palette button selects original-size placement definition")
|
||||
if OS.get_environment("THE_TREE_PREMIUM_CAPTURE") == "1":
|
||||
await process_frame
|
||||
await RenderingServer.frame_post_draw
|
||||
_expect(root.get_texture().get_image().save_png(ProjectSettings.globalize_path("res://artifacts/facility-dimensions-2026-09-29/premium-palette.png")) == OK, "capture premium room palette")
|
||||
premium_button.button_pressed = false
|
||||
var dorm_button: Button = (_main.get("build_buttons") as Dictionary)[&"staff_dormitory"]
|
||||
dorm_button.button_pressed = true
|
||||
_expect(_main.get("_selected_definition_id") == &"staff_dormitory" and _main.get("_selected_definition").footprint == Vector2i(2,1) and _preview.layer_mode == WorldPreview.LayerMode.BACK, "dormitory palette selects original footprint and back layer")
|
||||
if OS.get_environment("THE_TREE_DORMITORY_CAPTURE") == "1":
|
||||
await process_frame
|
||||
await RenderingServer.frame_post_draw
|
||||
_expect(root.get_texture().get_image().save_png(ProjectSettings.globalize_path("res://artifacts/facility-dimensions-2026-09-29/dormitory-palette.png")) == OK, "capture dormitory palette")
|
||||
dorm_button.button_pressed = false
|
||||
_main.call("_set_layer", 0)
|
||||
_main.call("_set_build_palette_open", false)
|
||||
var palette_scroll := _main.find_child("BuildPaletteScroll", true, false) as ScrollContainer
|
||||
_expect(
|
||||
palette_scroll != null and palette_scroll.is_ancestor_of(palette),
|
||||
@@ -124,7 +178,7 @@ func _run() -> void:
|
||||
_expect(alert_icon != null and alert_icon.texture != null, "top HUD consumes the theme warning icon")
|
||||
var selected_icon := _main.find_child("SelectedEntityIcon", true, false) as TextureRect
|
||||
_expect(selected_icon != null, "facility inspector reserves a theme-driven identity icon")
|
||||
var guest_count := _main.get("guest_count_label") as Label
|
||||
var guest_count := _main.get("guest_count_label") as Button
|
||||
var lodging_count := _main.get("lodging_count_label") as Label
|
||||
var alert_count := _main.get("alert_count_label") as Label
|
||||
_expect(
|
||||
@@ -187,9 +241,9 @@ func _test_staff_candidate_hiring_ui() -> void:
|
||||
var toggle := _main.find_child("StaffCandidateToggleButton", true, false) as Button
|
||||
var buttons := _main.get("staff_candidate_buttons") as Dictionary
|
||||
_expect(panel != null and not panel.visible, "staff candidate screen starts collapsed")
|
||||
_expect(list != null and list.get_child_count() == 20, "all twenty validated Staff candidates have UI cards")
|
||||
_expect(toggle != null and "20" in toggle.text, "collapsed hiring control exposes the available candidate count")
|
||||
_expect(buttons.size() == 20 and buttons.has(&"staff_akane"), "every candidate has a stable hire control")
|
||||
_expect(list != null and list.get_child_count() == 22, "twenty-one general candidates plus approved Anri recruitment have UI cards")
|
||||
_expect(toggle != null and "22" in toggle.text, "collapsed hiring control exposes the available candidate count")
|
||||
_expect(buttons.size() == 22 and buttons.has(&"staff_akane") and buttons.has(&"heroine_anri"), "every candidate has a stable hire control")
|
||||
var akane_detail := _main.find_child("CandidateDetail_staff_akane", true, false) as Label
|
||||
_expect(
|
||||
akane_detail != null
|
||||
@@ -264,6 +318,21 @@ func _test_excavation_rank_gate_and_tool_exclusion() -> void:
|
||||
_expect(reception_button != null and not reception_button.button_pressed, "exclusive excavation mode clears the palette toggle")
|
||||
_main.call("_unhandled_key_input", _key_event(KEY_ESCAPE))
|
||||
_expect(not bool(_main.get("_excavation_mode")) and not _preview.excavation_mode, "Escape exits excavation mode")
|
||||
var pan_button := _main.find_child("PanModeButton", true, false) as Button
|
||||
_expect(pan_button != null, "camera movement has a visible text button")
|
||||
_main.call("_select_build_definition", &"reception")
|
||||
pan_button.pressed.emit()
|
||||
_expect(_preview.pan_mode and pan_button.button_pressed and _main.get("_selected_definition") == null,
|
||||
"pan button exits construction so a camera drag cannot place a facility")
|
||||
_main.call("_select_build_definition", &"reception")
|
||||
_expect(not _preview.pan_mode and not pan_button.button_pressed, "choosing construction exits pan mode")
|
||||
pan_button.pressed.emit()
|
||||
_main.call("_unhandled_key_input", _key_event(KEY_E))
|
||||
_expect(not _preview.pan_mode and _preview.excavation_mode, "excavation exits pan mode")
|
||||
pan_button.pressed.emit()
|
||||
_expect(_preview.pan_mode and not _preview.excavation_mode, "pan mode exits excavation")
|
||||
_main.call("_unhandled_key_input", _key_event(KEY_ESCAPE))
|
||||
_expect(not _preview.pan_mode and not pan_button.button_pressed, "Escape exits pan mode and resets its button")
|
||||
|
||||
|
||||
func _test_coordinate_round_trip() -> void:
|
||||
@@ -274,7 +343,7 @@ func _test_coordinate_round_trip() -> void:
|
||||
_preview.layer_mode = WorldPreview.LayerMode.BACK
|
||||
var back_cell := Vector3i(4, 0, 1)
|
||||
_expect(_preview.canvas_to_cell(_preview.cell_to_canvas(back_cell)) == back_cell, "BACK layer coordinate round trip preserves the layer")
|
||||
_expect(_preview.canvas_to_cell(Vector2(-10, -10)) == null, "points outside the map do not produce build cells")
|
||||
_expect(_preview.canvas_to_cell(_preview.get_map_rect().position-Vector2(10, 10)) == null, "points outside the map do not produce build cells")
|
||||
|
||||
|
||||
func _test_build_payload_and_hit_test() -> void:
|
||||
@@ -417,14 +486,54 @@ func _promote_rank_two() -> bool:
|
||||
|
||||
func _test_manual_save_and_load() -> void:
|
||||
SaveService.delete_save(_manual_save_path)
|
||||
var facilities: Array = _runtime.facility_service.get_instances()
|
||||
_expect(not facilities.is_empty(), "selection save fixture has a completed facility")
|
||||
if facilities.is_empty():
|
||||
return
|
||||
var selected_id: StringName = facilities[0].instance_id
|
||||
_main.call("_on_facility_selected", selected_id)
|
||||
_main.call("_set_layer", 1)
|
||||
_main.call("_save_manual")
|
||||
var status := _main.get("build_status_label") as Label
|
||||
_expect(status != null and "保存しました" in status.text, "manual save button writes the runtime snapshot")
|
||||
var expected_gold: int = _state.get_resource(&"gold")
|
||||
_state.set_resource(&"gold", expected_gold + 7)
|
||||
_main.set("_selected_entity_id", &"")
|
||||
_main.set("_selected_entity_kind", &"")
|
||||
_main.call("_set_layer", 0)
|
||||
_main.call("_load_manual")
|
||||
_expect(_state.get_resource(&"gold") == expected_gold, "manual load button restores the saved simulation")
|
||||
_expect(status != null and "読み込みました" in status.text, "manual load reports success in Japanese")
|
||||
_expect(_main.get("_selected_entity_id") == selected_id and _main.get("_selected_entity_kind") == &"facility", "manual load restores saved facility selection")
|
||||
_expect(_preview.selected_entity_id == selected_id, "loaded selection restores map highlight")
|
||||
_expect(_preview.layer_mode == 1 and _state.active_layer == 1, "load synchronizes saved layer and visible layer")
|
||||
var loaded: Dictionary = SaveService.load_snapshot(_manual_save_path)
|
||||
_expect(loaded[&"manifest"].get("interface_selection", {}).get("id", "") == String(selected_id), "selection persisted in the actual save package")
|
||||
# Missing or malformed optional UI metadata cannot break an otherwise valid save.
|
||||
for selection: Variant in [null, {"version": 99}, {"version": 1, "kind": [], "id": String(selected_id)}, {"version": 1, "kind": "facility", "id": "missing"}, {"version": 1, "kind": "unknown", "id": String(selected_id)}]:
|
||||
var saved: Dictionary = _runtime.save_to_path(_manual_save_path, {"interface_selection": selection})
|
||||
_expect(saved.get(&"ok", false), "write fixture with optional presentation metadata")
|
||||
_main.call("_load_manual", true)
|
||||
_expect("読み込みました" in status.text and _main.get("_selected_entity_id") == &"", "invalid presentation selection is ignored without breaking gameplay load")
|
||||
var old_saved: Dictionary = SaveService.save_snapshot(_manual_save_path, _runtime.create_snapshot(), {})
|
||||
_expect(old_saved.get(&"ok", false), "save without UI metadata remains supported")
|
||||
_main.call("_load_manual", true)
|
||||
_expect(_main.get("_selected_entity_id") == &"", "legacy save loads without inventing a selection")
|
||||
# Failed loading must preserve the currently selected facility.
|
||||
_main.call("_on_facility_selected", selected_id)
|
||||
_main.set("manual_save_path", _manual_save_path + "_missing")
|
||||
_main.call("_load_manual", true)
|
||||
_expect(_main.get("_selected_entity_id") == selected_id, "failed load preserves current selection")
|
||||
_main.set("manual_save_path", _manual_save_path)
|
||||
_main.call("_save_manual")
|
||||
_main.set("_selected_entity_id", &"")
|
||||
_main.set("_selected_entity_kind", &"")
|
||||
_main.call("_save_manual")
|
||||
var corrupt := FileAccess.open(_manual_save_path.path_join(SaveService.WORLD_FILE), FileAccess.WRITE)
|
||||
corrupt.store_string("invalid test package")
|
||||
corrupt.close()
|
||||
_main.call("_load_manual")
|
||||
_expect("読み込みました" in status.text and _main.get("_selected_entity_id") == selected_id, "backup recovery uses the selected candidate's UI metadata")
|
||||
|
||||
|
||||
func _test_event_choice_ui() -> void:
|
||||
@@ -467,6 +576,43 @@ func _test_event_choice_ui() -> void:
|
||||
_clock.set_paused(true)
|
||||
|
||||
|
||||
func _test_defense_notice() -> void:
|
||||
var before: Dictionary = _runtime.create_snapshot()
|
||||
var notice: Label = _main.get("alert_count_label")
|
||||
var summary: Label = _main.get("dashboard_summary_label")
|
||||
_expect(not "襲撃" in notice.text, "empty defense keeps compact normal HUD")
|
||||
var created: CommandResult = _runtime.submit_command(&"create_defense_raid", {
|
||||
&"raid_id": &"ui.hud.defense", &"definition": {
|
||||
&"entry_points": [&"gate"], &"objective_ids": [&"core"],
|
||||
&"waves": [{&"wave_id": &"wave.one", &"threat_strength": 15}],
|
||||
}}, &"defense_controller")
|
||||
_expect(created.is_success(), "HUD fixture creates preparing raid through Runtime command")
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect("襲撃 1" in notice.text and "準備中 1" in summary.text, "Runtime publication shows preparing threat in HUD and management")
|
||||
_expect("配属変更できません" in notice.tooltip_text and "戦闘中 0" in notice.tooltip_text, "HUD distinguishes preparation and explains employee lock")
|
||||
if OS.get_environment("THE_TREE_DEFENSE_CAPTURE") == "1":
|
||||
_main.call("_set_management_panel_open", true)
|
||||
await process_frame
|
||||
await RenderingServer.frame_post_draw
|
||||
_expect(root.get_texture().get_image().save_png(ProjectSettings.globalize_path("res://artifacts/defense-hud-2026-09-29/preparing.png")) == OK, "capture rendered defense notice")
|
||||
_main.call("_set_management_panel_open", false)
|
||||
var saved: Dictionary = _runtime.create_snapshot()
|
||||
var cancelled: CommandResult = _runtime.submit_command(&"cancel_defense_raid", {&"raid_id": &"ui.hud.defense"}, &"defense_controller")
|
||||
_expect(cancelled.is_success(), "HUD fixture cancels incomplete preparation")
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(not "襲撃" in notice.text and "準備中 0 / 戦闘中 0 / 次波待ち 0" in summary.text and "ありません" in notice.tooltip_text, "terminal history clears HUD warning and stale tooltip")
|
||||
_expect(_runtime.restore_snapshot(saved), "restore preparing raid snapshot")
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect("襲撃 1" in notice.text and "準備中 1" in summary.text, "HUD follows restored preparing raid without a new raid signal")
|
||||
_expect(_runtime.restore_snapshot(before), "restore pre-raid gameplay")
|
||||
await process_frame
|
||||
await process_frame
|
||||
_expect(not "襲撃" in notice.text, "restoring empty defense clears warning")
|
||||
|
||||
|
||||
func _expect(condition: bool, message: String) -> void:
|
||||
_checks += 1
|
||||
if condition:
|
||||
|
||||
Reference in New Issue
Block a user