Files
TheTree_mock/tests/ui/fixtures/selection_cross_process.gd
T

101 lines
4.4 KiB
GDScript

extends SceneTree
## Passive observer: no selection, save/load, command or engine input injection.
## Runner launches separate owned processes with private user-data directories.
var _main: Control
var _elapsed := 0.0
var _last := ""
var _sequence := 0
var _output := ""
var _source_map: Dictionary = {}
func _initialize() -> void:
call_deferred("_start")
func _start() -> void:
_output = OS.get_environment("P24_OBSERVER_OUTPUT")
var pins := OS.get_environment("P24_OBSERVER_SOURCE_MAP")
if not _output.is_absolute_path() or not DirAccess.dir_exists_absolute(_output) or not pins.is_absolute_path():
push_error("P24 observer requires existing absolute output directory and source-map JSON")
quit(1)
return
var parsed: Variant = JSON.parse_string(FileAccess.get_file_as_string(pins))
if not parsed is Dictionary or parsed.is_empty():
push_error("P24 observer source map missing")
quit(1)
return
_source_map = parsed
root.size = Vector2i(1440, 810)
_main = load("res://scenes/main/main.tscn").instantiate()
root.add_child(_main)
print("P24_PROCESS pid=%d scene=res://scenes/main/main.tscn" % OS.get_process_id())
# Use the ordinary Main pause control through OS input when a frozen state
# is needed. The observer itself never changes Runtime or Clock.
func _process(delta: float) -> bool:
_elapsed += delta
if _elapsed >= 1.0 and is_instance_valid(_main):
_elapsed = 0.0
_capture()
return false
func _capture() -> void:
var runtime: Variant = root.get_node("SimulationRuntime")
var selection: Dictionary = _main.call("_capture_interface_selection")
var facility_id := StringName(selection.get("id", ""))
var facility: Variant = runtime.facility_service.get_instance(facility_id)
var guest_panel: GuestObservationPanel
var dialog: Variant = _main.get("guest_observer")
if dialog != null:
guest_panel = dialog.find_child("GuestObservationPanel", true, false) as GuestObservationPanel
var staff_panel: StaffManagementPanel = _main.get("staff_management_panel")
var staff_model: Dictionary = {}
for row: Dictionary in runtime.get_staff_management_report().get(&"staff", []):
if String(row.get(&"staff_id", "")) == String(selection.get("staff_id", "")):
staff_model = row.duplicate(true)
var needs: Dictionary = {}
if guest_panel != null:
for need: StringName in guest_panel.bars:
needs[need] = guest_panel.bars[need].value
var observation := {
"interface_selection": selection,
"layer": root.get_node("GameState").get("active_layer"),
"facility": {"id": String(facility_id), "model_snapshot": facility.create_snapshot() if facility != null else {},
"heading_text": _main.get("selected_heading_label").text,
"detail_text": _main.get("selected_detail_label").text,
"highlight_id": String(_main.get("world_preview").get("selected_entity_id"))},
"guest": {"id": selection.get("guest_id", ""),
"model_report": runtime.guest_service.get_observation(StringName(selection.get("guest_id", ""))),
"detail_text": guest_panel.details.text if guest_panel != null else "",
"priority_text": guest_panel.priority_label.text if guest_panel != null else "",
"decision_text": guest_panel.decision_label.text if guest_panel != null else "", "need_bars": needs},
"staff": {"id": selection.get("staff_id", ""), "model_report": staff_model,
"detail_text": staff_panel.staff_detail_label.text,
"editor_visible": staff_panel.editor_panel.is_visible_in_tree()},
}
var encoded := JSON.stringify(observation, "", true)
if encoded == _last:
return
_sequence += 1
var stem := "process-%d-observation-%d" % [OS.get_process_id(), _sequence]
var report_path := _output.path_join(stem + ".json")
var frame_path := _output.path_join(stem + ".png")
if FileAccess.file_exists(report_path) or FileAccess.file_exists(frame_path):
push_error("P24 observer refuses artifact overwrite")
return
var image := root.get_texture().get_image()
if image.save_png(frame_path) != OK:
push_error("P24 observer frame capture failed")
return
var file := FileAccess.open(report_path, FileAccess.WRITE)
if file == null:
push_error("P24 observer report write failed")
return
file.store_string(JSON.stringify({"pid": OS.get_process_id(), "source_map": _source_map,
"scene": "res://scenes/main/main.tscn", "ticks_usec": Time.get_ticks_usec(),
"raw_observation": observation, "screenshot": stem + ".png",
"formal_acceptance": false}, "\t", true) + "\n")
file.close()
_last = encoded
print("P24_RAW_OBSERVATION " + encoded)