OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_face_set_live.gd

77 lines · gd ref:
extends Node
## GATE — A FACE SET DROPS A DELETED BRUSH'S FACE (#129 deferred bug; docs §14.4).
## A removed brush is a TOMBSTONE that brush_by_key / get_brush still return, so the face
## set (Alt+J, Alt+E, the cable bundle) resolved faces of deleted brushes. The edge set
## checks get_live_brush_ids (gate_edge_set E8); the face set must too.
##   F1  two faces in the set: both resolve
##   F2  one brush deleted: only the live one's face resolves
##
## RUN AS A SCENE: "$HYPER_TPS_GODOT" --headless res://scenes/test/gate_face_set_live.tscn

var fails := 0
var checks := 0
var map: Node3D


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)
	for i in 6:
		await get_tree().process_frame
	_run()
	get_tree().root.get_node("/root/GameMode").set_mode("play")
	if checks < 2:
		print("  **FAIL** only %d checks ran -- setup died before the assertions" % checks)
		fails += 1
	print("\nGATE face_set_live: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
	get_tree().quit(0 if fails == 0 else 1)


static func _box_planes(lo: Vector3, hi: Vector3) -> Array:
	return [-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 _run() -> void:
	var persist: Node = map.get("_persist")
	var level: Node = map.get("level")
	persist.begin_gesture("two")
	for x: float in [700.0, 704.0]:
		persist.record("brush.create", {"planes": _box_planes(Vector3(x, 0, 700), Vector3(x + 1, 1, 701)), "proj": [],
			"material_id": 1, "level_id": 0, "sky": false, "clearance": false, "group": "", "face_tex": []})
	persist.end_gesture()
	persist.refold()
	var ids: Array = []
	for b: int in (level.get_live_brush_ids() as PackedInt32Array):
		var c: Vector3 = (level.get_brush(b)["aabb_min"] as Vector3)
		if c.z > 699.0 and c.z < 701.0:
			ids.append(b)
	# TYPED, as the map's: set() with an untyped Array on an Array[Dictionary] property
	# silently leaves it as it was.
	var faces: Array[Dictionary] = []
	for b: int in ids:
		var pk: PackedStringArray = level.get_brush(b).get("plane_keys", PackedStringArray())
		faces.append({"b": String(level.get_brush_key(b)), "p": pk[3]})       # the top face
	map.set("_sel_faces", faces)
	_ok("F1 two faces in the set resolve", ids.size() == 2 and (map.call("_selected_face_polys") as Array).size() == 2,
		[ids.size(), (map.call("_selected_face_polys") as Array).size()])
	persist.begin_gesture("del")
	persist.record("brush.remove", {"brush_key": String(faces[1]["b"])})
	persist.end_gesture()
	persist.refold()
	map.set("_sel_faces", faces)                  # as a selection that outlived the delete
	_ok("F2 the deleted brush's face drops out", (map.call("_selected_face_polys") as Array).size() == 1,
		(map.call("_selected_face_polys") as Array).size())