Skip to content

Commit

Permalink
Main: Fixup bogus fallback to project manager with more bolognese
Browse files Browse the repository at this point in the history
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 godotengine#41435.
Fixes godotengine#49392.
Fixes godotengine#49658.
Fixes godotengine#38202 (comment).
  • Loading branch information
akien-mga committed Jun 16, 2021
1 parent 48fe9c9 commit aa2215e
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 19 deletions.
4 changes: 1 addition & 3 deletions editor/editor_paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -209,6 +209,4 @@ EditorPaths::EditorPaths() {
dir_res->make_dir(ProjectSettings::IMPORTED_FILES_PATH);
}
}

print_line("paths valid: " + itos((int)paths_valid));
}
56 changes: 40 additions & 16 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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", " ");
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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;
Expand All @@ -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") {
Expand Down Expand Up @@ -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") {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 != "") {
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions main/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit aa2215e

Please sign in to comment.