extends Node
## GATE — C = Blender 2.79's CIRCLE SELECT (view3d.select_circle; #109 "remaining step 6"):
## a ring follows the pointer, LMB drag PAINTS brushes into the selection, Shift+LMB
## paints them out, the wheel resizes the ring, RMB / Esc / Enter leaves. A brush counts
## when its centre projects inside the ring — box select's (B) rule.
##
## Three 1 m brushes A, B, C in a row 6 m apart, the camera looking down at them:
## C1 C (through Keymap.run, the real input path) enters circle mode
## C2 LMB on A's screen point, ring smaller than the spacing: selects A only
## C3 dragging (still pressed) onto B paints B in: A + B, not C
## C4 Shift+LMB on A paints A out: B only
## C5 the wheel grows the ring
## C6 RMB leaves circle mode, the selection kept
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_circle_select.tscn
var fails := 0
var checks := 0
var _cam: Camera3D = null
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")
var map: Node3D = (load("res://scenes/maps/map_test.tscn") as PackedScene).instantiate()
add_child(map)
_cam = Camera3D.new()
add_child(_cam)
_cam.current = true
_cam.global_position = Vector3(206, 30, 0.01)
_cam.look_at(Vector3(206, 0, 0), Vector3.UP)
for i in 8:
await get_tree().process_frame
await _run(map)
get_tree().root.get_node("/root/GameMode").set_mode("play")
if checks < 7:
print(" **FAIL** only %d checks ran -- setup died before the assertions" % checks)
fails += 1
print("\nGATE circle_select: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
get_tree().quit(0 if fails == 0 else 1)
func _brush(map: Node, x: float) -> int:
var persist: Node = map.get("_persist")
var dot: String = persist.record("brush.create", {"planes": [1, 0, 0, x + 0.5, -1, 0, 0, -(x - 0.5),
0, 1, 0, 1, 0, -1, 0, 0, 0, 0, 1, 0.5, 0, 0, -1, 0.5], "proj": [], "material_id": 2,
"level_id": 0, "sky": false, "group": ""})
persist.refold()
return (map.get("level") as Node).brush_by_key(dot)
func _button(pos: Vector2, idx: MouseButton, pressed: bool, shift := false) -> InputEventMouseButton:
var e := InputEventMouseButton.new()
e.position = pos
e.button_index = idx
e.pressed = pressed
e.shift_pressed = shift
return e
func _motion(pos: Vector2, held: bool) -> InputEventMouseMotion:
var e := InputEventMouseMotion.new()
e.position = pos
e.button_mask = MOUSE_BUTTON_MASK_LEFT if held else 0
return e
func _sel(map: Node) -> Array:
return Array(map.get("_sel_brushes"))
func _run(map: Node3D) -> void:
var a := _brush(map, 200.0)
var b := _brush(map, 206.0)
var c := _brush(map, 212.0)
await get_tree().process_frame
var pa := _cam.unproject_position(Vector3(200, 0.5, 0))
var pb := _cam.unproject_position(Vector3(206, 0.5, 0))
var spacing := pa.distance_to(pb)
map.select_brushes(PackedInt32Array())
Keymap.run("builder.select_circle")
await get_tree().process_frame
_ok("C1 C enters circle select", bool(map.call("is_circle_selecting")))
map.set("_circ_radius", spacing * 0.3)
map.call("_circle_select_input", _motion(pa, false))
map.call("_circle_select_input", _button(pa, MOUSE_BUTTON_LEFT, true))
_ok("C2 LMB on A selects A only", _sel(map) == [a], _sel(map))
map.call("_circle_select_input", _motion(pa.lerp(pb, 0.5), true))
map.call("_circle_select_input", _motion(pb, true))
map.call("_circle_select_input", _button(pb, MOUSE_BUTTON_LEFT, false))
var s := _sel(map)
_ok("C3 dragging onto B paints it in: A + B, not C", s.has(a) and s.has(b) and not s.has(c), s)
map.call("_circle_select_input", _motion(pa, false))
map.call("_circle_select_input", _button(pa, MOUSE_BUTTON_LEFT, true, true))
map.call("_circle_select_input", _button(pa, MOUSE_BUTTON_LEFT, false, true))
_ok("C4 Shift+LMB on A paints it out: B only", _sel(map) == [b], _sel(map))
var r0: float = map.get("_circ_radius")
map.call("_circle_select_input", _button(pb, MOUSE_BUTTON_WHEEL_UP, true))
_ok("C5 the wheel grows the ring", float(map.get("_circ_radius")) > r0, [r0, map.get("_circ_radius")])
map.call("_circle_select_input", _button(pb, MOUSE_BUTTON_RIGHT, true))
_ok("C6 RMB leaves circle select", not bool(map.call("is_circle_selecting")))
_ok("C6 and the selection is kept", _sel(map) == [b], _sel(map))