StreamOverlay/addons/custom_runner/plugin.gd

168 lines
4.7 KiB
GDScript3
Raw Normal View History

@tool
extends EditorPlugin
var _runner_btn: RunnerButton
var _play_icon: Texture2D
var _stop_icon: Texture2D
func _enter_tree() -> void:
if not ProjectSettings.has_setting("application/run/custom_rinner"):
ProjectSettings.set("application/run/custom_runner", "")
ProjectSettings.add_property_info({
"name": "application/run/custom_runner",
"type": TYPE_STRING,
"hint": PROPERTY_HINT_GLOBAL_FILE,
"hint_string": ""
})
_runner_btn = RunnerButton.new()
add_control_to_container(EditorPlugin.CONTAINER_TOOLBAR, _runner_btn)
var cnt := _runner_btn.get_parent()
cnt.move_child(_runner_btn, cnt.get_child_count() - 3)
func _exit_tree() -> void:
remove_control_from_container(EditorPlugin.CONTAINER_TOOLBAR, _runner_btn)
_runner_btn.queue_free()
_runner_btn = null
class RunnerButton:
extends Button
var _play: Texture2D
var _stop: Texture2D
var _running_pid: int = -1
var _io: FileAccess = null
var _err: FileAccess = null
var _output: RichTextLabel = null
func _init() -> void:
_play = EditorInterface.get_editor_theme().get_icon(&"Play", &"EditorIcons")
_stop = EditorInterface.get_editor_theme().get_icon(&"Stop", &"EditorIcons")
shortcut = Shortcut.new()
var key := InputEventKey.new()
key.keycode = KEY_F5
key.shift_pressed = true
shortcut.events = [key]
modulate = Color.GREEN
var esb := StyleBoxEmpty.new()
add_theme_stylebox_override(&"normal", esb)
func _ready() -> void:
icon = _play
func _process(_d: float) -> void:
if _running_pid == -1: return
if not OS.is_process_running(_running_pid):
_running_pid = -1
icon = _play
modulate = Color.GREEN
func _pressed() -> void:
if _running_pid != -1:
OS.kill(_running_pid)
_running_pid = -1
icon = _play
modulate = Color.GREEN
return
var runner := ProjectSettings.get_setting("application/run/custom_runner", "")
if runner == "":
EditorInterface.play_main_scene()
return
if not FileAccess.file_exists(runner):
EditorInterface.get_editor_toaster().push_toast("Custom runner does not exist!",
EditorToaster.SEVERITY_ERROR,
"Provide the full path to the custom runner!")
return
var godot = OS.get_executable_path()
var project = ProjectSettings.globalize_path("res://").rstrip("/")
var host: String = EditorInterface.get_editor_settings().get_setting("network/debug/remote_host")
var port: int = EditorInterface.get_editor_settings().get_setting("network/debug/remote_port")
var pid: int = OS.get_process_id()
var main_scene: String = ProjectSettings.get_setting("application/run/main_scene")
var run_arguments := [
godot,
"--path", project,
#"-d"
"--remote-debug", "tcp://%s:%s" % [host, port],
"--editor-pid", "%s" % pid,
"--position", "320,-24",
"--scene", main_scene
]
# --remote-debug tcp://127.0.0.1:6007 --editor-pid 3480813 --position 320,-24 --scene uid://2t2hslaaewee
if not _output: _output = _get_output()
if _output:
_output.clear()
print("Executing project with the following Command Line: %s %s" % [runner, run_arguments])
#_running_pid = OS.create_process(runner, run_arguments)
var res := OS.execute_with_pipe(runner, run_arguments, false)
if res.is_empty():
EditorInterface.get_editor_toaster().push_toast("Failed to Run custom runner.",EditorToaster.SEVERITY_ERROR)
_running_pid = res.pid
_io = res.stdio
_err = res.stderr
icon = _stop
modulate = Color.RED
_monitor_input_output()
func _monitor_input_output() -> void:
var output: PackedByteArray = []
var err: PackedByteArray = []
while OS.is_process_running(_running_pid):
await get_tree().process_frame
var res := _read_io(_io, output)
#if res != "":
#print_rich(res)
res = _read_io(_err, err)
#if res != "":
#print_rich(res)
await get_tree().process_frame
var str := _read_io(_io, output)
if str != "":
print(str)
str = _read_io(_err, err)
if str != "":
print(str)
_io.close()
_err.close()
_io = null
_err = null
func _read_io(io: FileAccess, buffer: PackedByteArray) -> String:
if io.get_position() < io.get_length():
buffer.append_array(io.get_buffer(io.get_length() - io.get_position()))
var nl = buffer.rfind(10)
if nl == -1:
return ""
var part := buffer.slice(0,nl)
var leftover := buffer.slice(nl+1)
buffer.clear()
buffer.append_array(leftover)
return part.get_string_from_utf8()
func _get_output() -> RichTextLabel:
return _find_output(get_tree().root)
func _find_output(current: Node) -> RichTextLabel:
if current is RichTextLabel and current.get_parent() and current.get_parent().get_parent() and current.get_parent().get_parent().name.begins_with("@EditorLog"):
return current
for c in current.get_children(true):
var r = _find_output(c)
if r:
return r
return null