Skip to content

Commit

Permalink
Add a dialog to customize run instances
Browse files Browse the repository at this point in the history
  • Loading branch information
KoBeWi committed Feb 5, 2024
1 parent d335281 commit 5ab9e50
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 125 deletions.
105 changes: 13 additions & 92 deletions editor/editor_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,48 +34,10 @@
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/run_instances_dialog.h"
#include "main/main.h"
#include "servers/display_server.h"

/**
* Separates command line arguments without splitting up quoted strings.
*/
Vector<String> EditorRun::_split_cmdline_args(const String &arg_string) {
Vector<String> split_args;
int arg_start = 0;
bool is_quoted = false;
char32_t quote_char = '-';
char32_t arg_char;
int arg_length;
for (int i = 0; i < arg_string.length(); i++) {
arg_char = arg_string[i];
if (arg_char == '\"' || arg_char == '\'') {
if (i == 0 || arg_string[i - 1] != '\\') {
if (is_quoted) {
if (arg_char == quote_char) {
is_quoted = false;
quote_char = '-';
}
} else {
is_quoted = true;
quote_char = arg_char;
}
}
} else if (!is_quoted && arg_char == ' ') {
arg_length = i - arg_start;
if (arg_length > 0) {
split_args.push_back(arg_string.substr(arg_start, arg_length));
}
arg_start = i + 1;
}
}
arg_length = arg_string.length() - arg_start;
if (arg_length > 0) {
split_args.push_back(arg_string.substr(arg_start, arg_length));
}
return split_args;
}

EditorRun::Status EditorRun::get_status() const {
return status;
}
Expand Down Expand Up @@ -261,67 +223,26 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
args.push_back(p_scene);
}

String exec = OS::get_singleton()->get_executable_path();

const String raw_custom_args = GLOBAL_GET("editor/run/main_run_args");
if (!raw_custom_args.is_empty()) {
// Allow the user to specify a command to run, similar to Steam's launch options.
// In this case, Godot will no longer be run directly; it's up to the underlying command
// to run it. For instance, this can be used on Linux to force a running project
// to use Optimus using `prime-run` or similar.
// Example: `prime-run %command% --time-scale 0.5`
const int placeholder_pos = raw_custom_args.find("%command%");

Vector<String> custom_args;

if (placeholder_pos != -1) {
// Prepend executable-specific custom arguments.
// If nothing is placed before `%command%`, behave as if no placeholder was specified.
Vector<String> exec_args = _split_cmdline_args(raw_custom_args.substr(0, placeholder_pos));
if (exec_args.size() >= 1) {
exec = exec_args[0];
exec_args.remove_at(0);

// Append the Godot executable name before we append executable arguments
// (since the order is reversed when using `push_front()`).
args.push_front(OS::get_singleton()->get_executable_path());
}

for (int i = exec_args.size() - 1; i >= 0; i--) {
// Iterate backwards as we're pushing items in the reverse order.
args.push_front(exec_args[i].replace(" ", "%20"));
}

// Append Godot-specific custom arguments.
custom_args = _split_cmdline_args(raw_custom_args.substr(placeholder_pos + String("%command%").size()));
for (int i = 0; i < custom_args.size(); i++) {
args.push_back(custom_args[i].replace(" ", "%20"));
}
} else {
// Append Godot-specific custom arguments.
custom_args = _split_cmdline_args(raw_custom_args);
for (int i = 0; i < custom_args.size(); i++) {
args.push_back(custom_args[i].replace(" ", "%20"));
}
}
}

// Pass the debugger stop shortcut to the running instance(s).
String shortcut;
VariantWriter::write_to_string(ED_GET_SHORTCUT("editor/stop_running_project"), shortcut);
OS::get_singleton()->set_environment("__GODOT_EDITOR_STOP_SHORTCUT__", shortcut);

if (OS::get_singleton()->is_stdout_verbose()) {
print_line(vformat("Running: %s", exec));
for (const String &E : args) {
print_line(vformat(" %s", E));
String exec = OS::get_singleton()->get_executable_path();
int instance_count = RunInstancesDialog::get_singleton()->get_instance_count();
for (int i = 0; i < instance_count; i++) {
List<String> instance_args(args);
RunInstancesDialog::get_singleton()->get_argument_list_for_instance(i, instance_args);

if (OS::get_singleton()->is_stdout_verbose()) {
print_line(vformat("Running: %s", exec));
for (const String &E : instance_args) {
print_line(" %s", E);
}
}
}

int instances = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_instances", 1);
for (int i = 0; i < instances; i++) {
OS::ProcessID pid = 0;
Error err = OS::get_singleton()->create_instance(args, &pid);
Error err = OS::get_singleton()->create_instance(instance_args, &pid);
ERR_FAIL_COND_V(err, err);
if (pid != 0) {
pids.push_back(pid);
Expand Down
2 changes: 0 additions & 2 deletions editor/editor_run.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ class EditorRun {
Status status;
String running_scene;

Vector<String> _split_cmdline_args(const String &arg_string);

public:
Status get_status() const;
String get_running_scene() const;
Expand Down
39 changes: 10 additions & 29 deletions editor/plugins/debugger_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/run_instances_dialog.h"
#include "editor/themes/editor_scale.h"
#include "scene/gui/menu_button.h"

Expand Down Expand Up @@ -93,37 +94,20 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(PopupMenu *p_debug_menu) {
debug_menu->set_item_tooltip(-1,
TTR("When this option is enabled, the editor debug server will stay open and listen for new sessions started outside of the editor itself."));

// Multi-instance, start/stop
instances_menu = memnew(PopupMenu);
instances_menu->set_name("RunInstances");
instances_menu->set_hide_on_checkable_item_selection(false);

debug_menu->add_child(instances_menu);
// Multi-instance, start/stop.
debug_menu->add_separator();
debug_menu->add_submenu_item(TTR("Run Multiple Instances"), "RunInstances");

for (int i = 1; i <= 4; i++) {
instances_menu->add_radio_check_item(vformat(TTRN("Run %d Instance", "Run %d Instances", i), i));
instances_menu->set_item_metadata(i - 1, i);
}
instances_menu->set_item_checked(0, true);
instances_menu->connect("index_pressed", callable_mp(this, &DebuggerEditorPlugin::_select_run_count));
debug_menu->add_item(TTR("Run Multiple Instances..."), RUN_MULTIPLE_INSTANCES);
debug_menu->connect("id_pressed", callable_mp(this, &DebuggerEditorPlugin::_menu_option));

run_instances_dialog = memnew(RunInstancesDialog);
EditorNode::get_singleton()->get_gui_base()->add_child(run_instances_dialog);
}

DebuggerEditorPlugin::~DebuggerEditorPlugin() {
EditorDebuggerServer::deinitialize();
memdelete(file_server);
}

void DebuggerEditorPlugin::_select_run_count(int p_index) {
int len = instances_menu->get_item_count();
for (int idx = 0; idx < len; idx++) {
instances_menu->set_item_checked(idx, idx == p_index);
}
EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_instances", instances_menu->get_item_metadata(p_index));
}

void DebuggerEditorPlugin::_menu_option(int p_option) {
switch (p_option) {
case RUN_FILE_SERVER: {
Expand Down Expand Up @@ -201,6 +185,10 @@ void DebuggerEditorPlugin::_menu_option(int p_option) {
EditorSettings::get_singleton()->set_project_metadata("debug_options", "server_keep_open", !ischecked);

} break;
case RUN_MULTIPLE_INSTANCES: {
run_instances_dialog->popup_centered();

} break;
}
}

Expand All @@ -227,7 +215,6 @@ void DebuggerEditorPlugin::_update_debug_options() {
bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", true);
bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", true);
bool check_server_keep_open = EditorSettings::get_singleton()->get_project_metadata("debug_options", "server_keep_open", false);
int instances = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_instances", 1);

if (check_deploy_remote) {
_menu_option(RUN_DEPLOY_REMOTE_DEBUG);
Expand Down Expand Up @@ -259,10 +246,4 @@ void DebuggerEditorPlugin::_update_debug_options() {
if (check_server_keep_open) {
_menu_option(SERVER_KEEP_OPEN);
}

int len = instances_menu->get_item_count();
for (int idx = 0; idx < len; idx++) {
bool checked = (int)instances_menu->get_item_metadata(idx) == instances;
instances_menu->set_item_checked(idx, checked);
}
}
5 changes: 3 additions & 2 deletions editor/plugins/debugger_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@
class EditorFileServer;
class MenuButton;
class PopupMenu;
class RunInstancesDialog;

class DebuggerEditorPlugin : public EditorPlugin {
GDCLASS(DebuggerEditorPlugin, EditorPlugin);

private:
PopupMenu *debug_menu = nullptr;
EditorFileServer *file_server = nullptr;
PopupMenu *instances_menu = nullptr;
RunInstancesDialog *run_instances_dialog = nullptr;

enum MenuOptions {
RUN_FILE_SERVER,
Expand All @@ -56,11 +57,11 @@ class DebuggerEditorPlugin : public EditorPlugin {
RUN_DEPLOY_REMOTE_DEBUG,
RUN_RELOAD_SCRIPTS,
SERVER_KEEP_OPEN,
RUN_MULTIPLE_INSTANCES,
};

void _update_debug_options();
void _notification(int p_what);
void _select_run_count(int p_index);
void _menu_option(int p_option);

public:
Expand Down
Loading

0 comments on commit 5ab9e50

Please sign in to comment.