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]