extends Node
## PROBE (not a gate) — WHERE OutlinerPanel.refresh()'s TIME GOES (hyper-games #127: ~200 ms
## of a 20-cable bundle's ~660 ms fold). The bundle20 room of _probe_fold_split, then each
## stage of refresh() and of OutlinerModel.rows() the way they run, median of PROBE_REPS:
## rows() WARM (the brush-row cache hit: an object edit) and COLD (cache dropped: what a
## brush / shape fold pays), its five builders one by one, then the panel's own stages.
##
## RUN: CI=true HYPERTPS_DAEMON_TCP=127.0.0.1:1 "$HYPER_TPS_GODOT" --headless --path . res://scenes/test/_probe_outliner_split.tscn
var map: Node3D
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
var n := int(OS.get_environment("PROBE_N")) if OS.get_environment("PROBE_N") != "" else 20
var A := {"pts": PackedVector3Array([Vector3(400, 0, 300), Vector3(400, 0, 302), Vector3(400, 2, 302), Vector3(400, 2, 300)]), "n": Vector3.RIGHT}
var B := {"pts": PackedVector3Array([Vector3(410, 0, 300), Vector3(410, 2, 300), Vector3(410, 2, 302), Vector3(410, 0, 302)]), "n": Vector3.LEFT}
map.cable_bundle([A, B], {"count": n, "random": true, "seed": 1, "tension": 1.0, "jitter": 0.3, "slack": 1.0},
{"radius": 0.03})
var ol: Node = map.get("_outliner")
if ol == null:
print("PROBE no outliner")
get_tree().quit(1)
return
var m: OutlinerModel = ol.get("model")
var reps := int(OS.get_environment("PROBE_REPS")) if OS.get_environment("PROBE_REPS") != "" else 5
var t := {}
for rep in reps:
_time(t, "refresh() warm", func() -> void: ol.refresh())
_time(t, "refresh() cold", _cold_refresh.bind(ol, m))
_time(t, "rows() warm", func() -> void: m.rows())
_time(t, "rows() cold", _cold_rows.bind(m))
_time(t, " _add_node_rows", func() -> void: m.call("_add_node_rows", []))
_time(t, " _add_object_rows", func() -> void: m.call("_add_object_rows", []))
_time(t, " _build_brush_rows", func() -> void: m.call("_build_brush_rows", []))
_time(t, " _add_collection_rows", func() -> void: m.call("_add_collection_rows", []))
var rs: Array = m.rows()
_time(t, " _resolve_hidden", func() -> void: m.call("_resolve_hidden", rs))
_time(t, " live_shapes", func() -> void: map.get("_persist").live_shapes())
_time(t, " collection_tree", func() -> void: map.get("_persist").collection_tree())
_time(t, "panel _on_map_selection", func() -> void: ol.call("_on_map_selection"))
_time(t, "panel _sync_position", func() -> void: ol.call("_sync_position"))
_time(t, "panel _update_status", func() -> void: ol.call("_update_status"))
var sel: Array = map.get("_sel_brushes")
print("PROBE outliner: %d rows, %d live brushes, %d selected brushes, sel_shape '%s', %d objects selected"
% [m.rows().size(), (map.get("level").get_live_brush_ids() as PackedInt32Array).size(), sel.size(),
String(map.get("_sel_shape")), (map.selected_objects() as Array).size()])
for k: String in t:
var a: Array = t[k]
a.sort()
print("PROBE outliner: %-28s %8.1f ms" % [k, a[a.size() / 2]])
get_tree().quit(0)
func _time(t: Dictionary, k: String, f: Callable) -> void:
var t0 := Time.get_ticks_usec()
f.call()
(t.get_or_add(k, []) as Array).append(float(Time.get_ticks_usec() - t0) / 1000.0)
func _cold_refresh(ol: Node, m: OutlinerModel) -> void:
m.set("_brush_rows_key", "")
ol.refresh()
func _cold_rows(m: OutlinerModel) -> void:
m.set("_brush_rows_key", "")
m.rows()