@tool extends EditorPlugin var server: TCPServer var port := 6009 var peers : Array[StreamPeerTCP] = [] enum COMMAND {OPEN_SCENE} func node_to_tree(node, root=false): var n = {} n["name"] = node.name n["type"] = node.get_class() n["index"] = node.get_index() n["path"] = "/" + node.get_path().get_concatenated_names() var c = [] for i in node.get_children(): c.append(node_to_tree(i)) if len(c) > 0: n["children"] = c return n func node_to_props(node): var n = {} n["name"] = node.name n["type"] = node.get_class() n["path"] = "/" + node.get_path().get_concatenated_names() n["props"] = [] var props = node.get_property_list() var i = 0 # NOTE: I cannot begin to fathom the reasons for why this shit is done # the way that it is, but this is bordering on an exercise # in pure futility at this stage. while i < len(props): var p = props[i] if p["usage"] & 128 == 128: var cat = {} cat["name"] = p["name"] cat["props"] = [] if i == len(props) - 1: break i += 1 while i < len(props): p = props[i] if p["usage"] & 128 == 128: break if p["usage"] & 4 == 4: var c = {} c["name"] = p["name"] c["value"] = node.get(p["name"]) cat["props"].append(c) i += 1 n["props"].append(cat) else: print(p["name"], " ", p["usage"]) break n["props"].reverse() return n func parse_command(str: String, peer: StreamPeerTCP): var cmd = JSON.parse_string(str) print(cmd) match cmd["command"]: "open-scene": print("Opening") EditorInterface.open_scene_from_path(cmd["scene"]) "select-node": var n = get_node(NodePath(cmd["path"])) EditorInterface.edit_node(n) "get-scene-tree": var result = node_to_props(EditorInterface.get_selection().get_selected_nodes()[0]) result = JSON.stringify({"for-cmd": "get-selected-node", "value": result}) peer.put_data(result.to_utf8_buffer()) # TODO: this is terrible await get_tree().create_timer(0.05).timeout result = node_to_tree(EditorInterface.get_edited_scene_root(), true) result = JSON.stringify({"for-cmd": "get-scene-tree", "value": result}) peer.put_data(result.to_utf8_buffer()) "set-node-name": var n = get_node(NodePath(cmd["path"])) var new_name = cmd["new-name"] print("setting ", n, "'s name as ", new_name) n.name = new_name "update-property": var n = get_node(NodePath(cmd["path"])) var prop = cmd["name"] var val = cmd ["new-value"] n.set(prop, val) _: print("Not a valid command: ", cmd["command"]) if cmd["command"] != "get-scene-tree": await parse_command(JSON.stringify({"command": "get-scene-tree"}), peer) func _enter_tree() -> void: server = TCPServer.new() server.listen(port) print("Remote control server listening on port ", port) func _process(delta: float) -> void: if server.is_connection_available(): var peer = server.take_connection() peer.set_no_delay(true) peers.append(peer) print("Took connection") for peer in peers: if peer.get_status() == 2 and peer.poll() == Error.OK: if peer.get_available_bytes() > 0: print("-----") print(peer.get_status()) var packet = peer.get_utf8_string(peer.get_available_bytes()) parse_command(packet, peer) print("-----") else: if peer.get_status() != 0: peer.disconnect_from_host() peers.erase(peer) print("Peer removed.") func _exit_tree() -> void: server.stop() print("Remote control server stopped.")