diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 25dd408dce9..0d699cdacbc 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1104,6 +1104,8 @@ ProjectSettings::ProjectSettings() { } extensions.push_back("shader"); + GLOBAL_DEF("editor/run/main_run_args", ""); + GLOBAL_DEF("editor/script/search_in_file_extensions", extensions); custom_prop_info["editor/script/search_in_file_extensions"] = PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions"); diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 8c90108aef1..d997073849e 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -143,7 +143,7 @@ Returns the command-line arguments passed to the engine. Command-line arguments can be written in any form, including both [code]--key value[/code] and [code]--key=value[/code] forms so they can be properly parsed, as long as custom command-line arguments do not conflict with engine arguments. You can also incorporate environment variables using the [method get_environment] method. - You can set [code]editor/main_run_args[/code] in the Project Settings to define command-line arguments to be passed by the editor when running the project. + You can set [member ProjectSettings.editor/run/main_run_args] to define command-line arguments to be passed by the editor when running the project. Here's a minimal example on how to parse command-line arguments into a dictionary using the [code]--key=value[/code] form for arguments: [codeblocks] [gdscript] diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 005873c2fff..3200f789b89 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -542,6 +542,14 @@ What to use to separate node name from number. This is mostly an editor setting. + + The command-line arguments to append to Godot's own command line when running the project. This doesn't affect the editor itself. + It is possible to make another executable run Godot by using the [code]%command%[/code] placeholder. The placeholder will be replaced with Godot's own command line. Program-specific arguments should be placed [i]before[/i] the placeholder, whereas Godot-specific arguments should be placed [i]after[/i] the placeholder. + For example, this can be used to force the project to run on the dedicated GPU in a NVIDIA Optimus system on Linux: + [codeblock] + prime-run %command% + [/codeblock] + Text-based file extensions to include in the script editor's "Find in Files" feature. You can add e.g. [code]tscn[/code] if you wish to also parse your scene files, especially if you use built-in scripts which are serialized in the scene files. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index ed670b12960..07e95e7b831 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5877,8 +5877,6 @@ EditorNode::EditorNode() { register_exporters(); - GLOBAL_DEF("editor/run/main_run_args", ""); - ClassDB::set_class_enabled("RootMotionView", true); //defs here, use EDITOR_GET in logic diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index e46f4eb65a8..5e6d2ab69c3 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -183,15 +183,50 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L args.push_back(p_scene); } + String exec = OS::get_singleton()->get_executable_path(); + if (p_custom_args != "") { - Vector cargs = p_custom_args.split(" ", false); - for (int i = 0; i < cargs.size(); i++) { - args.push_back(cargs[i].replace(" ", "%20")); + // 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 = p_custom_args.find("%command%"); + + Vector 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 exec_args = p_custom_args.substr(0, placeholder_pos).split(" ", false); + if (exec_args.size() >= 1) { + exec = exec_args[0]; + exec_args.remove(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 = p_custom_args.substr(placeholder_pos + String("%command%").size()).split(" ", false); + 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 = p_custom_args.split(" ", false); + for (int i = 0; i < custom_args.size(); i++) { + args.push_back(custom_args[i].replace(" ", "%20")); + } } } - String exec = OS::get_singleton()->get_executable_path(); - printf("Running: %s", exec.utf8().get_data()); for (List::Element *E = args.front(); E; E = E->next()) { printf(" %s", E->get().utf8().get_data());