OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / gate_shape_child_names.gd

96 lines · gd ref:
extends SceneTree
## GATE — a parametric shape's Outliner rows are NAMED BY ROLE (hyper-games #109,
## 2026-10-12: "when clicking on a group object like a staircase it is currently labeled
## as passage, should be labelled as to what it is and children should also be named
## appropriately, passage is fine a name for the actual subtractive brush";
## parametric-shapes-design §13.4).
##
##   N1  the group row is the shape's type ("◇ Stairs"), not "passage"
##   N2  stairs, 2 flights x 3 steps, in climbing order: step 1..3, landing 1,
##       step 4..6, then passage (the cut)
##   N3  tunnel, round, 4 facets + floor: voussoir 1..4, floor, passage
##   N4  spiral stairs with its column: step 1..n, column, passage
##   N5  box: one row named box
##
## RUN: CI=true HYPERTPS_DAEMON_TCP=127.0.0.1:1 "$GODOT" --headless --path . --script res://scenes/test/gate_shape_child_names.gd

var _frame := 0
var _map: Node = null
var fails := 0
var checks := 0


func _p(c: bool, m: String, got: Variant = "") -> void:
	checks += 1
	if not c:
		fails += 1
	print("  %-66s %s  %s" % [m, "OK" if c else "**FAIL**", str(got)])


func _process(_d: float) -> bool:
	_frame += 1
	if _frame == 1:
		root.get_node("/root/GameMode").set_mode("build")
		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")
		_map = (load("res://scenes/maps/map_flat.tscn") as PackedScene).instantiate()
		root.add_child(_map)
		return false
	if _frame < 30:
		return false
	_run()
	if checks < 5:
		print("  **FAIL** only %d checks ran -- setup died before the assertions" % checks)
		fails += 1
	print("\nGATE shape_child_names: %s (%d checks, %d failed)" % ["PASS" if fails == 0 else "FAIL", checks, fails])
	quit(0 if fails == 0 else 1)
	return true


## Place a shape of `shape` (CreateBoxOperator.Shape) at x, then set its params.
func _make(shape: int, x: float, params: Dictionary) -> String:
	var bx: CreateBoxOperator = _map.get("_box")
	bx.set_tool_setting("shape", shape)
	bx.set_tool_setting("size", 8)
	bx.adjust_restore({"origin": Vector3(x, 0, 0), "normal": Vector3.UP, "axis": 1,
		"view": Vector3(1, 0, 0.01), "material": 0, "level_id": 0})
	bx.confirm()
	var dot: String = _map.selected_shape()
	if not params.is_empty():
		_map.set_shape_params(dot, params)
	return dot


## The child names (the part before " · ") of the shape group `dot`, and its row name.
func _names(dot: String) -> Array:
	var model: Variant = (_map.get("_outliner") as Node).get("model")
	var ids: PackedInt32Array = _map.level.get_group_brush_ids(dot)
	for r: Dictionary in model.rows():
		if int(r["kind"]) == OutlinerModel.Kind.GROUP and (r["brushes"] as PackedInt32Array) == ids:
			var out: Array = []
			for m: Dictionary in model.members(String(r["id"]), ids, 200):
				out.append(String(m["name"]).get_slice(" · ", 0))
			return [String(r["name"]), out]
	return ["<no row>", []]


func _run() -> void:
	var st := _make(CreateBoxOperator.Shape.STAIRS, 0.0, {"flights": 2, "steps": 3})
	var a := _names(st)
	_p(String(a[0]).contains("Stairs") and not String(a[0]).contains("passage"), "N1 the group row is the type", a[0])
	_p(a[1] == ["step 1", "step 2", "step 3", "landing 1", "step 4", "step 5", "step 6", "passage"],
		"N2 stairs, in climbing order: steps, landing, steps, then the passage", a[1])
	var tn := _make(CreateBoxOperator.Shape.ARCH, 20.0, {"facets": 4, "floor": true})
	_p(_names(tn)[1] == ["voussoir 1", "voussoir 2", "voussoir 3", "voussoir 4", "floor", "passage"],
		"N3 tunnel: voussoirs, the floor, the passage", _names(tn)[1])
	var sp := _make(CreateBoxOperator.Shape.SPIRAL_STAIRS, 40.0, {"center_column": true})
	var sn: Array = _names(sp)[1]
	_p(sn.size() >= 3 and String(sn[0]) == "step 1" and sn[sn.size() - 2] == "column" and sn[sn.size() - 1] == "passage",
		"N4 spiral: steps, the column, the passage", sn)
	var bxd := _make(CreateBoxOperator.Shape.BOX, 60.0, {})
	_p(_names(bxd)[1] == ["box"], "N5 box: one row named box", _names(bxd)[1])