scopedvr-map-editor/tests/test_drag_bibliothek.gd
slyphax 3f0d0f3f33 Map-Editor: UI aufgeräumt, Auswahl-Sync, Drag&Drop, Bauen (Wände bündig, Geschosshöhe, große Dächer)
- 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>
2026-10-25 20:32:32 +01:00

99 lines
3.9 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)