2014-02-09 22:10:30 -03:00
/*************************************************************************/
2017-12-20 01:04:30 +01:00
/* main.cpp */
2014-02-09 22:10:30 -03:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-09 22:10:30 -03:00
/*************************************************************************/
2022-01-03 21:27:34 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-09 22:10:30 -03:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-09 22:10:30 -03:00
# include "main.h"
2017-08-19 16:45:03 +02:00
2020-11-07 19:33:38 -03:00
# include "core/config/project_settings.h"
2020-07-20 17:35:34 +01:00
# include "core/core_string_names.h"
2019-07-19 15:29:57 +02:00
# include "core/crypto/crypto.h"
2020-02-27 03:30:20 +01:00
# include "core/debugger/engine_debugger.h"
2021-06-19 12:58:49 -03:00
# include "core/extension/extension_api_dump.h"
2020-04-28 15:19:37 +02:00
# include "core/input/input.h"
2020-03-01 19:14:37 -03:00
# include "core/input/input_map.h"
2021-06-11 14:51:48 +02:00
# include "core/io/dir_access.h"
2018-09-11 18:13:45 +02:00
# include "core/io/file_access_network.h"
# include "core/io/file_access_pack.h"
# include "core/io/file_access_zip.h"
2018-09-30 17:21:07 +02:00
# include "core/io/image_loader.h"
2018-09-11 18:13:45 +02:00
# include "core/io/ip.h"
# include "core/io/resource_loader.h"
2020-11-07 19:33:38 -03:00
# include "core/object/message_queue.h"
2018-09-11 18:13:45 +02:00
# include "core/os/os.h"
2021-05-24 07:54:05 -04:00
# include "core/os/time.h"
2014-02-09 22:10:30 -03:00
# include "core/register_core_types.h"
2020-11-07 19:33:38 -03:00
# include "core/string/translation.h"
2018-09-11 18:13:45 +02:00
# include "core/version.h"
# include "core/version_hash.gen.h"
2014-02-09 22:10:30 -03:00
# include "drivers/register_driver_types.h"
2018-09-11 18:13:45 +02:00
# include "main/app_icon.gen.h"
2019-02-12 14:23:35 +01:00
# include "main/main_timer_sync.h"
2018-09-11 18:13:45 +02:00
# include "main/performance.h"
# include "main/splash.gen.h"
2014-02-09 22:10:30 -03:00
# include "modules/register_module_types.h"
2017-11-16 01:33:48 +01:00
# include "platform/register_platform_apis.h"
2017-06-26 22:58:03 -03:00
# include "scene/main/scene_tree.h"
2020-03-03 22:51:12 -03:00
# include "scene/main/window.h"
2018-09-11 18:13:45 +02:00
# include "scene/register_scene_types.h"
# include "scene/resources/packed_scene.h"
2017-01-15 16:06:14 -03:00
# include "servers/audio_server.h"
2019-11-29 08:54:39 +02:00
# include "servers/camera_server.h"
2020-03-03 10:36:29 -03:00
# include "servers/display_server.h"
2020-03-27 15:21:27 -03:00
# include "servers/navigation_server_2d.h"
# include "servers/navigation_server_3d.h"
# include "servers/physics_server_2d.h"
# include "servers/physics_server_3d.h"
2018-09-11 18:13:45 +02:00
# include "servers/register_server_types.h"
2020-12-03 18:09:47 -03:00
# include "servers/rendering/rendering_server_default.h"
2020-08-05 09:25:28 +03:00
# include "servers/text_server.h"
2020-04-09 00:47:36 +10:00
# include "servers/xr_server.h"
2014-02-09 22:10:30 -03:00
2020-07-25 16:59:30 +03:00
# ifdef TESTS_ENABLED
2020-07-26 00:06:07 +03:00
# include "tests/test_main.h"
2020-07-25 16:59:30 +03:00
# endif
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
2020-03-24 09:54:49 +01:00
# include "editor/doc_data_class_path.gen.h"
2020-11-29 09:12:06 +05:30
# include "editor/doc_tools.h"
2017-03-05 14:21:25 +01:00
# include "editor/editor_node.h"
2018-09-15 14:45:54 +02:00
# include "editor/editor_settings.h"
2021-12-15 23:01:06 +08:00
# include "editor/editor_translation.h"
2019-12-24 15:17:23 +08:00
# include "editor/progress_dialog.h"
2017-03-05 14:21:25 +01:00
# include "editor/project_manager.h"
2021-11-30 12:36:56 +01:00
# ifndef NO_EDITOR_SPLASH
# include "main/splash_editor.gen.h"
# endif
2014-02-09 22:10:30 -03:00
# endif
2021-11-12 13:42:58 +01:00
# include "modules/modules_enabled.gen.h" // For mono.
2018-09-20 11:45:05 +02:00
/* Static members */
// Singletons
// Initialized in setup()
2020-04-02 01:20:12 +02:00
static Engine * engine = nullptr ;
static ProjectSettings * globals = nullptr ;
2020-04-28 15:19:37 +02:00
static Input * input = nullptr ;
2020-04-02 01:20:12 +02:00
static InputMap * input_map = nullptr ;
static TranslationServer * translation_server = nullptr ;
static Performance * performance = nullptr ;
static PackedData * packed_data = nullptr ;
2021-05-24 07:54:05 -04:00
static Time * time_singleton = nullptr ;
2015-04-20 19:38:02 -03:00
# ifdef MINIZIP_ENABLED
2020-04-02 01:20:12 +02:00
static ZipArchive * zip_packed_data = nullptr ;
2015-04-20 19:38:02 -03:00
# endif
2020-04-02 01:20:12 +02:00
static FileAccessNetworkClient * file_access_network_client = nullptr ;
static MessageQueue * message_queue = nullptr ;
2018-09-20 11:45:05 +02:00
// Initialized in setup2()
2020-04-02 01:20:12 +02:00
static AudioServer * audio_server = nullptr ;
static DisplayServer * display_server = nullptr ;
static RenderingServer * rendering_server = nullptr ;
static CameraServer * camera_server = nullptr ;
2020-04-09 00:47:36 +10:00
static XRServer * xr_server = nullptr ;
2020-08-05 09:25:28 +03:00
static TextServerManager * tsman = nullptr ;
2020-04-02 01:20:12 +02:00
static PhysicsServer3D * physics_server = nullptr ;
static PhysicsServer2D * physics_2d_server = nullptr ;
static NavigationServer3D * navigation_server = nullptr ;
static NavigationServer2D * navigation_2d_server = nullptr ;
2018-09-20 11:45:05 +02:00
// We error out if setup2() doesn't turn this true
static bool _start_success = false ;
// Drivers
2021-02-17 16:07:56 +02:00
String tablet_driver = " " ;
2020-09-03 14:22:16 +03:00
String text_driver = " " ;
2020-11-18 18:11:30 +00:00
String rendering_driver = " " ;
2020-08-05 09:25:28 +03:00
static int text_driver_idx = - 1 ;
2020-03-03 10:36:29 -03:00
static int display_driver_idx = - 1 ;
2018-09-20 11:45:05 +02:00
static int audio_driver_idx = - 1 ;
// Engine config/tools
static bool editor = false ;
static bool project_manager = false ;
2021-06-16 19:08:29 +02:00
static bool cmdline_tool = false ;
2018-09-20 11:45:05 +02:00
static String locale ;
static bool show_help = false ;
static bool auto_quit = false ;
static OS : : ProcessID allow_focus_steal_pid = 0 ;
2018-10-03 14:05:17 +02:00
# ifdef TOOLS_ENABLED
static bool auto_build_solutions = false ;
2021-08-29 01:58:15 +02:00
static String debug_server_uri ;
2018-10-03 14:05:17 +02:00
# endif
2018-09-20 11:45:05 +02:00
// Display
2014-02-09 22:10:30 -03:00
2020-03-03 10:36:29 -03:00
static DisplayServer : : WindowMode window_mode = DisplayServer : : WINDOW_MODE_WINDOWED ;
static DisplayServer : : ScreenOrientation window_orientation = DisplayServer : : SCREEN_LANDSCAPE ;
2021-06-19 17:44:59 +02:00
static DisplayServer : : VSyncMode window_vsync_mode = DisplayServer : : VSYNC_ENABLED ;
2020-03-03 10:36:29 -03:00
static uint32_t window_flags = 0 ;
static Size2i window_size = Size2i ( 1024 , 600 ) ;
2018-09-20 11:45:05 +02:00
static int init_screen = - 1 ;
static bool init_fullscreen = false ;
2017-03-05 16:44:50 +01:00
static bool init_maximized = false ;
static bool init_windowed = false ;
2017-12-27 20:51:19 +01:00
static bool init_always_on_top = false ;
2017-03-05 16:44:50 +01:00
static bool init_use_custom_pos = false ;
2018-09-20 11:45:05 +02:00
static Vector2 init_custom_pos ;
// Debug
static bool use_debug_profiler = false ;
2017-04-07 16:17:16 +02:00
# ifdef DEBUG_ENABLED
2017-03-05 16:44:50 +01:00
static bool debug_collisions = false ;
static bool debug_navigation = false ;
2017-04-07 16:17:16 +02:00
# endif
2017-03-05 16:44:50 +01:00
static int frame_delay = 0 ;
2017-08-30 12:40:35 +02:00
static bool disable_render_loop = false ;
static int fixed_fps = - 1 ;
2018-03-21 08:46:05 +01:00
static bool print_fps = false ;
2021-06-19 12:58:49 -03:00
# ifdef TOOLS_ENABLED
static bool dump_extension_api = false ;
# endif
2021-01-22 20:50:24 -03:00
bool profile_gpu = false ;
2018-09-20 11:45:05 +02:00
/* Helper methods */
2018-02-16 16:00:54 +01:00
2018-09-20 11:45:05 +02:00
// Used by Mono module, should likely be registered in Engine singleton instead
// FIXME: This is also not 100% accurate, `project_manager` is only true when it was requested,
// but not if e.g. we fail to load and project and fallback to the manager.
2018-02-16 16:00:54 +01:00
bool Main : : is_project_manager ( ) {
return project_manager ;
}
2021-06-16 19:08:29 +02:00
bool Main : : is_cmdline_tool ( ) {
return cmdline_tool ;
}
2018-09-20 11:45:05 +02:00
static String unescape_cmdline ( const String & p_str ) {
return p_str . replace ( " %20 " , " " ) ;
}
2017-10-21 13:02:06 +02:00
2018-09-20 11:45:05 +02:00
static String get_full_version_string ( ) {
String hash = String ( VERSION_HASH ) ;
2020-05-14 16:41:43 +02:00
if ( hash . length ( ) ! = 0 ) {
2019-06-01 13:51:10 +02:00
hash = " . " + hash . left ( 9 ) ;
2020-05-14 16:41:43 +02:00
}
2018-09-20 11:45:05 +02:00
return String ( VERSION_FULL_BUILD ) + hash ;
}
2020-03-27 15:21:27 -03:00
// FIXME: Could maybe be moved to PhysicsServer3DManager and PhysicsServer2DManager directly
2018-09-20 11:45:05 +02:00
// to have less code in main.cpp.
void initialize_physics ( ) {
2017-10-21 13:02:06 +02:00
/// 3D Physics Server
2020-07-20 17:35:34 +01:00
physics_server = PhysicsServer3DManager : : new_server (
ProjectSettings : : get_singleton ( ) - > get ( PhysicsServer3DManager : : setting_property_name ) ) ;
2017-10-21 13:02:06 +02:00
if ( ! physics_server ) {
// Physics server not found, Use the default physics
2020-03-27 15:21:27 -03:00
physics_server = PhysicsServer3DManager : : new_default_server ( ) ;
2017-10-21 13:02:06 +02:00
}
ERR_FAIL_COND ( ! physics_server ) ;
physics_server - > init ( ) ;
/// 2D Physics server
2020-07-20 17:35:34 +01:00
physics_2d_server = PhysicsServer2DManager : : new_server (
ProjectSettings : : get_singleton ( ) - > get ( PhysicsServer2DManager : : setting_property_name ) ) ;
2017-10-21 13:02:06 +02:00
if ( ! physics_2d_server ) {
// Physics server not found, Use the default physics
2020-03-27 15:21:27 -03:00
physics_2d_server = PhysicsServer2DManager : : new_default_server ( ) ;
2017-10-21 13:02:06 +02:00
}
ERR_FAIL_COND ( ! physics_2d_server ) ;
physics_2d_server - > init ( ) ;
}
void finalize_physics ( ) {
physics_server - > finish ( ) ;
memdelete ( physics_server ) ;
physics_2d_server - > finish ( ) ;
memdelete ( physics_2d_server ) ;
}
2020-03-03 10:36:29 -03:00
void finalize_display ( ) {
2020-03-27 15:21:27 -03:00
rendering_server - > finish ( ) ;
memdelete ( rendering_server ) ;
2020-03-03 10:36:29 -03:00
memdelete ( display_server ) ;
}
2020-01-10 12:22:34 +01:00
void initialize_navigation_server ( ) {
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND ( navigation_server ! = nullptr ) ;
2020-02-26 09:42:51 +01:00
2020-03-27 15:21:27 -03:00
navigation_server = NavigationServer3DManager : : new_default_server ( ) ;
navigation_2d_server = memnew ( NavigationServer2D ) ;
2020-01-10 12:22:34 +01:00
}
void finalize_navigation_server ( ) {
memdelete ( navigation_server ) ;
2020-04-02 01:20:12 +02:00
navigation_server = nullptr ;
2020-02-26 09:42:51 +01:00
2020-01-10 12:22:34 +01:00
memdelete ( navigation_2d_server ) ;
2020-04-02 01:20:12 +02:00
navigation_2d_server = nullptr ;
2020-01-10 12:22:34 +01:00
}
2014-02-09 22:10:30 -03:00
//#define DEBUG_INIT
# ifdef DEBUG_INIT
# define MAIN_PRINT(m_txt) print_line(m_txt)
# else
# define MAIN_PRINT(m_txt)
# endif
2017-03-05 16:44:50 +01:00
void Main : : print_help ( const char * p_binary ) {
2019-05-28 11:19:21 +02:00
print_line ( String ( VERSION_NAME ) + " v " + get_full_version_string ( ) + " - " + String ( VERSION_WEBSITE ) ) ;
OS : : get_singleton ( ) - > print ( " Free and open source software under the terms of the MIT license. \n " ) ;
2022-01-03 21:27:34 +01:00
OS : : get_singleton ( ) - > print ( " (c) 2007-2022 Juan Linietsky, Ariel Manzur. \n " ) ;
OS : : get_singleton ( ) - > print ( " (c) 2014-2022 Godot Engine contributors. \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
2017-06-21 11:09:30 +02:00
OS : : get_singleton ( ) - > print ( " Usage: %s [options] [path to scene or 'project.godot' file] \n " , p_binary ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
OS : : get_singleton ( ) - > print ( " General options: \n " ) ;
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " -h, --help Display this help message. \n " ) ;
OS : : get_singleton ( ) - > print ( " --version Display the version string. \n " ) ;
OS : : get_singleton ( ) - > print ( " -v, --verbose Use verbose stdout mode. \n " ) ;
OS : : get_singleton ( ) - > print ( " --quiet Quiet mode, silences stdout messages. Errors are still displayed. \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
OS : : get_singleton ( ) - > print ( " Run options: \n " ) ;
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
2021-01-12 14:12:40 -03:00
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 " ) ;
2021-08-29 01:58:15 +02:00
OS : : get_singleton ( ) - > print ( " --debug-server <uri> Start the editor debug server (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007) \n " ) ;
2014-02-09 22:10:30 -03:00
# endif
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " -q, --quit Quit after the first iteration. \n " ) ;
OS : : get_singleton ( ) - > print ( " -l, --language <locale> Use a specific locale (<locale> being a two-letter code). \n " ) ;
OS : : get_singleton ( ) - > print ( " --path <directory> Path to a project (<directory> must contain a 'project.godot' file). \n " ) ;
OS : : get_singleton ( ) - > print ( " -u, --upwards Scan folders upwards for project.godot file. \n " ) ;
OS : : get_singleton ( ) - > print ( " --main-pack <file> Path to a pack (.pck) file to load. \n " ) ;
OS : : get_singleton ( ) - > print ( " --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate'). \n " ) ;
OS : : get_singleton ( ) - > print ( " --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address). \n " ) ;
OS : : get_singleton ( ) - > print ( " --remote-fs-password <password> Password for remote filesystem. \n " ) ;
OS : : get_singleton ( ) - > print ( " --audio-driver <driver> Audio driver [ " ) ;
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < AudioDriverManager : : get_driver_count ( ) ; i + + ) {
2020-03-27 10:48:30 +01:00
if ( i > 0 ) {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " , " ) ;
2020-03-27 10:48:30 +01:00
}
2020-03-03 10:36:29 -03:00
OS : : get_singleton ( ) - > print ( " '%s' " , AudioDriverManager : : get_driver ( i ) - > get_name ( ) ) ;
2014-02-09 22:10:30 -03:00
}
2020-03-27 10:48:30 +01:00
OS : : get_singleton ( ) - > print ( " ]. \n " ) ;
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --display-driver <driver> Display driver (and rendering driver) [ " ) ;
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < DisplayServer : : get_create_function_count ( ) ; i + + ) {
2020-03-27 10:48:30 +01:00
if ( i > 0 ) {
OS : : get_singleton ( ) - > print ( " , " ) ;
}
OS : : get_singleton ( ) - > print ( " '%s' ( " , DisplayServer : : get_create_function_name ( i ) ) ;
2020-03-03 10:36:29 -03:00
Vector < String > rd = DisplayServer : : get_create_function_rendering_drivers ( i ) ;
for ( int j = 0 ; j < rd . size ( ) ; j + + ) {
if ( j > 0 ) {
OS : : get_singleton ( ) - > print ( " , " ) ;
}
OS : : get_singleton ( ) - > print ( " '%s' " , rd [ j ] . utf8 ( ) . get_data ( ) ) ;
}
2020-03-27 10:48:30 +01:00
OS : : get_singleton ( ) - > print ( " ) " ) ;
2014-02-09 22:10:30 -03:00
}
2020-03-27 10:48:30 +01:00
OS : : get_singleton ( ) - > print ( " ]. \n " ) ;
2020-08-05 09:25:28 +03:00
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --rendering-driver <driver> Rendering driver (depends on display driver). \n " ) ;
2021-11-15 14:55:41 +02:00
OS : : get_singleton ( ) - > print ( " --gpu-index <device_index> Use a specific GPU (run with --verbose to get available device list). \n " ) ;
2020-08-05 09:25:28 +03:00
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --text-driver <driver> Text driver (Fonts, BiDi, shaping) \n " ) ;
2020-08-05 09:25:28 +03:00
2021-08-03 16:59:18 +02:00
OS : : get_singleton ( ) - > print ( " --headless Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script. \n " ) ;
2020-03-27 10:48:30 +01:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
2017-08-19 16:45:03 +02:00
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Display options: \n " ) ;
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " -f, --fullscreen Request fullscreen mode. \n " ) ;
OS : : get_singleton ( ) - > print ( " -m, --maximized Request a maximized window. \n " ) ;
OS : : get_singleton ( ) - > print ( " -w, --windowed Request windowed mode. \n " ) ;
OS : : get_singleton ( ) - > print ( " -t, --always-on-top Request an always-on-top window. \n " ) ;
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 " ) ;
2021-02-17 16:07:56 +02:00
OS : : get_singleton ( ) - > print ( " --tablet-driver Pen tablet input driver. \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
2017-08-19 17:47:27 -03:00
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Debug options: \n " ) ;
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " -d, --debug Debug (local stdout debugger). \n " ) ;
OS : : get_singleton ( ) - > print ( " -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead). \n " ) ;
OS : : get_singleton ( ) - > print ( " --profiling Enable profiling in the script debugger. \n " ) ;
OS : : get_singleton ( ) - > print ( " --vk-layers Enable Vulkan Validation layers for debugging. \n " ) ;
2021-12-22 10:15:12 +03:00
# ifdef DEBUG_ENABLED
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes. \n " ) ;
2020-10-27 16:00:15 +01:00
# endif
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007). \n " ) ;
2021-08-03 16:59:18 +02:00
# if defined(DEBUG_ENABLED)
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --debug-collisions Show collision shapes when running the scene. \n " ) ;
OS : : get_singleton ( ) - > print ( " --debug-navigation Show navigation polygons when running the scene. \n " ) ;
2017-08-19 16:45:03 +02:00
# endif
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds). \n " ) ;
OS : : get_singleton ( ) - > print ( " --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed). \n " ) ;
OS : : get_singleton ( ) - > print ( " --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script. \n " ) ;
OS : : get_singleton ( ) - > print ( " --disable-crash-handler Disable crash handler when supported by the platform code. \n " ) ;
OS : : get_singleton ( ) - > print ( " --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization. \n " ) ;
OS : : get_singleton ( ) - > print ( " --print-fps Print the frames per second to the stdout. \n " ) ;
OS : : get_singleton ( ) - > print ( " --profile-gpu Show a simple profile of the tasks that took more time during frame rendering. \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
OS : : get_singleton ( ) - > print ( " Standalone tools: \n " ) ;
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " -s, --script <script> Run a script. \n " ) ;
OS : : get_singleton ( ) - > print ( " --check-only Only parse for errors and quit (use with --script). \n " ) ;
2017-08-19 17:47:27 -03:00
# ifdef TOOLS_ENABLED
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg. \n " ) ;
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 " ) ;
2021-04-05 15:35:19 +02:00
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 " ) ;
2021-01-12 14:12:40 -03:00
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 " ) ;
2021-10-20 12:04:59 +02:00
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 " ) ;
2017-08-19 16:45:03 +02:00
# ifdef DEBUG_METHODS_ENABLED
2021-10-20 12:04:59 +02:00
// TODO: Should be removed together with nativescript eventually.
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --gdnative-generate-json-api <path> Generate JSON dump of the Godot API for GDNative bindings and save it on the file specified in <path>. \n " ) ;
OS : : get_singleton ( ) - > print ( " --gdnative-generate-json-builtin-api <path> Generate JSON dump of the Godot API of the builtin Variant types and utility functions for GDNative bindings and save it on the file specified in <path>. \n " ) ;
2017-08-19 16:45:03 +02:00
# endif
2020-07-25 16:59:30 +03:00
# ifdef TESTS_ENABLED
2021-01-12 14:12:40 -03:00
OS : : get_singleton ( ) - > print ( " --test [--help] Run unit tests. Use --test --help for more information. \n " ) ;
2020-07-25 16:59:30 +03:00
# endif
2014-02-09 22:10:30 -03:00
# endif
2020-08-04 00:22:30 -07:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
2014-02-09 22:10:30 -03:00
}
2020-08-02 21:30:56 +03:00
# ifdef TESTS_ENABLED
// The order is the same as in `Main::setup()`, only core and some editor types
// are initialized here. This also combines `Main::setup2()` initialization.
Error Main : : test_setup ( ) {
OS : : get_singleton ( ) - > initialize ( ) ;
engine = memnew ( Engine ) ;
register_core_types ( ) ;
register_core_driver_types ( ) ;
2021-04-07 14:23:18 -03:00
packed_data = memnew ( PackedData ) ;
2020-08-02 21:30:56 +03:00
globals = memnew ( ProjectSettings ) ;
GLOBAL_DEF ( " debug/settings/crash_handler/message " ,
String ( " Please include this when reporting the bug on https://github.com/godotengine/godot/issues " ) ) ;
2021-07-11 14:25:27 +01:00
GLOBAL_DEF_RST ( " rendering/occlusion_culling/bvh_build_quality " , 2 ) ;
2020-08-02 21:30:56 +03:00
2021-02-22 15:16:46 +02:00
translation_server = memnew ( TranslationServer ) ;
2021-08-28 00:19:51 +03:00
tsman = memnew ( TextServerManager ) ;
2021-02-22 15:16:46 +02:00
2021-06-19 12:58:49 -03:00
register_core_extensions ( ) ;
2020-08-02 21:30:56 +03:00
// From `Main::setup2()`.
preregister_module_types ( ) ;
preregister_server_types ( ) ;
register_core_singletons ( ) ;
register_server_types ( ) ;
2021-02-22 15:16:46 +02:00
translation_server - > setup ( ) ; //register translations, load them, etc.
2021-12-09 03:42:46 -06:00
if ( ! locale . is_empty ( ) ) {
2021-02-22 15:16:46 +02:00
translation_server - > set_locale ( locale ) ;
}
translation_server - > load_translations ( ) ;
ResourceLoader : : load_translation_remaps ( ) ; //load remaps for resources
ResourceLoader : : load_path_remaps ( ) ;
2020-08-02 21:30:56 +03:00
register_scene_types ( ) ;
# ifdef TOOLS_ENABLED
ClassDB : : set_current_api ( ClassDB : : API_EDITOR ) ;
EditorNode : : register_editor_types ( ) ;
ClassDB : : set_current_api ( ClassDB : : API_CORE ) ;
# endif
register_platform_apis ( ) ;
register_module_types ( ) ;
register_driver_types ( ) ;
2021-11-30 19:09:29 +03:00
// Theme needs modules to be initialized so that sub-resources can be loaded.
initialize_theme ( ) ;
2021-08-28 00:19:51 +03:00
ERR_FAIL_COND_V ( TextServerManager : : get_singleton ( ) - > get_interface_count ( ) = = 0 , ERR_CANT_CREATE ) ;
TextServerManager : : get_singleton ( ) - > set_primary_interface ( TextServerManager : : get_singleton ( ) - > get_interface ( 0 ) ) ;
2020-08-02 21:30:56 +03:00
ClassDB : : set_current_api ( ClassDB : : API_NONE ) ;
_start_success = true ;
return OK ;
}
// The order is the same as in `Main::cleanup()`.
void Main : : test_cleanup ( ) {
ERR_FAIL_COND ( ! _start_success ) ;
EngineDebugger : : deinitialize ( ) ;
ResourceLoader : : remove_custom_loaders ( ) ;
ResourceSaver : : remove_custom_savers ( ) ;
2021-09-19 13:10:38 +01:00
unregister_driver_types ( ) ;
2020-08-02 21:30:56 +03:00
# ifdef TOOLS_ENABLED
EditorNode : : unregister_editor_types ( ) ;
# endif
2021-08-28 00:19:51 +03:00
2020-08-02 21:30:56 +03:00
unregister_module_types ( ) ;
unregister_platform_apis ( ) ;
unregister_scene_types ( ) ;
unregister_server_types ( ) ;
OS : : get_singleton ( ) - > finalize ( ) ;
2021-02-22 15:16:46 +02:00
if ( translation_server ) {
memdelete ( translation_server ) ;
}
2021-08-28 00:19:51 +03:00
if ( tsman ) {
memdelete ( tsman ) ;
}
2020-08-02 21:30:56 +03:00
if ( globals ) {
memdelete ( globals ) ;
}
2021-04-07 14:23:18 -03:00
if ( packed_data ) {
memdelete ( packed_data ) ;
}
2020-08-02 21:30:56 +03:00
if ( engine ) {
memdelete ( engine ) ;
}
unregister_core_driver_types ( ) ;
unregister_core_types ( ) ;
OS : : get_singleton ( ) - > finalize_core ( ) ;
}
# endif
2020-07-20 17:35:34 +01:00
int Main : : test_entrypoint ( int argc , char * argv [ ] , bool & tests_need_run ) {
2020-07-25 16:59:30 +03:00
# ifdef TESTS_ENABLED
2020-07-20 17:35:34 +01:00
for ( int x = 0 ; x < argc ; x + + ) {
2020-08-08 21:53:51 +03:00
if ( ( strncmp ( argv [ x ] , " --test " , 6 ) = = 0 ) & & ( strlen ( argv [ x ] ) = = 6 ) ) {
2020-07-20 17:35:34 +01:00
tests_need_run = true ;
2020-08-02 21:30:56 +03:00
// TODO: need to come up with different test contexts.
// Not every test requires high-level functionality like `ClassDB`.
test_setup ( ) ;
2020-07-24 14:38:57 +01:00
int status = test_main ( argc , argv ) ;
2020-08-02 21:30:56 +03:00
test_cleanup ( ) ;
2020-07-24 14:38:57 +01:00
return status ;
2020-07-20 17:35:34 +01:00
}
}
# endif
tests_need_run = false ;
return 0 ;
}
2018-09-20 11:45:05 +02:00
/* Engine initialization
*
* Consists of several methods that are called by each platform's specific main(argc, argv).
* To fully understand engine init, one should therefore start from the platform's main and
* see how it calls into the Main class' methods.
*
* The initialization is typically done in 3 steps (with the setup2 step triggered either
* automatically by setup, or manually in the platform's main).
*
* - setup(execpath, argc, argv, p_second_phase) is the main entry point for all platforms,
* responsible for the initialization of all low level singletons and core types, and parsing
* command line arguments to configure things accordingly.
* If p_second_phase is true, it will chain into setup2() (default behaviour). This is
* disabled on some platforms (Android, iOS, UWP) which trigger the second step in their
* own time.
*
* - setup2(p_main_tid_override) registers high level servers and singletons, displays the
* boot splash, then registers higher level types (scene, editor, etc.).
*
* - start() is the last step and that's where command line tools can run, or the main loop
* can be created eventually and the project settings put into action. That's also where
* the editor node is created, if relevant.
* start() does it own argument parsing for a subset of the command line arguments described
* in help, it's a bit messy and should be globalized with the setup() parsing somehow.
*/
2017-03-05 16:44:50 +01:00
Error Main : : setup ( const char * execpath , int argc , char * argv [ ] , bool p_second_phase ) {
2020-03-03 10:36:29 -03:00
OS : : get_singleton ( ) - > initialize ( ) ;
2017-01-13 12:51:14 -03:00
2017-03-05 16:44:50 +01:00
engine = memnew ( Engine ) ;
2017-01-13 12:51:14 -03:00
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: Initialize CORE " ) ;
register_core_types ( ) ;
register_core_driver_types ( ) ;
MAIN_PRINT ( " Main: Initialize Globals " ) ;
2017-03-05 16:44:50 +01:00
input_map = memnew ( InputMap ) ;
2021-05-24 07:54:05 -04:00
time_singleton = memnew ( Time ) ;
2020-12-07 21:31:51 +10:00
globals = memnew ( ProjectSettings ) ;
2014-02-09 22:10:30 -03:00
2021-03-12 19:05:16 +05:30
register_core_settings ( ) ; //here globals are present
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
translation_server = memnew ( TranslationServer ) ;
performance = memnew ( Performance ) ;
2021-07-11 19:30:33 -03:00
GDREGISTER_CLASS ( Performance ) ;
2017-11-13 21:46:57 +01:00
engine - > add_singleton ( Engine : : Singleton ( " Performance " , performance ) ) ;
2014-02-09 22:10:30 -03:00
2020-12-29 22:20:02 +01:00
// Only flush stdout in debug builds by default, as spamming `print()` will
// decrease performance if this is enabled.
2021-02-28 19:26:14 -03:00
GLOBAL_DEF_RST ( " application/run/flush_stdout_on_print " , false ) ;
GLOBAL_DEF_RST ( " application/run/flush_stdout_on_print.debug " , true ) ;
2020-12-29 22:20:02 +01:00
2020-07-20 17:35:34 +01:00
GLOBAL_DEF ( " debug/settings/crash_handler/message " ,
String ( " Please include this when reporting the bug on https://github.com/godotengine/godot/issues " ) ) ;
2017-09-07 22:01:49 -03:00
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: Parse CMDLine " ) ;
/* argument parsing and main creation */
List < String > args ;
List < String > main_args ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < argc ; i + + ) {
2014-02-18 14:37:22 +01:00
args . push_back ( String : : utf8 ( argv [ i ] ) ) ;
2014-02-09 22:10:30 -03:00
}
2017-03-05 16:44:50 +01:00
List < String > : : Element * I = args . front ( ) ;
2014-02-09 22:10:30 -03:00
while ( I ) {
2019-05-31 15:27:53 +02:00
I - > get ( ) = unescape_cmdline ( I - > get ( ) . strip_edges ( ) ) ;
2017-03-05 16:44:50 +01:00
I = I - > next ( ) ;
2014-02-09 22:10:30 -03:00
}
2017-03-05 16:44:50 +01:00
I = args . front ( ) ;
2016-03-09 00:00:52 +01:00
2020-03-03 10:36:29 -03:00
String display_driver = " " ;
2017-03-05 16:44:50 +01:00
String audio_driver = " " ;
2018-05-12 13:21:26 +02:00
String project_path = " . " ;
2017-10-10 23:45:54 +11:00
bool upwards = false ;
2020-02-27 03:30:20 +01:00
String debug_uri = " " ;
2019-07-29 20:09:22 +02:00
bool skip_breakpoints = false ;
2014-06-27 23:21:45 -03:00
String main_pack ;
2017-03-05 16:44:50 +01:00
bool quiet_stdout = false ;
int rtm = - 1 ;
2014-02-09 22:10:30 -03:00
String remotefs ;
String remotefs_pass ;
Vector < String > breakpoints ;
2017-03-05 16:44:50 +01:00
bool use_custom_res = true ;
bool force_res = false ;
2019-02-18 20:28:40 +01:00
# ifdef TOOLS_ENABLED
2018-02-26 17:16:29 +01:00
bool found_project = false ;
2019-02-18 20:28:40 +01:00
# endif
2014-02-09 22:10:30 -03:00
2014-06-27 23:21:45 -03:00
packed_data = PackedData : : get_singleton ( ) ;
2020-05-14 16:41:43 +02:00
if ( ! packed_data ) {
2014-06-27 23:21:45 -03:00
packed_data = memnew ( PackedData ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
# ifdef MINIZIP_ENABLED
2016-03-09 00:00:52 +01:00
2015-05-06 20:37:25 -03:00
//XXX: always get_singleton() == 0x0
2015-04-20 19:38:02 -03:00
zip_packed_data = ZipArchive : : get_singleton ( ) ;
2015-05-06 20:37:25 -03:00
//TODO: remove this temporary fix
if ( ! zip_packed_data ) {
zip_packed_data = memnew ( ZipArchive ) ;
}
2015-04-20 19:38:02 -03:00
packed_data - > add_pack_source ( zip_packed_data ) ;
2014-02-09 22:10:30 -03:00
# endif
2017-08-19 16:45:03 +02:00
I = args . front ( ) ;
2017-03-05 16:44:50 +01:00
while ( I ) {
2020-04-09 20:06:43 +03:00
# ifdef OSX_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_ " ) ) {
I = I - > next ( ) ;
continue ;
}
# endif
2016-06-18 16:03:00 -03:00
2017-03-05 16:44:50 +01:00
List < String > : : Element * N = I - > next ( ) ;
2014-02-09 22:10:30 -03:00
2017-08-19 16:45:03 +02:00
if ( I - > get ( ) = = " -h " | | I - > get ( ) = = " --help " | | I - > get ( ) = = " /? " ) { // display help
2016-03-09 00:00:52 +01:00
2017-08-19 16:45:03 +02:00
show_help = true ;
2014-02-09 22:10:30 -03:00
goto error ;
2016-03-09 00:00:52 +01:00
2017-09-24 11:32:05 +02:00
} else if ( I - > get ( ) = = " --version " ) {
print_line ( get_full_version_string ( ) ) ;
goto error ;
2019-05-19 01:33:13 +02:00
} else if ( I - > get ( ) = = " -v " | | I - > get ( ) = = " --verbose " ) { // verbose output
OS : : get_singleton ( ) - > _verbose_stdout = true ;
} else if ( I - > get ( ) = = " --quiet " ) { // quieter output
quiet_stdout = true ;
} else if ( I - > get ( ) = = " --audio-driver " ) { // audio driver
if ( I - > next ( ) ) {
audio_driver = I - > next ( ) - > get ( ) ;
2019-09-27 15:06:15 +02:00
bool found = false ;
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < AudioDriverManager : : get_driver_count ( ) ; i + + ) {
if ( audio_driver = = AudioDriverManager : : get_driver ( i ) - > get_name ( ) ) {
2019-09-27 15:06:15 +02:00
found = true ;
}
}
if ( ! found ) {
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > print ( " Unknown audio driver '%s', aborting. \n Valid options are " ,
audio_driver . utf8 ( ) . get_data ( ) ) ;
2019-09-27 15:06:15 +02:00
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < AudioDriverManager : : get_driver_count ( ) ; i + + ) {
if ( i = = AudioDriverManager : : get_driver_count ( ) - 1 ) {
2019-09-27 15:06:15 +02:00
OS : : get_singleton ( ) - > print ( " and " ) ;
} else if ( i ! = 0 ) {
OS : : get_singleton ( ) - > print ( " , " ) ;
}
2020-03-03 10:36:29 -03:00
OS : : get_singleton ( ) - > print ( " '%s' " , AudioDriverManager : : get_driver ( i ) - > get_name ( ) ) ;
2019-09-27 15:06:15 +02:00
}
OS : : get_singleton ( ) - > print ( " . \n " ) ;
goto error ;
}
2019-05-19 01:33:13 +02:00
N = I - > next ( ) - > next ( ) ;
} else {
OS : : get_singleton ( ) - > print ( " Missing audio driver argument, aborting. \n " ) ;
goto error ;
}
2020-08-05 09:25:28 +03:00
} else if ( I - > get ( ) = = " --text-driver " ) {
if ( I - > next ( ) ) {
text_driver = I - > next ( ) - > get ( ) ;
N = I - > next ( ) - > next ( ) ;
} else {
OS : : get_singleton ( ) - > print ( " Missing text driver argument, aborting. \n " ) ;
goto error ;
}
2019-05-19 01:33:13 +02:00
2020-03-03 10:36:29 -03:00
} else if ( I - > get ( ) = = " --display-driver " ) { // force video driver
2019-05-19 01:33:13 +02:00
if ( I - > next ( ) ) {
2020-03-03 10:36:29 -03:00
display_driver = I - > next ( ) - > get ( ) ;
2019-09-27 15:06:15 +02:00
bool found = false ;
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < DisplayServer : : get_create_function_count ( ) ; i + + ) {
if ( display_driver = = DisplayServer : : get_create_function_name ( i ) ) {
2019-09-27 15:06:15 +02:00
found = true ;
}
}
if ( ! found ) {
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > print ( " Unknown display driver '%s', aborting. \n Valid options are " ,
display_driver . utf8 ( ) . get_data ( ) ) ;
2019-09-27 15:06:15 +02:00
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < DisplayServer : : get_create_function_count ( ) ; i + + ) {
if ( i = = DisplayServer : : get_create_function_count ( ) - 1 ) {
2019-09-27 15:06:15 +02:00
OS : : get_singleton ( ) - > print ( " and " ) ;
} else if ( i ! = 0 ) {
OS : : get_singleton ( ) - > print ( " , " ) ;
}
2020-03-03 10:36:29 -03:00
OS : : get_singleton ( ) - > print ( " '%s' " , DisplayServer : : get_create_function_name ( i ) ) ;
2019-09-27 15:06:15 +02:00
}
OS : : get_singleton ( ) - > print ( " . \n " ) ;
goto error ;
}
2019-05-19 01:33:13 +02:00
N = I - > next ( ) - > next ( ) ;
} else {
2020-11-18 18:11:30 +00:00
OS : : get_singleton ( ) - > print ( " Missing display driver argument, aborting. \n " ) ;
goto error ;
}
} else if ( I - > get ( ) = = " --rendering-driver " ) {
if ( I - > next ( ) ) {
rendering_driver = I - > next ( ) - > get ( ) ;
// as the rendering drivers available may depend on the display driver selected,
// we can't do an exhaustive check here, but we can look through all the options in
// all the display drivers for a match
bool found = false ;
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 + + ) {
if ( rendering_driver = = r_drivers [ d ] ) {
found = true ;
break ;
}
}
}
if ( ! found ) {
OS : : get_singleton ( ) - > print ( " Unknown rendering driver '%s', aborting. \n Valid options are " ,
rendering_driver . utf8 ( ) . get_data ( ) ) ;
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 ( ) ) ;
}
}
OS : : get_singleton ( ) - > print ( " . \n " ) ;
goto error ;
}
N = I - > next ( ) - > next ( ) ;
} else {
OS : : get_singleton ( ) - > print ( " Missing rendering driver argument, aborting. \n " ) ;
2019-05-19 01:33:13 +02:00
goto error ;
}
} else if ( I - > get ( ) = = " -f " | | I - > get ( ) = = " --fullscreen " ) { // force fullscreen
init_fullscreen = true ;
} else if ( I - > get ( ) = = " -m " | | I - > get ( ) = = " --maximized " ) { // force maximized window
init_maximized = true ;
2020-03-03 10:36:29 -03:00
window_mode = DisplayServer : : WINDOW_MODE_MAXIMIZED ;
2019-05-19 01:33:13 +02:00
} else if ( I - > get ( ) = = " -w " | | I - > get ( ) = = " --windowed " ) { // force windowed window
init_windowed = true ;
2021-11-15 14:55:41 +02:00
} else if ( I - > get ( ) = = " --gpu-index " ) {
if ( I - > next ( ) ) {
Engine : : singleton - > gpu_idx = I - > next ( ) - > get ( ) . to_int ( ) ;
N = I - > next ( ) - > next ( ) ;
} else {
OS : : get_singleton ( ) - > print ( " Missing gpu index argument, aborting. \n " ) ;
goto error ;
}
2020-10-27 16:00:15 +01:00
} else if ( I - > get ( ) = = " --vk-layers " ) {
Engine : : singleton - > use_validation_layers = true ;
2020-11-18 12:01:41 -06:00
# ifdef DEBUG_ENABLED
2020-10-27 16:00:15 +01:00
} else if ( I - > get ( ) = = " --gpu-abort " ) {
2019-10-05 10:27:43 -03:00
Engine : : singleton - > abort_on_gpu_errors = true ;
2020-10-27 16:00:15 +01:00
# endif
2020-05-19 23:34:26 +03:00
} else if ( I - > get ( ) = = " --tablet-driver " ) {
if ( I - > next ( ) ) {
tablet_driver = I - > next ( ) - > get ( ) ;
N = I - > next ( ) - > next ( ) ;
} else {
OS : : get_singleton ( ) - > print ( " Missing tablet driver argument, aborting. \n " ) ;
goto error ;
}
2020-03-14 13:06:39 -03:00
} else if ( I - > get ( ) = = " --single-window " ) { // force single window
2020-09-14 18:52:45 -04:00
OS : : get_singleton ( ) - > _single_window = true ;
2019-05-19 01:33:13 +02:00
} else if ( I - > get ( ) = = " -t " | | I - > get ( ) = = " --always-on-top " ) { // force always-on-top window
init_always_on_top = true ;
2017-08-19 16:45:03 +02:00
} else if ( I - > get ( ) = = " --resolution " ) { // force resolution
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
2017-03-05 16:44:50 +01:00
String vm = I - > next ( ) - > get ( ) ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
if ( vm . find ( " x " ) = = - 1 ) { // invalid parameter format
2016-03-09 00:00:52 +01:00
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > print ( " Invalid resolution '%s', it should be e.g. '1280x720'. \n " ,
vm . utf8 ( ) . get_data ( ) ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
int w = vm . get_slice ( " x " , 0 ) . to_int ( ) ;
int h = vm . get_slice ( " x " , 1 ) . to_int ( ) ;
2016-03-09 00:00:52 +01:00
2017-08-19 16:45:03 +02:00
if ( w < = 0 | | h < = 0 ) {
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > print ( " Invalid resolution '%s', width and height must be above 0. \n " ,
vm . utf8 ( ) . get_data ( ) ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2016-03-09 00:00:52 +01:00
2020-03-03 10:36:29 -03:00
window_size . width = w ;
window_size . height = h ;
2017-03-05 16:44:50 +01:00
force_res = true ;
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing resolution argument, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2019-05-19 01:33:13 +02:00
2017-08-19 16:45:03 +02:00
} else if ( I - > get ( ) = = " --position " ) { // set window position
2015-08-30 23:36:46 -03:00
if ( I - > next ( ) ) {
2017-03-05 16:44:50 +01:00
String vm = I - > next ( ) - > get ( ) ;
2015-08-30 23:36:46 -03:00
2017-06-21 11:09:30 +02:00
if ( vm . find ( " , " ) = = - 1 ) { // invalid parameter format
2015-08-30 23:36:46 -03:00
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > print ( " Invalid position '%s', it should be e.g. '80,128'. \n " ,
vm . utf8 ( ) . get_data ( ) ) ;
2015-08-30 23:36:46 -03:00
goto error ;
}
2017-06-21 11:09:30 +02:00
int x = vm . get_slice ( " , " , 0 ) . to_int ( ) ;
int y = vm . get_slice ( " , " , 1 ) . to_int ( ) ;
2015-08-30 23:36:46 -03:00
2017-03-05 16:44:50 +01:00
init_custom_pos = Point2 ( x , y ) ;
init_use_custom_pos = true ;
2015-08-30 23:36:46 -03:00
2017-03-05 16:44:50 +01:00
N = I - > next ( ) - > next ( ) ;
2015-08-30 23:36:46 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing position argument, aborting. \n " ) ;
2015-08-30 23:36:46 -03:00
goto error ;
}
2021-08-03 16:59:18 +02:00
} else if ( I - > get ( ) = = " --headless " ) { // enable headless mode (no audio, no rendering).
audio_driver = " Dummy " ;
display_driver = " headless " ;
2017-12-27 20:51:19 +01:00
2017-08-19 16:45:03 +02:00
} else if ( I - > get ( ) = = " --profiling " ) { // enable profiling
2015-12-12 12:06:53 -03:00
2017-03-05 16:44:50 +01:00
use_debug_profiler = true ;
2016-03-09 00:00:52 +01:00
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " -l " | | I - > get ( ) = = " --language " ) { // language
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
2017-03-05 16:44:50 +01:00
locale = I - > next ( ) - > get ( ) ;
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing language argument, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2016-05-30 00:28:29 -03:00
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --remote-fs " ) { // remote filesystem
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
2017-03-05 16:44:50 +01:00
remotefs = I - > next ( ) - > get ( ) ;
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing remote filesystem address, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --remote-fs-password " ) { // remote filesystem password
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
2017-03-05 16:44:50 +01:00
remotefs_pass = I - > next ( ) - > get ( ) ;
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing remote filesystem password, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2017-08-19 16:45:03 +02:00
} else if ( I - > get ( ) = = " --render-thread " ) { // render thread mode
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
2020-05-14 16:41:43 +02:00
if ( I - > next ( ) - > get ( ) = = " safe " ) {
2017-03-05 16:44:50 +01:00
rtm = OS : : RENDER_THREAD_SAFE ;
2020-05-14 16:41:43 +02:00
} else if ( I - > next ( ) - > get ( ) = = " unsafe " ) {
2017-03-05 16:44:50 +01:00
rtm = OS : : RENDER_THREAD_UNSAFE ;
2020-05-14 16:41:43 +02:00
} else if ( I - > next ( ) - > get ( ) = = " separate " ) {
2017-03-05 16:44:50 +01:00
rtm = OS : : RENDER_SEPARATE_THREAD ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing render thread mode argument, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2018-02-16 19:40:22 +01:00
# ifdef TOOLS_ENABLED
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " -e " | | I - > get ( ) = = " --editor " ) { // starts editor
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
editor = true ;
2018-02-13 18:56:38 +01:00
} else if ( I - > get ( ) = = " -p " | | I - > get ( ) = = " --project-manager " ) { // starts project manager
project_manager = true ;
2021-08-29 01:58:15 +02:00
} else if ( I - > get ( ) = = " --debug-server " ) {
if ( I - > next ( ) ) {
debug_server_uri = I - > next ( ) - > get ( ) ;
if ( debug_server_uri . find ( " :// " ) = = - 1 ) { // wrong address
OS : : get_singleton ( ) - > print ( " Invalid debug server uri. It should be of the form <protocol>://<bind_address>:<port>. \n " ) ;
goto error ;
}
N = I - > next ( ) - > next ( ) ;
} else {
OS : : get_singleton ( ) - > print ( " Missing remote debug server uri, aborting. \n " ) ;
goto error ;
}
2018-02-14 10:23:04 -05:00
} else if ( I - > get ( ) = = " --build-solutions " ) { // Build the scripting solution such C#
auto_build_solutions = true ;
2018-06-15 17:08:59 -05:00
editor = true ;
2021-06-16 19:08:29 +02:00
cmdline_tool = true ;
2021-10-20 12:04:59 +02:00
# ifdef DEBUG_METHODS_ENABLED
2021-01-12 14:12:40 -03:00
} else if ( I - > get ( ) = = " --gdnative-generate-json-api " | | I - > get ( ) = = " --gdnative-generate-json-builtin-api " ) {
2020-02-13 10:08:52 +01:00
// Register as an editor instance to use low-end fallback if relevant.
2019-08-19 16:14:58 +02:00
editor = true ;
2021-06-16 19:08:29 +02:00
cmdline_tool = true ;
2021-10-20 12:04:59 +02:00
// We still pass it to the main arguments since the argument handling itself is not done in this function,
// it's done in nativescript init code.
2019-08-19 16:14:58 +02:00
main_args . push_back ( I - > get ( ) ) ;
2021-10-20 12:04:59 +02:00
# endif
2021-06-19 12:58:49 -03:00
} else if ( I - > get ( ) = = " --dump-extension-api " ) {
// Register as an editor instance to use low-end fallback if relevant.
editor = true ;
cmdline_tool = true ;
dump_extension_api = true ;
2021-10-20 12:04:59 +02:00
print_line ( " Dumping Extension API " ) ;
2021-10-21 09:43:39 +02:00
// Hack. Not needed but otherwise we end up detecting that this should
// run the project instead of a cmdline tool.
// Needs full refactoring to fix properly.
main_args . push_back ( I - > get ( ) ) ;
2020-07-20 17:35:34 +01:00
} else if ( I - > get ( ) = = " --export " | | I - > get ( ) = = " --export-debug " | |
2021-10-28 15:19:35 +02:00
I - > get ( ) = = " --export-pack " ) { // Export project
2021-06-16 19:08:29 +02:00
// Actually handling is done in start().
2019-06-28 15:34:09 +03:00
editor = true ;
2021-06-16 19:08:29 +02:00
cmdline_tool = true ;
main_args . push_back ( I - > get ( ) ) ;
} else if ( I - > get ( ) = = " --doctool " ) {
// Actually handling is done in start().
cmdline_tool = true ;
2019-06-28 15:34:09 +03:00
main_args . push_back ( I - > get ( ) ) ;
2018-02-16 19:40:22 +01:00
# endif
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --path " ) { // set path of project to start or edit
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
String p = I - > next ( ) - > get ( ) ;
2017-03-05 16:44:50 +01:00
if ( OS : : get_singleton ( ) - > set_cwd ( p ) = = OK ) {
2014-02-09 22:10:30 -03:00
//nothing
} else {
2018-05-12 13:21:26 +02:00
project_path = I - > next ( ) - > get ( ) ; //use project_path instead
2014-02-09 22:10:30 -03:00
}
2017-03-05 16:44:50 +01:00
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing relative or absolute path, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2017-10-10 23:45:54 +11:00
} else if ( I - > get ( ) = = " -u " | | I - > get ( ) = = " --upwards " ) { // scan folders upwards
upwards = true ;
2018-02-24 18:22:29 +01:00
} else if ( I - > get ( ) = = " -q " | | I - > get ( ) = = " --quit " ) { // Auto quit at the end of the first main loop iteration
2018-02-14 10:23:04 -05:00
auto_quit = true ;
2017-05-01 17:44:52 +02:00
} else if ( I - > get ( ) . ends_with ( " project.godot " ) ) {
String path ;
String file = I - > get ( ) ;
2020-07-03 15:26:22 +02:00
int sep = MAX ( file . rfind ( " / " ) , file . rfind ( " \\ " ) ) ;
2020-05-14 16:41:43 +02:00
if ( sep = = - 1 ) {
2017-05-01 17:44:52 +02:00
path = " . " ;
2020-05-14 16:41:43 +02:00
} else {
2017-05-01 17:44:52 +02:00
path = file . substr ( 0 , sep ) ;
}
if ( OS : : get_singleton ( ) - > set_cwd ( path ) = = OK ) {
// path already specified, don't override
} else {
2018-05-12 13:21:26 +02:00
project_path = path ;
2017-05-01 17:44:52 +02:00
}
# ifdef TOOLS_ENABLED
editor = true ;
# endif
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " -b " | | I - > get ( ) = = " --breakpoints " ) { // add breakpoints
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
String bplist = I - > next ( ) - > get ( ) ;
2017-03-05 16:44:50 +01:00
breakpoints = bplist . split ( " , " ) ;
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing list of breakpoints, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --frame-delay " ) { // force frame delay
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
2017-03-05 16:44:50 +01:00
frame_delay = I - > next ( ) - > get ( ) . to_int ( ) ;
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing frame delay argument, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
}
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --time-scale " ) { // force time scale
2014-09-21 01:43:42 -03:00
if ( I - > next ( ) ) {
2020-07-24 14:07:57 -04:00
Engine : : get_singleton ( ) - > set_time_scale ( I - > next ( ) - > get ( ) . to_float ( ) ) ;
2017-03-05 16:44:50 +01:00
N = I - > next ( ) - > next ( ) ;
2014-09-21 01:43:42 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing time scale argument, aborting. \n " ) ;
2014-09-21 01:43:42 -03:00
goto error ;
}
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --main-pack " ) {
2014-06-27 23:21:45 -03:00
if ( I - > next ( ) ) {
2017-03-05 16:44:50 +01:00
main_pack = I - > next ( ) - > get ( ) ;
2014-06-27 23:21:45 -03:00
N = I - > next ( ) - > next ( ) ;
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing path to main pack file, aborting. \n " ) ;
2014-06-27 23:21:45 -03:00
goto error ;
} ;
2017-08-19 16:45:03 +02:00
} else if ( I - > get ( ) = = " -d " | | I - > get ( ) = = " --debug " ) {
2020-02-27 03:30:20 +01:00
debug_uri = " local:// " ;
2020-07-09 09:32:42 +02:00
OS : : get_singleton ( ) - > _debug_stdout = true ;
2021-07-20 17:01:18 -03:00
# if defined(DEBUG_ENABLED)
2017-08-19 16:45:03 +02:00
} else if ( I - > get ( ) = = " --debug-collisions " ) {
2017-03-05 16:44:50 +01:00
debug_collisions = true ;
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --debug-navigation " ) {
2017-03-05 16:44:50 +01:00
debug_navigation = true ;
2021-07-20 17:01:18 -03:00
} else if ( I - > get ( ) = = " --debug-stringnames " ) {
StringName : : set_debug_stringnames ( true ) ;
2017-04-07 16:17:16 +02:00
# endif
2017-06-21 11:09:30 +02:00
} else if ( I - > get ( ) = = " --remote-debug " ) {
2014-02-09 22:10:30 -03:00
if ( I - > next ( ) ) {
2020-02-27 03:30:20 +01:00
debug_uri = I - > next ( ) - > get ( ) ;
2020-03-16 09:37:43 +01:00
if ( debug_uri . find ( " :// " ) = = - 1 ) { // wrong address
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > print (
" Invalid debug host address, it should be of the form <protocol>://<host/IP>:<port>. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
2015-09-10 00:10:54 -03:00
}
2017-03-05 16:44:50 +01:00
N = I - > next ( ) - > next ( ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing remote debug host address, aborting. \n " ) ;
2014-02-09 22:10:30 -03:00
goto error ;
2016-09-14 04:02:18 +02:00
}
2017-08-19 16:45:03 +02:00
} else if ( I - > get ( ) = = " --allow_focus_steal_pid " ) { // not exposed to user
2016-09-14 04:02:18 +02:00
if ( I - > next ( ) ) {
2020-05-13 05:31:51 -04:00
allow_focus_steal_pid = I - > next ( ) - > get ( ) . to_int ( ) ;
2017-03-05 16:44:50 +01:00
N = I - > next ( ) - > next ( ) ;
2016-09-14 04:02:18 +02:00
} else {
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Missing editor PID argument, aborting. \n " ) ;
2016-09-14 04:02:18 +02:00
goto error ;
2014-02-09 22:10:30 -03:00
}
2017-08-30 12:40:35 +02:00
} else if ( I - > get ( ) = = " --disable-render-loop " ) {
disable_render_loop = true ;
} else if ( I - > get ( ) = = " --fixed-fps " ) {
if ( I - > next ( ) ) {
fixed_fps = I - > next ( ) - > get ( ) . to_int ( ) ;
N = I - > next ( ) - > next ( ) ;
} else {
OS : : get_singleton ( ) - > print ( " Missing fixed-fps argument, aborting. \n " ) ;
goto error ;
}
2018-03-21 08:46:05 +01:00
} else if ( I - > get ( ) = = " --print-fps " ) {
print_fps = true ;
2021-01-22 20:50:24 -03:00
} else if ( I - > get ( ) = = " --profile-gpu " ) {
profile_gpu = true ;
2017-09-07 22:01:49 -03:00
} else if ( I - > get ( ) = = " --disable-crash-handler " ) {
OS : : get_singleton ( ) - > disable_crash_handler ( ) ;
2019-07-29 20:09:22 +02:00
} else if ( I - > get ( ) = = " --skip-breakpoints " ) {
skip_breakpoints = true ;
2014-02-09 22:10:30 -03:00
} else {
2018-05-12 12:51:41 +02:00
main_args . push_back ( I - > get ( ) ) ;
2014-02-09 22:10:30 -03:00
}
2016-03-09 00:00:52 +01:00
2017-03-05 16:44:50 +01:00
I = N ;
2014-02-09 22:10:30 -03:00
}
2020-01-10 09:48:03 +01:00
# ifdef TOOLS_ENABLED
if ( editor & & project_manager ) {
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > print (
" Error: Command line arguments implied opening both editor and project manager, which is not possible. Aborting. \n " ) ;
2020-01-10 09:48:03 +01:00
goto error ;
}
# endif
2018-11-08 15:42:41 -02:00
// Network file system needs to be configured before globals, since globals are based on the
// 'project.godot' file which will only be available through the network if this is enabled
FileAccessNetwork : : configure ( ) ;
2021-12-09 03:42:46 -06:00
if ( ! remotefs . is_empty ( ) ) {
2018-11-08 15:42:41 -02:00
file_access_network_client = memnew ( FileAccessNetworkClient ) ;
int port ;
if ( remotefs . find ( " : " ) ! = - 1 ) {
port = remotefs . get_slicec ( ' : ' , 1 ) . to_int ( ) ;
remotefs = remotefs . get_slicec ( ' : ' , 0 ) ;
} else {
port = 6010 ;
}
Error err = file_access_network_client - > connect ( remotefs , port , remotefs_pass ) ;
if ( err ) {
OS : : get_singleton ( ) - > printerr ( " Could not connect to remotefs: %s:%i. \n " , remotefs . utf8 ( ) . get_data ( ) , port ) ;
goto error ;
}
FileAccess : : make_default < FileAccessNetwork > ( FileAccess : : ACCESS_RESOURCES ) ;
}
2021-11-22 16:10:31 +01:00
if ( globals - > setup ( project_path , main_pack , upwards , editor ) = = OK ) {
2019-02-18 20:28:40 +01:00
# ifdef TOOLS_ENABLED
2018-03-15 12:22:10 +01:00
found_project = true ;
2019-02-18 20:28:40 +01:00
# endif
2018-03-15 12:22:10 +01:00
} else {
# ifdef TOOLS_ENABLED
editor = false ;
# else
2020-01-28 00:10:31 +01:00
const String error_msg = " Error: Couldn't load project data at path \" " + project_path + " \" . Is the .pck file missing? \n If you've renamed the executable, the associated .pck file should also be renamed to match the executable's name (without the extension). \n " ;
2021-09-01 16:19:25 +02:00
OS : : get_singleton ( ) - > print ( " %s " , error_msg . utf8 ( ) . get_data ( ) ) ;
2021-07-22 19:23:48 +03:00
OS : : get_singleton ( ) - > alert ( error_msg ) ;
2018-03-15 12:22:10 +01:00
goto error ;
# endif
}
2020-06-15 14:32:46 +02:00
// Initialize user data dir.
OS : : get_singleton ( ) - > ensure_user_data_dir ( ) ;
2021-07-23 16:01:18 -03:00
ResourceUID : : get_singleton ( ) - > load_from_cache ( ) ; // load UUIDs from cache.
2017-07-17 21:05:38 -03:00
GLOBAL_DEF ( " memory/limits/multithreaded_server/rid_pool_prealloc " , 60 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " memory/limits/multithreaded_server/rid_pool_prealloc " ,
PropertyInfo ( Variant : : INT ,
" memory/limits/multithreaded_server/rid_pool_prealloc " ,
PROPERTY_HINT_RANGE ,
" 0,500,1 " ) ) ; // No negative and limit to 500 due to crashes
2020-02-27 03:30:20 +01:00
GLOBAL_DEF ( " network/limits/debugger/max_chars_per_second " , 32768 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " network/limits/debugger/max_chars_per_second " ,
PropertyInfo ( Variant : : INT ,
" network/limits/debugger/max_chars_per_second " ,
PROPERTY_HINT_RANGE ,
" 0, 4096, 1, or_greater " ) ) ;
2020-02-27 03:30:20 +01:00
GLOBAL_DEF ( " network/limits/debugger/max_queued_messages " , 2048 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " network/limits/debugger/max_queued_messages " ,
PropertyInfo ( Variant : : INT ,
" network/limits/debugger/max_queued_messages " ,
PROPERTY_HINT_RANGE ,
" 0, 8192, 1, or_greater " ) ) ;
2020-02-27 03:30:20 +01:00
GLOBAL_DEF ( " network/limits/debugger/max_errors_per_second " , 400 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " network/limits/debugger/max_errors_per_second " ,
PropertyInfo ( Variant : : INT ,
" network/limits/debugger/max_errors_per_second " ,
PROPERTY_HINT_RANGE ,
" 0, 200, 1, or_greater " ) ) ;
2020-02-27 03:30:20 +01:00
GLOBAL_DEF ( " network/limits/debugger/max_warnings_per_second " , 400 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " network/limits/debugger/max_warnings_per_second " ,
PropertyInfo ( Variant : : INT ,
" network/limits/debugger/max_warnings_per_second " ,
PROPERTY_HINT_RANGE ,
" 0, 200, 1, or_greater " ) ) ;
2014-02-09 22:10:30 -03:00
2020-02-27 03:30:20 +01:00
EngineDebugger : : initialize ( debug_uri , skip_breakpoints , breakpoints ) ;
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
if ( editor ) {
packed_data - > set_disabled ( true ) ;
2017-07-19 17:00:46 -03:00
globals - > set_disable_feature_overrides ( true ) ;
2014-02-09 22:10:30 -03:00
}
# endif
2018-02-19 13:31:06 +01:00
# ifdef TOOLS_ENABLED
2014-02-09 22:10:30 -03:00
if ( editor ) {
2017-08-13 16:21:45 +02:00
Engine : : get_singleton ( ) - > set_editor_hint ( true ) ;
2017-06-21 11:09:30 +02:00
main_args . push_back ( " --editor " ) ;
2017-12-29 20:10:15 +01:00
if ( ! init_windowed ) {
init_maximized = true ;
2020-03-03 10:36:29 -03:00
window_mode = DisplayServer : : WINDOW_MODE_MAXIMIZED ;
2017-12-29 20:10:15 +01:00
}
2014-02-09 22:10:30 -03:00
}
2020-01-10 09:48:03 +01:00
if ( ! project_manager & & ! editor ) {
2021-06-16 19:08:29 +02:00
// If we didn't find a project, we fall back to the project manager.
project_manager = ! found_project & & ! cmdline_tool ;
2018-02-13 18:56:38 +01:00
}
2014-02-09 22:10:30 -03:00
# endif
2021-02-17 13:44:49 -03:00
GLOBAL_DEF ( " debug/file_logging/enable_file_logging " , false ) ;
2020-07-12 14:22:06 +02:00
// Only file logging by default on desktop platforms as logs can't be
// accessed easily on mobile/Web platforms (if at all).
// This also prevents logs from being created for the editor instance, as feature tags
// are disabled while in the editor (even if they should logically apply).
2021-02-17 13:44:49 -03:00
GLOBAL_DEF ( " debug/file_logging/enable_file_logging.pc " , true ) ;
GLOBAL_DEF ( " debug/file_logging/log_path " , " user://logs/godot.log " ) ;
GLOBAL_DEF ( " debug/file_logging/max_log_files " , 5 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " debug/file_logging/max_log_files " ,
2020-07-20 17:35:34 +01:00
PropertyInfo ( Variant : : INT ,
2021-02-17 13:44:49 -03:00
" debug/file_logging/max_log_files " ,
2020-07-20 17:35:34 +01:00
PROPERTY_HINT_RANGE ,
" 0,20,1,or_greater " ) ) ; //no negative numbers
if ( ! project_manager & & ! editor & & FileAccess : : get_create_func ( FileAccess : : ACCESS_USERDATA ) & &
2021-02-17 13:44:49 -03:00
GLOBAL_GET ( " debug/file_logging/enable_file_logging " ) ) {
2020-07-12 14:22:06 +02:00
// Don't create logs for the project manager as they would be written to
// the current working directory, which is inconvenient.
2021-02-17 13:44:49 -03:00
String base_path = GLOBAL_GET ( " debug/file_logging/log_path " ) ;
int max_files = GLOBAL_GET ( " debug/file_logging/max_log_files " ) ;
2020-07-12 14:22:06 +02:00
OS : : get_singleton ( ) - > add_logger ( memnew ( RotatedFileLogger ( base_path , max_files ) ) ) ;
}
2021-02-17 13:44:49 -03:00
if ( main_args . size ( ) = = 0 & & String ( GLOBAL_GET ( " application/run/main_scene " ) ) = = " " ) {
2018-02-26 17:16:29 +01:00
# ifdef TOOLS_ENABLED
if ( ! editor & & ! project_manager ) {
# endif
2021-09-01 16:19:25 +02:00
const String error_msg = " Error: Can't run project: no main scene defined in the project. \n " ;
OS : : get_singleton ( ) - > print ( " %s " , error_msg . utf8 ( ) . get_data ( ) ) ;
OS : : get_singleton ( ) - > alert ( error_msg ) ;
2018-02-26 17:16:29 +01:00
goto error ;
# ifdef TOOLS_ENABLED
}
# endif
}
2018-02-19 13:31:06 +01:00
if ( editor | | project_manager ) {
2019-03-09 01:04:53 +01:00
Engine : : get_singleton ( ) - > set_editor_hint ( true ) ;
2018-02-19 13:31:06 +01:00
use_custom_res = false ;
2016-06-05 01:19:42 -03:00
input_map - > load_default ( ) ; //keys for editor
2018-02-19 13:31:06 +01:00
} else {
2020-10-02 17:04:09 +10:00
input_map - > load_from_project_settings ( ) ; //keys for game
2018-02-19 13:31:06 +01:00
}
if ( bool ( ProjectSettings : : get_singleton ( ) - > get ( " application/run/disable_stdout " ) ) ) {
quiet_stdout = true ;
}
if ( bool ( ProjectSettings : : get_singleton ( ) - > get ( " application/run/disable_stderr " ) ) ) {
_print_error_enabled = false ;
} ;
2020-05-14 16:41:43 +02:00
if ( quiet_stdout ) {
2018-02-19 13:31:06 +01:00
_print_line_enabled = false ;
2020-05-14 16:41:43 +02:00
}
2018-02-19 13:31:06 +01:00
2021-02-28 19:26:14 -03:00
Logger : : set_flush_stdout_on_print ( ProjectSettings : : get_singleton ( ) - > get ( " application/run/flush_stdout_on_print " ) ) ;
2018-02-19 13:31:06 +01:00
OS : : get_singleton ( ) - > set_cmdline ( execpath , main_args ) ;
2014-02-09 22:10:30 -03:00
2021-06-19 12:58:49 -03:00
register_core_extensions ( ) ; //before display
2020-11-18 18:11:30 +00:00
// possibly be worth changing the default from vulkan to something lower spec,
// for the project manager, depending on how smooth the fallback is.
2021-11-01 22:04:36 +01:00
GLOBAL_DEF_RST ( " rendering/driver/driver_name " , " vulkan " ) ;
2020-11-18 18:11:30 +00:00
// this list is hard coded, which makes it more difficult to add new backends.
// can potentially be changed to more of a plugin system at a later date.
2021-02-17 13:44:49 -03:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/driver/driver_name " ,
2020-07-20 17:35:34 +01:00
PropertyInfo ( Variant : : STRING ,
2021-02-17 13:44:49 -03:00
" rendering/driver/driver_name " ,
2021-11-01 22:04:36 +01:00
PROPERTY_HINT_ENUM , " vulkan,opengl3 " ) ) ;
2020-11-18 18:11:30 +00:00
// if not set on the command line
2021-12-09 03:42:46 -06:00
if ( rendering_driver . is_empty ( ) ) {
2020-11-18 18:11:30 +00:00
rendering_driver = GLOBAL_GET ( " rendering/driver/driver_name " ) ;
}
// 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 ) ;
2021-09-27 01:07:10 +02:00
// always convert to lower case for consistency in the code
rendering_driver = rendering_driver . to_lower ( ) ;
2014-02-09 22:10:30 -03:00
2021-03-31 12:50:24 +01:00
GLOBAL_DEF_BASIC ( " display/window/size/viewport_width " , 1024 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/viewport_width " ,
PropertyInfo ( Variant : : INT , " display/window/size/viewport_width " ,
2020-07-20 17:35:34 +01:00
PROPERTY_HINT_RANGE ,
" 0,7680,or_greater " ) ) ; // 8K resolution
2022-02-01 00:19:01 +01:00
2021-03-31 12:50:24 +01:00
GLOBAL_DEF_BASIC ( " display/window/size/viewport_height " , 600 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/viewport_height " ,
PropertyInfo ( Variant : : INT , " display/window/size/viewport_height " ,
2020-07-20 17:35:34 +01:00
PROPERTY_HINT_RANGE ,
2022-02-01 00:19:01 +01:00
" 0,4320,1,or_greater " ) ) ; // 8K resolution
2021-02-17 13:44:49 -03:00
GLOBAL_DEF_BASIC ( " display/window/size/resizable " , true ) ;
GLOBAL_DEF_BASIC ( " display/window/size/borderless " , false ) ;
GLOBAL_DEF_BASIC ( " display/window/size/fullscreen " , false ) ;
2017-12-27 20:51:19 +01:00
GLOBAL_DEF ( " display/window/size/always_on_top " , false ) ;
2021-03-31 12:50:24 +01:00
GLOBAL_DEF ( " display/window/size/window_width_override " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/window_width_override " ,
2020-07-20 17:35:34 +01:00
PropertyInfo ( Variant : : INT ,
2021-03-31 12:50:24 +01:00
" display/window/size/window_width_override " ,
2020-07-20 17:35:34 +01:00
PROPERTY_HINT_RANGE ,
2022-02-01 00:19:01 +01:00
" 0,7680,1,or_greater " ) ) ; // 8K resolution
2021-03-31 12:50:24 +01:00
GLOBAL_DEF ( " display/window/size/window_height_override " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/window_height_override " ,
2020-07-20 17:35:34 +01:00
PropertyInfo ( Variant : : INT ,
2021-03-31 12:50:24 +01:00
" display/window/size/window_height_override " ,
2020-07-20 17:35:34 +01:00
PROPERTY_HINT_RANGE ,
" 0,4320,or_greater " ) ) ; // 8K resolution
2017-11-09 13:55:51 -03:00
2017-11-09 13:01:29 -03:00
if ( use_custom_res ) {
if ( ! force_res ) {
2021-03-31 12:50:24 +01:00
window_size . width = GLOBAL_GET ( " display/window/size/viewport_width " ) ;
window_size . height = GLOBAL_GET ( " display/window/size/viewport_height " ) ;
if ( globals - > has_setting ( " display/window/size/window_width_override " ) & &
globals - > has_setting ( " display/window/size/window_height_override " ) ) {
int desired_width = globals - > get ( " display/window/size/window_width_override " ) ;
if ( desired_width > 0 ) {
window_size . width = desired_width ;
2019-10-04 10:26:02 -03:00
}
2021-03-31 12:50:24 +01:00
int desired_height = globals - > get ( " display/window/size/window_height_override " ) ;
if ( desired_height > 0 ) {
window_size . height = desired_height ;
2017-11-09 13:01:29 -03:00
}
}
2014-09-15 11:33:30 -03:00
}
2017-11-09 13:01:29 -03:00
2020-03-03 10:36:29 -03:00
if ( ! bool ( GLOBAL_GET ( " display/window/size/resizable " ) ) ) {
window_flags | = DisplayServer : : WINDOW_FLAG_RESIZE_DISABLED_BIT ;
}
if ( bool ( GLOBAL_GET ( " display/window/size/borderless " ) ) ) {
window_flags | = DisplayServer : : WINDOW_FLAG_BORDERLESS_BIT ;
}
if ( bool ( GLOBAL_GET ( " display/window/size/fullscreen " ) ) ) {
window_mode = DisplayServer : : WINDOW_MODE_FULLSCREEN ;
}
if ( bool ( GLOBAL_GET ( " display/window/size/always_on_top " ) ) ) {
2020-08-15 17:53:06 +03:00
window_flags | = DisplayServer : : WINDOW_FLAG_ALWAYS_ON_TOP_BIT ;
2020-03-03 10:36:29 -03:00
}
2014-09-15 11:33:30 -03:00
}
2014-02-09 22:10:30 -03:00
2021-02-17 13:44:49 -03:00
GLOBAL_DEF ( " internationalization/rendering/force_right_to_left_layout_direction " , false ) ;
2021-04-22 15:08:59 +03:00
GLOBAL_DEF ( " internationalization/locale/include_text_server_data " , false ) ;
2020-09-03 14:22:16 +03:00
2021-12-29 02:21:06 +01:00
OS : : get_singleton ( ) - > _allow_hidpi = GLOBAL_DEF ( " display/window/dpi/allow_hidpi " , true ) ;
2017-11-09 13:01:29 -03:00
2021-10-28 15:43:36 +02:00
// 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
2018-02-13 18:56:38 +01:00
if ( editor | | project_manager ) {
// The editor and project manager always detect and use hiDPI if needed
OS : : get_singleton ( ) - > _allow_hidpi = true ;
2017-12-10 20:38:26 +02:00
OS : : get_singleton ( ) - > _allow_layered = false ;
2017-10-05 16:41:42 -03:00
}
2018-02-13 18:56:38 +01:00
2017-07-17 21:05:38 -03:00
OS : : get_singleton ( ) - > _keep_screen_on = GLOBAL_DEF ( " display/window/energy_saving/keep_screen_on " , true ) ;
2017-03-05 16:44:50 +01:00
if ( rtm = = - 1 ) {
2021-02-17 13:44:49 -03:00
rtm = GLOBAL_DEF ( " rendering/driver/threads/thread_model " , OS : : RENDER_THREAD_SAFE ) ;
2014-02-09 22:10:30 -03:00
}
2017-03-05 16:44:50 +01:00
if ( rtm > = 0 & & rtm < 3 ) {
2020-09-23 11:24:01 +02:00
# ifdef NO_THREADS
rtm = OS : : RENDER_THREAD_UNSAFE ; // No threads available on this platform.
# else
2015-12-31 16:24:27 -03:00
if ( editor ) {
2017-03-05 16:44:50 +01:00
rtm = OS : : RENDER_THREAD_SAFE ;
2015-12-31 16:24:27 -03:00
}
2020-09-23 11:24:01 +02:00
# endif
2017-03-05 16:44:50 +01:00
OS : : get_singleton ( ) - > _render_thread_mode = OS : : RenderThreadMode ( rtm ) ;
2015-12-31 16:24:27 -03:00
}
2014-02-09 22:10:30 -03:00
2017-08-19 16:45:03 +02:00
/* Determine audio and video drivers */
2016-03-09 00:00:52 +01:00
2020-11-18 18:11:30 +00:00
// Display driver, e.g. X11, Wayland.
// print_line("requested display driver : " + display_driver);
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < DisplayServer : : get_create_function_count ( ) ; i + + ) {
2020-11-18 18:11:30 +00:00
String name = DisplayServer : : get_create_function_name ( i ) ;
// print_line("\t" + itos(i) + " : " + name);
if ( display_driver = = name ) {
2020-03-03 10:36:29 -03:00
display_driver_idx = i ;
2014-02-09 22:10:30 -03:00
break ;
}
}
2020-03-03 10:36:29 -03:00
if ( display_driver_idx < 0 ) {
display_driver_idx = 0 ;
2014-02-09 22:10:30 -03:00
}
2020-11-18 18:11:30 +00:00
// Store this in a globally accessible place, so we can retrieve the rendering drivers
// list from the display driver for the editor UI.
OS : : get_singleton ( ) - > set_display_driver_id ( display_driver_idx ) ;
2021-10-20 16:37:19 +02:00
GLOBAL_DEF_RST_NOVAL ( " audio/driver/driver " , AudioDriverManager : : get_driver ( 0 ) - > get_name ( ) ) ;
2021-12-09 03:42:46 -06:00
if ( audio_driver . is_empty ( ) ) { // Specified in project.godot.
2021-10-20 16:37:19 +02:00
audio_driver = GLOBAL_GET ( " audio/driver/driver " ) ;
2017-08-19 16:45:03 +02:00
}
2020-03-03 10:36:29 -03:00
for ( int i = 0 ; i < AudioDriverManager : : get_driver_count ( ) ; i + + ) {
if ( audio_driver = = AudioDriverManager : : get_driver ( i ) - > get_name ( ) ) {
2017-03-05 16:44:50 +01:00
audio_driver_idx = i ;
2014-02-09 22:10:30 -03:00
break ;
}
}
2017-03-05 16:44:50 +01:00
if ( audio_driver_idx < 0 ) {
2016-01-31 18:47:13 -03:00
audio_driver_idx = 0 ;
2014-02-09 22:10:30 -03:00
}
{
2021-05-21 21:29:24 +02:00
window_orientation = DisplayServer : : ScreenOrientation ( int ( GLOBAL_DEF_BASIC ( " display/window/handheld/orientation " , DisplayServer : : ScreenOrientation : : SCREEN_LANDSCAPE ) ) ) ;
2014-02-09 22:10:30 -03:00
}
2021-06-19 17:44:59 +02:00
{
2021-07-12 03:35:51 +02:00
window_vsync_mode = DisplayServer : : VSyncMode ( int ( GLOBAL_DEF ( " display/window/vsync/vsync_mode " , DisplayServer : : VSyncMode : : VSYNC_ENABLED ) ) ) ;
2021-06-19 17:44:59 +02:00
}
2021-08-11 02:35:16 +02:00
Engine : : get_singleton ( ) - > set_physics_ticks_per_second ( GLOBAL_DEF_BASIC ( " physics/common/physics_ticks_per_second " , 60 ) ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " physics/common/physics_ticks_per_second " ,
PropertyInfo ( Variant : : INT , " physics/common/physics_ticks_per_second " ,
2021-06-08 19:52:48 +02:00
PROPERTY_HINT_RANGE , " 1,1000,1 " ) ) ;
2018-02-11 00:03:31 +01:00
Engine : : get_singleton ( ) - > set_physics_jitter_fix ( GLOBAL_DEF ( " physics/common/physics_jitter_fix " , 0.5 ) ) ;
2017-07-17 21:05:38 -03:00
Engine : : get_singleton ( ) - > set_target_fps ( GLOBAL_DEF ( " debug/settings/fps/force_fps " , 0 ) ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " debug/settings/fps/force_fps " ,
PropertyInfo ( Variant : : INT ,
" debug/settings/fps/force_fps " ,
2021-06-08 19:52:48 +02:00
PROPERTY_HINT_RANGE , " 0,1000,1 " ) ) ;
2017-01-05 09:16:00 -03:00
2018-03-21 08:46:05 +01:00
GLOBAL_DEF ( " debug/settings/stdout/print_fps " , false ) ;
2021-08-10 21:50:28 -03:00
GLOBAL_DEF ( " debug/settings/stdout/print_gpu_profile " , false ) ;
2020-04-20 12:29:34 +02:00
GLOBAL_DEF ( " debug/settings/stdout/verbose_stdout " , false ) ;
2014-02-09 22:10:30 -03:00
2020-04-20 12:29:34 +02:00
if ( ! OS : : get_singleton ( ) - > _verbose_stdout ) { // Not manually overridden.
OS : : get_singleton ( ) - > _verbose_stdout = GLOBAL_GET ( " debug/settings/stdout/verbose_stdout " ) ;
}
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
if ( frame_delay = = 0 ) {
2017-07-17 21:05:38 -03:00
frame_delay = GLOBAL_DEF ( " application/run/frame_delay_msec " , 0 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/run/frame_delay_msec " ,
PropertyInfo ( Variant : : INT ,
" application/run/frame_delay_msec " ,
PROPERTY_HINT_RANGE ,
" 0,100,1,or_greater " ) ) ; // No negative numbers
2016-07-09 12:34:30 -03:00
}
2017-11-22 14:40:43 -03:00
OS : : get_singleton ( ) - > set_low_processor_usage_mode ( GLOBAL_DEF ( " application/run/low_processor_mode " , false ) ) ;
2020-07-20 17:35:34 +01:00
OS : : get_singleton ( ) - > set_low_processor_usage_mode_sleep_usec (
GLOBAL_DEF ( " application/run/low_processor_mode_sleep_usec " , 6900 ) ) ; // Roughly 144 FPS
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/run/low_processor_mode_sleep_usec " ,
PropertyInfo ( Variant : : INT ,
" application/run/low_processor_mode_sleep_usec " ,
PROPERTY_HINT_RANGE ,
" 0,33200,1,or_greater " ) ) ; // No negative numbers
2017-11-22 14:40:43 -03:00
2019-12-09 20:38:22 +01:00
GLOBAL_DEF ( " display/window/ios/hide_home_indicator " , true ) ;
2020-09-28 22:24:35 +03:00
GLOBAL_DEF ( " input_devices/pointing/ios/touch_delay " , 0.150 ) ;
2019-12-09 20:38:22 +01:00
2017-01-13 12:51:14 -03:00
Engine : : get_singleton ( ) - > set_frame_delay ( frame_delay ) ;
2016-07-09 12:34:30 -03:00
2017-03-05 16:44:50 +01:00
message_queue = memnew ( MessageQueue ) ;
2014-02-09 22:10:30 -03:00
2020-05-14 16:41:43 +02:00
if ( p_second_phase ) {
2014-02-09 22:10:30 -03:00
return setup2 ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
return OK ;
2017-03-05 16:44:50 +01:00
error :
2016-03-09 00:00:52 +01:00
2020-08-05 09:25:28 +03:00
text_driver = " " ;
2020-03-03 10:36:29 -03:00
display_driver = " " ;
2017-03-05 16:44:50 +01:00
audio_driver = " " ;
2020-05-19 23:34:26 +03:00
tablet_driver = " " ;
2018-05-12 13:21:26 +02:00
project_path = " " ;
2016-03-09 00:00:52 +01:00
args . clear ( ) ;
2014-02-09 22:10:30 -03:00
main_args . clear ( ) ;
2016-03-09 00:00:52 +01:00
2020-05-14 16:41:43 +02:00
if ( show_help ) {
2017-08-19 16:45:03 +02:00
print_help ( execpath ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
2020-02-27 03:30:20 +01:00
EngineDebugger : : deinitialize ( ) ;
2020-05-14 16:41:43 +02:00
if ( performance ) {
2014-02-09 22:10:30 -03:00
memdelete ( performance ) ;
2020-05-14 16:41:43 +02:00
}
if ( input_map ) {
2014-02-09 22:10:30 -03:00
memdelete ( input_map ) ;
2020-05-14 16:41:43 +02:00
}
2021-05-24 07:54:05 -04:00
if ( time_singleton ) {
memdelete ( time_singleton ) ;
}
2020-05-14 16:41:43 +02:00
if ( translation_server ) {
2017-03-05 16:44:50 +01:00
memdelete ( translation_server ) ;
2020-05-14 16:41:43 +02:00
}
if ( globals ) {
2014-02-09 22:10:30 -03:00
memdelete ( globals ) ;
2020-05-14 16:41:43 +02:00
}
if ( engine ) {
2017-01-13 12:51:14 -03:00
memdelete ( engine ) ;
2020-05-14 16:41:43 +02:00
}
if ( packed_data ) {
2014-02-09 22:10:30 -03:00
memdelete ( packed_data ) ;
2020-05-14 16:41:43 +02:00
}
if ( file_access_network_client ) {
2014-02-09 22:10:30 -03:00
memdelete ( file_access_network_client ) ;
2020-05-14 16:41:43 +02:00
}
2015-04-20 19:38:02 -03:00
2015-10-30 19:56:07 +08:00
unregister_core_driver_types ( ) ;
2014-02-09 22:10:30 -03:00
unregister_core_types ( ) ;
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
OS : : get_singleton ( ) - > _cmdline . clear ( ) ;
2020-05-14 16:41:43 +02:00
if ( message_queue ) {
2017-03-05 16:44:50 +01:00
memdelete ( message_queue ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
OS : : get_singleton ( ) - > finalize_core ( ) ;
2017-03-05 16:44:50 +01:00
locale = String ( ) ;
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
return ERR_INVALID_PARAMETER ;
}
2017-08-22 17:21:41 +02:00
Error Main : : setup2 ( Thread : : ID p_main_tid_override ) {
2021-08-28 00:19:51 +03:00
tsman = memnew ( TextServerManager ) ;
2019-07-28 19:58:32 -03:00
preregister_module_types ( ) ;
2019-08-20 17:54:03 -03:00
preregister_server_types ( ) ;
2019-07-28 19:58:32 -03:00
2019-05-28 11:19:21 +02:00
// Print engine name and version
print_line ( String ( VERSION_NAME ) + " v " + get_full_version_string ( ) + " - " + String ( VERSION_WEBSITE ) ) ;
2021-01-19 13:29:41 +01:00
# if !defined(NO_THREADS)
2017-08-22 17:21:41 +02:00
if ( p_main_tid_override ) {
2021-01-19 13:29:41 +01:00
Thread : : main_thread_id = p_main_tid_override ;
2017-08-22 17:21:41 +02:00
}
2021-01-19 13:29:41 +01:00
# endif
2014-02-09 22:10:30 -03:00
2021-05-24 21:25:11 -03:00
# ifdef TOOLS_ENABLED
2021-06-16 19:08:29 +02:00
if ( editor | | project_manager | | cmdline_tool ) {
2021-06-09 10:47:32 +02:00
EditorPaths : : create ( ) ;
2021-05-24 21:25:11 -03:00
}
# endif
2020-03-03 10:36:29 -03:00
/* Initialize Input */
2020-04-28 15:19:37 +02:00
input = memnew ( Input ) ;
2020-03-03 10:36:29 -03:00
2021-03-12 19:05:16 +05:30
/* Initialize Display Server */
2020-03-03 10:36:29 -03:00
{
2020-11-18 18:11:30 +00:00
String display_driver = DisplayServer : : get_create_function_name ( display_driver_idx ) ;
2020-03-03 10:36:29 -03:00
2020-11-18 18:11:30 +00:00
// rendering_driver now held in static global String in main and initialized in setup()
2020-03-03 10:36:29 -03:00
Error err ;
2021-06-19 17:44:59 +02:00
display_server = DisplayServer : : create ( display_driver_idx , rendering_driver , window_mode , window_vsync_mode , window_flags , window_size , err ) ;
2020-08-05 09:25:28 +03:00
if ( err ! = OK | | display_server = = nullptr ) {
2020-03-03 10:36:29 -03:00
//ok i guess we can't use this display server, try other ones
for ( int i = 0 ; i < DisplayServer : : get_create_function_count ( ) ; i + + ) {
if ( i = = display_driver_idx ) {
continue ; //don't try the same twice
}
2021-06-19 17:44:59 +02:00
display_server = DisplayServer : : create ( i , rendering_driver , window_mode , window_vsync_mode , window_flags , window_size , err ) ;
2020-08-05 09:25:28 +03:00
if ( err = = OK & & display_server ! = nullptr ) {
2020-03-03 10:36:29 -03:00
break ;
}
}
}
2020-08-05 09:25:28 +03:00
if ( err ! = OK | | display_server = = nullptr ) {
2020-03-03 10:36:29 -03:00
ERR_PRINT ( " Unable to create DisplayServer, all display drivers failed. " ) ;
return err ;
}
}
if ( display_server - > has_feature ( DisplayServer : : FEATURE_ORIENTATION ) ) {
display_server - > screen_set_orientation ( window_orientation ) ;
2018-01-03 18:26:44 +01:00
}
2018-08-25 00:04:25 +02:00
2021-12-20 19:49:04 +01:00
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 ) {
case DisplayServer : : VSyncMode : : VSYNC_DISABLED :
print_line ( " Requested V-Sync mode: Disabled " ) ;
break ;
case DisplayServer : : VSyncMode : : VSYNC_ENABLED :
print_line ( " Requested V-Sync mode: Enabled - FPS will likely be capped to the monitor refresh rate. " ) ;
break ;
case DisplayServer : : VSyncMode : : VSYNC_ADAPTIVE :
print_line ( " Requested V-Sync mode: Adaptive " ) ;
break ;
case DisplayServer : : VSyncMode : : VSYNC_MAILBOX :
print_line ( " Requested V-Sync mode: Mailbox " ) ;
break ;
}
}
2021-03-12 19:05:16 +05:30
/* Initialize Pen Tablet Driver */
2021-02-17 16:07:56 +02:00
{
GLOBAL_DEF_RST_NOVAL ( " input_devices/pen_tablet/driver " , " " ) ;
2021-03-26 15:33:36 +01:00
GLOBAL_DEF_RST_NOVAL ( " input_devices/pen_tablet/driver.windows " , " " ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " input_devices/pen_tablet/driver.windows " , PropertyInfo ( Variant : : STRING , " input_devices/pen_tablet/driver.windows " , PROPERTY_HINT_ENUM , " wintab,winink " ) ) ;
2021-02-17 16:07:56 +02:00
}
2021-12-09 03:42:46 -06:00
if ( tablet_driver . is_empty ( ) ) { // specified in project.godot
2021-02-17 16:07:56 +02:00
tablet_driver = GLOBAL_GET ( " input_devices/pen_tablet/driver " ) ;
2021-12-09 03:42:46 -06:00
if ( tablet_driver . is_empty ( ) ) {
2021-02-17 16:07:56 +02:00
tablet_driver = DisplayServer : : get_singleton ( ) - > tablet_get_driver_name ( 0 ) ;
}
}
for ( int i = 0 ; i < DisplayServer : : get_singleton ( ) - > tablet_get_driver_count ( ) ; i + + ) {
if ( tablet_driver = = DisplayServer : : get_singleton ( ) - > tablet_get_driver_name ( i ) ) {
DisplayServer : : get_singleton ( ) - > tablet_set_current_driver ( DisplayServer : : get_singleton ( ) - > tablet_get_driver_name ( i ) ) ;
break ;
}
}
2021-12-09 03:42:46 -06:00
if ( DisplayServer : : get_singleton ( ) - > tablet_get_current_driver ( ) . is_empty ( ) ) {
2021-02-17 16:07:56 +02:00
DisplayServer : : get_singleton ( ) - > tablet_set_current_driver ( DisplayServer : : get_singleton ( ) - > tablet_get_driver_name ( 0 ) ) ;
}
print_verbose ( " Using \" " + tablet_driver + " \" pen tablet driver... " ) ;
2021-06-16 19:08:29 +02:00
/* Initialize Rendering Server */
2020-03-03 10:36:29 -03:00
2021-02-09 13:19:03 -03:00
rendering_server = memnew ( RenderingServerDefault ( OS : : get_singleton ( ) - > get_render_thread_mode ( ) = = OS : : RENDER_SEPARATE_THREAD ) ) ;
2020-03-03 10:36:29 -03:00
2020-03-27 15:21:27 -03:00
rendering_server - > init ( ) ;
2020-11-18 18:11:30 +00:00
//rendering_server->call_set_use_vsync(OS::get_singleton()->_use_vsync);
2020-06-14 18:06:48 +01:00
rendering_server - > set_render_loop_enabled ( ! disable_render_loop ) ;
2020-03-03 10:36:29 -03:00
2021-08-10 21:50:28 -03:00
if ( profile_gpu | | ( ! editor & & bool ( GLOBAL_GET ( " debug/settings/stdout/print_gpu_profile " ) ) ) ) {
2021-01-22 20:50:24 -03:00
rendering_server - > set_print_gpu_profile ( true ) ;
}
2021-07-31 16:23:26 +02:00
# ifdef UNIX_ENABLED
// Print warning after initializing the renderer but before initializing audio.
if ( OS : : get_singleton ( ) - > get_environment ( " USER " ) = = " root " & & ! OS : : get_singleton ( ) - > has_environment ( " GODOT_SILENCE_ROOT_WARNING " ) ) {
WARN_PRINT ( " Started the engine as `root`/superuser. This is a security risk, and subsystems like audio may not work correctly. \n Set the environment variable `GODOT_SILENCE_ROOT_WARNING` to 1 to silence this warning. " ) ;
}
# endif
2020-03-03 10:36:29 -03:00
OS : : get_singleton ( ) - > initialize_joypads ( ) ;
/* Initialize Audio Driver */
AudioDriverManager : : initialize ( audio_driver_idx ) ;
2019-06-04 15:20:37 +02:00
print_line ( " " ) ; //add a blank line for readability
2015-08-30 23:36:46 -03:00
if ( init_use_custom_pos ) {
2020-03-03 10:36:29 -03:00
display_server - > window_set_position ( init_custom_pos ) ;
2015-08-30 23:36:46 -03:00
}
2015-12-12 12:06:53 -03:00
2017-10-08 00:51:17 +11:00
// right moment to create and initialize the audio server
2017-01-15 16:06:14 -03:00
2017-03-05 16:44:50 +01:00
audio_server = memnew ( AudioServer ) ;
2017-01-15 16:06:14 -03:00
audio_server - > init ( ) ;
2020-04-09 00:47:36 +10:00
// also init our xr_server from here
xr_server = memnew ( XRServer ) ;
2017-10-08 00:51:17 +11:00
2014-02-09 22:10:30 -03:00
register_core_singletons ( ) ;
MAIN_PRINT ( " Main: Setup Logo " ) ;
2021-02-18 01:54:35 -08:00
# if defined(JAVASCRIPT_ENABLED) || defined(ANDROID_ENABLED)
2017-08-21 15:15:36 -04:00
bool show_logo = false ;
# else
bool show_logo = true ;
2014-02-09 22:10:30 -03:00
# endif
2017-03-05 16:44:50 +01:00
if ( init_screen ! = - 1 ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > window_set_current_screen ( init_screen ) ;
2015-06-13 22:12:53 -03:00
}
2015-12-12 12:06:53 -03:00
if ( init_windowed ) {
//do none..
} else if ( init_maximized ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > window_set_mode ( DisplayServer : : WINDOW_MODE_MAXIMIZED ) ;
2015-12-12 12:06:53 -03:00
} else if ( init_fullscreen ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > window_set_mode ( DisplayServer : : WINDOW_MODE_FULLSCREEN ) ;
2015-06-13 22:12:53 -03:00
}
2017-12-27 20:51:19 +01:00
if ( init_always_on_top ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > window_set_flag ( DisplayServer : : WINDOW_FLAG_ALWAYS_ON_TOP , true ) ;
2017-12-27 20:51:19 +01:00
}
2017-04-09 20:02:04 -03:00
2019-02-23 12:09:35 -03:00
if ( allow_focus_steal_pid ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > enable_for_stealing_focus ( allow_focus_steal_pid ) ;
2019-02-23 12:09:35 -03:00
}
2017-04-09 20:02:04 -03:00
register_server_types ( ) ;
2021-02-02 15:15:13 +01:00
MAIN_PRINT ( " Main: Load Boot Image " ) ;
2015-09-03 23:24:55 -03:00
2021-02-17 13:44:49 -03:00
Color clear = GLOBAL_DEF ( " rendering/environment/defaults/default_clear_color " , Color ( 0.3 , 0.3 , 0.3 ) ) ;
2020-03-27 15:21:27 -03:00
RenderingServer : : get_singleton ( ) - > set_default_clear_color ( clear ) ;
2017-01-05 09:16:00 -03:00
2014-02-09 22:10:30 -03:00
if ( show_logo ) { //boot logo!
2021-04-02 15:33:50 +02:00
const bool boot_logo_image = GLOBAL_DEF ( " application/boot_splash/show_image " , true ) ;
2021-11-23 19:07:41 +01:00
const String boot_logo_path = String ( GLOBAL_DEF ( " application/boot_splash/image " , String ( ) ) ) . strip_edges ( ) ;
2022-01-19 16:09:52 +01:00
const bool boot_logo_scale = GLOBAL_DEF ( " application/boot_splash/fullsize " , true ) ;
2021-04-02 15:33:50 +02:00
const bool boot_logo_filter = GLOBAL_DEF ( " application/boot_splash/use_filter " , true ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/boot_splash/image " ,
2022-01-19 16:09:52 +01:00
PropertyInfo ( Variant : : STRING ,
" application/boot_splash/image " ,
2020-07-20 17:35:34 +01:00
PROPERTY_HINT_FILE , " *.png " ) ) ;
2015-04-12 17:55:01 -03:00
2017-05-17 07:36:47 -03:00
Ref < Image > boot_logo ;
2015-04-12 17:55:01 -03:00
2021-04-02 15:33:50 +02:00
if ( boot_logo_image ) {
2021-12-09 03:42:46 -06:00
if ( ! boot_logo_path . is_empty ( ) ) {
2021-04-02 15:33:50 +02:00
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. " ) ;
}
2020-05-14 16:41:43 +02:00
}
2021-04-02 15:33:50 +02:00
} else {
// Create a 1× 1 transparent image. This will effectively hide the splash image.
boot_logo . instantiate ( ) ;
boot_logo - > create ( 1 , 1 , false , Image : : FORMAT_RGBA8 ) ;
boot_logo - > set_pixel ( 0 , 0 , Color ( 0 , 0 , 0 , 0 ) ) ;
2015-04-12 17:55:01 -03:00
}
2014-02-09 22:10:30 -03:00
2021-03-17 22:56:58 +01:00
# if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
const Color boot_bg_color =
GLOBAL_DEF ( " application/boot_splash/bg_color " ,
( editor | | project_manager ) ? boot_splash_editor_bg_color : boot_splash_bg_color ) ;
# else
const Color boot_bg_color = GLOBAL_DEF ( " application/boot_splash/bg_color " , boot_splash_bg_color ) ;
# endif
2017-05-17 07:36:47 -03:00
if ( boot_logo . is_valid ( ) ) {
2022-01-19 16:09:52 +01:00
RenderingServer : : get_singleton ( ) - > set_boot_image ( boot_logo , boot_bg_color , boot_logo_scale ,
boot_logo_filter ) ;
2014-02-09 22:10:30 -03:00
} else {
# ifndef NO_DEFAULT_BOOT_LOGO
2015-11-23 00:38:12 +01:00
MAIN_PRINT ( " Main: Create bootsplash " ) ;
2017-12-16 16:11:13 -03:00
# if defined(TOOLS_ENABLED) && !defined(NO_EDITOR_SPLASH)
2018-02-19 13:31:06 +01:00
Ref < Image > splash = ( editor | | project_manager ) ? memnew ( Image ( boot_splash_editor_png ) ) : memnew ( Image ( boot_splash_png ) ) ;
2017-12-16 16:11:13 -03:00
# else
2017-05-17 07:36:47 -03:00
Ref < Image > splash = memnew ( Image ( boot_splash_png ) ) ;
2017-12-16 16:11:13 -03:00
# endif
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: ClearColor " ) ;
2020-03-27 15:21:27 -03:00
RenderingServer : : get_singleton ( ) - > set_default_clear_color ( boot_bg_color ) ;
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: Image " ) ;
2022-01-19 16:09:52 +01:00
RenderingServer : : get_singleton ( ) - > set_boot_image ( splash , boot_bg_color , false ) ;
2014-02-09 22:10:30 -03:00
# endif
}
2017-09-15 13:41:11 -03:00
# ifdef TOOLS_ENABLED
2021-05-13 09:25:09 +03:00
if ( OS : : get_singleton ( ) - > get_bundle_icon_path ( ) . is_empty ( ) ) {
Ref < Image > icon = memnew ( Image ( app_icon_png ) ) ;
DisplayServer : : get_singleton ( ) - > set_icon ( icon ) ;
}
2017-09-15 13:41:11 -03:00
# endif
2014-02-09 22:10:30 -03:00
}
2016-04-08 01:30:00 +02:00
MAIN_PRINT ( " Main: DCC " ) ;
2020-07-20 17:35:34 +01:00
RenderingServer : : get_singleton ( ) - > set_default_clear_color (
2021-02-17 13:44:49 -03:00
GLOBAL_DEF ( " rendering/environment/defaults/default_clear_color " , Color ( 0.3 , 0.3 , 0.3 ) ) ) ;
2016-04-08 01:30:00 +02:00
2017-07-17 21:05:38 -03:00
GLOBAL_DEF ( " application/config/icon " , String ( ) ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/config/icon " ,
PropertyInfo ( Variant : : STRING , " application/config/icon " ,
2022-01-17 12:39:57 +01:00
PROPERTY_HINT_FILE , " *.png,*.webp,*.svg " ) ) ;
2014-02-09 22:10:30 -03:00
2019-05-17 16:43:56 +03:00
GLOBAL_DEF ( " application/config/macos_native_icon " , String ( ) ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/config/macos_native_icon " ,
PropertyInfo ( Variant : : STRING ,
" application/config/macos_native_icon " ,
PROPERTY_HINT_FILE , " *.icns " ) ) ;
2019-05-17 16:43:56 +03:00
GLOBAL_DEF ( " application/config/windows_native_icon " , String ( ) ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/config/windows_native_icon " ,
PropertyInfo ( Variant : : STRING ,
" application/config/windows_native_icon " ,
PROPERTY_HINT_FILE , " *.ico " ) ) ;
2019-05-17 16:43:56 +03:00
2020-04-28 15:19:37 +02:00
Input * id = Input : : get_singleton ( ) ;
2018-02-24 03:04:30 +01:00
if ( id ) {
2020-09-21 01:35:20 +02:00
agile_input_event_flushing = GLOBAL_DEF ( " input_devices/buffering/agile_event_flushing " , false ) ;
2020-07-20 17:35:34 +01:00
if ( bool ( GLOBAL_DEF ( " input_devices/pointing/emulate_touch_from_mouse " , false ) ) & &
! ( editor | | project_manager ) ) {
2020-03-03 10:36:29 -03:00
bool found_touchscreen = false ;
for ( int i = 0 ; i < DisplayServer : : get_singleton ( ) - > get_screen_count ( ) ; i + + ) {
if ( DisplayServer : : get_singleton ( ) - > screen_is_touchscreen ( i ) ) {
found_touchscreen = true ;
}
}
if ( ! found_touchscreen ) {
2018-02-24 03:04:30 +01:00
//only if no touchscreen ui hint, set emulation
id - > set_emulate_touch_from_mouse ( true ) ;
}
2015-08-29 17:16:11 -03:00
}
2018-02-24 03:04:30 +01:00
2018-05-10 14:26:28 +09:00
id - > set_emulate_mouse_from_touch ( bool ( GLOBAL_DEF ( " input_devices/pointing/emulate_mouse_from_touch " , true ) ) ) ;
2015-08-29 17:16:11 -03:00
}
2015-09-24 18:06:15 -03:00
2021-02-02 15:15:13 +01:00
MAIN_PRINT ( " Main: Load Translations and Remaps " ) ;
translation_server - > setup ( ) ; //register translations, load them, etc.
2021-12-09 03:42:46 -06:00
if ( ! locale . is_empty ( ) ) {
2021-02-02 15:15:13 +01:00
translation_server - > set_locale ( locale ) ;
}
translation_server - > load_translations ( ) ;
ResourceLoader : : load_translation_remaps ( ) ; //load remaps for resources
ResourceLoader : : load_path_remaps ( ) ;
2014-02-09 22:10:30 -03:00
2021-08-28 00:19:51 +03:00
MAIN_PRINT ( " Main: Load TextServer " ) ;
/* Enum text drivers */
GLOBAL_DEF ( " internationalization/rendering/text_driver " , " " ) ;
String text_driver_options ;
for ( int i = 0 ; i < TextServerManager : : get_singleton ( ) - > get_interface_count ( ) ; i + + ) {
if ( i > 0 ) {
text_driver_options + = " , " ;
}
text_driver_options + = TextServerManager : : get_singleton ( ) - > get_interface ( i ) - > get_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 ) ) ;
/* Determine text driver */
2021-12-09 03:42:46 -06:00
if ( text_driver . is_empty ( ) ) {
2021-08-28 00:19:51 +03:00
text_driver = GLOBAL_GET ( " internationalization/rendering/text_driver " ) ;
}
2021-12-09 03:42:46 -06:00
if ( ! text_driver . is_empty ( ) ) {
2021-08-28 00:19:51 +03:00
/* Load user selected text server. */
for ( int i = 0 ; i < TextServerManager : : get_singleton ( ) - > get_interface_count ( ) ; i + + ) {
if ( TextServerManager : : get_singleton ( ) - > get_interface ( i ) - > get_name ( ) = = text_driver ) {
text_driver_idx = i ;
break ;
}
}
}
if ( text_driver_idx < 0 ) {
/* If not selected, use one with the most features available. */
int max_features = 0 ;
for ( int i = 0 ; i < TextServerManager : : get_singleton ( ) - > get_interface_count ( ) ; i + + ) {
uint32_t features = TextServerManager : : get_singleton ( ) - > get_interface ( i ) - > get_features ( ) ;
int feature_number = 0 ;
while ( features ) {
feature_number + = features & 1 ;
features > > = 1 ;
}
if ( feature_number > = max_features ) {
max_features = feature_number ;
text_driver_idx = i ;
}
}
}
if ( text_driver_idx > = 0 ) {
TextServerManager : : get_singleton ( ) - > set_primary_interface ( TextServerManager : : get_singleton ( ) - > get_interface ( text_driver_idx ) ) ;
} else {
ERR_PRINT ( " TextServer: Unable to create TextServer interface. " ) ;
return ERR_CANT_CREATE ;
}
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: Load Scene Types " ) ;
register_scene_types ( ) ;
2021-03-05 17:22:06 +01:00
# ifdef TOOLS_ENABLED
ClassDB : : set_current_api ( ClassDB : : API_EDITOR ) ;
EditorNode : : register_editor_types ( ) ;
ClassDB : : set_current_api ( ClassDB : : API_CORE ) ;
# endif
2021-08-28 00:19:51 +03:00
MAIN_PRINT ( " Main: Load Modules " ) ;
2021-03-05 17:22:06 +01:00
register_platform_apis ( ) ;
register_module_types ( ) ;
2021-11-30 19:09:29 +03:00
// Theme needs modules to be initialized so that sub-resources can be loaded.
initialize_theme ( ) ;
2017-03-05 16:44:50 +01:00
GLOBAL_DEF ( " display/mouse_cursor/custom_image " , String ( ) ) ;
GLOBAL_DEF ( " display/mouse_cursor/custom_image_hotspot " , Vector2 ( ) ) ;
2019-03-02 12:11:42 +01:00
GLOBAL_DEF ( " display/mouse_cursor/tooltip_position_offset " , Point2 ( 10 , 10 ) ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/mouse_cursor/custom_image " ,
PropertyInfo ( Variant : : STRING ,
" display/mouse_cursor/custom_image " ,
PROPERTY_HINT_FILE , " *.png,*.webp " ) ) ;
2015-09-24 18:06:15 -03:00
2017-07-19 17:00:46 -03:00
if ( String ( ProjectSettings : : get_singleton ( ) - > get ( " display/mouse_cursor/custom_image " ) ) ! = String ( ) ) {
2020-07-20 17:35:34 +01:00
Ref < Texture2D > cursor = ResourceLoader : : load (
ProjectSettings : : get_singleton ( ) - > get ( " display/mouse_cursor/custom_image " ) ) ;
2015-09-24 18:06:15 -03:00
if ( cursor . is_valid ( ) ) {
2017-07-19 17:00:46 -03:00
Vector2 hotspot = ProjectSettings : : get_singleton ( ) - > get ( " display/mouse_cursor/custom_image_hotspot " ) ;
2020-04-28 15:19:37 +02:00
Input : : get_singleton ( ) - > set_custom_mouse_cursor ( cursor , Input : : CURSOR_ARROW , hotspot ) ;
2015-09-24 18:06:15 -03:00
}
}
2017-10-21 13:02:06 +02:00
2019-11-29 08:54:39 +02:00
camera_server = CameraServer : : create ( ) ;
2021-08-28 00:19:51 +03:00
MAIN_PRINT ( " Main: Load Physics, Drivers, Scripts " ) ;
2017-10-21 13:02:06 +02:00
initialize_physics ( ) ;
2020-01-10 12:22:34 +01:00
initialize_navigation_server ( ) ;
2017-10-21 13:02:06 +02:00
register_server_singletons ( ) ;
2014-02-09 22:10:30 -03:00
register_driver_types ( ) ;
2018-06-11 02:59:53 +02:00
// This loads global classes, so it must happen before custom loaders and savers are registered
2014-11-13 00:53:12 -03:00
ScriptServer : : init_languages ( ) ;
2017-01-25 14:30:40 -03:00
audio_server - > load_default_bus_layout ( ) ;
2014-02-09 22:10:30 -03:00
2020-02-27 03:30:20 +01:00
if ( use_debug_profiler & & EngineDebugger : : is_active ( ) ) {
// Start the "scripts" profiler, used in local debugging.
// We could add more, and make the CLI arg require a comma-separated list of profilers.
EngineDebugger : : get_singleton ( ) - > profiler_enable ( " scripts " , true ) ;
2016-05-21 21:18:16 -03:00
}
2020-04-16 23:52:00 -03:00
if ( ! project_manager ) {
// If not running the project manager, and now that the engine is
// able to load resources, load the global shader variables.
2021-03-12 19:05:16 +05:30
// If running on editor, don't load the textures because the editor
2020-04-16 23:52:00 -03:00
// may want to import them first. Editor will reload those later.
rendering_server - > global_variables_load_settings ( ! editor ) ;
}
2017-03-05 16:44:50 +01:00
_start_success = true ;
2014-02-09 22:10:30 -03:00
2021-03-12 19:05:16 +05:30
ClassDB : : set_current_api ( ClassDB : : API_NONE ) ; //no more APIs are registered at this point
2016-09-14 19:37:37 -03:00
2019-11-01 16:16:31 +01:00
print_verbose ( " CORE API HASH: " + uitos ( ClassDB : : get_api_hash ( ClassDB : : API_CORE ) ) ) ;
print_verbose ( " EDITOR API HASH: " + uitos ( ClassDB : : get_api_hash ( ClassDB : : API_EDITOR ) ) ) ;
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: Done " ) ;
return OK ;
}
2018-02-11 00:03:31 +01:00
// everything the main loop needs to know about frame timings
2018-05-15 17:12:35 -03:00
static MainTimerSync main_timer_sync ;
2018-02-11 00:03:31 +01:00
2014-02-09 22:10:30 -03:00
bool Main : : start ( ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! _start_success , false ) ;
2014-02-09 22:10:30 -03:00
2017-09-15 13:41:11 -03:00
bool hasicon = false ;
2019-10-29 01:42:57 +01:00
String positional_arg ;
2014-02-09 22:10:30 -03:00
String game_path ;
String script ;
2020-01-08 14:22:50 +01:00
bool check_only = false ;
# ifdef TOOLS_ENABLED
2021-06-16 19:08:29 +02:00
String doc_tool_path ;
2020-01-08 14:22:50 +01:00
bool doc_base = true ;
2017-08-14 20:15:06 +07:00
String _export_preset ;
2017-03-05 16:44:50 +01:00
bool export_debug = false ;
2020-01-08 14:22:50 +01:00
bool export_pack_only = false ;
# endif
2017-08-19 16:45:03 +02:00
2018-05-15 17:12:35 -03:00
main_timer_sync . init ( OS : : get_singleton ( ) - > get_ticks_usec ( ) ) ;
2014-02-09 22:10:30 -03:00
List < String > args = OS : : get_singleton ( ) - > get_cmdline_args ( ) ;
2020-07-20 17:35:34 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < args . size ( ) ; i + + ) {
2021-06-16 19:08:29 +02:00
// First check parameters that do not have an argument to the right.
2020-07-20 17:35:34 +01:00
// Doctest Unit Testing Handler
// Designed to override and pass arguments to the unit test handler.
2019-02-18 20:28:40 +01:00
if ( args [ i ] = = " --check-only " ) {
check_only = true ;
2018-02-16 19:40:22 +01:00
# ifdef TOOLS_ENABLED
2019-02-18 20:28:40 +01:00
} else if ( args [ i ] = = " --no-docbase " ) {
doc_base = false ;
2017-08-19 16:45:03 +02:00
} else if ( args [ i ] = = " -e " | | args [ i ] = = " --editor " ) {
2017-03-05 16:44:50 +01:00
editor = true ;
2017-08-19 16:45:03 +02:00
} else if ( args [ i ] = = " -p " | | args [ i ] = = " --project-manager " ) {
2018-02-13 18:56:38 +01:00
project_manager = true ;
2018-02-16 19:40:22 +01:00
# endif
2021-12-09 03:42:46 -06:00
} else if ( args [ i ] . length ( ) & & args [ i ] [ 0 ] ! = ' - ' & & positional_arg . is_empty ( ) ) {
2019-10-29 01:42:57 +01:00
positional_arg = args [ i ] ;
2020-05-06 19:59:29 +02:00
if ( args [ i ] . ends_with ( " .scn " ) | |
args [ i ] . ends_with ( " .tscn " ) | |
args [ i ] . ends_with ( " .escn " ) | |
args [ i ] . ends_with ( " .res " ) | |
args [ i ] . ends_with ( " .tres " ) ) {
2019-10-29 01:42:57 +01:00
// Only consider the positional argument to be a scene path if it ends with
// a file extension associated with Godot scenes. This makes it possible
// for projects to parse command-line arguments for custom CLI arguments
// or other file extensions without trouble. This can be used to implement
// "drag-and-drop onto executable" logic, which can prove helpful
// for non-game applications.
game_path = args [ i ] ;
}
2015-11-01 17:50:44 +01:00
}
2021-06-16 19:08:29 +02:00
// Then parameters that have an argument to the right.
2017-03-05 16:44:50 +01:00
else if ( i < ( args . size ( ) - 1 ) ) {
bool parsed_pair = true ;
2018-02-16 19:40:22 +01:00
if ( args [ i ] = = " -s " | | args [ i ] = = " --script " ) {
2017-03-05 16:44:50 +01:00
script = args [ i + 1 ] ;
2018-02-16 19:40:22 +01:00
# ifdef TOOLS_ENABLED
} else if ( args [ i ] = = " --doctool " ) {
2021-04-05 15:35:19 +02:00
doc_tool_path = args [ i + 1 ] ;
if ( doc_tool_path . begins_with ( " - " ) ) {
// Assuming other command line arg, so default to cwd.
doc_tool_path = " . " ;
parsed_pair = false ;
2020-05-14 16:41:43 +02:00
}
2017-06-21 11:09:30 +02:00
} else if ( args [ i ] = = " --export " ) {
2017-03-05 16:44:50 +01:00
editor = true ; //needs editor
2019-06-28 15:34:09 +03:00
_export_preset = args [ i + 1 ] ;
2017-06-21 11:09:30 +02:00
} else if ( args [ i ] = = " --export-debug " ) {
2017-03-05 16:44:50 +01:00
editor = true ; //needs editor
2019-06-28 15:34:09 +03:00
_export_preset = args [ i + 1 ] ;
2017-03-05 16:44:50 +01:00
export_debug = true ;
2020-01-08 14:22:50 +01:00
} else if ( args [ i ] = = " --export-pack " ) {
editor = true ;
_export_preset = args [ i + 1 ] ;
export_pack_only = true ;
2018-02-16 19:40:22 +01:00
# endif
2015-11-01 17:50:44 +01:00
} else {
// The parameter does not match anything known, don't skip the next argument
2017-03-05 16:44:50 +01:00
parsed_pair = false ;
2015-11-01 17:50:44 +01:00
}
if ( parsed_pair ) {
i + + ;
2015-09-16 15:51:19 -05:00
}
2021-06-16 19:08:29 +02:00
}
# ifdef TOOLS_ENABLED
// Handle case where no path is given to --doctool.
else if ( args [ i ] = = " --doctool " ) {
2021-04-05 15:35:19 +02:00
doc_tool_path = " . " ;
2014-02-09 22:10:30 -03:00
}
2021-06-16 19:08:29 +02:00
# endif
2014-02-09 22:10:30 -03:00
}
# ifdef TOOLS_ENABLED
2021-12-09 03:42:46 -06:00
if ( ! doc_tool_path . is_empty ( ) ) {
2021-06-16 19:08:29 +02:00
// Needed to instance editor-only classes for their default values
Engine : : get_singleton ( ) - > set_editor_hint ( true ) ;
2019-06-01 16:42:22 +03:00
2021-12-15 23:01:06 +08:00
// Translate the class reference only when `-l LOCALE` parameter is given.
if ( ! locale . is_empty ( ) & & locale ! = " en " ) {
load_doc_translations ( locale ) ;
}
2017-09-12 17:42:36 -03:00
{
2021-04-05 15:35:19 +02:00
DirAccessRef da = DirAccess : : open ( doc_tool_path ) ;
2020-03-07 16:40:59 +02:00
ERR_FAIL_COND_V_MSG ( ! da , false , " Argument supplied to --doctool must be a valid directory path. " ) ;
2017-09-12 17:42:36 -03:00
}
2020-04-20 17:57:38 +02:00
# 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 ) ;
2021-11-10 17:31:54 +01:00
GLOBAL_DEF ( " mono/runtime/unhandled_exception_policy " , 0 ) ;
2020-04-20 17:57:38 +02:00
# endif
2022-01-17 23:54:53 +01:00
Error err ;
2020-11-29 09:12:06 +05:30
DocTools doc ;
2014-02-09 22:10:30 -03:00
doc . generate ( doc_base ) ;
2020-11-29 09:12:06 +05:30
DocTools docsrc ;
2017-09-13 09:13:23 +02:00
Map < String , String > doc_data_classes ;
2017-09-12 17:42:36 -03:00
Set < String > checked_paths ;
2018-04-22 19:36:01 +02:00
print_line ( " Loading docs... " ) ;
2017-09-12 17:42:36 -03:00
2017-09-13 09:13:23 +02:00
for ( int i = 0 ; i < _doc_data_class_path_count ; i + + ) {
2020-03-08 18:34:09 +02:00
// Custom modules are always located by absolute path.
String path = _doc_data_class_paths [ i ] . path ;
2021-08-29 19:43:47 -04:00
if ( path . is_relative_path ( ) ) {
2021-04-05 15:35:19 +02:00
path = doc_tool_path . plus_file ( path ) ;
2020-03-08 18:34:09 +02:00
}
2017-09-12 17:42:36 -03:00
String name = _doc_data_class_paths [ i ] . name ;
2017-09-13 09:13:23 +02:00
doc_data_classes [ name ] = path ;
2017-09-12 17:42:36 -03:00
if ( ! checked_paths . has ( path ) ) {
checked_paths . insert ( path ) ;
2019-06-08 21:13:16 +02:00
// Create the module documentation directory if it doesn't exist
DirAccess * da = DirAccess : : create_for_path ( path ) ;
2022-01-17 23:54:53 +01:00
err = da - > make_dir_recursive ( path ) ;
2019-06-08 21:13:16 +02:00
memdelete ( da ) ;
2022-01-17 23:54:53 +01:00
ERR_FAIL_COND_V_MSG ( err ! = OK , false , " Error: Can't create directory: " + path + " : " + itos ( err ) ) ;
2019-06-08 21:13:16 +02:00
2017-09-13 09:13:23 +02:00
print_line ( " Loading docs from: " + path ) ;
2022-01-17 23:54:53 +01:00
err = docsrc . load_classes ( path ) ;
ERR_FAIL_COND_V_MSG ( err ! = OK , false , " Error loading docs from: " + path + " : " + itos ( err ) ) ;
2017-09-12 17:42:36 -03:00
}
2014-02-09 22:10:30 -03:00
}
2021-04-05 15:35:19 +02:00
String index_path = doc_tool_path . plus_file ( " doc/classes " ) ;
2019-06-08 21:13:16 +02:00
// Create the main documentation directory if it doesn't exist
DirAccess * da = DirAccess : : create_for_path ( index_path ) ;
2022-01-17 23:54:53 +01:00
err = da - > make_dir_recursive ( index_path ) ;
2019-06-08 21:13:16 +02:00
memdelete ( da ) ;
2022-01-17 23:54:53 +01:00
ERR_FAIL_COND_V_MSG ( err ! = OK , false , " Error: Can't create index directory: " + index_path + " : " + itos ( err ) ) ;
2019-06-08 21:13:16 +02:00
2022-01-17 23:54:53 +01:00
print_line ( " Loading classes from: " + index_path ) ;
err = docsrc . load_classes ( index_path ) ;
ERR_FAIL_COND_V_MSG ( err ! = OK , false , " Error loading classes from: " + index_path + " : " + itos ( err ) ) ;
2017-09-12 17:42:36 -03:00
checked_paths . insert ( index_path ) ;
2018-04-22 19:36:01 +02:00
print_line ( " Merging docs... " ) ;
2017-09-12 17:42:36 -03:00
doc . merge_from ( docsrc ) ;
2022-01-17 23:54:53 +01:00
2017-09-13 09:13:23 +02:00
for ( Set < String > : : Element * E = checked_paths . front ( ) ; E ; E = E - > next ( ) ) {
print_line ( " Erasing old docs at: " + E - > get ( ) ) ;
2022-01-17 23:54:53 +01:00
err = DocTools : : erase_classes ( E - > get ( ) ) ;
ERR_FAIL_COND_V_MSG ( err ! = OK , false , " Error erasing old docs at: " + E - > get ( ) + " : " + itos ( err ) ) ;
2016-12-16 19:12:22 +08:00
}
2018-04-22 19:36:01 +02:00
print_line ( " Generating new docs... " ) ;
2022-01-17 23:54:53 +01:00
err = doc . save_classes ( index_path , doc_data_classes ) ;
ERR_FAIL_COND_V_MSG ( err ! = OK , false , " Error saving new docs: " + itos ( err ) ) ;
2014-02-09 22:10:30 -03:00
2022-01-17 23:54:53 +01:00
OS : : get_singleton ( ) - > set_exit_code ( EXIT_SUCCESS ) ;
2020-07-24 14:16:02 +01:00
return false ;
2014-02-09 22:10:30 -03:00
}
2021-06-19 12:58:49 -03:00
if ( dump_extension_api ) {
NativeExtensionAPIDump : : generate_extension_json_file ( " extension_api.json " ) ;
return false ;
}
2020-01-08 14:22:50 +01:00
# endif
2015-11-26 21:59:25 +01:00
2021-12-09 03:42:46 -06:00
if ( script . is_empty ( ) & & game_path . is_empty ( ) & & String ( GLOBAL_GET ( " application/run/main_scene " ) ) ! = " " ) {
2021-02-17 13:44:49 -03:00
game_path = GLOBAL_GET ( " application/run/main_scene " ) ;
2014-02-09 22:10:30 -03:00
}
2021-06-16 19:08:29 +02:00
# ifdef TOOLS_ENABLED
2021-12-09 03:42:46 -06:00
if ( ! editor & & ! project_manager & & ! cmdline_tool & & script . is_empty ( ) & & game_path . is_empty ( ) ) {
2021-06-16 19:08:29 +02:00
// If we end up here, it means we didn't manage to detect what we want to run.
// Let's throw an error gently. The code leading to this is pretty brittle so
// this might end up triggered by valid usage, in which case we'll have to
// fine-tune further.
2021-07-22 19:23:48 +03:00
OS : : get_singleton ( ) - > alert ( " Couldn't detect whether to run the editor, the project manager or a specific project. Aborting. " ) ;
2021-06-16 19:08:29 +02:00
ERR_FAIL_V_MSG ( false , " Couldn't detect whether to run the editor, the project manager or a specific project. Aborting. " ) ;
}
# endif
2020-04-02 01:20:12 +02:00
MainLoop * main_loop = nullptr ;
2014-02-09 22:10:30 -03:00
if ( editor ) {
2014-11-05 21:20:42 -03:00
main_loop = memnew ( SceneTree ) ;
2021-06-16 19:08:29 +02:00
}
2020-08-11 20:20:30 +03:00
String main_loop_type = GLOBAL_DEF ( " application/run/main_loop_type " , " SceneTree " ) ;
2014-02-09 22:10:30 -03:00
2021-12-09 03:42:46 -06:00
if ( ! script . is_empty ( ) ) {
2014-02-09 22:10:30 -03:00
Ref < Script > script_res = ResourceLoader : : load ( script ) ;
2019-08-08 17:08:27 -03:00
ERR_FAIL_COND_V_MSG ( script_res . is_null ( ) , false , " Can't load script: " + script ) ;
2016-03-09 00:00:52 +01:00
2018-05-31 00:23:23 +02:00
if ( check_only ) {
2019-11-25 22:39:51 +01:00
if ( ! script_res - > is_valid ( ) ) {
2020-06-04 22:03:45 +02:00
OS : : get_singleton ( ) - > set_exit_code ( EXIT_FAILURE ) ;
2021-10-21 20:34:43 +02:00
} else {
OS : : get_singleton ( ) - > set_exit_code ( EXIT_SUCCESS ) ;
2019-11-25 22:39:51 +01:00
}
2020-07-24 14:16:02 +01:00
return false ;
2018-05-31 00:23:23 +02:00
}
2021-06-17 16:03:09 -06:00
if ( script_res - > can_instantiate ( ) ) {
2017-03-05 16:44:50 +01:00
StringName instance_type = script_res - > get_instance_base_type ( ) ;
2021-06-17 16:03:09 -06:00
Object * obj = ClassDB : : instantiate ( instance_type ) ;
2017-08-24 22:58:51 +02:00
MainLoop * script_loop = Object : : cast_to < MainLoop > ( obj ) ;
2014-02-09 22:10:30 -03:00
if ( ! script_loop ) {
2020-05-14 16:41:43 +02:00
if ( obj ) {
2014-02-09 22:10:30 -03:00
memdelete ( obj ) ;
2020-05-14 16:41:43 +02:00
}
2021-07-22 19:23:48 +03:00
OS : : get_singleton ( ) - > alert ( vformat ( " Can't load the script \" %s \" as it doesn't inherit from SceneTree or MainLoop. " , script ) ) ;
ERR_FAIL_V_MSG ( false , vformat ( " Can't load the script \" %s \" as it doesn't inherit from SceneTree or MainLoop. " , script ) ) ;
2014-02-09 22:10:30 -03:00
}
2020-12-22 09:50:29 +00:00
script_loop - > set_initialize_script ( script_res ) ;
2017-03-05 16:44:50 +01:00
main_loop = script_loop ;
2014-02-09 22:10:30 -03:00
} else {
2020-07-24 14:16:02 +01:00
return false ;
2014-02-09 22:10:30 -03:00
}
2020-08-11 20:20:30 +03:00
} else { // Not based on script path.
if ( ! editor & & ! ClassDB : : class_exists ( main_loop_type ) & & ScriptServer : : is_global_class ( main_loop_type ) ) {
String script_path = ScriptServer : : get_global_class_path ( main_loop_type ) ;
Ref < Script > script_res = ResourceLoader : : load ( script_path ) ;
StringName script_base = ScriptServer : : get_global_class_native_base ( main_loop_type ) ;
2021-06-17 16:03:09 -06:00
Object * obj = ClassDB : : instantiate ( script_base ) ;
2020-08-11 20:20:30 +03:00
MainLoop * script_loop = Object : : cast_to < MainLoop > ( obj ) ;
if ( ! script_loop ) {
if ( obj ) {
memdelete ( obj ) ;
}
2021-07-22 19:23:48 +03:00
OS : : get_singleton ( ) - > alert ( " Error: Invalid MainLoop script base type: " + script_base ) ;
2020-08-11 20:20:30 +03:00
ERR_FAIL_V_MSG ( false , vformat ( " The global class %s does not inherit from SceneTree or MainLoop. " , main_loop_type ) ) ;
}
2020-12-22 09:50:29 +00:00
script_loop - > set_initialize_script ( script_res ) ;
2020-08-11 20:20:30 +03:00
main_loop = script_loop ;
}
2014-02-09 22:10:30 -03:00
}
2016-03-09 00:00:52 +01:00
2021-12-09 03:42:46 -06:00
if ( ! main_loop & & main_loop_type . is_empty ( ) ) {
2017-03-05 16:44:50 +01:00
main_loop_type = " SceneTree " ;
2020-05-14 16:41:43 +02:00
}
2016-03-09 00:00:52 +01:00
2014-02-09 22:10:30 -03:00
if ( ! main_loop ) {
2017-01-02 23:03:46 -03:00
if ( ! ClassDB : : class_exists ( main_loop_type ) ) {
2021-07-22 19:23:48 +03:00
OS : : get_singleton ( ) - > alert ( " Error: MainLoop type doesn't exist: " + main_loop_type ) ;
2020-07-24 14:16:02 +01:00
return false ;
2014-02-09 22:10:30 -03:00
} else {
2021-06-17 16:03:09 -06:00
Object * ml = ClassDB : : instantiate ( main_loop_type ) ;
2019-08-08 17:08:27 -03:00
ERR_FAIL_COND_V_MSG ( ! ml , false , " Can't instance MainLoop type. " ) ;
2014-02-09 22:10:30 -03:00
2017-08-24 22:58:51 +02:00
main_loop = Object : : cast_to < MainLoop > ( ml ) ;
2014-02-09 22:10:30 -03:00
if ( ! main_loop ) {
memdelete ( ml ) ;
2019-08-08 17:08:27 -03:00
ERR_FAIL_V_MSG ( false , " Invalid MainLoop type. " ) ;
2014-02-09 22:10:30 -03:00
}
}
}
2017-01-02 23:03:46 -03:00
if ( main_loop - > is_class ( " SceneTree " ) ) {
2017-08-24 22:58:51 +02:00
SceneTree * sml = Object : : cast_to < SceneTree > ( main_loop ) ;
2014-02-09 22:10:30 -03:00
2017-04-07 16:17:16 +02:00
# ifdef DEBUG_ENABLED
2015-09-18 23:10:58 -03:00
if ( debug_collisions ) {
sml - > set_debug_collisions_hint ( true ) ;
}
2015-09-20 13:03:46 -03:00
if ( debug_navigation ) {
sml - > set_debug_navigation_hint ( true ) ;
}
2017-04-07 16:17:16 +02:00
# endif
2021-07-21 03:54:45 +02:00
bool embed_subwindows = GLOBAL_DEF ( " display/window/subwindows/embed_subwindows " , true ) ;
2020-03-28 21:56:50 +01:00
2020-09-14 18:52:45 -04:00
if ( OS : : get_singleton ( ) - > is_single_window ( ) | | ( ! project_manager & & ! editor & & embed_subwindows ) ) {
2020-03-14 13:06:39 -03:00
sml - > get_root ( ) - > set_embed_subwindows_hint ( true ) ;
}
2018-06-11 02:59:53 +02:00
ResourceLoader : : add_custom_loaders ( ) ;
ResourceSaver : : add_custom_savers ( ) ;
2018-05-22 13:26:13 -03:00
if ( ! project_manager & & ! editor ) { // game
2021-12-09 03:42:46 -06:00
if ( ! game_path . is_empty ( ) | | ! script . is_empty ( ) ) {
2018-05-01 11:06:23 -03:00
//autoload
2021-08-26 20:46:51 -07:00
OrderedHashMap < StringName , ProjectSettings : : AutoloadInfo > autoloads = ProjectSettings : : get_singleton ( ) - > get_autoload_list ( ) ;
2018-05-01 11:06:23 -03:00
//first pass, add the constants so they exist before any script is loaded
2021-08-26 20:46:51 -07:00
for ( OrderedHashMap < StringName , ProjectSettings : : AutoloadInfo > : : Element E = autoloads . front ( ) ; E ; E = E . next ( ) ) {
const ProjectSettings : : AutoloadInfo & info = E . get ( ) ;
2018-05-01 11:06:23 -03:00
2020-06-17 20:45:08 -03:00
if ( info . is_singleton ) {
2018-05-01 11:06:23 -03:00
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
2020-06-17 20:45:08 -03:00
ScriptServer : : get_language ( i ) - > add_global_constant ( info . name , Variant ( ) ) ;
2018-05-01 11:06:23 -03:00
}
}
}
//second pass, load into global constants
List < Node * > to_add ;
2021-08-26 20:46:51 -07:00
for ( OrderedHashMap < StringName , ProjectSettings : : AutoloadInfo > : : Element E = autoloads . front ( ) ; E ; E = E . next ( ) ) {
const ProjectSettings : : AutoloadInfo & info = E . get ( ) ;
2018-05-01 11:06:23 -03:00
2020-06-17 20:45:08 -03:00
RES res = ResourceLoader : : load ( info . path ) ;
ERR_CONTINUE_MSG ( res . is_null ( ) , " Can't autoload: " + info . path ) ;
2020-04-02 01:20:12 +02:00
Node * n = nullptr ;
2018-05-01 11:06:23 -03:00
if ( res - > is_class ( " PackedScene " ) ) {
Ref < PackedScene > ps = res ;
2021-06-17 16:03:09 -06:00
n = ps - > instantiate ( ) ;
2018-05-01 11:06:23 -03:00
} else if ( res - > is_class ( " Script " ) ) {
2019-02-12 21:10:08 +01:00
Ref < Script > script_res = res ;
StringName ibt = script_res - > get_instance_base_type ( ) ;
2018-05-01 11:06:23 -03:00
bool valid_type = ClassDB : : is_parent_class ( ibt , " Node " ) ;
2020-06-17 20:45:08 -03:00
ERR_CONTINUE_MSG ( ! valid_type , " Script does not inherit a Node: " + info . path ) ;
2018-05-01 11:06:23 -03:00
2021-06-17 16:03:09 -06:00
Object * obj = ClassDB : : instantiate ( ibt ) ;
2018-05-01 11:06:23 -03:00
2020-07-20 17:35:34 +01:00
ERR_CONTINUE_MSG ( obj = = nullptr ,
" Cannot instance script for autoload, expected 'Node' inheritance, got: " +
String ( ibt ) ) ;
2018-05-01 11:06:23 -03:00
n = Object : : cast_to < Node > ( obj ) ;
2020-02-13 16:03:10 -03:00
n - > set_script ( script_res ) ;
2018-05-01 11:06:23 -03:00
}
2020-06-17 20:45:08 -03:00
ERR_CONTINUE_MSG ( ! n , " Path in autoload not a node or script: " + info . path ) ;
n - > set_name ( info . name ) ;
2018-05-01 11:06:23 -03:00
//defer so references are all valid on _ready()
to_add . push_back ( n ) ;
2020-06-17 20:45:08 -03:00
if ( info . is_singleton ) {
2018-05-01 11:06:23 -03:00
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
2020-06-17 20:45:08 -03:00
ScriptServer : : get_language ( i ) - > add_global_constant ( info . name , n ) ;
2018-05-01 11:06:23 -03:00
}
}
}
2021-07-15 23:45:57 -04:00
for ( Node * E : to_add ) {
sml - > get_root ( ) - > add_child ( E ) ;
2018-05-01 11:06:23 -03:00
}
}
}
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
2020-04-02 01:20:12 +02:00
EditorNode * editor_node = nullptr ;
2014-02-09 22:10:30 -03:00
if ( editor ) {
2017-03-05 16:44:50 +01:00
editor_node = memnew ( EditorNode ) ;
2014-02-09 22:10:30 -03:00
sml - > get_root ( ) - > add_child ( editor_node ) ;
2021-12-09 03:42:46 -06:00
if ( ! _export_preset . is_empty ( ) ) {
2019-10-29 01:42:57 +01:00
editor_node - > export_preset ( _export_preset , positional_arg , export_debug , export_pack_only ) ;
2020-01-07 13:29:02 +01:00
game_path = " " ; // Do not load anything.
2014-02-09 22:10:30 -03:00
}
}
# endif
2018-02-19 13:31:06 +01:00
if ( ! editor & & ! project_manager ) {
2014-02-09 22:10:30 -03:00
//standard helpers that can be changed from main config
2021-02-17 13:44:49 -03:00
String stretch_mode = GLOBAL_DEF_BASIC ( " display/window/stretch/mode " , " disabled " ) ;
2020-03-07 00:36:55 +01:00
String stretch_aspect = GLOBAL_DEF_BASIC ( " display/window/stretch/aspect " , " keep " ) ;
2021-03-31 12:50:24 +01:00
Size2i stretch_size = Size2i ( GLOBAL_DEF_BASIC ( " display/window/size/viewport_width " , 0 ) ,
GLOBAL_DEF_BASIC ( " display/window/size/viewport_height " , 0 ) ) ;
2021-12-17 13:11:19 +01:00
real_t stretch_scale = GLOBAL_DEF_BASIC ( " display/window/stretch/scale " , 1.0 ) ;
2014-04-14 22:43:44 -03:00
2020-03-03 22:51:12 -03:00
Window : : ContentScaleMode cs_sm = Window : : CONTENT_SCALE_MODE_DISABLED ;
2020-07-02 17:15:11 -03:00
if ( stretch_mode = = " canvas_items " ) {
cs_sm = Window : : CONTENT_SCALE_MODE_CANVAS_ITEMS ;
} else if ( stretch_mode = = " viewport " ) {
cs_sm = Window : : CONTENT_SCALE_MODE_VIEWPORT ;
2020-05-14 16:41:43 +02:00
}
2014-04-14 22:43:44 -03:00
2020-03-03 22:51:12 -03:00
Window : : ContentScaleAspect cs_aspect = Window : : CONTENT_SCALE_ASPECT_IGNORE ;
2020-05-14 16:41:43 +02:00
if ( stretch_aspect = = " keep " ) {
2020-03-03 22:51:12 -03:00
cs_aspect = Window : : CONTENT_SCALE_ASPECT_KEEP ;
2020-05-14 16:41:43 +02:00
} else if ( stretch_aspect = = " keep_width " ) {
2020-03-03 22:51:12 -03:00
cs_aspect = Window : : CONTENT_SCALE_ASPECT_KEEP_WIDTH ;
2020-05-14 16:41:43 +02:00
} else if ( stretch_aspect = = " keep_height " ) {
2020-03-03 22:51:12 -03:00
cs_aspect = Window : : CONTENT_SCALE_ASPECT_KEEP_HEIGHT ;
2020-05-14 16:41:43 +02:00
} else if ( stretch_aspect = = " expand " ) {
2020-03-03 22:51:12 -03:00
cs_aspect = Window : : CONTENT_SCALE_ASPECT_EXPAND ;
2020-05-14 16:41:43 +02:00
}
2014-04-14 22:43:44 -03:00
2020-03-03 22:51:12 -03:00
sml - > get_root ( ) - > set_content_scale_mode ( cs_sm ) ;
sml - > get_root ( ) - > set_content_scale_aspect ( cs_aspect ) ;
sml - > get_root ( ) - > set_content_scale_size ( stretch_size ) ;
2021-12-17 13:11:19 +01:00
sml - > get_root ( ) - > set_content_scale_factor ( stretch_scale ) ;
2014-02-09 22:10:30 -03:00
2017-07-17 21:05:38 -03:00
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 ) ) ;
2017-07-19 17:00:46 -03:00
String appname = ProjectSettings : : get_singleton ( ) - > get ( " application/config/name " ) ;
2014-02-09 22:10:30 -03:00
appname = TranslationServer : : get_singleton ( ) - > translate ( appname ) ;
2020-06-16 11:27:46 +02:00
# ifdef DEBUG_ENABLED
// Append a suffix to the window title to denote that the project is running
// from a debug build (including the editor). Since this results in lower performance,
// this should be clearly presented to the user.
DisplayServer : : get_singleton ( ) - > window_set_title ( vformat ( " %s (DEBUG) " , appname ) ) ;
# else
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > window_set_title ( appname ) ;
2020-06-16 11:27:46 +02:00
# endif
2014-02-09 22:10:30 -03:00
2020-03-23 22:09:22 +01:00
// Define a very small minimum window size to prevent bugs such as GH-37242.
// It can still be overridden by the user in a script.
DisplayServer : : get_singleton ( ) - > window_set_min_size ( Size2i ( 64 , 64 ) ) ;
2017-09-07 11:22:07 -03:00
bool snap_controls = GLOBAL_DEF ( " gui/common/snap_controls_to_pixels " , true ) ;
sml - > get_root ( ) - > set_snap_controls_to_pixels ( snap_controls ) ;
2021-02-17 13:44:49 -03:00
bool font_oversampling = GLOBAL_DEF ( " gui/fonts/dynamic_fonts/use_oversampling " , true ) ;
2020-03-03 22:51:12 -03:00
sml - > get_root ( ) - > set_use_font_oversampling ( font_oversampling ) ;
2017-12-19 18:48:30 -03:00
2021-02-17 13:44:49 -03:00
int texture_filter = GLOBAL_DEF ( " rendering/textures/canvas_textures/default_texture_filter " , 1 ) ;
int texture_repeat = GLOBAL_DEF ( " rendering/textures/canvas_textures/default_texture_repeat " , 0 ) ;
2020-07-20 17:35:34 +01:00
sml - > get_root ( ) - > set_default_canvas_item_texture_filter (
Viewport : : DefaultCanvasItemTextureFilter ( texture_filter ) ) ;
sml - > get_root ( ) - > set_default_canvas_item_texture_repeat (
Viewport : : DefaultCanvasItemTextureRepeat ( texture_repeat ) ) ;
2019-06-24 22:24:07 -03:00
2014-02-09 22:10:30 -03:00
} else {
2021-02-17 13:44:49 -03:00
GLOBAL_DEF_BASIC ( " display/window/stretch/mode " , " disabled " ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/stretch/mode " ,
PropertyInfo ( Variant : : STRING ,
" display/window/stretch/mode " ,
PROPERTY_HINT_ENUM ,
" disabled,canvas_items,viewport " ) ) ;
2020-03-07 00:36:55 +01:00
GLOBAL_DEF_BASIC ( " display/window/stretch/aspect " , " keep " ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/stretch/aspect " ,
PropertyInfo ( Variant : : STRING ,
" display/window/stretch/aspect " ,
PROPERTY_HINT_ENUM ,
" ignore,keep,keep_width,keep_height,expand " ) ) ;
2021-02-17 13:44:49 -03:00
GLOBAL_DEF_BASIC ( " display/window/stretch/shrink " , 1.0 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/stretch/shrink " ,
PropertyInfo ( Variant : : FLOAT ,
" display/window/stretch/shrink " ,
PROPERTY_HINT_RANGE ,
" 1.0,8.0,0.1 " ) ) ;
2017-07-17 21:05:38 -03:00
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 ) ) ;
2021-02-17 13:44:49 -03:00
GLOBAL_DEF_BASIC ( " gui/common/snap_controls_to_pixels " , true ) ;
GLOBAL_DEF_BASIC ( " gui/fonts/dynamic_fonts/use_oversampling " , true ) ;
2019-06-24 22:24:07 -03:00
2021-02-17 13:44:49 -03:00
GLOBAL_DEF_BASIC ( " rendering/textures/canvas_textures/default_texture_filter " , 1 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info (
2021-02-17 13:44:49 -03:00
" rendering/textures/canvas_textures/default_texture_filter " ,
PropertyInfo ( Variant : : INT , " rendering/textures/canvas_textures/default_texture_filter " , PROPERTY_HINT_ENUM ,
2020-02-29 18:04:28 +01:00
" Nearest,Linear,Linear Mipmap,Nearest Mipmap " ) ) ;
2021-02-17 13:44:49 -03:00
GLOBAL_DEF_BASIC ( " rendering/textures/canvas_textures/default_texture_repeat " , 0 ) ;
2020-07-20 17:35:34 +01:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info (
2021-02-17 13:44:49 -03:00
" rendering/textures/canvas_textures/default_texture_repeat " ,
PropertyInfo ( Variant : : INT , " rendering/textures/canvas_textures/default_texture_repeat " , PROPERTY_HINT_ENUM ,
2020-07-20 17:35:34 +01:00
" Disable,Enable,Mirror " ) ) ;
2014-02-09 22:10:30 -03:00
}
2020-05-22 01:55:28 +02:00
# ifdef TOOLS_ENABLED
if ( editor ) {
2020-07-20 17:35:34 +01:00
bool editor_embed_subwindows = EditorSettings : : get_singleton ( ) - > get_setting (
" interface/editor/single_window_mode " ) ;
2020-05-22 01:55:28 +02:00
if ( editor_embed_subwindows ) {
sml - > get_root ( ) - > set_embed_subwindows_hint ( true ) ;
}
}
# endif
2016-09-06 19:45:35 +03:00
String local_game_path ;
2021-12-09 03:42:46 -06:00
if ( ! game_path . is_empty ( ) & & ! project_manager ) {
2017-03-05 16:44:50 +01:00
local_game_path = game_path . replace ( " \\ " , " / " ) ;
2014-02-09 22:10:30 -03:00
if ( ! local_game_path . begins_with ( " res:// " ) ) {
2020-07-20 17:35:34 +01:00
bool absolute =
( local_game_path . size ( ) > 1 ) & & ( local_game_path [ 0 ] = = ' / ' | | local_game_path [ 1 ] = = ' : ' ) ;
2014-02-09 22:10:30 -03:00
if ( ! absolute ) {
2017-07-19 17:00:46 -03:00
if ( ProjectSettings : : get_singleton ( ) - > is_using_datapack ( ) ) {
2017-03-05 16:44:50 +01:00
local_game_path = " res:// " + local_game_path ;
2014-02-09 22:10:30 -03:00
2014-02-19 11:57:14 -03:00
} else {
2020-07-03 15:26:22 +02:00
int sep = local_game_path . rfind ( " / " ) ;
2014-02-19 11:57:14 -03:00
2017-03-05 16:44:50 +01:00
if ( sep = = - 1 ) {
2014-02-19 11:57:14 -03:00
DirAccess * da = DirAccess : : create ( DirAccess : : ACCESS_FILESYSTEM ) ;
2019-06-16 13:31:57 +01:00
local_game_path = da - > get_current_dir ( ) . plus_file ( local_game_path ) ;
2017-03-05 16:44:50 +01:00
memdelete ( da ) ;
2014-02-19 11:57:14 -03:00
} else {
2017-03-05 16:44:50 +01:00
DirAccess * da = DirAccess : : open ( local_game_path . substr ( 0 , sep ) ) ;
2014-02-19 11:57:14 -03:00
if ( da ) {
2020-07-20 17:35:34 +01:00
local_game_path = da - > get_current_dir ( ) . plus_file (
local_game_path . substr ( sep + 1 , local_game_path . length ( ) ) ) ;
2014-02-19 11:57:14 -03:00
memdelete ( da ) ;
}
2014-02-09 22:10:30 -03:00
}
}
}
}
2017-07-19 17:00:46 -03:00
local_game_path = ProjectSettings : : get_singleton ( ) - > localize_path ( local_game_path ) ;
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
if ( editor ) {
2020-11-04 23:01:55 -03:00
if ( game_path ! = String ( GLOBAL_GET ( " application/run/main_scene " ) ) | | ! editor_node - > has_scenes_in_session ( ) ) {
2018-09-21 00:14:04 -03:00
Error serr = editor_node - > load_scene ( local_game_path ) ;
2020-05-14 16:41:43 +02:00
if ( serr ! = OK ) {
2018-09-21 00:14:04 -03:00
ERR_PRINT ( " Failed to load scene " ) ;
2020-05-14 16:41:43 +02:00
}
2018-09-21 00:14:04 -03:00
}
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > set_context ( DisplayServer : : CONTEXT_EDITOR ) ;
2021-08-29 01:58:15 +02:00
if ( ! debug_server_uri . is_empty ( ) ) {
EditorDebuggerNode : : get_singleton ( ) - > start ( debug_server_uri ) ;
}
2016-09-06 19:45:35 +03:00
}
2014-02-09 22:10:30 -03:00
# endif
2018-10-05 17:18:10 -03:00
if ( ! editor ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > set_context ( DisplayServer : : CONTEXT_ENGINE ) ;
2018-10-05 17:18:10 -03:00
}
2016-09-06 19:45:35 +03:00
}
2014-02-09 22:10:30 -03:00
2018-02-19 13:31:06 +01:00
if ( ! project_manager & & ! editor ) { // game
2018-09-15 14:45:54 +02:00
2019-08-08 17:08:27 -03:00
// Load SSL Certificates from Project Settings (or builtin).
2020-05-12 10:10:54 +02:00
Crypto : : load_default_certificates ( GLOBAL_DEF ( " network/ssl/certificate_bundle_override " , " " ) ) ;
2018-09-15 14:45:54 +02:00
2021-12-09 03:42:46 -06:00
if ( ! game_path . is_empty ( ) ) {
2020-04-02 01:20:12 +02:00
Node * scene = nullptr ;
2014-02-09 22:10:30 -03:00
Ref < PackedScene > scenedata = ResourceLoader : : load ( local_game_path ) ;
2020-05-14 16:41:43 +02:00
if ( scenedata . is_valid ( ) ) {
2021-06-17 16:03:09 -06:00
scene = scenedata - > instantiate ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
2019-08-08 17:08:27 -03:00
ERR_FAIL_COND_V_MSG ( ! scene , false , " Failed loading scene: " + local_game_path ) ;
2015-05-17 16:33:35 -03:00
sml - > add_current_scene ( scene ) ;
2014-02-09 22:10:30 -03:00
2019-05-17 16:43:56 +03:00
# ifdef OSX_ENABLED
String mac_iconpath = GLOBAL_DEF ( " application/config/macos_native_icon " , " Variant() " ) ;
2021-12-09 03:42:46 -06:00
if ( ! mac_iconpath . is_empty ( ) ) {
2020-03-07 18:02:54 +02:00
DisplayServer : : get_singleton ( ) - > set_native_icon ( mac_iconpath ) ;
2019-05-17 16:43:56 +03:00
hasicon = true ;
}
# endif
# ifdef WINDOWS_ENABLED
String win_iconpath = GLOBAL_DEF ( " application/config/windows_native_icon " , " Variant() " ) ;
2021-12-09 03:42:46 -06:00
if ( ! win_iconpath . is_empty ( ) ) {
2020-03-09 12:56:48 -03:00
DisplayServer : : get_singleton ( ) - > set_native_icon ( win_iconpath ) ;
2019-05-17 16:43:56 +03:00
hasicon = true ;
}
# endif
2017-07-17 21:05:38 -03:00
String iconpath = GLOBAL_DEF ( " application/config/icon " , " Variant() " ) ;
2021-12-09 03:42:46 -06:00
if ( ( ! iconpath . is_empty ( ) ) & & ( ! hasicon ) ) {
2017-05-17 07:36:47 -03:00
Ref < Image > icon ;
2021-06-17 16:03:09 -06:00
icon . instantiate ( ) ;
2018-09-30 17:21:07 +02:00
if ( ImageLoader : : load_image ( iconpath , icon ) = = OK ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > set_icon ( icon ) ;
2017-09-15 13:41:11 -03:00
hasicon = true ;
}
2014-02-09 22:10:30 -03:00
}
}
}
# ifdef TOOLS_ENABLED
2021-06-16 19:08:29 +02:00
if ( project_manager ) {
2018-09-10 14:53:31 +02:00
Engine : : get_singleton ( ) - > set_editor_hint ( true ) ;
2017-03-05 16:44:50 +01:00
ProjectManager * pmanager = memnew ( ProjectManager ) ;
ProgressDialog * progress_dialog = memnew ( ProgressDialog ) ;
2016-07-10 17:19:19 -03:00
pmanager - > add_child ( progress_dialog ) ;
2014-02-09 22:10:30 -03:00
sml - > get_root ( ) - > add_child ( pmanager ) ;
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > set_context ( DisplayServer : : CONTEXT_PROJECTMAN ) ;
2014-02-09 22:10:30 -03:00
}
2018-09-15 14:45:54 +02:00
if ( project_manager | | editor ) {
2019-07-19 15:29:57 +02:00
// Load SSL Certificates from Editor Settings (or builtin)
2021-06-09 10:47:32 +02:00
Crypto : : load_default_certificates (
EditorSettings : : get_singleton ( ) - > get_setting ( " network/ssl/editor_ssl_certificates " ) . operator String ( ) ) ;
2019-07-19 15:29:57 +02:00
}
2014-02-09 22:10:30 -03:00
# endif
}
2021-05-13 09:25:09 +03:00
if ( ! hasicon & & OS : : get_singleton ( ) - > get_bundle_icon_path ( ) . is_empty ( ) ) {
2017-09-15 13:41:11 -03:00
Ref < Image > icon = memnew ( Image ( app_icon_png ) ) ;
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > set_icon ( icon ) ;
2017-09-15 13:41:11 -03:00
}
2017-03-05 16:44:50 +01:00
OS : : get_singleton ( ) - > set_main_loop ( main_loop ) ;
2014-02-09 22:10:30 -03:00
2020-07-24 14:16:02 +01:00
return true ;
2014-02-09 22:10:30 -03:00
}
2018-09-20 11:45:05 +02:00
/* Main iteration
*
* This is the iteration of the engine's game loop, advancing the state of physics,
* rendering and audio.
* It's called directly by the platform's OS::run method, where the loop is created
* and monitored.
*
* The OS implementation can impact its draw step with the Main::force_redraw() method.
*/
2017-03-05 16:44:50 +01:00
uint64_t Main : : last_ticks = 0 ;
2018-05-28 08:47:09 -03:00
uint32_t Main : : frames = 0 ;
2017-03-05 16:44:50 +01:00
uint32_t Main : : frame = 0 ;
2014-02-09 22:10:30 -03:00
bool Main : : force_redraw_requested = false ;
2019-01-24 13:09:05 -03:00
int Main : : iterating = 0 ;
2020-09-21 01:35:20 +02:00
bool Main : : agile_input_event_flushing = false ;
2020-07-20 17:35:34 +01:00
2019-01-22 13:17:39 -03:00
bool Main : : is_iterating ( ) {
2019-01-24 13:09:05 -03:00
return iterating > 0 ;
2019-01-22 13:17:39 -03:00
}
2014-02-09 22:10:30 -03:00
2019-08-08 17:08:27 -03:00
// For performance metrics.
2017-09-30 16:19:07 +02:00
static uint64_t physics_process_max = 0 ;
2020-12-22 09:50:29 +00:00
static uint64_t process_max = 0 ;
2014-02-09 22:10:30 -03:00
bool Main : : iteration ( ) {
2019-01-24 12:42:05 -03:00
//for now do not error on this
//ERR_FAIL_COND_V(iterating, false);
2019-01-22 13:17:39 -03:00
2019-01-24 13:09:05 -03:00
iterating + + ;
2019-01-22 13:17:39 -03:00
2021-09-07 23:25:35 -05:00
const uint64_t ticks = OS : : get_singleton ( ) - > get_ticks_usec ( ) ;
2017-07-15 01:23:10 -03:00
Engine : : get_singleton ( ) - > _frame_ticks = ticks ;
2018-05-15 17:12:35 -03:00
main_timer_sync . set_cpu_ticks_usec ( ticks ) ;
main_timer_sync . set_fixed_fps ( fixed_fps ) ;
2017-07-15 01:23:10 -03:00
2021-09-07 23:25:35 -05:00
const uint64_t ticks_elapsed = ticks - last_ticks ;
2014-02-09 22:10:30 -03:00
2021-09-07 23:25:35 -05:00
const int physics_ticks_per_second = Engine : : get_singleton ( ) - > get_physics_ticks_per_second ( ) ;
const double physics_step = 1.0 / physics_ticks_per_second ;
2017-08-30 12:40:35 +02:00
2021-09-07 23:25:35 -05:00
const double time_scale = Engine : : get_singleton ( ) - > get_time_scale ( ) ;
2018-05-09 08:11:43 +02:00
2021-08-11 02:35:16 +02:00
MainFrameTime advance = main_timer_sync . advance ( physics_step , physics_ticks_per_second ) ;
2020-12-22 09:50:29 +00:00
double process_step = advance . process_step ;
double scaled_step = process_step * time_scale ;
2015-04-14 22:05:14 -03:00
2020-12-22 09:50:29 +00:00
Engine : : get_singleton ( ) - > _process_step = process_step ;
2019-07-01 17:42:02 +01:00
Engine : : get_singleton ( ) - > _physics_interpolation_fraction = advance . interpolation_fraction ;
2017-07-15 01:23:10 -03:00
2017-09-30 16:19:07 +02:00
uint64_t physics_process_ticks = 0 ;
2020-12-22 09:50:29 +00:00
uint64_t process_ticks = 0 ;
2016-05-21 21:18:16 -03:00
2017-03-05 16:44:50 +01:00
frame + = ticks_elapsed ;
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
last_ticks = ticks ;
2014-02-09 22:10:30 -03:00
2018-02-11 00:03:31 +01:00
static const int max_physics_steps = 8 ;
if ( fixed_fps = = - 1 & & advance . physics_steps > max_physics_steps ) {
2020-12-22 09:50:29 +00:00
process_step - = ( advance . physics_steps - max_physics_steps ) * physics_step ;
2018-02-11 00:03:31 +01:00
advance . physics_steps = max_physics_steps ;
}
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
bool exit = false ;
2014-02-09 22:10:30 -03:00
2021-08-29 16:05:11 +10:00
// process all our active interfaces
XRServer : : get_singleton ( ) - > _process ( ) ;
2018-02-11 00:03:31 +01:00
for ( int iters = 0 ; iters < advance . physics_steps ; + + iters ) {
2020-09-21 01:35:20 +02:00
if ( Input : : get_singleton ( ) - > is_using_input_buffering ( ) & & agile_input_event_flushing ) {
Input : : get_singleton ( ) - > flush_buffered_events ( ) ;
}
Engine : : get_singleton ( ) - > _in_physics = true ;
2017-10-21 21:28:08 +07:00
uint64_t physics_begin = OS : : get_singleton ( ) - > get_ticks_usec ( ) ;
2014-02-09 22:10:30 -03:00
2021-02-09 13:19:03 -03:00
PhysicsServer3D : : get_singleton ( ) - > sync ( ) ;
2020-03-27 15:21:27 -03:00
PhysicsServer3D : : get_singleton ( ) - > flush_queries ( ) ;
2014-02-09 22:10:30 -03:00
2020-03-27 15:21:27 -03:00
PhysicsServer2D : : get_singleton ( ) - > sync ( ) ;
PhysicsServer2D : : get_singleton ( ) - > flush_queries ( ) ;
2014-02-09 22:10:30 -03:00
2020-12-22 09:50:29 +00:00
if ( OS : : get_singleton ( ) - > get_main_loop ( ) - > physics_process ( physics_step * time_scale ) ) {
2017-03-05 16:44:50 +01:00
exit = true ;
2014-02-09 22:10:30 -03:00
break ;
}
2020-12-22 09:50:29 +00:00
NavigationServer3D : : get_singleton_mut ( ) - > process ( physics_step * time_scale ) ;
2014-02-09 22:10:30 -03:00
2020-02-26 09:42:51 +01:00
message_queue - > flush ( ) ;
2020-01-10 12:22:34 +01:00
2021-02-09 13:19:03 -03:00
PhysicsServer3D : : get_singleton ( ) - > end_sync ( ) ;
2020-12-22 09:50:29 +00:00
PhysicsServer3D : : get_singleton ( ) - > step ( physics_step * time_scale ) ;
2015-05-26 01:05:08 -03:00
2020-03-27 15:21:27 -03:00
PhysicsServer2D : : get_singleton ( ) - > end_sync ( ) ;
2020-12-22 09:50:29 +00:00
PhysicsServer2D : : get_singleton ( ) - > step ( physics_step * time_scale ) ;
2014-02-09 22:10:30 -03:00
message_queue - > flush ( ) ;
2020-12-22 09:50:29 +00:00
physics_process_ticks = MAX ( physics_process_ticks , OS : : get_singleton ( ) - > get_ticks_usec ( ) - physics_begin ) ; // keep the largest one for reference
2017-10-21 21:28:08 +07:00
physics_process_max = MAX ( OS : : get_singleton ( ) - > get_ticks_usec ( ) - physics_begin , physics_process_max ) ;
2017-09-30 16:19:07 +02:00
Engine : : get_singleton ( ) - > _physics_frames + + ;
2020-09-21 01:35:20 +02:00
Engine : : get_singleton ( ) - > _in_physics = false ;
2014-02-09 22:10:30 -03:00
}
2020-09-21 01:35:20 +02:00
if ( Input : : get_singleton ( ) - > is_using_input_buffering ( ) & & agile_input_event_flushing ) {
Input : : get_singleton ( ) - > flush_buffered_events ( ) ;
}
2016-09-01 18:58:52 -03:00
2020-12-22 09:50:29 +00:00
uint64_t process_begin = OS : : get_singleton ( ) - > get_ticks_usec ( ) ;
2014-02-09 22:10:30 -03:00
2020-12-22 09:50:29 +00:00
if ( OS : : get_singleton ( ) - > get_main_loop ( ) - > process ( process_step * time_scale ) ) {
2019-03-09 17:06:37 +05:30
exit = true ;
}
2014-02-09 22:10:30 -03:00
message_queue - > flush ( ) ;
2020-03-27 15:21:27 -03:00
RenderingServer : : get_singleton ( ) - > sync ( ) ; //sync if still drawing from previous frames.
2015-06-06 22:06:58 -03:00
2020-07-20 17:35:34 +01:00
if ( DisplayServer : : get_singleton ( ) - > can_any_window_draw ( ) & &
RenderingServer : : get_singleton ( ) - > is_render_loop_enabled ( ) ) {
2014-02-09 22:10:30 -03:00
if ( ( ! force_redraw_requested ) & & OS : : get_singleton ( ) - > is_in_low_processor_usage_mode ( ) ) {
2020-03-27 15:21:27 -03:00
if ( RenderingServer : : get_singleton ( ) - > has_changed ( ) ) {
RenderingServer : : get_singleton ( ) - > draw ( true , scaled_step ) ; // flush visual commands
2017-01-13 12:51:14 -03:00
Engine : : get_singleton ( ) - > frames_drawn + + ;
2014-02-09 22:10:30 -03:00
}
} else {
2020-03-27 15:21:27 -03:00
RenderingServer : : get_singleton ( ) - > draw ( true , scaled_step ) ; // flush visual commands
2017-01-13 12:51:14 -03:00
Engine : : get_singleton ( ) - > frames_drawn + + ;
2014-02-09 22:10:30 -03:00
force_redraw_requested = false ;
}
}
2020-12-22 09:50:29 +00:00
process_ticks = OS : : get_singleton ( ) - > get_ticks_usec ( ) - process_begin ;
process_max = MAX ( process_ticks , process_max ) ;
2016-05-21 21:18:16 -03:00
uint64_t frame_time = OS : : get_singleton ( ) - > get_ticks_usec ( ) - ticks ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < ScriptServer : : get_language_count ( ) ; i + + ) {
2014-02-09 22:10:30 -03:00
ScriptServer : : get_language ( i ) - > frame ( ) ;
}
2018-06-20 21:02:02 -03:00
AudioServer : : get_singleton ( ) - > update ( ) ;
2020-05-14 16:41:43 +02:00
if ( EngineDebugger : : is_active ( ) ) {
2020-12-22 09:50:29 +00:00
EngineDebugger : : get_singleton ( ) - > iteration ( frame_time , process_ticks , physics_process_ticks , physics_step ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
2018-05-28 08:47:09 -03:00
frames + + ;
2020-12-22 09:50:29 +00:00
Engine : : get_singleton ( ) - > _process_frames + + ;
2014-02-09 22:10:30 -03:00
2018-05-28 08:47:09 -03:00
if ( frame > 1000000 ) {
2018-03-21 08:46:05 +01:00
if ( editor | | project_manager ) {
if ( print_fps ) {
2021-11-09 17:17:55 +01:00
print_line ( vformat ( " Editor FPS: %d (%s mspf) " , frames , rtos ( 1000.0 / frames ) . pad_decimals ( 2 ) ) ) ;
2018-03-21 08:46:05 +01:00
}
} else if ( GLOBAL_GET ( " debug/settings/stdout/print_fps " ) | | print_fps ) {
2021-11-09 17:17:55 +01:00
print_line ( vformat ( " Project FPS: %d (%s mspf) " , frames , rtos ( 1000.0 / frames ) . pad_decimals ( 2 ) ) ) ;
2018-03-21 08:46:05 +01:00
}
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
Engine : : get_singleton ( ) - > _fps = frames ;
2020-12-22 09:50:29 +00:00
performance - > set_process_time ( USEC_TO_SEC ( process_max ) ) ;
2017-09-30 16:19:07 +02:00
performance - > set_physics_process_time ( USEC_TO_SEC ( physics_process_max ) ) ;
2020-12-22 09:50:29 +00:00
process_max = 0 ;
2017-09-30 16:19:07 +02:00
physics_process_max = 0 ;
2014-02-09 22:10:30 -03:00
2018-05-28 08:47:09 -03:00
frame % = 1000000 ;
frames = 0 ;
2014-02-09 22:10:30 -03:00
}
2019-01-24 13:09:05 -03:00
iterating - - ;
2019-01-22 13:17:39 -03:00
2021-08-13 00:38:41 +02:00
// Needed for OSs using input buffering regardless accumulation (like Android)
2020-09-21 01:35:20 +02:00
if ( Input : : get_singleton ( ) - > is_using_input_buffering ( ) & & ! agile_input_event_flushing ) {
2021-08-13 00:38:41 +02:00
Input : : get_singleton ( ) - > flush_buffered_events ( ) ;
}
2020-05-14 16:41:43 +02:00
if ( fixed_fps ! = - 1 ) {
2017-08-30 12:40:35 +02:00
return exit ;
2020-05-14 16:41:43 +02:00
}
2017-08-30 12:40:35 +02:00
2020-06-29 20:46:21 +02:00
OS : : get_singleton ( ) - > add_frame_delay ( DisplayServer : : get_singleton ( ) - > window_can_draw ( ) ) ;
2014-02-19 23:35:39 +08:00
2018-02-14 10:23:04 -05:00
# ifdef TOOLS_ENABLED
if ( auto_build_solutions ) {
auto_build_solutions = false ;
2020-01-13 13:55:54 +01:00
// Only relevant when running the editor.
if ( ! editor ) {
2020-07-20 17:35:34 +01:00
ERR_FAIL_V_MSG ( true ,
" Command line option --build-solutions was passed, but no project is being edited. Aborting. " ) ;
2020-01-13 13:55:54 +01:00
}
2018-02-14 10:23:04 -05:00
if ( ! EditorNode : : get_singleton ( ) - > call_build ( ) ) {
2020-07-20 17:35:34 +01:00
ERR_FAIL_V_MSG ( true ,
" Command line option --build-solutions was passed, but the build callback failed. Aborting. " ) ;
2018-02-14 10:23:04 -05:00
}
}
# endif
return exit | | auto_quit ;
2014-02-09 22:10:30 -03:00
}
void Main : : force_redraw ( ) {
force_redraw_requested = true ;
2018-09-20 11:45:05 +02:00
}
/* Engine deinitialization
*
* Responsible for freeing all the memory allocated by previous setup steps,
* so that the engine closes cleanly without leaking memory or crashing.
* The order matters as some of those steps are linked with each other.
*/
2021-02-22 11:06:33 +01:00
void Main : : cleanup ( bool p_force ) {
if ( ! p_force ) {
ERR_FAIL_COND ( ! _start_success ) ;
}
2014-02-09 22:10:30 -03:00
2020-02-27 03:30:20 +01:00
EngineDebugger : : deinitialize ( ) ;
2019-11-29 14:01:56 +01:00
2018-06-11 02:59:53 +02:00
ResourceLoader : : remove_custom_loaders ( ) ;
ResourceSaver : : remove_custom_savers ( ) ;
2020-06-24 16:57:37 +02:00
// Flush before uninitializing the scene, but delete the MessageQueue as late as possible.
2018-01-14 09:50:52 -03:00
message_queue - > flush ( ) ;
2014-02-09 22:10:30 -03:00
OS : : get_singleton ( ) - > delete_main_loop ( ) ;
OS : : get_singleton ( ) - > _cmdline . clear ( ) ;
2017-03-05 16:44:50 +01:00
OS : : get_singleton ( ) - > _execpath = " " ;
OS : : get_singleton ( ) - > _local_clipboard = " " ;
2014-02-09 22:10:30 -03:00
2017-12-14 15:33:54 -03:00
ResourceLoader : : clear_translation_remaps ( ) ;
ResourceLoader : : clear_path_remaps ( ) ;
2017-07-22 16:11:04 -03:00
ScriptServer : : finish_languages ( ) ;
2017-01-15 16:06:14 -03:00
2020-01-13 21:46:41 +01:00
// Sync pending commands that may have been queued from a different thread during ScriptServer finalization
2020-03-27 15:21:27 -03:00
RenderingServer : : get_singleton ( ) - > sync ( ) ;
2020-01-13 21:46:41 +01:00
2021-03-12 19:05:16 +05:30
//clear global shader variables before scene and other graphics stuff are deinitialized.
2020-04-16 23:52:00 -03:00
rendering_server - > global_variables_clear ( ) ;
2020-04-09 00:47:36 +10:00
if ( xr_server ) {
2021-09-28 12:15:00 +10:00
// Now that we're unregistering properly in plugins we need to keep access to xr_server for a little longer
// We do however unset our primary interface
xr_server - > set_primary_interface ( Ref < XRInterface > ( ) ) ;
2017-10-08 00:51:17 +11:00
}
2021-09-11 12:08:12 +10:00
unregister_driver_types ( ) ;
# ifdef TOOLS_ENABLED
EditorNode : : unregister_editor_types ( ) ;
# endif
2018-09-03 14:06:35 +09:30
ImageLoader : : cleanup ( ) ;
2014-02-09 22:10:30 -03:00
unregister_module_types ( ) ;
2017-11-16 01:33:48 +01:00
unregister_platform_apis ( ) ;
2016-03-09 00:00:52 +01:00
unregister_scene_types ( ) ;
2014-02-09 22:10:30 -03:00
unregister_server_types ( ) ;
2021-09-28 12:15:00 +10:00
if ( xr_server ) {
memdelete ( xr_server ) ;
}
2018-01-11 17:01:35 +07:00
if ( audio_server ) {
audio_server - > finish ( ) ;
memdelete ( audio_server ) ;
}
2019-11-29 08:54:39 +02:00
if ( camera_server ) {
memdelete ( camera_server ) ;
}
2014-02-09 22:10:30 -03:00
OS : : get_singleton ( ) - > finalize ( ) ;
2020-03-03 10:36:29 -03:00
2017-10-21 13:02:06 +02:00
finalize_physics ( ) ;
2020-01-10 12:22:34 +01:00
finalize_navigation_server ( ) ;
2020-03-03 10:36:29 -03:00
finalize_display ( ) ;
if ( input ) {
memdelete ( input ) ;
}
2016-03-09 00:00:52 +01:00
2020-05-14 16:41:43 +02:00
if ( packed_data ) {
2014-02-09 22:10:30 -03:00
memdelete ( packed_data ) ;
2020-05-14 16:41:43 +02:00
}
if ( file_access_network_client ) {
2014-02-09 22:10:30 -03:00
memdelete ( file_access_network_client ) ;
2020-05-14 16:41:43 +02:00
}
if ( performance ) {
2014-02-09 22:10:30 -03:00
memdelete ( performance ) ;
2020-05-14 16:41:43 +02:00
}
if ( input_map ) {
2014-02-09 22:10:30 -03:00
memdelete ( input_map ) ;
2020-05-14 16:41:43 +02:00
}
2021-05-24 07:54:05 -04:00
if ( time_singleton ) {
memdelete ( time_singleton ) ;
}
2020-05-14 16:41:43 +02:00
if ( translation_server ) {
2017-03-05 16:44:50 +01:00
memdelete ( translation_server ) ;
2020-05-14 16:41:43 +02:00
}
2021-08-28 00:19:51 +03:00
if ( tsman ) {
memdelete ( tsman ) ;
}
2020-05-14 16:41:43 +02:00
if ( globals ) {
2014-02-09 22:10:30 -03:00
memdelete ( globals ) ;
2020-05-14 16:41:43 +02:00
}
if ( engine ) {
2017-01-13 12:51:14 -03:00
memdelete ( engine ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
2018-07-19 18:58:15 -03:00
if ( OS : : get_singleton ( ) - > is_restart_on_exit_set ( ) ) {
//attempt to restart with arguments
2018-07-20 08:37:10 +02:00
List < String > args = OS : : get_singleton ( ) - > get_restart_on_exit_arguments ( ) ;
2021-11-01 11:12:52 +02:00
OS : : get_singleton ( ) - > create_instance ( args ) ;
2018-07-19 18:58:15 -03:00
OS : : get_singleton ( ) - > set_restart_on_exit ( false , List < String > ( ) ) ; //clear list (uses memory)
}
2020-06-24 16:57:37 +02:00
// Now should be safe to delete MessageQueue (famous last words).
message_queue - > flush ( ) ;
memdelete ( message_queue ) ;
2014-02-09 22:10:30 -03:00
unregister_core_driver_types ( ) ;
unregister_core_types ( ) ;
OS : : get_singleton ( ) - > finalize_core ( ) ;
}