OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / _probe_asset_fold.gd

103 lines · gd ref:
extends Node
## PROBE (not a gate) — WHAT PLACED ASSETS COST THE FOLD (#120 L4 §15.8 step 7). One room
## per process, PROBE_N placements (default 10) of a 50-shape asset ("Kit": 50 boxes in a
## 10 x 5 grid, every 5th with a mirror), then, each the median of PROBE_REPS (3):
##   refold()               the whole fold, forced (no skip, no tail)
##   AssetFold.expand       the placements' expansion alone
##   move one placement     asset.xform + its refold (what a G on one costs)
## and the SAME geometry as ordinary shapes — N copies of the 50 boxes recorded directly — for
## the reference: what instancing adds over owning the records.
## DIGESTS: the placements' brushes vs the copies' (offset), so the two rooms are the same.
##
## RUN: PROBE_N=10 CI=true HYPERTPS_DAEMON_TCP=127.0.0.1:1 "$HYPER_TPS_GODOT" --headless --path . res://scenes/test/_probe_asset_fold.tscn

var map: Node3D
var persist: Node
var level: Node


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 = "probe"
	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
	persist = map.get("_persist")
	level = map.get("level")
	var n := int(OS.get_environment("PROBE_N")) if OS.get_environment("PROBE_N") != "" else 10
	var reps := int(OS.get_environment("PROBE_REPS")) if OS.get_environment("PROBE_REPS") != "" else 3
	var mode := OS.get_environment("PROBE_MODE") if OS.get_environment("PROBE_MODE") != "" else "assets"
	var O0 := Vector3(1000, 0, 1000)
	# The asset: 50 boxes, every 5th mirrored.
	persist.begin_gesture("kit")
	var members: Array = []
	for i in 50:
		var at := O0 + Vector3((i % 10) * 3.0, 0, (i / 10) * 3.0)
		var d: String = persist.record("shape.create", {"type": "box", "gv": 1, "params": {},
			"frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, at)), "size": [2, 2, 2], "material_id": 2, "level_id": 0})
		if i % 5 == 0:
			persist.record("mod.create", {"target": d, "mod": "mirror", "params": {"axis": "x", "offset": 0.0}})
		members.append("g:" + d)
	var kit: String = persist.record("col.create", {"name": "Kit", "parent": ""})
	persist.record("col.link", {"target": kit, "members": members})
	persist.end_gesture()
	persist.refold()
	var lib: Node = map.asset_library()
	lib.save_collection(kit, "Kit", true, false)
	var base_brushes := (level.get_live_brush_ids() as PackedInt32Array).size()
	var dots: Array = []
	persist.begin_gesture("place")
	for k in n:
		var f := Transform3D(Basis.IDENTITY, O0 + Vector3(0, 0, 40 + k * 20))
		if mode == "assets":
			dots.append(persist.record("asset.place", {"asset": lib.rows()[0]["oid"], "name": "Kit", "frame": SceneObjects.xform_to(f)}))
		else:
			# The reference: the same 50 boxes (+ mirrors) recorded as the user's own shapes.
			for i2 in 50:
				var at2 := f.origin + Vector3((i2 % 10) * 3.0, 0, (i2 / 10) * 3.0) - Vector3(0, 0, 0)
				var d2: String = persist.record("shape.create", {"type": "box", "gv": 1, "params": {},
					"frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, at2)), "size": [2, 2, 2], "material_id": 2, "level_id": 0})
				if i2 % 5 == 0:
					persist.record("mod.create", {"target": d2, "mod": "mirror", "params": {"axis": "x", "offset": 0.0}})
	persist.end_gesture()
	persist.refold()
	var brushes := (level.get_live_brush_ids() as PackedInt32Array).size() - base_brushes
	var tf := []
	for r in reps:
		persist.set("_brush_ver_folded", -1)
		persist.set("_ix_tail_ok", false)
		var t0 := Time.get_ticks_usec()
		persist.refold()
		tf.append(float(Time.get_ticks_usec() - t0) / 1000.0)
	var te := []
	if mode == "assets":
		var arecs: Array = (persist.records(false) as Array).filter(func(x: Dictionary) -> bool: return String(x["kind"]).begins_with("asset."))
		for r2 in reps:
			var t1 := Time.get_ticks_usec()
			LevelPersistence.AssetFold.expand(arecs, persist.get("_asset_docs"), persist._parse_as)
			te.append(float(Time.get_ticks_usec() - t1) / 1000.0)
	var tm := []
	for r3 in reps:
		var t2 := Time.get_ticks_usec()
		persist.begin_gesture("move")
		if mode == "assets":
			persist.record("asset.xform", {"target": dots[0], "frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, O0 + Vector3(r3 + 1, 0, 40)))})
		else:
			persist.record("shape.xform", {"target": String(members[0]).substr(2), "frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, O0 + Vector3(r3 + 1, 0, 0)))})
		persist.end_gesture()
		persist.refold()
		tm.append(float(Time.get_ticks_usec() - t2) / 1000.0)
	print("PROBE %s N=%d: %d brushes from them | refold() %.1f ms | AssetFold.expand %s | move one %.1f ms"
		% [mode, n, brushes, _med(tf), ("%.1f ms" % _med(te)) if not te.is_empty() else "—", _med(tm)])
	get_tree().quit(0)


func _med(ts: Array) -> float:
	ts.sort()
	return ts[ts.size() / 2]