summaryrefslogtreecommitdiffstats
path: root/main/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main/main.cpp')
-rw-r--r--main/main.cpp477
1 files changed, 357 insertions, 120 deletions
diff --git a/main/main.cpp b/main/main.cpp
index 2b69f2c9a4..791562a9bb 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();
@@ -1204,6 +1208,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 +1517,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 +1941,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 +1954,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 +2070,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 +2078,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 +2189,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 +2228,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 +2273,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") {
@@ -2326,12 +2446,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 +2502,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");
@@ -2434,7 +2555,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 +2578,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 +2645,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 +2678,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 +2720,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 +2737,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 +2754,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 +2784,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
@@ -2756,6 +2922,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 +2956,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 +3110,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,74 +3121,16 @@ 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,*.bmp,*.hdr,*.jpg,*.jpeg,*.svg,*.tga,*.exr,*.webp"), String());
GLOBAL_DEF(PropertyInfo(Variant::STRING, "application/config/macos_native_icon", PROPERTY_HINT_FILE, "*.icns"), String());
@@ -2990,7 +3140,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 +3154,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 +3266,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
@@ -3211,11 +3367,78 @@ 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) {
+ 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
+ }
+ 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 +3450,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;
@@ -3815,6 +4040,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 +4177,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 +4199,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 +4259,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 +4287,7 @@ bool Main::iteration() {
#endif // _3D_DISABLED
PhysicsServer2D::get_singleton()->end_sync();
+ Engine::get_singleton()->_in_physics = false;
exit = true;
break;
}
@@ -4083,14 +4311,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 +4332,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,16 +4391,17 @@ 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;
}
@@ -4204,6 +4434,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 +4454,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 +4477,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 +4613,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();