Main: Fixup bogus fallback to project manager with more bolognese

WARNING: Hacks everywhere!

The logic in `main.cpp` is due a full rewrite as it's extremely hacky,
splitting argument parsing over several functions, with a mess of global state
and assumptions about what combinations of arguments or lack thereof should
mean in terms of what we want to read: game, editor, project manager, or
command line tools such as `--doctool`, `--export` or `--script`.

Until this is fully rewritten, this patch hacks things some more to ensure
that we don't fall back to the project manager in cases where it's not
warranted, and especially not *too late*, as it can mean that we haven't
properly initialized stuff like `EditorPaths` needed by the PM (which in turn
impacts what kind of path will be used for logs and the shader cache, etc...
the rabbit hole goes deep).

Fixes #41435.
Fixes #49392.
Fixes #49658.
Fixes https://github.com/godotengine/godot/issues/38202#issuecomment-773158477.
This commit is contained in:
Rémi Verschelde 2021-06-16 19:08:29 +02:00
parent 48fe9c9794
commit aa2215e681
No known key found for this signature in database
GPG key ID: C3336907360768E1
3 changed files with 42 additions and 19 deletions

View file

@ -186,7 +186,7 @@ EditorPaths::EditorPaths() {
// Validate or create project-specific editor data dir (`res://.godot`),
// including shader cache subdir.
if (Main::is_project_manager()) {
if (Main::is_project_manager() || Main::is_cmdline_tool()) {
// Nothing to create, use shared editor data dir for shader cache.
Engine::get_singleton()->set_shader_cache_path(data_dir);
} else {
@ -209,6 +209,4 @@ EditorPaths::EditorPaths() {
dir_res->make_dir(ProjectSettings::IMPORTED_FILES_PATH);
}
}
print_line("paths valid: " + itos((int)paths_valid));
}

View file

@ -137,6 +137,7 @@ static int audio_driver_idx = -1;
static bool single_window = false;
static bool editor = false;
static bool project_manager = false;
static bool cmdline_tool = false;
static String locale;
static bool show_help = false;
static bool auto_quit = false;
@ -185,6 +186,10 @@ bool Main::is_project_manager() {
return project_manager;
}
bool Main::is_cmdline_tool() {
return cmdline_tool;
}
static String unescape_cmdline(const String &p_str) {
return p_str.replace("%20", " ");
}
@ -881,18 +886,25 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
auto_build_solutions = true;
editor = true;
cmdline_tool = true;
#ifdef DEBUG_METHODS_ENABLED
} else if (I->get() == "--gdnative-generate-json-api" || I->get() == "--gdnative-generate-json-builtin-api") {
// Register as an editor instance to use low-end fallback if relevant.
editor = true;
cmdline_tool = true;
// We still pass it to the main arguments since the argument handling itself is not done in this function
main_args.push_back(I->get());
#endif
} else if (I->get() == "--export" || I->get() == "--export-debug" ||
I->get() == "--export-pack") { // Export project
// Actually handling is done in start().
editor = true;
cmdline_tool = true;
main_args.push_back(I->get());
} else if (I->get() == "--doctool") {
// Actually handling is done in start().
cmdline_tool = true;
main_args.push_back(I->get());
#endif
} else if (I->get() == "--path") { // set path of project to start or edit
@ -1125,8 +1137,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
if (!project_manager && !editor) {
// Determine if the project manager should be requested
project_manager = main_args.size() == 0 && !found_project;
// If we didn't find a project, we fall back to the project manager.
project_manager = !found_project && !cmdline_tool;
}
#endif
@ -1452,7 +1464,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
#endif
#ifdef TOOLS_ENABLED
if (editor || project_manager) {
if (editor || project_manager || cmdline_tool) {
EditorPaths::create();
}
#endif
@ -1577,7 +1589,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
print_verbose("Using \"" + tablet_driver + "\" pen tablet driver...");
/* Initialize Visual Server */
/* Initialize Rendering Server */
rendering_server = memnew(RenderingServerDefault(OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD));
@ -1828,13 +1840,13 @@ bool Main::start() {
ERR_FAIL_COND_V(!_start_success, false);
bool hasicon = false;
String doc_tool_path;
String positional_arg;
String game_path;
String script;
bool check_only = false;
#ifdef TOOLS_ENABLED
String doc_tool_path;
bool doc_base = true;
String _export_preset;
bool export_debug = false;
@ -1844,8 +1856,9 @@ bool Main::start() {
main_timer_sync.init(OS::get_singleton()->get_ticks_usec());
List<String> args = OS::get_singleton()->get_cmdline_args();
// parameters that do not have an argument to the right
for (int i = 0; i < args.size(); i++) {
// First check parameters that do not have an argument to the right.
// Doctest Unit Testing Handler
// Designed to override and pass arguments to the unit test handler.
if (args[i] == "--check-only") {
@ -1875,7 +1888,7 @@ bool Main::start() {
game_path = args[i];
}
}
//parameters that have an argument to the right
// Then parameters that have an argument to the right.
else if (i < (args.size() - 1)) {
bool parsed_pair = true;
if (args[i] == "-s" || args[i] == "--script") {
@ -1907,16 +1920,19 @@ bool Main::start() {
if (parsed_pair) {
i++;
}
} else if (args[i] == "--doctool") {
// Handle case where no path is given to --doctool.
}
#ifdef TOOLS_ENABLED
// Handle case where no path is given to --doctool.
else if (args[i] == "--doctool") {
doc_tool_path = ".";
}
#endif
}
#ifdef TOOLS_ENABLED
if (doc_tool_path != "") {
Engine::get_singleton()->set_editor_hint(
true); // Needed to instance editor-only classes for their default values
// Needed to instance editor-only classes for their default values
Engine::get_singleton()->set_editor_hint(true);
{
DirAccessRef da = DirAccess::open(doc_tool_path);
@ -1988,17 +2004,26 @@ bool Main::start() {
return false;
}
#endif
if (script == "" && game_path == "" && String(GLOBAL_GET("application/run/main_scene")) != "") {
game_path = GLOBAL_GET("application/run/main_scene");
}
#ifdef TOOLS_ENABLED
if (!editor && !project_manager && !cmdline_tool && script == "" && game_path == "") {
// If we end up here, it means we didn't manage to detect what we want to run.
// Let's throw an error gently. The code leading to this is pretty brittle so
// this might end up triggered by valid usage, in which case we'll have to
// fine-tune further.
ERR_FAIL_V_MSG(false, "Couldn't detect whether to run the editor, the project manager or a specific project. Aborting.");
}
#endif
MainLoop *main_loop = nullptr;
if (editor) {
main_loop = memnew(SceneTree);
};
}
String main_loop_type = GLOBAL_DEF("application/run/main_loop_type", "SceneTree");
if (script != "") {
@ -2360,14 +2385,13 @@ bool Main::start() {
}
#ifdef TOOLS_ENABLED
if (project_manager || (script == "" && game_path == "" && !editor)) {
if (project_manager) {
Engine::get_singleton()->set_editor_hint(true);
ProjectManager *pmanager = memnew(ProjectManager);
ProgressDialog *progress_dialog = memnew(ProgressDialog);
pmanager->add_child(progress_dialog);
sml->get_root()->add_child(pmanager);
DisplayServer::get_singleton()->set_context(DisplayServer::CONTEXT_PROJECTMAN);
project_manager = true;
}
if (project_manager || editor) {

View file

@ -45,6 +45,7 @@ class Main {
public:
static bool is_project_manager();
static bool is_cmdline_tool();
static int test_entrypoint(int argc, char *argv[], bool &tests_need_run);
static Error setup(const char *execpath, int argc, char *argv[], bool p_second_phase = true);
static Error setup2(Thread::ID p_main_tid_override = 0);