OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / _probe_outliner_split.gd

78 lines · gd ref:
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()