- Tabs Auswahl/Prüfen/Test-Start/Einstellungen/Symmetrie weg; Spawn-Zonen, Test-Start, Symmetrie im Map-Tab; Einstellungen-Fenster (Gitter, Höhenlinien, Symmetrie-Modus, UI-Größe, Raster-Snap, Gizmo-Schritt, Karte prüfen) - Bauen-Tab nur Bauteile; Objekt-Werkzeuge entfernt - Klick in der Map-Inhalt-Liste wählt in der Szene aus (SELECT_MULTI feuert nur multi_selected) - Objekt-Kachel per Ziehen in die Szene setzen - Wände bündig in der Zelle, gleiche Geschosshöhe mit/ohne Decke, Dächer/Giebelwände 4 m und 6 m Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
99 lines
3.9 KiB
GDScript
99 lines
3.9 KiB
GDScript
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://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)
|