152 lines
4.2 KiB
GDScript3
152 lines
4.2 KiB
GDScript3
|
|
@tool
|
||
|
|
extends EditorPlugin
|
||
|
|
|
||
|
|
var _runner_btn: RunnerButton
|
||
|
|
var _play_icon: Texture2D
|
||
|
|
var _stop_icon: Texture2D
|
||
|
|
|
||
|
|
func _enter_tree() -> void:
|
||
|
|
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
|
||
|
|
|
||
|
|
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
|
||
|
|
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()
|