extends Node
## GATE — G ON A SELECTED CURVE, BY SELECT MODE (#120 §17.7 Q4, §17.8 step 1).
## C1 switching select mode keeps a selected curve (a curve is a whole object; only an
## element selection is cleared, being a set of planes)
## C2 vertex mode (1): G starts Edit curve on the point nearest the pointer
## C3 ... the point is the one aimed at, not the first
## C4 brush mode (4): G moves the whole curve (§16 step 4b)
## C5 with no curve selected, vertex-mode G is not Edit curve
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_curve_g_mode.tscn
var fails := 0
var checks := 0
var map: Node3D
var cam: Camera3D
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)
cam = Camera3D.new()
add_child(cam)
cam.current = true
for i in 6:
await get_tree().process_frame
await _run()
get_tree().root.get_node("/root/GameMode").set_mode("play")
if checks < 6:
print(" **FAIL** only %d checks ran -- setup died before the assertions" % checks)
fails += 1
print("\nGATE curve_g_mode: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
get_tree().quit(0 if fails == 0 else 1)
func _aim_at(at: Vector3) -> void:
cam.global_position = at + Vector3(0.01, 4.0, 0.01)
cam.look_at(at, Vector3.UP)
await get_tree().process_frame
map.set("_wrap_offset", get_viewport().get_visible_rect().size * 0.5 - get_viewport().get_mouse_position())
func _g() -> void:
var ev := InputEventAction.new()
ev.action = "builder.move"
ev.pressed = true
map._unhandled_input(ev)
await get_tree().process_frame
func _run() -> void:
var ops: Node = map.call("_ensure_ops")
var O0 := Vector3(150.137, 1.31, 149.873)
var c: String = map.create_curve([CurveMath.point(O0), CurveMath.point(O0 + Vector3(4.1, 0, 0)),
CurveMath.point(O0 + Vector3(4.1, 0, 3.3))], false, "G mode")
_ok("setup: a curve", map.curve_states().has(c))
# ---- C1 ----
map.select_curve(c)
map.set_select_mode("vertex")
_ok("C1 switching to vertex mode keeps the selected curve", map.selected_curve() == c, map.selected_curve())
# ---- C2 / C3 ----
var p2: Vector3 = (map.curve_states()[c]["points"] as Array)[2]["p"]
await _aim_at(p2)
await _g()
var ce: Node = map.get("_curve_edit")
_ok("C2 vertex mode: G starts Edit curve", ops.get("active") == ce, ops.get("active"))
_ok("C3 ... on the point aimed at (3 of 3)", ops.get("active") == ce and String(ce.status()).contains("point: 3 of 3"),
ce.status() if ops.get("active") == ce else "")
ops.cancel()
await get_tree().process_frame
# ---- C4 ----
map.set_select_mode("brush")
map.select_curve(c)
await _g()
var mv: Node = map.get("_move")
_ok("C4 brush mode: G moves the whole curve", ops.get("active") == mv and String(mv.get("_curve")) == c,
[ops.get("active"), mv.get("_curve") if ops.get("active") == mv else ""])
ops.cancel()
await get_tree().process_frame
# ---- C5 ----
map.set_select_mode("vertex")
map.clear_selection()
await _g()
_ok("C5 no curve selected: vertex-mode G is not Edit curve", ops.get("active") != ce, ops.get("active"))
if ops.get("active") != null:
ops.cancel()
map.set_select_mode("brush")