82 lines
2.7 KiB
GDScript
82 lines
2.7 KiB
GDScript
extends SceneTree
|
|
|
|
## Structural checks for the map-cohesion pass.
|
|
##
|
|
## godot --headless --path . -s res://debug/sakura_boundary_audit.gd
|
|
|
|
const MAP := "res://scenes/maps/sakura_crossing/sakura_crossing.tscn"
|
|
const EXPECTED_AREA := Vector3(236.0, 60.0, 176.0)
|
|
|
|
var _level: Node
|
|
var _frames := 0
|
|
var _fails := 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
_level = (load(MAP) as PackedScene).instantiate()
|
|
root.add_child(_level)
|
|
|
|
|
|
func _check(ok: bool, message: String) -> void:
|
|
print("BOUNDARY_AUDIT %s %s" % ["OK" if ok else "FAIL", message])
|
|
if not ok:
|
|
_fails += 1
|
|
|
|
|
|
func _process(_delta: float) -> bool:
|
|
_frames += 1
|
|
if _frames < 8:
|
|
return false
|
|
|
|
var area: CombatArea = null
|
|
for candidate in _level.find_children("*", "CombatArea", true, false):
|
|
area = candidate as CombatArea
|
|
break
|
|
_check(area != null, "combat area exists")
|
|
if area != null:
|
|
var collision := area.get_child(0) as CollisionShape3D
|
|
var box := collision.shape as BoxShape3D if collision != null else null
|
|
_check(box != null and box.size.is_equal_approx(EXPECTED_AREA),
|
|
"combat area matches the visible wall rectangle")
|
|
|
|
var gates: Array[Node] = []
|
|
for body in _level.find_children("*", "StaticBody3D", true, false):
|
|
if body.has_meta("boundary_gate"):
|
|
gates.append(body)
|
|
_check(gates.size() == 60, "six road closures have ten beam segments each")
|
|
var kei_cars := _level.find_children("KeiCar*", "Node3D", true, false)
|
|
_check(not kei_cars.is_empty(), "kei hatchbacks are present")
|
|
|
|
var house_meshes: Array[MeshInstance3D] = []
|
|
for body in _level.find_children("HouseBody*", "StaticBody3D", true, false):
|
|
var mesh := body.get_child(1) as MeshInstance3D
|
|
if mesh != null:
|
|
house_meshes.append(mesh)
|
|
var overlaps := 0
|
|
for i in range(house_meshes.size()):
|
|
for j in range(i + 1, house_meshes.size()):
|
|
var overlap := _global_aabb(house_meshes[i]).intersection(_global_aabb(house_meshes[j]))
|
|
if overlap.size.x > 0.02 and overlap.size.y > 0.02 and overlap.size.z > 0.02:
|
|
overlaps += 1
|
|
if overlaps <= 8:
|
|
print("BOUNDARY_AUDIT HOUSE_OVERLAP %s %s size=%s" % [
|
|
house_meshes[i].get_path(), house_meshes[j].get_path(), overlap.size])
|
|
_check(overlaps == 0, "detached house bodies do not overlap")
|
|
|
|
print("=== SAKURA BOUNDARY AUDIT: %s ===" %
|
|
("ALL CLEAR" if _fails == 0 else "%d FAILED" % _fails))
|
|
quit(0 if _fails == 0 else 1)
|
|
return true
|
|
|
|
|
|
func _global_aabb(mesh: MeshInstance3D) -> AABB:
|
|
var local := mesh.get_aabb()
|
|
var result := AABB(mesh.global_transform * local.position, Vector3.ZERO)
|
|
for x in 2:
|
|
for y in 2:
|
|
for z in 2:
|
|
var corner := local.position + Vector3(
|
|
local.size.x * float(x), local.size.y * float(y), local.size.z * float(z))
|
|
result = result.expand(mesh.global_transform * corner)
|
|
return result
|