OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / undersea_bridge_driver.gd

78 lines · gd ref:
extends SceneTree
## Godot end of scripts/gate_undersea_bridge.py — the undersea scene in a REAL
## blender-bridge session, Godot leading (what "Open in Blender" does in the editor).
##
##   -- <scratch> <socket> <shm>
##   godot_ready         the bridge is listening and expects a Godot-led Blender for
##                       UnderseaGeissGraph.SCENE (it pushes the scene on that bind)
##   cmd_report <tag>    -> undersea_state.json {clients, nodes, knobs}, ack_report_<tag>
##   cmd_quit            stop and exit
##
## The scene instance is never processed: ProcGeometryNode would otherwise evaluate a
## density graph every frame for nothing. The bridge writes its graph regardless.

var _dir := ""
var _bridge: Node
var _scene: Node
var _frames := 0
var _seen := ""


func _init() -> void:
	var a := OS.get_cmdline_user_args()
	if a.size() < 3:
		push_error("undersea_bridge_driver: -- <scratch> <socket> <shm>")
		quit(2)
		return
	_dir = a[0]
	_scene = (load(UnderseaGeissGraph.SCENE) as PackedScene).instantiate()
	_scene.process_mode = Node.PROCESS_MODE_DISABLED
	get_root().add_child(_scene)
	_bridge = ClassDB.instantiate("BlenderBridge")
	_bridge.name = "BlenderBridge"
	get_root().add_child(_bridge)
	_bridge.set_shm_name(a[2])
	_bridge.start_server(a[1])
	_bridge.expect_godot_led(UnderseaGeissGraph.SCENE, _scene)
	_bridge.auto_sync = true
	process_frame.connect(_tick)
	_write("godot_ready", "1")


func _tick() -> void:
	_frames += 1
	if _frames > 200000:          # a driver that outlives its gate is a hung CI job
		push_error("undersea_bridge_driver: no cmd_quit, giving up")
		quit(3)
		return
	var tag := _read("cmd_report")
	if tag != "" and tag != _seen:
		_seen = tag
		var holder := _scene.get_node_or_null(UnderseaGeissGraph.HOLDER)
		var g := holder.get("graph") as ProcNodeGraph if holder != null else null
		var knobs := {}
		var kf := UnderseaGeissGraph.knobs_from(g)
		for k: String in kf:
			knobs[k] = var_to_str(kf[k])
		_write("undersea_state.json", JSON.stringify({
			"clients": _bridge.get_client_count(),
			"nodes": g.get_node_count() if g != null else -1,
			"knobs": knobs,
		}))
		_write("ack_report_" + tag, "1")
	if FileAccess.file_exists(_dir.path_join("cmd_quit")):
		_bridge.auto_sync = false
		_bridge.stop_server()
		quit(0)


func _read(name: String) -> String:
	var p := _dir.path_join(name)
	return FileAccess.get_file_as_string(p).strip_edges() if FileAccess.file_exists(p) else ""


func _write(name: String, text: String) -> void:
	var f := FileAccess.open(_dir.path_join(name), FileAccess.WRITE)
	f.store_string(text)
	f.close()