extends SceneTree ## test_drag_bibliothek (Test-Befund 25.10.): Objekt-Kachel anklicken, gedrückt ## halten, in die Szene ziehen — beim Loslassen wird das Objekt platziert. ## Echte Mausereignisse (push_input), kein Direktaufruf. var checks := 0 var failures := 0 func _check(cond: bool, label: String) -> void: checks += 1 if cond: print(" ok: ", label) else: failures += 1 print(" FAIL: ", label) func _mouse(pos: Vector2, pressed: bool, motion := false) -> void: var ev: InputEvent if motion: var mm := InputEventMouseMotion.new() mm.position = pos mm.global_position = pos mm.button_mask = MOUSE_BUTTON_MASK_LEFT ev = mm else: var mb := InputEventMouseButton.new() mb.button_index = MOUSE_BUTTON_LEFT mb.position = pos mb.global_position = pos mb.pressed = pressed ev = mb root.push_input(ev) func _init() -> void: var main: Control = (load("res://core/scenes/main.tscn") as PackedScene).instantiate() root.add_child(main) await process_frame await process_frame await process_frame main.sym_mode = SymmetryCore.Mode.OFF # sonst setzt der Standard (Punkt) einen Zwilling dazu var n0: int = (main.doc["objects"] as Array).size() var oid := "barrel_001" var btn: Button = main.library_buttons.get(oid) _check(btn != null, "Kachel für %s vorhanden" % oid) if btn == null: _finish() return # Kachel sichtbar machen: Bibliotheks-Gruppen aufklappen, Scroll an die Kachel. main.assets_mod._on_library_expand_all() await process_frame await process_frame # Headless-Fenster ist 64×64 px: echte Mausereignisse erreichen weder Kachel # noch Szene. Darum die drei Stationen der Ziehen-Kette einzeln und exakt wie # Godot sie aufruft (drag_forwarding → can_drop (je Mausbewegung) → drop). var data: Variant = main.assets_mod.call("_tile_drag_data", Vector2(5, 5), oid, btn) _check(data is Dictionary and str((data as Dictionary).get("svr_oid", "")) == oid, "Ziehen-Start liefert die Objekt-ID") var pos_a := Vector2(300, 150) var pos_b := Vector2(320, 170) _check(main.call("_viewport_can_drop", pos_a, data), "Über der Szene: Ablegen erlaubt") _check(main.interaction.placing and main.interaction.place_oid == oid, "Über der Szene: Platzier-Vorschau läuft") _check(main.call("_viewport_can_drop", pos_b, data), "Mausbewegung: weiter erlaubt") _check(main.interaction.placing, "Vorschau wird nicht neu gestartet") main.call("_viewport_drop", pos_b, data) await process_frame var objs: Array = main.doc["objects"] _check(objs.size() == n0 + 1, "Loslassen setzt genau EIN Objekt (%d → %d)" % [n0, objs.size()]) if objs.size() == n0 + 1: _check(str((objs.back() as Dictionary).get("id", "")) == oid, "Das gesetzte Objekt ist %s" % oid) _check(int(main.interaction.selected_index) == n0, "Das neue Objekt ist ausgewählt") _check(not main.interaction.placing, "Danach ist das Platzieren beendet (kein hängender Geist)") _check(main.history.can_undo(), "Undo-Schritt vorhanden") main.history.undo() main.call("_after_structure_change") _check((main.doc["objects"] as Array).size() == n0, "Strg+Z nimmt es zurück") main.call("_clear_edit_state") # Abbruch: Ziehen über der Szene, dann außerhalb loslassen (DRAG_END ohne Drop). data = main.assets_mod.call("_tile_drag_data", Vector2(5, 5), oid, btn) main.call("_viewport_can_drop", pos_a, data) _check(main.interaction.placing, "Abbruch-Zug: Vorschau läuft") main.assets_mod.notification(Node.NOTIFICATION_DRAG_END) _check(not main.interaction.placing, "Außerhalb losgelassen: Vorschau weg") _check((main.doc["objects"] as Array).size() == n0, "Außerhalb losgelassen: nichts gesetzt") # Fremde Ziehdaten werden abgelehnt. _check(not main.call("_viewport_can_drop", pos_a, "irgendwas"), "Fremde Ziehdaten: kein Ablegen") _finish() func _finish() -> void: if failures == 0: print("ALL OK: %d checks" % checks) quit(0) else: print("FAILED: %d/%d checks" % [failures, checks]) quit(1)