diff options
Diffstat (limited to 'main/main.cpp')
-rw-r--r-- | main/main.cpp | 507 |
1 files changed, 377 insertions, 130 deletions
diff --git a/main/main.cpp b/main/main.cpp index 1cbd732747..e59f6d03b0 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -49,7 +49,7 @@ #include "core/os/os.h" #include "core/os/time.h" #include "core/register_core_types.h" -#include "core/string/translation.h" +#include "core/string/translation_server.h" #include "core/version.h" #include "drivers/register_driver_types.h" #include "main/app_icon.gen.h" @@ -60,6 +60,7 @@ #include "platform/register_platform_apis.h" #include "scene/main/scene_tree.h" #include "scene/main/window.h" +#include "scene/property_list_helper.h" #include "scene/register_scene_types.h" #include "scene/resources/packed_scene.h" #include "scene/theme/theme_db.h" @@ -196,6 +197,7 @@ static bool found_project = false; static bool auto_build_solutions = false; static String debug_server_uri; static bool wait_for_import = false; +static bool restore_editor_window_layout = true; #ifndef DISABLE_DEPRECATED static int converter_max_kb_file = 4 * 1024; // 4MB static int converter_max_line_length = 100000; @@ -604,6 +606,9 @@ void Main::print_help(const char *p_binary) { print_help_option("--gpu-abort", "Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n", CLI_OPTION_AVAILABILITY_TEMPLATE_DEBUG); #endif print_help_option("--generate-spirv-debug-info", "Generate SPIR-V debug information. This allows source-level shader debugging with RenderDoc.\n"); +#if defined(DEBUG_ENABLED) || defined(DEV_ENABLED) + print_help_option("--extra-gpu-memory-tracking", "Enables additional memory tracking (see class reference for `RenderingDevice.get_driver_and_device_memory_report()` and linked methods). Currently only implemented for Vulkan. Enabling this feature may cause crashes on some systems due to buggy drivers or bugs in the Vulkan Loader. See https://github.com/godotengine/godot/issues/95967\n"); +#endif print_help_option("--remote-debug <uri>", "Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n"); print_help_option("--single-threaded-scene", "Force scene tree to run in single-threaded mode. Sub-thread groups are disabled and run on the main thread.\n"); #if defined(DEBUG_ENABLED) @@ -793,6 +798,7 @@ void Main::test_cleanup() { ResourceLoader::remove_custom_loaders(); ResourceSaver::remove_custom_savers(); + PropertyListHelper::clear_base_helpers(); #ifdef TOOLS_ENABLED GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_EDITOR); @@ -909,13 +915,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // Benchmark tracking must be done after `OS::get_singleton()->initialize()` as on some // platforms, it's used to set up the time utilities. - OS::get_singleton()->benchmark_begin_measure("Startup", "Total"); - OS::get_singleton()->benchmark_begin_measure("Startup", "Setup"); + OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Setup"); engine = memnew(Engine); MAIN_PRINT("Main: Initialize CORE"); - OS::get_singleton()->benchmark_begin_measure("Startup", "Core"); register_core_types(); register_core_driver_types(); @@ -1033,7 +1037,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (arg == "--audio-driver" || arg == "--display-driver" || arg == "--rendering-method" || - arg == "--rendering-driver") { + arg == "--rendering-driver" || + arg == "--xr-mode") { if (N) { forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(arg); forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(N->get()); @@ -1204,6 +1209,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #endif } else if (arg == "--generate-spirv-debug-info") { Engine::singleton->generate_spirv_debug_info = true; + } else if (arg == "--extra-gpu-memory-tracking") { + Engine::singleton->extra_gpu_memory_tracking = true; } else if (arg == "--tablet-driver") { if (N) { tablet_driver = N->get(); @@ -1511,6 +1518,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph main_args.push_back(arg); main_args.push_back(N->get()); N = N->next(); + // GDScript docgen requires Autoloads, but loading those also creates a main loop. + // This forces main loop to quit without adding more GDScript-specific exceptions to setup. + quit_after = 1; } else { OS::get_singleton()->print("Missing relative or absolute path to project for --gdscript-docs, aborting.\n"); goto error; @@ -1932,6 +1942,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph { String driver_hints = ""; String driver_hints_with_d3d12 = ""; + String driver_hints_with_metal = ""; { Vector<String> driver_hints_arr; @@ -1944,18 +1955,28 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph driver_hints_arr.push_back("d3d12"); #endif driver_hints_with_d3d12 = String(",").join(driver_hints_arr); + +#ifdef METAL_ENABLED + // Make metal the preferred and default driver. + driver_hints_arr.insert(0, "metal"); +#endif + driver_hints_with_metal = String(",").join(driver_hints_arr); } String default_driver = driver_hints.get_slice(",", 0); String default_driver_with_d3d12 = driver_hints_with_d3d12.get_slice(",", 0); + String default_driver_with_metal = driver_hints_with_metal.get_slice(",", 0); // For now everything defaults to vulkan when available. This can change in future updates. GLOBAL_DEF_RST_NOVAL("rendering/rendering_device/driver", default_driver); GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.windows", PROPERTY_HINT_ENUM, driver_hints_with_d3d12), default_driver_with_d3d12); GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.linuxbsd", PROPERTY_HINT_ENUM, driver_hints), default_driver); GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver); - GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver); - GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.macos", PROPERTY_HINT_ENUM, driver_hints), default_driver); + GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.ios", PROPERTY_HINT_ENUM, driver_hints_with_metal), default_driver_with_metal); + GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/rendering_device/driver.macos", PROPERTY_HINT_ENUM, driver_hints_with_metal), default_driver_with_metal); + + GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_vulkan", true); + GLOBAL_DEF_RST("rendering/rendering_device/fallback_to_d3d12", true); } { @@ -2050,7 +2071,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph BLOCK_DEVICE("Intel", "Intel HD Graphics P3000"); BLOCK_DEVICE("Intel", "Intel(R) HD Graphics P3000"); BLOCK_DEVICE("0x8086", "0x0112"); // HD Graphics P3000, Gen6, Sandy Bridge - BLOCK_DEVICE("0x8086", "0x0122"); // HD Graphics P3000, Gen6, Sandy Bridge + BLOCK_DEVICE("0x8086", "0x0122"); BLOCK_DEVICE("0x8086", "0x015A"); // HD Graphics, Gen7, Ivy Bridge BLOCK_DEVICE("Intel", "Intel HD Graphics 2500"); BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 2500"); @@ -2058,10 +2079,81 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph BLOCK_DEVICE("Intel", "Intel HD Graphics 4000"); BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 4000"); BLOCK_DEVICE("0x8086", "0x0162"); // HD Graphics 4000, Gen7, Ivy Bridge - BLOCK_DEVICE("0x8086", "0x0166"); // HD Graphics 4000, Gen7, Ivy Bridge + BLOCK_DEVICE("0x8086", "0x0166"); BLOCK_DEVICE("Intel", "Intel HD Graphics P4000"); BLOCK_DEVICE("Intel", "Intel(R) HD Graphics P4000"); BLOCK_DEVICE("0x8086", "0x016A"); // HD Graphics P4000, Gen7, Ivy Bridge + BLOCK_DEVICE("Intel", "Intel(R) Vallyview Graphics"); + BLOCK_DEVICE("0x8086", "0x0F30"); // Intel(R) Vallyview Graphics, Gen7, Vallyview + BLOCK_DEVICE("0x8086", "0x0F31"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 4200"); + BLOCK_DEVICE("0x8086", "0x0A1E"); // Intel(R) HD Graphics 4200, Gen7.5, Haswell + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 4400"); + BLOCK_DEVICE("0x8086", "0x0A16"); // Intel(R) HD Graphics 4400, Gen7.5, Haswell + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 4600"); + BLOCK_DEVICE("0x8086", "0x0412"); // Intel(R) HD Graphics 4600, Gen7.5, Haswell + BLOCK_DEVICE("0x8086", "0x0416"); + BLOCK_DEVICE("0x8086", "0x0426"); + BLOCK_DEVICE("0x8086", "0x0D12"); + BLOCK_DEVICE("0x8086", "0x0D16"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics P4600/P4700"); + BLOCK_DEVICE("0x8086", "0x041A"); // Intel(R) HD Graphics P4600/P4700, Gen7.5, Haswell + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 5000"); + BLOCK_DEVICE("0x8086", "0x0422"); // Intel(R) HD Graphics 5000, Gen7.5, Haswell + BLOCK_DEVICE("0x8086", "0x042A"); + BLOCK_DEVICE("0x8086", "0x0A26"); + BLOCK_DEVICE("Intel", "Intel(R) Iris(TM) Graphics 5100"); + BLOCK_DEVICE("0x8086", "0x0A22"); // Intel(R) Iris(TM) Graphics 5100, Gen7.5, Haswell + BLOCK_DEVICE("0x8086", "0x0A2A"); + BLOCK_DEVICE("0x8086", "0x0A2B"); + BLOCK_DEVICE("0x8086", "0x0A2E"); + BLOCK_DEVICE("Intel", "Intel(R) Iris(TM) Pro Graphics 5200"); + BLOCK_DEVICE("0x8086", "0x0D22"); // Intel(R) Iris(TM) Pro Graphics 5200, Gen7.5, Haswell + BLOCK_DEVICE("0x8086", "0x0D26"); + BLOCK_DEVICE("0x8086", "0x0D2A"); + BLOCK_DEVICE("0x8086", "0x0D2B"); + BLOCK_DEVICE("0x8086", "0x0D2E"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 400"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 405"); + BLOCK_DEVICE("0x8086", "0x22B0"); // Intel(R) HD Graphics, Gen8, Cherryview Braswell + BLOCK_DEVICE("0x8086", "0x22B1"); + BLOCK_DEVICE("0x8086", "0x22B2"); + BLOCK_DEVICE("0x8086", "0x22B3"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 5300"); + BLOCK_DEVICE("0x8086", "0x161E"); // Intel(R) HD Graphics 5300, Gen8, Broadwell + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 5500"); + BLOCK_DEVICE("0x8086", "0x1616"); // Intel(R) HD Graphics 5500, Gen8, Broadwell + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 5600"); + BLOCK_DEVICE("0x8086", "0x1612"); // Intel(R) HD Graphics 5600, Gen8, Broadwell + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 6000"); + BLOCK_DEVICE("0x8086", "0x1626"); // Intel(R) HD Graphics 6000, Gen8, Broadwell + BLOCK_DEVICE("Intel", "Intel(R) Iris(TM) Graphics 6100"); + BLOCK_DEVICE("0x8086", "0x162B"); // Intel(R) Iris(TM) Graphics 6100, Gen8, Broadwell + BLOCK_DEVICE("Intel", "Intel(R) Iris(TM) Pro Graphics 6200"); + BLOCK_DEVICE("0x8086", "0x1622"); // Intel(R) Iris(TM) Pro Graphics 6200, Gen8, Broadwell + BLOCK_DEVICE("Intel", "Intel(R) Iris(TM) Pro Graphics P6300"); + BLOCK_DEVICE("0x8086", "0x162A"); // Intel(R) Iris(TM) Pro Graphics P6300, Gen8, Broadwell + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 500"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 505"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 510"); + BLOCK_DEVICE("0x8086", "0x1902"); // Intel(R) HD Graphics 510, Gen9, Skylake + BLOCK_DEVICE("0x8086", "0x1906"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 520"); + BLOCK_DEVICE("0x8086", "0x1916"); // Intel(R) HD Graphics 520, Gen9, Skylake + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 530"); + BLOCK_DEVICE("0x8086", "0x1912"); // Intel(R) HD Graphics 530, Gen9, Skylake + BLOCK_DEVICE("0x8086", "0x191B"); + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics P530"); + BLOCK_DEVICE("0x8086", "0x191D"); // Intel(R) HD Graphics P530, Gen9, Skylake + BLOCK_DEVICE("Intel", "Intel(R) HD Graphics 515"); + BLOCK_DEVICE("0x8086", "0x191E"); // Intel(R) HD Graphics 515, Gen9, Skylake + BLOCK_DEVICE("Intel", "Intel(R) Iris Graphics 540"); + BLOCK_DEVICE("0x8086", "0x1926"); // Intel(R) Iris Graphics 540, Gen9, Skylake + BLOCK_DEVICE("0x8086", "0x1927"); + BLOCK_DEVICE("Intel", "Intel(R) Iris Pro Graphics 580"); + BLOCK_DEVICE("0x8086", "0x193B"); // Intel(R) Iris Pro Graphics 580, Gen9, Skylake + BLOCK_DEVICE("Intel", "Intel(R) Iris Pro Graphics P580"); + BLOCK_DEVICE("0x8086", "0x193D"); // Intel(R) Iris Pro Graphics P580, Gen9, Skylake #undef BLOCK_DEVICE @@ -2098,7 +2190,20 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (rendering_method != "forward_plus" && rendering_method != "mobile" && rendering_method != "gl_compatibility") { - OS::get_singleton()->print("Unknown renderer name '%s', aborting. Valid options are: %s\n", rendering_method.utf8().get_data(), renderer_hints.utf8().get_data()); + OS::get_singleton()->print("Unknown rendering method '%s', aborting.\nValid options are ", + rendering_method.utf8().get_data()); + + const Vector<String> rendering_method_hints = renderer_hints.split(","); + for (int i = 0; i < rendering_method_hints.size(); i++) { + if (i == rendering_method_hints.size() - 1) { + OS::get_singleton()->print(" and "); + } else if (i != 0) { + OS::get_singleton()->print(", "); + } + OS::get_singleton()->print("'%s'", rendering_method_hints[i].utf8().get_data()); + } + + OS::get_singleton()->print(".\n"); goto error; } } @@ -2124,14 +2229,27 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->print("Unknown rendering driver '%s', aborting.\nValid options are ", rendering_driver.utf8().get_data()); + // Deduplicate driver entries, as a rendering driver may be supported by several display servers. + Vector<String> unique_rendering_drivers; for (int i = 0; i < DisplayServer::get_create_function_count(); i++) { Vector<String> r_drivers = DisplayServer::get_create_function_rendering_drivers(i); for (int d = 0; d < r_drivers.size(); d++) { - OS::get_singleton()->print("'%s', ", r_drivers[d].utf8().get_data()); + if (!unique_rendering_drivers.has(r_drivers[d])) { + unique_rendering_drivers.append(r_drivers[d]); + } } } + for (int i = 0; i < unique_rendering_drivers.size(); i++) { + if (i == unique_rendering_drivers.size() - 1) { + OS::get_singleton()->print(" and "); + } else if (i != 0) { + OS::get_singleton()->print(", "); + } + OS::get_singleton()->print("'%s'", unique_rendering_drivers[i].utf8().get_data()); + } + OS::get_singleton()->print(".\n"); goto error; @@ -2156,6 +2274,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #ifdef D3D12_ENABLED available_drivers.push_back("d3d12"); #endif +#ifdef METAL_ENABLED + available_drivers.push_back("metal"); +#endif } #ifdef GLES3_ENABLED if (rendering_method == "gl_compatibility") { @@ -2207,15 +2328,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } - // note this is the desired rendering driver, it doesn't mean we will get it. - // TODO - make sure this is updated in the case of fallbacks, so that the user interface - // shows the correct driver string. - OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); - OS::get_singleton()->set_current_rendering_method(rendering_method); - // always convert to lower case for consistency in the code rendering_driver = rendering_driver.to_lower(); + OS::get_singleton()->set_current_rendering_driver_name(rendering_driver); + OS::get_singleton()->set_current_rendering_method(rendering_method); + if (use_custom_res) { if (!force_res) { window_size.width = GLOBAL_GET("display/window/size/viewport_width"); @@ -2326,12 +2444,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // Make sure that headless is the last one, which it is assumed to be by design. DEV_ASSERT(NULL_DISPLAY_DRIVER == DisplayServer::get_create_function_name(DisplayServer::get_create_function_count() - 1)); - GLOBAL_DEF_RST_NOVAL("display/display_server/driver", "default"); - GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.windows", PROPERTY_HINT_ENUM_SUGGESTION, "default,windows,headless"), "default"); - GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.linuxbsd", PROPERTY_HINT_ENUM_SUGGESTION, "default,x11,wayland,headless"), "default"); - GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.android", PROPERTY_HINT_ENUM_SUGGESTION, "default,android,headless"), "default"); - GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.ios", PROPERTY_HINT_ENUM_SUGGESTION, "default,iOS,headless"), "default"); - GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.macos", PROPERTY_HINT_ENUM_SUGGESTION, "default,macos,headless"), "default"); + GLOBAL_DEF_NOVAL("display/display_server/driver", "default"); + GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.windows", PROPERTY_HINT_ENUM_SUGGESTION, "default,windows,headless"), "default"); + GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.linuxbsd", PROPERTY_HINT_ENUM_SUGGESTION, "default,x11,wayland,headless"), "default"); + GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.android", PROPERTY_HINT_ENUM_SUGGESTION, "default,android,headless"), "default"); + GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.ios", PROPERTY_HINT_ENUM_SUGGESTION, "default,iOS,headless"), "default"); + GLOBAL_DEF_NOVAL(PropertyInfo(Variant::STRING, "display/display_server/driver.macos", PROPERTY_HINT_ENUM_SUGGESTION, "default,macos,headless"), "default"); GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name()); if (audio_driver.is_empty()) { // Specified in project.godot. @@ -2382,6 +2500,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF("debug/settings/stdout/print_fps", false); GLOBAL_DEF("debug/settings/stdout/print_gpu_profile", false); GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false); + GLOBAL_DEF("debug/settings/physics_interpolation/enable_warnings", true); if (!OS::get_singleton()->_verbose_stdout) { // Not manually overridden. OS::get_singleton()->_verbose_stdout = GLOBAL_GET("debug/settings/stdout/verbose_stdout"); @@ -2422,6 +2541,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // XR project settings. GLOBAL_DEF_RST_BASIC("xr/openxr/enabled", false); + GLOBAL_DEF_RST_BASIC("xr/openxr/enabled.editor", false); GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "xr/openxr/default_action_map", PROPERTY_HINT_FILE, "*.tres"), "res://openxr_action_map.tres"); GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/form_factor", PROPERTY_HINT_ENUM, "Head Mounted,Handheld"), "0"); GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/view_configuration", PROPERTY_HINT_ENUM, "Mono,Stereo"), "1"); // "Mono,Stereo,Quad,Observer" @@ -2434,7 +2554,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true); // OpenXR project extensions settings. - GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking", true); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/extensions/debug_utils", PROPERTY_HINT_ENUM, "Disabled,Error,Warning,Info,Verbose"), "0"); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/extensions/debug_message_types", PROPERTY_HINT_FLAGS, "General,Validation,Performance,Conformance"), "15"); + GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking", false); + GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking_unobstructed_data_source", false); // XR_HAND_TRACKING_DATA_SOURCE_UNOBSTRUCTED_EXT + GLOBAL_DEF_BASIC("xr/openxr/extensions/hand_tracking_controller_data_source", false); // XR_HAND_TRACKING_DATA_SOURCE_CONTROLLER_EXT GLOBAL_DEF_RST_BASIC("xr/openxr/extensions/hand_interaction_profile", false); GLOBAL_DEF_BASIC("xr/openxr/extensions/eye_gaze_interaction", false); @@ -2453,19 +2577,21 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph Thread::release_main_thread(); // If setup2() is called from another thread, that one will become main thread, so preventively release this one. set_current_thread_safe_for_nodes(false); - OS::get_singleton()->benchmark_end_measure("Startup", "Core"); - #if defined(STEAMAPI_ENABLED) if (editor || project_manager) { steam_tracker = memnew(SteamTracker); } #endif + OS::get_singleton()->benchmark_end_measure("Startup", "Main::Setup"); + if (p_second_phase) { - return setup2(); + exit_err = setup2(); + if (exit_err != OK) { + goto error; + } } - OS::get_singleton()->benchmark_end_measure("Startup", "Setup"); return OK; error: @@ -2518,8 +2644,7 @@ error: memdelete(message_queue); } - OS::get_singleton()->benchmark_end_measure("Startup", "Core"); - OS::get_singleton()->benchmark_end_measure("Startup", "Setup"); + OS::get_singleton()->benchmark_end_measure("Startup", "Main::Setup"); #if defined(STEAMAPI_ENABLED) if (steam_tracker) { @@ -2552,7 +2677,9 @@ Error _parse_resource_dummy(void *p_data, VariantParser::Stream *p_stream, Ref<R return OK; } -Error Main::setup2() { +Error Main::setup2(bool p_show_boot_logo) { + OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Setup2"); + Thread::make_main_thread(); // Make whatever thread call this the main thread. set_current_thread_safe_for_nodes(true); @@ -2592,6 +2719,8 @@ Error Main::setup2() { String screen_property; bool prefer_wayland_found = false; + bool prefer_wayland = false; + bool remember_window_size_and_position_found = false; if (editor) { screen_property = "interface/editor/editor_screen"; @@ -2607,7 +2736,7 @@ Error Main::setup2() { prefer_wayland_found = true; } - while (!screen_found || !prefer_wayland_found) { + while (!screen_found || !prefer_wayland_found || !remember_window_size_and_position_found) { assign = Variant(); next_tag.fields.clear(); next_tag.name = String(); @@ -2624,14 +2753,22 @@ Error Main::setup2() { } if (!prefer_wayland_found && assign == "run/platforms/linuxbsd/prefer_wayland") { - if (value) { - display_driver = "wayland"; - } else { - display_driver = "default"; - } - + prefer_wayland = value; prefer_wayland_found = true; } + + if (!remember_window_size_and_position_found && assign == "interface/editor/remember_window_size_and_position") { + restore_editor_window_layout = value; + remember_window_size_and_position_found = true; + } + } + } + + if (display_driver.is_empty()) { + if (prefer_wayland) { + display_driver = "wayland"; + } else { + display_driver = "default"; } } } @@ -2646,6 +2783,34 @@ Error Main::setup2() { } } + bool has_command_line_window_override = init_use_custom_pos || init_use_custom_screen || init_windowed; + if (editor && !has_command_line_window_override && restore_editor_window_layout) { + Ref<ConfigFile> config; + config.instantiate(); + // Load and amend existing config if it exists. + Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); + if (err == OK) { + init_screen = config->get_value("EditorWindow", "screen", init_screen); + String mode = config->get_value("EditorWindow", "mode", "maximized"); + window_size = config->get_value("EditorWindow", "size", window_size); + if (mode == "windowed") { + window_mode = DisplayServer::WINDOW_MODE_WINDOWED; + init_windowed = true; + } else if (mode == "fullscreen") { + window_mode = DisplayServer::WINDOW_MODE_FULLSCREEN; + init_fullscreen = true; + } else { + window_mode = DisplayServer::WINDOW_MODE_MAXIMIZED; + init_maximized = true; + } + + if (init_windowed) { + init_use_custom_pos = true; + init_custom_pos = config->get_value("EditorWindow", "position", Vector2i(0, 0)); + } + } + } + OS::get_singleton()->benchmark_end_measure("Startup", "Initialize Early Settings"); } #endif @@ -2740,6 +2905,8 @@ Error Main::setup2() { Error err; display_server = DisplayServer::create(display_driver_idx, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, context, err); if (err != OK || display_server == nullptr) { + String last_name = DisplayServer::get_create_function_name(display_driver_idx); + // We can't use this display server, try other ones as fallback. // Skip headless (always last registered) because that's not what users // would expect if they didn't request it explicitly. @@ -2747,6 +2914,9 @@ Error Main::setup2() { if (i == display_driver_idx) { continue; // Don't try the same twice. } + String name = DisplayServer::get_create_function_name(i); + WARN_PRINT(vformat("Display driver %s failed, falling back to %s.", last_name, name)); + display_server = DisplayServer::create(i, rendering_driver, window_mode, window_vsync_mode, window_flags, window_position, window_size, init_screen, context, err); if (err == OK && display_server != nullptr) { break; @@ -2756,6 +2926,30 @@ Error Main::setup2() { if (err != OK || display_server == nullptr) { ERR_PRINT("Unable to create DisplayServer, all display drivers failed.\nUse \"--headless\" command line argument to run the engine in headless mode if this is desired (e.g. for continuous integration)."); + + if (display_server) { + memdelete(display_server); + } + + GDExtensionManager::get_singleton()->deinitialize_extensions(GDExtension::INITIALIZATION_LEVEL_SERVERS); + uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); + unregister_server_types(); + + if (input) { + memdelete(input); + } + if (tsman) { + memdelete(tsman); + } +#ifndef _3D_DISABLED + if (physics_server_3d_manager) { + memdelete(physics_server_3d_manager); + } +#endif // _3D_DISABLED + if (physics_server_2d_manager) { + memdelete(physics_server_2d_manager); + } + return err; } @@ -2766,6 +2960,30 @@ Error Main::setup2() { OS::get_singleton()->benchmark_end_measure("Servers", "Display"); } +#ifdef TOOLS_ENABLED + // If the editor is running in windowed mode, ensure the window rect fits + // the screen in case screen count or position has changed. + if (editor && init_windowed) { + // We still need to check we are actually in windowed mode, because + // certain platform might only support one fullscreen window. + if (DisplayServer::get_singleton()->window_get_mode() == DisplayServer::WINDOW_MODE_WINDOWED) { + Vector2i current_size = DisplayServer::get_singleton()->window_get_size(); + Vector2i current_pos = DisplayServer::get_singleton()->window_get_position(); + int screen = DisplayServer::get_singleton()->window_get_current_screen(); + Rect2i screen_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen); + + Vector2i adjusted_end = screen_rect.get_end().min(current_pos + current_size); + Vector2i adjusted_pos = screen_rect.get_position().max(adjusted_end - current_size); + Vector2i adjusted_size = DisplayServer::get_singleton()->window_get_min_size().max(adjusted_end - adjusted_pos); + + if (current_pos != adjusted_end || current_size != adjusted_size) { + DisplayServer::get_singleton()->window_set_position(adjusted_pos); + DisplayServer::get_singleton()->window_set_size(adjusted_size); + } + } + } +#endif + if (GLOBAL_GET("debug/settings/stdout/print_fps") || print_fps) { // Print requested V-Sync mode at startup to diagnose the printed FPS not going above the monitor refresh rate. switch (window_vsync_mode) { @@ -2896,12 +3114,6 @@ Error Main::setup2() { MAIN_PRINT("Main: Setup Logo"); -#if !defined(TOOLS_ENABLED) && defined(WEB_ENABLED) - bool show_logo = false; -#else - bool show_logo = true; -#endif - if (init_windowed) { //do none.. } else if (init_maximized) { @@ -2913,76 +3125,18 @@ Error Main::setup2() { DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, true); } - MAIN_PRINT("Main: Load Boot Image"); - Color clear = GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3)); RenderingServer::get_singleton()->set_default_clear_color(clear); - if (show_logo) { //boot logo! - const bool boot_logo_image = GLOBAL_DEF_BASIC("application/boot_splash/show_image", true); - const String boot_logo_path = String(GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/boot_splash/image", PROPERTY_HINT_FILE, "*.png"), String())).strip_edges(); - const bool boot_logo_scale = GLOBAL_DEF_BASIC("application/boot_splash/fullsize", true); - const bool boot_logo_filter = GLOBAL_DEF_BASIC("application/boot_splash/use_filter", true); - - Ref<Image> boot_logo; - - if (boot_logo_image) { - if (!boot_logo_path.is_empty()) { - boot_logo.instantiate(); - Error load_err = ImageLoader::load_image(boot_logo_path, boot_logo); - if (load_err) { - ERR_PRINT("Non-existing or invalid boot splash at '" + boot_logo_path + "'. Loading default splash."); - } - } - } else { - // Create a 1×1 transparent image. This will effectively hide the splash image. - boot_logo.instantiate(); - boot_logo->initialize_data(1, 1, false, Image::FORMAT_RGBA8); - boot_logo->set_pixel(0, 0, Color(0, 0, 0, 0)); - } - - Color boot_bg_color = GLOBAL_GET("application/boot_splash/bg_color"); - -#if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH) - boot_bg_color = - GLOBAL_DEF_BASIC("application/boot_splash/bg_color", - (editor || project_manager) ? boot_splash_editor_bg_color : boot_splash_bg_color); -#endif - if (boot_logo.is_valid()) { - RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale, - boot_logo_filter); - - } else { -#ifndef NO_DEFAULT_BOOT_LOGO - MAIN_PRINT("Main: Create bootsplash"); -#if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH) - Ref<Image> splash = (editor || project_manager) ? memnew(Image(boot_splash_editor_png)) : memnew(Image(boot_splash_png)); -#else - Ref<Image> splash = memnew(Image(boot_splash_png)); -#endif - - MAIN_PRINT("Main: ClearColor"); - RenderingServer::get_singleton()->set_default_clear_color(boot_bg_color); - MAIN_PRINT("Main: Image"); - RenderingServer::get_singleton()->set_boot_image(splash, boot_bg_color, false); -#endif - } - -#if defined(TOOLS_ENABLED) && defined(MACOS_ENABLED) - if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_ICON) && OS::get_singleton()->get_bundle_icon_path().is_empty()) { - Ref<Image> icon = memnew(Image(app_icon_png)); - DisplayServer::get_singleton()->set_icon(icon); - } -#endif + if (p_show_boot_logo) { + setup_boot_logo(); } MAIN_PRINT("Main: Clear Color"); DisplayServer::set_early_window_clear_color_override(false); - RenderingServer::get_singleton()->set_default_clear_color( - GLOBAL_GET("rendering/environment/defaults/default_clear_color")); - GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/config/icon", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg"), String()); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/config/icon", PROPERTY_HINT_FILE, "*.png,*.bmp,*.hdr,*.jpg,*.jpeg,*.svg,*.tga,*.exr,*.webp"), String()); GLOBAL_DEF(PropertyInfo(Variant::STRING, "application/config/macos_native_icon", PROPERTY_HINT_FILE, "*.icns"), String()); GLOBAL_DEF(PropertyInfo(Variant::STRING, "application/config/windows_native_icon", PROPERTY_HINT_FILE, "*.ico"), String()); @@ -2990,7 +3144,8 @@ Error Main::setup2() { Input *id = Input::get_singleton(); if (id) { - agile_input_event_flushing = GLOBAL_DEF("input_devices/buffering/agile_event_flushing", false); + bool agile_input_event_flushing = GLOBAL_DEF("input_devices/buffering/agile_event_flushing", false); + id->set_agile_input_event_flushing(agile_input_event_flushing); if (bool(GLOBAL_DEF_BASIC("input_devices/pointing/emulate_touch_from_mouse", false)) && !(editor || project_manager)) { @@ -3003,9 +3158,6 @@ Error Main::setup2() { id->set_emulate_mouse_from_touch(bool(GLOBAL_DEF_BASIC("input_devices/pointing/emulate_mouse_from_touch", true))); } - GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_long_press_as_right_click", false); - GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_pan_and_scale_gestures", false); - GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "input_devices/pointing/android/rotary_input_scroll_axis", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), 1); OS::get_singleton()->benchmark_end_measure("Startup", "Setup Window and Boot"); } @@ -3118,6 +3270,14 @@ Error Main::setup2() { OS::get_singleton()->benchmark_end_measure("Scene", "Modules and Extensions"); } + PackedStringArray extensions; + extensions.push_back("gd"); + if (ClassDB::class_exists("CSharpScript")) { + extensions.push_back("cs"); + } + extensions.push_back("gdshader"); + GLOBAL_DEF_NOVAL(PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions"), extensions); // Note: should be defined after Scene level modules init to see .NET. + OS::get_singleton()->benchmark_end_measure("Startup", "Scene"); #ifdef TOOLS_ENABLED @@ -3145,7 +3305,7 @@ Error Main::setup2() { OS::get_singleton()->benchmark_end_measure("Startup", "Platforms"); - GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "display/mouse_cursor/custom_image", PROPERTY_HINT_FILE, "*.png,*.webp"), String()); + GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "display/mouse_cursor/custom_image", PROPERTY_HINT_FILE, "*.png,*.bmp,*.hdr,*.jpg,*.jpeg,*.svg,*.tga,*.exr,*.webp"), String()); GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image_hotspot", Vector2()); GLOBAL_DEF_BASIC("display/mouse_cursor/tooltip_position_offset", Point2(10, 10)); @@ -3211,11 +3371,79 @@ Error Main::setup2() { print_verbose("EDITOR API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_EDITOR))); MAIN_PRINT("Main: Done"); - OS::get_singleton()->benchmark_end_measure("Startup", "Setup"); + OS::get_singleton()->benchmark_end_measure("Startup", "Main::Setup2"); return OK; } +void Main::setup_boot_logo() { + MAIN_PRINT("Main: Load Boot Image"); + +#if !defined(TOOLS_ENABLED) && defined(WEB_ENABLED) + bool show_logo = false; +#else + bool show_logo = true; +#endif + + if (show_logo) { //boot logo! + const bool boot_logo_image = GLOBAL_DEF_BASIC("application/boot_splash/show_image", true); + const String boot_logo_path = String(GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/boot_splash/image", PROPERTY_HINT_FILE, "*.png"), String())).strip_edges(); + const bool boot_logo_scale = GLOBAL_DEF_BASIC("application/boot_splash/fullsize", true); + const bool boot_logo_filter = GLOBAL_DEF_BASIC("application/boot_splash/use_filter", true); + + Ref<Image> boot_logo; + + if (boot_logo_image) { + if (!boot_logo_path.is_empty()) { + boot_logo.instantiate(); + Error load_err = ImageLoader::load_image(boot_logo_path, boot_logo); + if (load_err) { + String msg = (boot_logo_path.ends_with(".png") ? "" : "The only supported format is PNG."); + ERR_PRINT("Non-existing or invalid boot splash at '" + boot_logo_path + +"'. " + msg + " Loading default splash."); + } + } + } else { + // Create a 1×1 transparent image. This will effectively hide the splash image. + boot_logo.instantiate(); + boot_logo->initialize_data(1, 1, false, Image::FORMAT_RGBA8); + boot_logo->set_pixel(0, 0, Color(0, 0, 0, 0)); + } + + Color boot_bg_color = GLOBAL_GET("application/boot_splash/bg_color"); + +#if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH) + boot_bg_color = GLOBAL_DEF_BASIC("application/boot_splash/bg_color", (editor || project_manager) ? boot_splash_editor_bg_color : boot_splash_bg_color); +#endif + if (boot_logo.is_valid()) { + RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale, boot_logo_filter); + + } else { +#ifndef NO_DEFAULT_BOOT_LOGO + MAIN_PRINT("Main: Create bootsplash"); +#if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH) + Ref<Image> splash = (editor || project_manager) ? memnew(Image(boot_splash_editor_png)) : memnew(Image(boot_splash_png)); +#else + Ref<Image> splash = memnew(Image(boot_splash_png)); +#endif + + MAIN_PRINT("Main: ClearColor"); + RenderingServer::get_singleton()->set_default_clear_color(boot_bg_color); + MAIN_PRINT("Main: Image"); + RenderingServer::get_singleton()->set_boot_image(splash, boot_bg_color, false); +#endif + } + +#if defined(TOOLS_ENABLED) && defined(MACOS_ENABLED) + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_ICON) && OS::get_singleton()->get_bundle_icon_path().is_empty()) { + Ref<Image> icon = memnew(Image(app_icon_png)); + DisplayServer::get_singleton()->set_icon(icon); + } +#endif + } + RenderingServer::get_singleton()->set_default_clear_color( + GLOBAL_GET("rendering/environment/defaults/default_clear_color")); +} + String Main::get_rendering_driver_name() { return rendering_driver; } @@ -3227,6 +3455,8 @@ static MainTimerSync main_timer_sync; // and should move on to `OS::run`, and EXIT_FAILURE otherwise for // an early exit with that error code. int Main::start() { + OS::get_singleton()->benchmark_begin_measure("Startup", "Main::Start"); + ERR_FAIL_COND_V(!_start_success, false); bool has_icon = false; @@ -3320,13 +3550,16 @@ int Main::start() { gdscript_docs_path = E->next()->get(); #endif } else if (E->get() == "--export-release") { + ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting."); editor = true; //needs editor _export_preset = E->next()->get(); } else if (E->get() == "--export-debug") { + ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting."); editor = true; //needs editor _export_preset = E->next()->get(); export_debug = true; } else if (E->get() == "--export-pack") { + ERR_FAIL_COND_V_MSG(!editor && !found_project, EXIT_FAILURE, "Please provide a valid project path when exporting, aborting."); editor = true; _export_preset = E->next()->get(); export_pack_only = true; @@ -3338,6 +3571,8 @@ int Main::start() { if (parsed_pair) { E = E->next(); } + } else if (E->get().begins_with("--export-")) { + ERR_FAIL_V_MSG(EXIT_FAILURE, "Missing export preset name, aborting."); } #ifdef TOOLS_ENABLED // Handle case where no path is given to --doctool. @@ -3815,6 +4050,8 @@ int Main::start() { if (editor_embed_subwindows) { sml->get_root()->set_embedding_subwindows(true); } + restore_editor_window_layout = EditorSettings::get_singleton()->get_setting( + "interface/editor/remember_window_size_and_position"); } #endif @@ -3950,7 +4187,7 @@ int Main::start() { } } - OS::get_singleton()->benchmark_end_measure("Startup", "Total"); + OS::get_singleton()->benchmark_end_measure("Startup", "Main::Start"); OS::get_singleton()->benchmark_dump(); return EXIT_SUCCESS; @@ -3972,7 +4209,6 @@ uint32_t Main::hide_print_fps_attempts = 3; uint32_t Main::frame = 0; bool Main::force_redraw_requested = false; int Main::iterating = 0; -bool Main::agile_input_event_flushing = false; bool Main::is_iterating() { return iterating > 0; @@ -4033,24 +4269,25 @@ bool Main::iteration() { NavigationServer3D::get_singleton()->sync(); for (int iters = 0; iters < advance.physics_steps; ++iters) { - if (Input::get_singleton()->is_using_input_buffering() && agile_input_event_flushing) { + if (Input::get_singleton()->is_agile_input_event_flushing()) { Input::get_singleton()->flush_buffered_events(); } Engine::get_singleton()->_in_physics = true; + Engine::get_singleton()->_physics_frames++; uint64_t physics_begin = OS::get_singleton()->get_ticks_usec(); -#ifndef _3D_DISABLED - PhysicsServer3D::get_singleton()->sync(); - PhysicsServer3D::get_singleton()->flush_queries(); -#endif // _3D_DISABLED - // Prepare the fixed timestep interpolated nodes BEFORE they are updated // by the physics server, otherwise the current and previous transforms // may be the same, and no interpolation takes place. OS::get_singleton()->get_main_loop()->iteration_prepare(); +#ifndef _3D_DISABLED + PhysicsServer3D::get_singleton()->sync(); + PhysicsServer3D::get_singleton()->flush_queries(); +#endif // _3D_DISABLED + PhysicsServer2D::get_singleton()->sync(); PhysicsServer2D::get_singleton()->flush_queries(); @@ -4060,6 +4297,7 @@ bool Main::iteration() { #endif // _3D_DISABLED PhysicsServer2D::get_singleton()->end_sync(); + Engine::get_singleton()->_in_physics = false; exit = true; break; } @@ -4083,14 +4321,15 @@ bool Main::iteration() { message_queue->flush(); + OS::get_singleton()->get_main_loop()->iteration_end(); + physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - physics_begin); // keep the largest one for reference physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - physics_begin, physics_process_max); - Engine::get_singleton()->_physics_frames++; Engine::get_singleton()->_in_physics = false; } - if (Input::get_singleton()->is_using_input_buffering() && agile_input_event_flushing) { + if (Input::get_singleton()->is_agile_input_event_flushing()) { Input::get_singleton()->flush_buffered_events(); } @@ -4103,7 +4342,7 @@ bool Main::iteration() { RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames. - if (DisplayServer::get_singleton()->can_any_window_draw() && + if ((DisplayServer::get_singleton()->can_any_window_draw() || DisplayServer::get_singleton()->has_additional_outputs()) && RenderingServer::get_singleton()->is_render_loop_enabled()) { if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { if (RenderingServer::get_singleton()->has_changed()) { @@ -4162,21 +4401,22 @@ bool Main::iteration() { iterating--; - // Needed for OSs using input buffering regardless accumulation (like Android) - if (Input::get_singleton()->is_using_input_buffering() && !agile_input_event_flushing) { - Input::get_singleton()->flush_buffered_events(); - } - if (movie_writer) { movie_writer->add_frame(); } +#ifdef TOOLS_ENABLED + bool quit_after_timeout = false; +#endif if ((quit_after > 0) && (Engine::get_singleton()->_process_frames >= quit_after)) { +#ifdef TOOLS_ENABLED + quit_after_timeout = true; +#endif exit = true; } #ifdef TOOLS_ENABLED - if (wait_for_import && EditorFileSystem::get_singleton()->doing_first_scan()) { + if (wait_for_import && EditorFileSystem::get_singleton() && EditorFileSystem::get_singleton()->doing_first_scan()) { exit = false; } #endif @@ -4204,6 +4444,12 @@ bool Main::iteration() { } #endif +#ifdef TOOLS_ENABLED + if (exit && quit_after_timeout && EditorNode::get_singleton()) { + EditorNode::get_singleton()->unload_editor_addons(); + } +#endif + return exit; } @@ -4218,7 +4464,7 @@ void Main::force_redraw() { * The order matters as some of those steps are linked with each other. */ void Main::cleanup(bool p_force) { - OS::get_singleton()->benchmark_begin_measure("Shutdown", "Total"); + OS::get_singleton()->benchmark_begin_measure("Shutdown", "Main::Cleanup"); if (!p_force) { ERR_FAIL_COND(!_start_success); } @@ -4241,6 +4487,7 @@ void Main::cleanup(bool p_force) { ResourceLoader::remove_custom_loaders(); ResourceSaver::remove_custom_savers(); + PropertyListHelper::clear_base_helpers(); // Flush before uninitializing the scene, but delete the MessageQueue as late as possible. message_queue->flush(); @@ -4376,7 +4623,7 @@ void Main::cleanup(bool p_force) { unregister_core_types(); - OS::get_singleton()->benchmark_end_measure("Shutdown", "Total"); + OS::get_singleton()->benchmark_end_measure("Shutdown", "Main::Cleanup"); OS::get_singleton()->benchmark_dump(); OS::get_singleton()->finalize_core(); |