extends Node
## GATE — THE UNION SELECTION, 5a (#120 §17.10): objects, brushes and curves held together.
## U1 Shift adds an object to a brush selection: both are held
## U2 ... and a curve: all three (the curve list holds it; it is the active curve)
## U3 Shift on a held brush takes it out, the rest stays
## U4 a plain pick replaces everything
## U5 A holds every object, every live brush and every curve
## U6 A again lets go of everything (2.79's A toggle)
## U7 the outliner lights the object's row AND the brush's row together
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_union_select.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 < 10:
print(" **FAIL** only %d checks ran -- setup died before the assertions" % checks)
fails += 1
print("\nGATE union_select: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
get_tree().quit(0 if fails == 0 else 1)
func _brushes() -> Array:
return map.get("_sel_brushes")
func _run() -> void:
persist = map.get("_persist")
var level: Node = map.get("level")
var live: PackedInt32Array = level.get_live_brush_ids()
var b0: int = live[0]
var b1: int = live[1]
var objs: Array = (map.get_node("SceneObjects").entries() as Array)
var o0 := String(objs[0]["dot"])
var c: String = map.create_curve([CurveMath.point(Vector3(50.13, 1, 50.11)), CurveMath.point(Vector3(53.3, 1, 50.11))],
false, "U")
_ok("setup: brushes, an object, a curve", live.size() >= 2 and objs.size() >= 1 and c != "")
_ok("U the map has the union API", map.has_method("select_all") and map.has_method("selected_curves"))
if not map.has_method("select_all"):
return
# ---- U1 / U2 ----
map.select_brushes(PackedInt32Array([b0]))
map.select_object(o0, true)
_ok("U1 Shift adds an object to a brush selection: both held", _brushes() == [b0]
and map.selected_objects() == [o0], [_brushes(), map.selected_objects()])
map.select_curve(c, true)
_ok("U2 ... and a curve: all three", _brushes() == [b0] and map.selected_objects() == [o0]
and map.selected_curves() == [c] and map.selected_curve() == c)
# ---- U3 ----
map.call("_note_selected", b1, true)
map.call("_note_selected", b0, true)
_ok("U3 Shift on a held brush takes it out, the rest stays", _brushes() == [b1]
and map.selected_objects() == [o0] and map.selected_curves() == [c], [_brushes(), map.selected_objects()])
# ---- U4 ----
map.select_object(o0)
_ok("U4 a plain pick replaces everything", _brushes().is_empty() and map.selected_objects() == [o0]
and map.selected_curves().is_empty())
# ---- U5 / U6 ----
map.clear_selection() # A toggles: from nothing, everything
map.select_all()
_ok("U5 A: every live brush", _brushes().size() == live.size(), [_brushes().size(), live.size()])
_ok("U5 ... every object", map.selected_objects().size() == objs.size(), [map.selected_objects().size(), objs.size()])
_ok("U5 ... every curve", map.selected_curves() == map.curve_states().keys())
map.select_all()
_ok("U6 A again: nothing", _brushes().is_empty() and map.selected_objects().is_empty() and map.selected_curves().is_empty())
# ---- U7 ----
map.select_brushes(PackedInt32Array([b0]))
map.select_object(o0, true)
await get_tree().process_frame
await get_tree().process_frame
var panel: Node = map.get("_outliner")
var lit_obj := false
var lit_brush := false
var it: TreeItem = (panel.get("_tree") as Tree).get_next_selected(null)
while it != null:
var r: Variant = it.get_metadata(0)
if r is Dictionary:
if String((r as Dictionary).get("object_dot", "")) == o0:
lit_obj = true
if ((r as Dictionary).get("brushes", PackedInt32Array()) as PackedInt32Array).has(b0):
lit_brush = true
it = (panel.get("_tree") as Tree).get_next_selected(it)
_ok("U7 the outliner lights the object's row and the brush's row", lit_obj and lit_brush, [lit_obj, lit_brush])