diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 0799b2fe687..dc0eb11ebf3 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -1028,6 +1028,8 @@ ProjectSettings::ProjectSettings() { } extensions.push_back("shader"); + GLOBAL_DEF("editor/main_run_args", ""); + GLOBAL_DEF("editor/search_in_file_extensions", extensions); custom_prop_info["editor/search_in_file_extensions"] = PropertyInfo(Variant::POOL_STRING_ARRAY, "editor/search_in_file_extensions"); diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index cb258bbcf1b..f81a1d9ee9b 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -157,7 +157,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/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: [codeblock] var arguments = {} diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index fbef3e599df..75694037264 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -514,6 +514,14 @@ If [code]Use Vsync[/code] is enabled and this setting is [code]true[/code], enables vertical synchronization via the operating system's window compositor when in windowed mode and the compositor is enabled. This will prevent stutter in certain situations. (Windows only.) [b]Note:[/b] This option is experimental and meant to alleviate stutter experienced by some users. However, some users have experienced a Vsync framerate halving (e.g. from 60 FPS to 30 FPS) when using it. + + 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] + Search path for project-specific script templates. Godot will search for script templates both in the editor-specific path and in this project-specific path. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 3de6651c9bb..6d258d792e8 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5842,8 +5842,6 @@ EditorNode::EditorNode() { register_exporters(); - GLOBAL_DEF("editor/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 743f49451e7..e6f04ea3cd7 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -186,15 +186,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: %ls", exec.c_str()); for (List::Element *E = args.front(); E; E = E->next()) { printf(" %ls", E->get().c_str());