extends SceneTree var failures := 0 func check(condition: bool, message: String) -> void: if not condition: failures += 1 push_error(message) func _initialize() -> void: run.call_deferred() func run() -> void: if "--preview" in OS.get_cmdline_user_args(): root.gui_embed_subwindows = true root.size = Vector2i(1200, 850) var board := CabinetPCBConfig.new() check(board.ports().size() == 22, "All 22 connectors must be present") check(board.port("J15").bcm == 21 and board.port("J10").bcm == 5, "Three pin order") check(board.port("J22").bcm == 25 and board.port("J17").bcm == 16, "Two pin order") check(board.port("J2").label == "001" and board.port("J8").label == "111", "Reader selector order") var reader := PCBConnection.new() reader.port_id = "J1" reader.device_type = "rfid" reader.device_id = "reader_left" reader.display_name = "Left RFID reader" board.set_connection(reader) var reader2: PCBConnection = reader.duplicate(true) reader2.port_id = "J2" reader2.device_id = "reader_right" board.set_connection(reader2) check(board.issues().is_empty(), "Valid readers") var cabinet := CabinetProfile.new() cabinet.display_name = "PCB editor test" cabinet.pcb_config = board var copy: CabinetProfile = cabinet.duplicate(true) copy.pcb_config.connection("J1").display_name = "Other cabinet" check(board.connection("J1").display_name == "Left RFID reader", "Cabinet deep-copy isolation") var path := "user://pcb_test_roundtrip.tres" check(ResourceSaver.save(cabinet, path) == OK, "Save cabinet") var loaded := ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_IGNORE) as CabinetProfile check(loaded.pcb_config.connection("J2").device_id == "reader_right", "Save/reload connector data") DirAccess.remove_absolute(path) reader2.device_id = reader.device_id check(not board.issues().is_empty(), "Duplicate IDs reported") reader2.device_id = "reader_right" var hardware := HardwareConfig.new() var action := HardwareAction.new() action.action_id = &"lamp" action.gpio_pin = 17 hardware.actions.append(action) check(not board.issues(hardware).is_empty(), "Reserved selector pin reported") var output := PCBConnection.new() output.port_id = "J22" output.device_type = "led" output.device_id = "lamp" output.binding_id = "lamp" board.set_connection(output) action.gpio_pin = 18 check(not board.issues(hardware).is_empty(), "Output BCM mismatch reported") action.gpio_pin = 25 check(board.issues(hardware).is_empty(), "Matching output action accepted") cabinet.hardware_config = hardware if not Engine.is_editor_hint(): print("PCB resource tests: ", "PASS" if failures == 0 else "FAIL") quit(failures) return var property := preload("res://editor/hardware/pcb_editor_property.gd").new() root.add_child(property) property.set_object_and_property(cabinet, "pcb_config") property._update_property() property._open() property._select("J2") check(property.device_id.text == "reader_right", "Editor selects correct reader") property.device_name.text = "Pending edit" property._store() check(board.connection("J2").display_name != "Pending edit", "Draft cannot change source before Apply") property.dialog.hide() property._open() check(property.device_name.text != "Pending edit", "Cancel/reopen discards draft") property._select("J22") property.device_name.text = "Reward lamp" property._store() property.property_changed.connect(func(_key: StringName, value: Variant, _field: StringName, _changing: bool): cabinet.pcb_config = value) property._apply() check(cabinet.pcb_config.connection("J22").display_name == "Reward lamp", "Apply emits updated configuration") if "--preview" in OS.get_cmdline_user_args(): root.size = Vector2i(1200, 850) property.dialog.popup_centered(Vector2i(1120, 760)) await process_frame await process_frame await RenderingServer.frame_post_draw root.get_texture().get_image().save_png("user://pcb_editor_preview.png") print("Preview: ", OS.get_user_data_dir(), "/pcb_editor_preview.png") property.queue_free() await process_frame print("PCB tests: ", "PASS" if failures == 0 else "FAIL") quit(failures)