extends Node
## GATE — X AND H ON A UNION SELECTION, 5b (#120 §17.10).
## O1 X on a box + a light + a curve deletes all three in ONE gesture
## O2 ... and one Ctrl+Z brings all three back
## O3 X on several curves (Shift-picked) is one gesture
## O4 A then X: a cable's curve goes WITH its cable (no "used" refusal), one gesture
## O5 H on a box + a light + a curve hides all three; Alt+H shows them again
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_union_ops.tscn
var fails := 0
var checks := 0
var map: Node3D
var persist: Node
func _ok(what: String, cond: bool, note: Variant = "") -> void:
checks += 1
if not cond:
fails += 1
print(" %-64s %s %s" % [what, "OK" if cond else "**FAIL**", str(note)])
func _ready() -> void:
var gs: Node = get_tree().root.get_node_or_null("/root/GameState")
gs.route("world:level:*", 1, "peer")
var keet: Node = get_tree().root.get_node_or_null("/root/KeetService")
if keet != null:
keet.current_member_id = "gate-author"
get_tree().root.get_node("/root/GameMode").set_mode("build")
map = (load("res://scenes/maps/map_dev_test.tscn") as PackedScene).instantiate()
add_child(map)
for i in 6:
await get_tree().process_frame
await _run()
get_tree().root.get_node("/root/GameMode").set_mode("play")
if checks < 8:
print(" **FAIL** only %d checks ran -- setup died before the assertions" % checks)
fails += 1
print("\nGATE union_ops: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
get_tree().quit(0 if fails == 0 else 1)
## ALL gestures, discarded ones too: gestures() drops an undone gesture once a newer one
## exists, so after an undo a new gesture would count as -1 + 1 = 0.
func _gestures() -> int:
return (persist.gestures(true) as Array).size()
func _run() -> void:
persist = map.get("_persist")
var P := Vector3(400.1, 1.0, 400.3)
persist.begin_gesture("box")
var box: String = persist.record("shape.create", {"type": "box", "gv": 1, "params": {},
"frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, P)), "size": [1, 1, 1],
"material_id": 2, "level_id": 0})
persist.end_gesture()
persist.refold()
var light: String = map.create_object(PrefabCatalogue.ids()[0], Transform3D(Basis.IDENTITY, P + Vector3(3, 0, 0)))
var c1: String = map.create_curve([CurveMath.point(P + Vector3(0, 0, 4)), CurveMath.point(P + Vector3(2.1, 0, 4))], false, "C1")
var c2: String = map.create_curve([CurveMath.point(P + Vector3(0, 0, 6)), CurveMath.point(P + Vector3(2.1, 0, 6))], false, "C2")
_ok("setup: a box, an object, two curves", box != "" and light != "" and c1 != "" and c2 != "")
# ---- O1 / O2 ----
map.select_shape(box)
map.select_object(light, true)
map.select_curve(c1, true)
var g0 := _gestures()
map.delete_selection()
var gone: bool = not (persist.live_shapes() as Dictionary).has(box) and map.object_node(light) == null \
and not map.curve_states().has(c1)
_ok("O1 X deletes the box, the object and the curve", gone, [(persist.live_shapes() as Dictionary).has(box),
map.object_node(light) != null, map.curve_states().has(c1)])
_ok("O1 ... in ONE gesture", _gestures() == g0 + 1, _gestures() - g0)
persist.undo_last()
persist.refold()
_ok("O2 one Ctrl+Z brings all three back", (persist.live_shapes() as Dictionary).has(box)
and map.object_node(light) != null and map.curve_states().has(c1))
# ---- O3 ----
map.select_curve(c1)
map.select_curve(c2, true)
var g1 := _gestures()
map.delete_selection()
_ok("O3 X on two curves: both gone, one gesture", not map.curve_states().has(c1) and not map.curve_states().has(c2)
and _gestures() == g1 + 1, _gestures() - g1)
persist.undo_last()
persist.refold()
# ---- O4 ----
var cable: String = map.add_cable([CurveMath.point(P + Vector3(0, 0, 9)), CurveMath.point(P + Vector3(3.3, 0, 9))],
false, {"radius": 0.05})
var cc := String(persist.shape_state(cable)["params"]["curve"])
map.clear_selection()
map.select_shape(cable)
map.select_curve(cc, true)
var g2 := _gestures()
map.delete_selection()
_ok("O4 a cable and its curve selected together both go", not (persist.live_shapes() as Dictionary).has(cable)
and not map.curve_states().has(cc) and _gestures() == g2 + 1, [(persist.live_shapes() as Dictionary).has(cable),
map.curve_states().has(cc), _gestures() - g2])
persist.undo_last()
persist.refold()
# ---- O5 ----
map.select_shape(box)
map.select_object(light, true)
map.select_curve(c1, true)
map.hide_selection()
var lvl: Node = map.get("level")
var hidden_ids: PackedInt32Array = lvl.get_hidden_brush_ids()
var pieces: PackedInt32Array = lvl.get_group_brush_ids(box)
var all_hidden: bool = not pieces.is_empty() and Array(pieces).all(func(b: int) -> bool: return hidden_ids.has(b)) \
and not (map.object_node(light) as Node3D).visible and map.is_curve_hidden(c1)
_ok("O5 H hides the box, the object and the curve", all_hidden, [hidden_ids.size(),
(map.object_node(light) as Node3D).visible, map.is_curve_hidden(c1)])
map.unhide_all()
_ok("O5 ... Alt+H shows them again", (lvl.get_hidden_brush_ids() as PackedInt32Array).is_empty()
and (map.object_node(light) as Node3D).visible and not map.is_curve_hidden(c1))
var panel: Node = map.get("_outliner")
panel.model.save(String(panel.get("_save_key")))