diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/main.cpp | 336 | ||||
-rw-r--r-- | main/main.h | 11 | ||||
-rw-r--r-- | main/performance.cpp | 9 | ||||
-rw-r--r-- | main/performance.h | 6 |
4 files changed, 277 insertions, 85 deletions
diff --git a/main/main.cpp b/main/main.cpp index eb401cd9ef..a338b71154 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -31,6 +31,7 @@ #include "main.h" #include "core/config/project_settings.h" +#include "core/core_globals.h" #include "core/core_string_names.h" #include "core/crypto/crypto.h" #include "core/debugger/engine_debugger.h" @@ -62,6 +63,7 @@ #include "scene/main/window.h" #include "scene/register_scene_types.h" #include "scene/resources/packed_scene.h" +#include "scene/theme/theme_db.h" #include "servers/audio_server.h" #include "servers/camera_server.h" #include "servers/display_server.h" @@ -124,10 +126,13 @@ static RenderingServer *rendering_server = nullptr; static CameraServer *camera_server = nullptr; static XRServer *xr_server = nullptr; static TextServerManager *tsman = nullptr; +static PhysicsServer3DManager *physics_server_3d_manager = nullptr; static PhysicsServer3D *physics_server_3d = nullptr; +static PhysicsServer2DManager *physics_server_2d_manager = nullptr; static PhysicsServer2D *physics_server_2d = nullptr; static NavigationServer3D *navigation_server_3d = nullptr; static NavigationServer2D *navigation_server_2d = nullptr; +static ThemeDB *theme_db = nullptr; // We error out if setup2() doesn't turn this true static bool _start_success = false; @@ -142,17 +147,24 @@ static int audio_driver_idx = -1; // Engine config/tools +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; -static OS::ProcessID allow_focus_steal_pid = 0; +static OS::ProcessID editor_pid = 0; #ifdef TOOLS_ENABLED static bool auto_build_solutions = false; static String debug_server_uri; +static int converter_max_kb_file = 4 * 1024; // 4MB +static int converter_max_line_length = 100000; + +HashMap<Main::CLIScope, Vector<String>> forwardable_cli_arguments; #endif +bool use_startup_benchmark = false; +String startup_benchmark_file; // Display @@ -160,7 +172,7 @@ static DisplayServer::WindowMode window_mode = DisplayServer::WINDOW_MODE_WINDOW static DisplayServer::ScreenOrientation window_orientation = DisplayServer::SCREEN_LANDSCAPE; static DisplayServer::VSyncMode window_vsync_mode = DisplayServer::VSYNC_ENABLED; static uint32_t window_flags = 0; -static Size2i window_size = Size2i(1024, 600); +static Size2i window_size = Size2i(1152, 648); static int init_screen = -1; static bool init_fullscreen = false; @@ -181,7 +193,6 @@ static bool debug_navigation = false; static int frame_delay = 0; static bool disable_render_loop = false; static int fixed_fps = -1; -static String write_movie_path; static MovieWriter *movie_writer = nullptr; static bool disable_vsync = false; static bool print_fps = false; @@ -196,6 +207,12 @@ bool Main::is_cmdline_tool() { return cmdline_tool; } +#ifdef TOOLS_ENABLED +const Vector<String> &Main::get_forwardable_cli_arguments(Main::CLIScope p_scope) { + return forwardable_cli_arguments[p_scope]; +} +#endif + static String unescape_cmdline(const String &p_str) { return p_str.replace("%20", " "); } @@ -208,25 +225,24 @@ static String get_full_version_string() { return String(VERSION_FULL_BUILD) + hash; } -// FIXME: Could maybe be moved to PhysicsServer3DManager and PhysicsServer2DManager directly -// to have less code in main.cpp. +// FIXME: Could maybe be moved to have less code in main.cpp. void initialize_physics() { /// 3D Physics Server - physics_server_3d = PhysicsServer3DManager::new_server( + physics_server_3d = PhysicsServer3DManager::get_singleton()->new_server( ProjectSettings::get_singleton()->get(PhysicsServer3DManager::setting_property_name)); if (!physics_server_3d) { // Physics server not found, Use the default physics - physics_server_3d = PhysicsServer3DManager::new_default_server(); + physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server(); } ERR_FAIL_COND(!physics_server_3d); physics_server_3d->init(); - /// 2D Physics server - physics_server_2d = PhysicsServer2DManager::new_server( - ProjectSettings::get_singleton()->get(PhysicsServer2DManager::setting_property_name)); + // 2D Physics server + physics_server_2d = PhysicsServer2DManager::get_singleton()->new_server( + ProjectSettings::get_singleton()->get(PhysicsServer2DManager::get_singleton()->setting_property_name)); if (!physics_server_2d) { // Physics server not found, Use the default physics - physics_server_2d = PhysicsServer2DManager::new_default_server(); + physics_server_2d = PhysicsServer2DManager::get_singleton()->new_default_server(); } ERR_FAIL_COND(!physics_server_2d); physics_server_2d->init(); @@ -262,6 +278,16 @@ void finalize_navigation_server() { navigation_server_2d = nullptr; } +void initialize_theme_db() { + theme_db = memnew(ThemeDB); + theme_db->initialize_theme(); +} + +void finalize_theme_db() { + memdelete(theme_db); + theme_db = nullptr; +} + //#define DEBUG_INIT #ifdef DEBUG_INIT #define MAIN_PRINT(m_txt) print_line(m_txt) @@ -286,6 +312,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print("\n"); OS::get_singleton()->print("Run options:\n"); + OS::get_singleton()->print(" -- Separator for user-provided arguments. Following arguments are not used by the engine, but can be read from `OS.get_cmdline_user_args()`.\n"); #ifdef TOOLS_ENABLED OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n"); OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n"); @@ -344,6 +371,7 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n"); OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n"); OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n"); + OS::get_singleton()->print(" --xr-mode <mode> Select XR mode (default/off/on).\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Debug options:\n"); @@ -378,12 +406,14 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n"); OS::get_singleton()->print(" --export-debug <preset> <path> Same as --export, but using the debug template.\n"); OS::get_singleton()->print(" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n"); - OS::get_singleton()->print(" --convert-3to4 Converts project from Godot 3.x to Godot 4.x.\n"); - OS::get_singleton()->print(" --validate-conversion-3to4 Shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x.\n"); + OS::get_singleton()->print(" --convert-3to4 [<max_file_kb>] [<max_line_size>] Converts project from Godot 3.x to Godot 4.x.\n"); + OS::get_singleton()->print(" --validate-conversion-3to4 [<max_file_kb>] [<max_line_size>] Shows what elements will be renamed when converting project from Godot 3.x to Godot 4.x.\n"); OS::get_singleton()->print(" --doctool [<path>] Dump the engine API reference to the given <path> (defaults to current dir) in XML format, merging if existing files are found.\n"); OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n"); OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n"); OS::get_singleton()->print(" --dump-extension-api Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n"); + OS::get_singleton()->print(" --startup-benchmark Benchmark the startup time and print it to console.\n"); + OS::get_singleton()->print(" --startup-benchmark-file <path> Benchmark the startup time and save it to a given file in JSON format.\n"); #ifdef TESTS_ENABLED OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n"); #endif @@ -410,6 +440,8 @@ Error Main::test_setup() { String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2); + register_core_settings(); //here globals are present + translation_server = memnew(TranslationServer); tsman = memnew(TextServerManager); @@ -419,6 +451,9 @@ Error Main::test_setup() { tsman->add_interface(ts); } + physics_server_3d_manager = memnew(PhysicsServer3DManager); + physics_server_2d_manager = memnew(PhysicsServer2DManager); + // From `Main::setup2()`. initialize_modules(MODULE_INITIALIZATION_LEVEL_CORE); register_core_extensions(); @@ -427,6 +462,7 @@ Error Main::test_setup() { /** INITIALIZE SERVERS **/ register_server_types(); + XRServer::set_xr_mode(XRServer::XRMODE_OFF); // Skip in tests. initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); @@ -457,7 +493,8 @@ Error Main::test_setup() { register_platform_apis(); // Theme needs modules to be initialized so that sub-resources can be loaded. - initialize_theme(); + initialize_theme_db(); + register_scene_singletons(); ERR_FAIL_COND_V(TextServerManager::get_singleton()->get_interface_count() == 0, ERR_CANT_CREATE); @@ -508,6 +545,8 @@ void Main::test_cleanup() { unregister_driver_types(); unregister_scene_types(); + finalize_theme_db(); + NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); unregister_server_types(); @@ -520,6 +559,12 @@ void Main::test_cleanup() { if (tsman) { memdelete(tsman); } + if (physics_server_3d_manager) { + memdelete(physics_server_3d_manager); + } + if (physics_server_2d_manager) { + memdelete(physics_server_2d_manager); + } if (globals) { memdelete(globals); } @@ -589,6 +634,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph engine = memnew(Engine); MAIN_PRINT("Main: Initialize CORE"); + engine->startup_begin(); + engine->startup_benchmark_begin_measure("core"); register_core_types(); register_core_driver_types(); @@ -621,6 +668,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph /* argument parsing and main creation */ List<String> args; List<String> main_args; + List<String> user_args; + bool adding_user_args = false; List<String> platform_args = OS::get_singleton()->get_cmdline_platform_args(); // Add command line arguments. @@ -685,7 +734,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph I = args.front(); while (I) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED // Ignore the process serial number argument passed by macOS Gatekeeper. // Otherwise, Godot would try to open a non-existent project on the first start and abort. if (I->get().begins_with("-psn_")) { @@ -693,9 +742,32 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph continue; } #endif + List<String>::Element *N = I->next(); - if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help +#ifdef TOOLS_ENABLED + if (I->get() == "--debug" || + I->get() == "--verbose" || + I->get() == "--disable-crash-handler") { + forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->get()); + forwardable_cli_arguments[CLI_SCOPE_PROJECT].push_back(I->get()); + } + if (I->get() == "--single-window") { + forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->get()); + } + if (I->get() == "--audio-driver" || + I->get() == "--display-driver" || + I->get() == "--rendering-driver") { + if (I->next()) { + forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->get()); + forwardable_cli_arguments[CLI_SCOPE_TOOL].push_back(I->next()->get()); + } + } +#endif + + if (adding_user_args) { + user_args.push_back(I->get()); + } else if (I->get() == "-h" || I->get() == "--help" || I->get() == "/?") { // display help show_help = true; exit_code = ERR_HELP; // Hack to force an early exit in `main()` with a success code. @@ -871,7 +943,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } else if (I->get() == "--single-window") { // force single window - OS::get_singleton()->_single_window = true; + single_window = true; } else if (I->get() == "-t" || I->get() == "--always-on-top") { // force always-on-top window init_always_on_top = true; @@ -1026,10 +1098,32 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph // Actually handling is done in start(). cmdline_tool = true; main_args.push_back(I->get()); + + if (I->next() && !I->next()->get().begins_with("-")) { + if (itos(I->next()->get().to_int()) == I->next()->get()) { + converter_max_kb_file = I->next()->get().to_int(); + } + if (I->next()->next() && !I->next()->next()->get().begins_with("-")) { + if (itos(I->next()->next()->get().to_int()) == I->next()->next()->get()) { + converter_max_line_length = I->next()->next()->get().to_int(); + } + } + } } else if (I->get() == "--validate-conversion-3to4") { // Actually handling is done in start(). cmdline_tool = true; main_args.push_back(I->get()); + + if (I->next() && !I->next()->get().begins_with("-")) { + if (itos(I->next()->get().to_int()) == I->next()->get()) { + converter_max_kb_file = I->next()->get().to_int(); + } + if (I->next()->next() && !I->next()->next()->get().begins_with("-")) { + if (itos(I->next()->next()->get().to_int()) == I->next()->next()->get()) { + converter_max_line_length = I->next()->next()->get().to_int(); + } + } + } } else if (I->get() == "--doctool") { // Actually handling is done in start(). cmdline_tool = true; @@ -1044,10 +1138,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph if (I->next()) { String p = I->next()->get(); - if (OS::get_singleton()->set_cwd(p) == OK) { - //nothing - } else { - project_path = I->next()->get(); //use project_path instead + if (OS::get_singleton()->set_cwd(p) != OK) { + OS::get_singleton()->print("Invalid project path specified: \"%s\", aborting.\n", p.utf8().get_data()); + goto error; } N = I->next()->next(); } else { @@ -1141,9 +1234,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->print("Missing remote debug host address, aborting.\n"); goto error; } - } else if (I->get() == "--allow_focus_steal_pid") { // not exposed to user + } else if (I->get() == "--editor-pid") { // not exposed to user if (I->next()) { - allow_focus_steal_pid = I->next()->get().to_int(); + editor_pid = I->next()->get().to_int(); N = I->next()->next(); } else { OS::get_singleton()->print("Missing editor PID argument, aborting.\n"); @@ -1161,7 +1254,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } else if (I->get() == "--write-movie") { if (I->next()) { - write_movie_path = I->next()->get(); + Engine::get_singleton()->set_write_movie_path(I->next()->get()); N = I->next()->next(); if (fixed_fps == -1) { fixed_fps = 60; @@ -1181,6 +1274,39 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph OS::get_singleton()->disable_crash_handler(); } else if (I->get() == "--skip-breakpoints") { skip_breakpoints = true; + } else if (I->get() == "--xr-mode") { + if (I->next()) { + String xr_mode = I->next()->get().to_lower(); + N = I->next()->next(); + if (xr_mode == "default") { + XRServer::set_xr_mode(XRServer::XRMODE_DEFAULT); + } else if (xr_mode == "off") { + XRServer::set_xr_mode(XRServer::XRMODE_OFF); + } else if (xr_mode == "on") { + XRServer::set_xr_mode(XRServer::XRMODE_ON); + } else { + OS::get_singleton()->print("Unknown --xr-mode argument \"%s\", aborting.\n", xr_mode.ascii().get_data()); + goto error; + } + } else { + OS::get_singleton()->print("Missing --xr-mode argument, aborting.\n"); + goto error; + } + + } else if (I->get() == "--startup-benchmark") { + use_startup_benchmark = true; + } else if (I->get() == "--startup-benchmark-file") { + if (I->next()) { + use_startup_benchmark = true; + startup_benchmark_file = I->next()->get(); + N = I->next()->next(); + } else { + OS::get_singleton()->print("Missing <path> argument for --startup-benchmark-file <path>.\n"); + goto error; + } + + } else if (I->get() == "--") { + adding_user_args = true; } else { main_args.push_back(I->get()); } @@ -1273,7 +1399,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph PROPERTY_HINT_RANGE, "0, 200, 1, or_greater")); - EngineDebugger::initialize(debug_uri, skip_breakpoints, breakpoints); + EngineDebugger::initialize(debug_uri, skip_breakpoints, breakpoints, []() { + if (editor_pid) { + DisplayServer::get_singleton()->enable_for_stealing_focus(editor_pid); + } + }); #ifdef TOOLS_ENABLED if (editor) { @@ -1344,16 +1474,16 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph quiet_stdout = true; } if (bool(ProjectSettings::get_singleton()->get("application/run/disable_stderr"))) { - _print_error_enabled = false; + CoreGlobals::print_error_enabled = false; }; if (quiet_stdout) { - _print_line_enabled = false; + CoreGlobals::print_line_enabled = false; } Logger::set_flush_stdout_on_print(ProjectSettings::get_singleton()->get("application/run/flush_stdout_on_print")); - OS::get_singleton()->set_cmdline(execpath, main_args); + OS::get_singleton()->set_cmdline(execpath, main_args, user_args); // possibly be worth changing the default from vulkan to something lower spec, // for the project manager, depending on how smooth the fallback is. @@ -1431,24 +1561,17 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } - GLOBAL_DEF("internationalization/rendering/force_right_to_left_layout_direction", false); + GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false); GLOBAL_DEF("internationalization/locale/include_text_server_data", false); OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", true); - - // FIXME: Restore support. -#if 0 - //OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false); - video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency/enabled", false); -#endif + OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/per_pixel_transparency/allowed", false); if (editor || project_manager) { // The editor and project manager always detect and use hiDPI if needed OS::get_singleton()->_allow_hidpi = true; - OS::get_singleton()->_allow_layered = false; } - OS::get_singleton()->_keep_screen_on = GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true); if (rtm == -1) { rtm = GLOBAL_DEF("rendering/driver/threads/thread_model", OS::RENDER_THREAD_SAFE); } @@ -1507,7 +1630,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph audio_driver_idx = 0; } - if (write_movie_path != String()) { + if (Engine::get_singleton()->get_write_movie_path() != String()) { // Always use dummy driver for audio driver (which is last), also in no threaded mode. audio_driver_idx = AudioDriverManager::get_driver_count() - 1; AudioDriverDummy::get_dummy_singleton()->set_use_threads(false); @@ -1592,6 +1715,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph message_queue = memnew(MessageQueue); + engine->startup_benchmark_end_measure(); // core + if (p_second_phase) { return setup2(); } @@ -1604,7 +1729,7 @@ error: display_driver = ""; audio_driver = ""; tablet_driver = ""; - write_movie_path = ""; + Engine::get_singleton()->set_write_movie_path(String()); project_path = ""; args.clear(); @@ -1646,6 +1771,7 @@ error: unregister_core_types(); OS::get_singleton()->_cmdline.clear(); + OS::get_singleton()->_user_args.clear(); if (message_queue) { memdelete(message_queue); @@ -1657,6 +1783,8 @@ error: } Error Main::setup2(Thread::ID p_main_tid_override) { + engine->startup_benchmark_begin_measure("servers"); + tsman = memnew(TextServerManager); if (tsman) { @@ -1665,6 +1793,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) { tsman->add_interface(ts); } + physics_server_3d_manager = memnew(PhysicsServer3DManager); + physics_server_2d_manager = memnew(PhysicsServer2DManager); + register_server_types(); initialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); @@ -1779,11 +1910,11 @@ Error Main::setup2(Thread::ID p_main_tid_override) { rendering_server->set_print_gpu_profile(true); } - if (write_movie_path != String()) { - movie_writer = MovieWriter::find_writer_for_file(write_movie_path); + if (Engine::get_singleton()->get_write_movie_path() != String()) { + movie_writer = MovieWriter::find_writer_for_file(Engine::get_singleton()->get_write_movie_path()); if (movie_writer == nullptr) { - ERR_PRINT("Can't find movie writer for file type, aborting: " + write_movie_path); - write_movie_path = String(); + ERR_PRINT("Can't find movie writer for file type, aborting: " + Engine::get_singleton()->get_write_movie_path()); + Engine::get_singleton()->set_write_movie_path(String()); } } @@ -1818,7 +1949,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { MAIN_PRINT("Main: Setup Logo"); -#if defined(JAVASCRIPT_ENABLED) || defined(ANDROID_ENABLED) +#if defined(WEB_ENABLED) || defined(ANDROID_ENABLED) bool show_logo = false; #else bool show_logo = true; @@ -1838,10 +1969,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) { DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP, true); } - if (allow_focus_steal_pid) { - DisplayServer::get_singleton()->enable_for_stealing_focus(allow_focus_steal_pid); - } - MAIN_PRINT("Main: Load Boot Image"); Color clear = GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3)); @@ -1965,13 +2092,19 @@ Error Main::setup2(Thread::ID p_main_tid_override) { MAIN_PRINT("Main: Load TextServer"); /* Enum text drivers */ - GLOBAL_DEF("internationalization/rendering/text_driver", ""); + GLOBAL_DEF_RST("internationalization/rendering/text_driver", ""); String text_driver_options; for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) { - if (i > 0) { + const String driver_name = TextServerManager::get_singleton()->get_interface(i)->get_name(); + if (driver_name == "Dummy") { + // Dummy text driver cannot draw any text, making the editor unusable if selected. + continue; + } + if (!text_driver_options.is_empty() && text_driver_options.find(",") == -1) { + // Not the first option; add a comma before it as a separator for the property hint. text_driver_options += ","; } - text_driver_options += TextServerManager::get_singleton()->get_interface(i)->get_name(); + text_driver_options += driver_name; } ProjectSettings::get_singleton()->set_custom_property_info("internationalization/rendering/text_driver", PropertyInfo(Variant::STRING, "internationalization/rendering/text_driver", PROPERTY_HINT_ENUM, text_driver_options)); @@ -2012,8 +2145,12 @@ Error Main::setup2(Thread::ID p_main_tid_override) { ERR_FAIL_V_MSG(ERR_CANT_CREATE, "TextServer: Unable to create TextServer interface."); } + engine->startup_benchmark_end_measure(); // servers + MAIN_PRINT("Main: Load Scene Types"); + engine->startup_benchmark_begin_measure("scene"); + register_scene_types(); register_driver_types(); @@ -2035,7 +2172,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) { register_platform_apis(); // Theme needs modules to be initialized so that sub-resources can be loaded. - initialize_theme(); + initialize_theme_db(); + register_scene_singletons(); GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image", String()); GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image_hotspot", Vector2()); @@ -2078,7 +2216,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { // able to load resources, load the global shader variables. // If running on editor, don't load the textures because the editor // may want to import them first. Editor will reload those later. - rendering_server->global_variables_load_settings(!editor); + rendering_server->global_shader_parameters_load_settings(!editor); } _start_success = true; @@ -2089,6 +2227,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) { print_verbose("EDITOR API HASH: " + uitos(ClassDB::get_api_hash(ClassDB::API_EDITOR))); MAIN_PRINT("Main: Done"); + engine->startup_benchmark_end_measure(); // scene + return OK; } @@ -2198,6 +2338,13 @@ bool Main::start() { #endif } + uint64_t minimum_time_msec = GLOBAL_DEF("application/boot_splash/minimum_display_time", 0); + ProjectSettings::get_singleton()->set_custom_property_info("application/boot_splash/minimum_display_time", + PropertyInfo(Variant::INT, + "application/boot_splash/minimum_display_time", + PROPERTY_HINT_RANGE, + "0,100,1,or_greater,suffix:ms")); // No negative numbers. + #ifdef TOOLS_ENABLED if (!doc_tool_path.is_empty()) { // Needed to instance editor-only classes for their default values @@ -2213,18 +2360,6 @@ bool Main::start() { ERR_FAIL_COND_V_MSG(da.is_null(), false, "Argument supplied to --doctool must be a valid directory path."); } -#ifndef MODULE_MONO_ENABLED - // Hack to define Mono-specific project settings even on non-Mono builds, - // so that we don't lose their descriptions and default values in DocData. - // Default values should be synced with mono_gd/gd_mono.cpp. - GLOBAL_DEF("mono/debugger_agent/port", 23685); - GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false); - GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000); - GLOBAL_DEF("mono/profiler/args", "log:calls,alloc,sample,output=output.mlpd"); - GLOBAL_DEF("mono/profiler/enabled", false); - GLOBAL_DEF("mono/runtime/unhandled_exception_policy", 0); -#endif - Error err; DocTools doc; doc.generate(doc_base); @@ -2238,7 +2373,7 @@ bool Main::start() { // Custom modules are always located by absolute path. String path = _doc_data_class_paths[i].path; if (path.is_relative_path()) { - path = doc_tool_path.plus_file(path); + path = doc_tool_path.path_join(path); } String name = _doc_data_class_paths[i].name; doc_data_classes[name] = path; @@ -2256,7 +2391,7 @@ bool Main::start() { } } - String index_path = doc_tool_path.plus_file("doc/classes"); + String index_path = doc_tool_path.path_join("doc/classes"); // Create the main documentation directory if it doesn't exist Ref<DirAccess> da = DirAccess::create_for_path(index_path); err = da->make_dir_recursive(index_path); @@ -2290,12 +2425,12 @@ bool Main::start() { } if (converting_project) { - int exit_code = ProjectConverter3To4().convert(); + int exit_code = ProjectConverter3To4(converter_max_kb_file, converter_max_line_length).convert(); OS::get_singleton()->set_exit_code(exit_code); return false; } if (validating_converting_project) { - int exit_code = ProjectConverter3To4().validate_conversion(); + int exit_code = ProjectConverter3To4(converter_max_kb_file, converter_max_line_length).validate_conversion(); OS::get_singleton()->set_exit_code(exit_code); return false; } @@ -2403,12 +2538,14 @@ bool Main::start() { } if (debug_navigation) { sml->set_debug_navigation_hint(true); + NavigationServer3D::get_singleton()->set_active(true); + NavigationServer3D::get_singleton_mut()->set_debug_enabled(true); } #endif bool embed_subwindows = GLOBAL_DEF("display/window/subwindows/embed_subwindows", true); - if (OS::get_singleton()->is_single_window() || (!project_manager && !editor && embed_subwindows) || !DisplayServer::get_singleton()->has_feature(DisplayServer::Feature::FEATURE_SUBWINDOWS)) { + if (single_window || (!project_manager && !editor && embed_subwindows) || !DisplayServer::get_singleton()->has_feature(DisplayServer::Feature::FEATURE_SUBWINDOWS)) { sml->get_root()->set_embedding_subwindows(true); } @@ -2418,6 +2555,7 @@ bool Main::start() { if (!project_manager && !editor) { // game if (!game_path.is_empty() || !script.is_empty()) { //autoload + Engine::get_singleton()->startup_benchmark_begin_measure("load_autoloads"); HashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); //first pass, add the constants so they exist before any script is loaded @@ -2472,12 +2610,14 @@ bool Main::start() { for (Node *E : to_add) { sml->get_root()->add_child(E); } + Engine::get_singleton()->startup_benchmark_end_measure(); // load autoloads } } #ifdef TOOLS_ENABLED EditorNode *editor_node = nullptr; if (editor) { + Engine::get_singleton()->startup_benchmark_begin_measure("editor"); editor_node = memnew(EditorNode); sml->get_root()->add_child(editor_node); @@ -2485,6 +2625,13 @@ bool Main::start() { editor_node->export_preset(_export_preset, positional_arg, export_debug, export_pack_only); game_path = ""; // Do not load anything. } + + Engine::get_singleton()->startup_benchmark_end_measure(); + + editor_node->set_use_startup_benchmark(use_startup_benchmark, startup_benchmark_file); + // Editor takes over + use_startup_benchmark = false; + startup_benchmark_file = String(); } #endif @@ -2568,7 +2715,7 @@ bool Main::start() { PropertyInfo(Variant::FLOAT, "display/window/stretch/scale", PROPERTY_HINT_RANGE, - "1.0,8.0,0.1")); + "0.5,8.0,0.01")); sml->set_auto_accept_quit(GLOBAL_DEF("application/config/auto_accept_quit", true)); sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true)); GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true); @@ -2614,11 +2761,11 @@ bool Main::start() { if (sep == -1) { Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - local_game_path = da->get_current_dir().plus_file(local_game_path); + local_game_path = da->get_current_dir().path_join(local_game_path); } else { Ref<DirAccess> da = DirAccess::open(local_game_path.substr(0, sep)); if (da.is_valid()) { - local_game_path = da->get_current_dir().plus_file( + local_game_path = da->get_current_dir().path_join( local_game_path.substr(sep + 1, local_game_path.length())); } } @@ -2649,8 +2796,10 @@ bool Main::start() { if (!project_manager && !editor) { // game + Engine::get_singleton()->startup_benchmark_begin_measure("game_load"); + // Load SSL Certificates from Project Settings (or builtin). - Crypto::load_default_certificates(GLOBAL_DEF("network/ssl/certificate_bundle_override", "")); + Crypto::load_default_certificates(GLOBAL_DEF("network/tls/certificate_bundle_override", "")); if (!game_path.is_empty()) { Node *scene = nullptr; @@ -2662,7 +2811,7 @@ bool Main::start() { ERR_FAIL_COND_V_MSG(!scene, false, "Failed loading scene: " + local_game_path); sml->add_current_scene(scene); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED String mac_iconpath = GLOBAL_DEF("application/config/macos_native_icon", "Variant()"); if (!mac_iconpath.is_empty()) { DisplayServer::get_singleton()->set_native_icon(mac_iconpath); @@ -2688,22 +2837,26 @@ bool Main::start() { } } } + + Engine::get_singleton()->startup_benchmark_end_measure(); // game_load } #ifdef TOOLS_ENABLED if (project_manager) { + Engine::get_singleton()->startup_benchmark_begin_measure("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); + Engine::get_singleton()->startup_benchmark_end_measure(); } if (project_manager || editor) { // Load SSL Certificates from Editor Settings (or builtin) Crypto::load_default_certificates( - EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String()); + EditorSettings::get_singleton()->get_setting("network/tls/editor_tls_certificates").operator String()); } #endif } @@ -2716,8 +2869,22 @@ bool Main::start() { OS::get_singleton()->set_main_loop(main_loop); if (movie_writer) { - movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, write_movie_path); + movie_writer->begin(DisplayServer::get_singleton()->window_get_size(), fixed_fps, Engine::get_singleton()->get_write_movie_path()); } + + if (minimum_time_msec) { + uint64_t minimum_time = 1000 * minimum_time_msec; + uint64_t elapsed_time = OS::get_singleton()->get_ticks_usec(); + if (elapsed_time < minimum_time) { + OS::get_singleton()->delay_usec(minimum_time - elapsed_time); + } + } + + if (use_startup_benchmark) { + Engine::get_singleton()->startup_dump(startup_benchmark_file); + startup_benchmark_file = String(); + } + return true; } @@ -2963,6 +3130,7 @@ void Main::cleanup(bool p_force) { OS::get_singleton()->delete_main_loop(); OS::get_singleton()->_cmdline.clear(); + OS::get_singleton()->_user_args.clear(); OS::get_singleton()->_execpath = ""; OS::get_singleton()->_local_clipboard = ""; @@ -2975,7 +3143,7 @@ void Main::cleanup(bool p_force) { RenderingServer::get_singleton()->sync(); //clear global shader variables before scene and other graphics stuff are deinitialized. - rendering_server->global_variables_clear(); + rendering_server->global_shader_parameters_clear(); if (xr_server) { // Now that we're unregistering properly in plugins we need to keep access to xr_server for a little longer @@ -2999,6 +3167,11 @@ void Main::cleanup(bool p_force) { unregister_driver_types(); unregister_scene_types(); + finalize_theme_db(); + + // Before deinitializing server extensions, finalize servers which may be loaded as extensions. + finalize_physics(); + NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); unregister_server_types(); @@ -3020,7 +3193,6 @@ void Main::cleanup(bool p_force) { OS::get_singleton()->finalize(); - finalize_physics(); finalize_navigation_server(); finalize_display(); @@ -3049,6 +3221,12 @@ void Main::cleanup(bool p_force) { if (tsman) { memdelete(tsman); } + if (physics_server_3d_manager) { + memdelete(physics_server_3d_manager); + } + if (physics_server_2d_manager) { + memdelete(physics_server_2d_manager); + } if (globals) { memdelete(globals); } diff --git a/main/main.h b/main/main.h index d1870ab8df..f0bfe69b34 100644 --- a/main/main.h +++ b/main/main.h @@ -35,6 +35,9 @@ #include "core/os/thread.h" #include "core/typedefs.h" +template <class T> +class Vector; + class Main { static void print_help(const char *p_binary); static uint64_t last_ticks; @@ -47,6 +50,14 @@ class Main { public: static bool is_cmdline_tool(); +#ifdef TOOLS_ENABLED + enum CLIScope { + CLI_SCOPE_TOOL, // Editor and project manager. + CLI_SCOPE_PROJECT, + }; + static const Vector<String> &get_forwardable_cli_arguments(CLIScope p_scope); +#endif + 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); diff --git a/main/performance.cpp b/main/performance.cpp index 25659b999f..bdcd07a216 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -32,6 +32,7 @@ #include "core/object/message_queue.h" #include "core/os/os.h" +#include "core/variant/typed_array.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "servers/audio_server.h" @@ -240,11 +241,11 @@ Variant Performance::get_custom_monitor(const StringName &p_id) { return return_value; } -Array Performance::get_custom_monitor_names() { +TypedArray<StringName> Performance::get_custom_monitor_names() { if (!_monitor_map.size()) { - return Array(); + return TypedArray<StringName>(); } - Array return_array; + TypedArray<StringName> return_array; return_array.resize(_monitor_map.size()); int index = 0; for (KeyValue<StringName, MonitorCall> i : _monitor_map) { @@ -283,7 +284,7 @@ Variant Performance::MonitorCall::call(bool &r_error, String &r_error_message) { int argc = _arguments.size(); Variant return_value; Callable::CallError error; - _callable.call(args, argc, return_value, error); + _callable.callp(args, argc, return_value, error); r_error = (error.error != Callable::CallError::CALL_OK); if (r_error) { r_error_message = Variant::get_callable_error_text(_callable, args, argc, error); diff --git a/main/performance.h b/main/performance.h index 2837d8f512..597666b57d 100644 --- a/main/performance.h +++ b/main/performance.h @@ -37,6 +37,9 @@ #define PERF_WARN_OFFLINE_FUNCTION #define PERF_WARN_PROCESS_SYNC +template <typename T> +class TypedArray; + class Performance : public Object { GDCLASS(Performance, Object); @@ -85,7 +88,6 @@ public: PHYSICS_3D_ACTIVE_OBJECTS, PHYSICS_3D_COLLISION_PAIRS, PHYSICS_3D_ISLAND_COUNT, - //physics AUDIO_OUTPUT_LATENCY, MONITOR_MAX }; @@ -108,7 +110,7 @@ public: void remove_custom_monitor(const StringName &p_id); bool has_custom_monitor(const StringName &p_id); Variant get_custom_monitor(const StringName &p_id); - Array get_custom_monitor_names(); + TypedArray<StringName> get_custom_monitor_names(); uint64_t get_monitor_modification_time(); |