extends SceneTree
## GATE — a pick names a brush ONLY when the ray hit the LEVEL's body.
##
## _brush_from_hit() turned any hit's shape index into a brush id via
## level.get_brush_id_from_shape(), without asking WHAT the ray hit. A scene box's
## shape 0 then named the level's brush 0 — an unrelated brush that click selected
## and Delete removed. Found by the 2026-10-05 delete audit; map_test has scene boxes
## (Ground, platforms) next to any brushes you build.
##
## Real physics: map_test + one brush placed away from the scene boxes, then real rays.
## Run: "$HYPER_TPS_GODOT" --headless --path . --script res://scenes/test/gate_pick_level_only.gd
var ok := true
var _step := 0
var _map: Node = null
var _bid := -1
func _p(c: bool, m: String) -> void:
print(("ok " if c else "FAIL: ") + m)
if not c:
ok = false
func _box(lo: Vector3, hi: Vector3) -> PackedFloat32Array:
return PackedFloat32Array([-1, 0, 0, -lo.x, 1, 0, 0, hi.x, 0, -1, 0, -lo.y,
0, 1, 0, hi.y, 0, 0, -1, -lo.z, 0, 0, 1, hi.z])
func _ray(from: Vector3, to: Vector3) -> Dictionary:
var q := PhysicsRayQueryParameters3D.create(from, to)
return (_map as Node3D).get_world_3d().direct_space_state.intersect_ray(q)
func _process(_delta: float) -> bool:
_step += 1
match _step:
1:
_map = (load("res://scenes/maps/map_test.tscn") as PackedScene).instantiate()
root.add_child(_map)
4:
var level: Node = _map.get("level")
_p(level != null, "map_test has its DCLevel")
# A brush far from everything (Ground spans x,z in [-50, 50] at y=0).
_bid = level.add_brush(_box(Vector3(200, 0, 200), Vector3(202, 2, 202)), 0)
level.rebuild()
_p(_bid > 0, "a brush added (id %d)" % _bid)
# A NON-level body with its own shape 0. map_test's scene boxes are baked into
# brushes now (_bake_scene_boxes), so the gate brings its own.
var body := StaticBody3D.new()
body.name = "GateForeignBox"
var cs := CollisionShape3D.new()
var bs := BoxShape3D.new()
bs.size = Vector3(4, 2, 4)
cs.shape = bs
body.add_child(cs)
body.position = Vector3(300, 1, 300)
_map.add_child(body)
8:
# 1. onto a foreign StaticBody3D whose shape 0 is NOT the level's
var g: Dictionary = _ray(Vector3(300, 10, 300), Vector3(300, -10, 300))
_p(not g.is_empty() and g.get("collider") != _map.get("level"),
"the ray hits the foreign box (%s)" % str(g.get("collider")))
_p(_map._brush_from_hit(g) < 0,
"a scene box is NOT a brush (got %d; was the unrelated brush %d)" % [_map._brush_from_hit(g), _bid])
# 2. onto the brush: still picked
var b: Dictionary = _ray(Vector3(201, 10, 201), Vector3(201, -10, 201))
_p(not b.is_empty() and b.get("collider") == _map.get("level"), "the ray hits the level body")
_p(_map._brush_from_hit(b) == _bid, "the brush IS picked (got %d)" % _map._brush_from_hit(b))
# 3. an explicit brush (the clearance view) still wins
_p(_map._brush_from_hit({"brush": _bid}) == _bid, "an explicit hit.brush is kept")
print("GATE pick_level_only: %s" % ("PASS" if ok else "FAIL"))
quit(0 if ok else 1)
return true
return false