extends SceneTree
## GATE — the 3D view is the free rectangle R for the POINTER (hyper-games #124, B2 as cut
## by the user 2026-10-18: "lets skip the recentering work for now" — the image is not
## re-centred in R; only hover and the tool wrap respect it).
## V1 hover: the pointer over a PANEL highlights nothing behind it
## V2 ... inside R it aims what is under it
## V3 a pointer-following tool (G) wraps at R's edge, not the window's
##
## RUN: CI=true HYPERTPS_DAEMON_TCP=127.0.0.1:1 "$GODOT" --headless --path . --script res://scenes/test/gate_view3d_rect.gd
var _frame := 0
var _map: Node = null
var _dock: Node = null
var _cam: Camera3D = null
var _brush := -1
var _step := 0
var fails := 0
var checks := 0
var _warped := Vector2(-1, -1)
func _p(c: bool, m: String, got: Variant = "") -> void:
checks += 1
if not c:
fails += 1
print(" %-68s %s %s" % [m, "OK" if c else "**FAIL**", str(got)])
func _box(lo: Vector3, hi: Vector3) -> Array:
return [1, 0, 0, hi.x, -1, 0, 0, -lo.x, 0, 1, 0, hi.y, 0, -1, 0, -lo.y, 0, 0, 1, hi.z, 0, 0, -1, -lo.z]
func _r() -> Rect2:
return _dock.view_rect()
## Put the map's pointer at `at`. A headless viewport keeps its mouse at (0, 0) whatever
## is pushed, so — as gate_curve_tool does — the map's wrap offset carries it there: the
## map's pointer is mouse + _wrap_offset everywhere it aims.
func _point(at: Vector2) -> void:
_map.set("_wrap_offset", at - root.get_mouse_position())
func _aimed() -> int:
var bv: Node = _map.get("_brush_view")
if bv == null or bv.get("_aimed_id") == null:
return -99
return int(bv.get("_aimed_id"))
func _process(_d: float) -> bool:
_frame += 1
if _frame == 1:
root.size = Vector2i(1920, 1080)
var keet: Node = root.get_node_or_null("/root/KeetService")
if keet != null:
keet.current_member_id = "gate-author"
var gs: Node = root.get_node_or_null("/root/GameState")
if gs != null:
gs.route("world:level:*", 1, "peer")
root.get_node("/root/GameMode").set_mode("build")
_map = (load("res://scenes/maps/map_flat.tscn") as PackedScene).instantiate()
root.add_child(_map)
_dock = root.get_node("/root/BuildDock")
_cam = Camera3D.new()
root.add_child(_cam)
_cam.current = true
_cam.fov = 70.0
_cam.global_transform = Transform3D(Basis.IDENTITY, Vector3(0, 3, 30)) # looking down -Z
return false
if _frame < 40 or _frame % 5 != 0:
return false
match _step:
0:
# A wall filling the whole window in front of the camera: behind every panel
# too, so a pointer over a panel is over the wall.
var persist: Node = _map.get("_persist")
var dot: String = persist.record("brush.create", {"planes": _box(Vector3(-200, -50, -1), Vector3(200, 100, 0)),
"proj": [], "material_id": 0, "level_id": 0, "sky": false})
persist.refold()
_brush = _map.get("level").brush_by_key(dot)
_point((_dock._sides["left"]["frame"] as Control).get_global_rect().get_center())
1:
_p(_aimed() == -1, "V1 hover over a panel highlights nothing behind it", _aimed())
_point(_r().get_center())
2:
_p(_aimed() == _brush, "V2 ... inside R it aims the wall", [_aimed(), _brush])
_map.select_brushes(PackedInt32Array([_brush]))
var g := InputEventKey.new()
g.keycode = KEY_G
g.physical_keycode = KEY_G
g.pressed = true
_map._unhandled_key_input(g)
_map.set("pointer_warp", func(p: Vector2) -> void: _warped = p)
var at := Vector2(_r().position.x + 1.0, _r().get_center().y)
_map.call("_update_pointer_wrap_at", at)
_map.call("_update_pointer_wrap_at", at)
3:
var r := _r()
_p(_warped.x > r.get_center().x and _warped.x < r.end.x,
"V3 G: the pointer at R's left edge wraps to R's right side (not the window's)", [_warped, r])
(_map.call("_ensure_ops") as Node).call("cancel")
_:
if checks < 3:
print(" **FAIL** only %d checks ran -- setup died before the assertions" % checks)
fails += 1
print("\nGATE view3d_rect: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
quit(0 if fails == 0 else 1)
return true
_step += 1
return false