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
/*************************************************************************/
2020-01-01 11:16:22 +01:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 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
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"
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"
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"
# include "core/message_queue.h"
# include "core/os/dir_access.h"
# include "core/os/os.h"
# include "core/project_settings.h"
2014-02-09 22:10:30 -03:00
# include "core/register_core_types.h"
2018-09-11 18:13:45 +02:00
# include "core/translation.h"
# 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"
# include "main/splash_editor.gen.h"
# include "main/tests/test_main.h"
2020-04-20 17:57:38 +02:00
# include "modules/modules_enabled.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-03-27 15:21:27 -03:00
# include "servers/rendering/rendering_server_raster.h"
# include "servers/rendering/rendering_server_wrap_mt.h"
2020-04-09 00:47:36 +10:00
# include "servers/xr_server.h"
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
2020-03-24 09:54:49 +01:00
# include "editor/doc_data.h"
# include "editor/doc_data_class_path.gen.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"
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"
2014-02-09 22:10:30 -03:00
# endif
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 ;
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-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
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
2020-03-14 13:06:39 -03:00
static bool single_window = false ;
2018-09-20 11:45:05 +02:00
static bool editor = false ;
static bool project_manager = false ;
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 ;
# 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 ;
static uint32_t window_flags = 0 ;
static Size2i window_size = Size2i ( 1024 , 600 ) ;
static bool window_vsync_via_compositor = false ;
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 ;
static bool force_lowdpi = false ;
// 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 ;
2015-06-13 22:12:53 -03:00
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 ;
}
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-03-27 15:21:27 -03: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-03-27 15:21:27 -03: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 " ) ;
2020-01-01 11:16:22 +01:00
OS : : get_singleton ( ) - > print ( " (c) 2007-2020 Juan Linietsky, Ariel Manzur. \n " ) ;
OS : : get_singleton ( ) - > print ( " (c) 2014-2020 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 " ) ;
2017-06-21 11:09:30 +02:00
OS : : get_singleton ( ) - > print ( " -h, --help Display this help message. \n " ) ;
2017-09-24 11:32:05 +02:00
OS : : get_singleton ( ) - > print ( " --version Display the version string. \n " ) ;
2017-08-19 16:45:03 +02:00
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 " ) ;
OS : : get_singleton ( ) - > print ( " \n " ) ;
OS : : get_singleton ( ) - > print ( " Run options: \n " ) ;
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
2017-08-19 16:45:03 +02: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 " ) ;
2014-02-09 22:10:30 -03:00
# endif
2018-02-24 18:22:29 +01:00
OS : : get_singleton ( ) - > print ( " -q, --quit Quit after the first iteration. \n " ) ;
2017-08-19 16:45:03 +02:00
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 " ) ;
2017-10-10 23:45:54 +11:00
OS : : get_singleton ( ) - > print ( " -u, --upwards Scan folders upwards for project.godot file. \n " ) ;
2017-08-19 16:45:03 +02:00
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 " ) ;
2020-03-27 10:48:30 +01:00
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 " ) ;
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 " ) ;
OS : : get_singleton ( ) - > print ( " --rendering-driver <driver> Rendering driver (depends on display driver). \n " ) ;
OS : : get_singleton ( ) - > print ( " \n " ) ;
2017-08-19 16:45:03 +02:00
2019-05-19 01:33:13 +02:00
# ifndef SERVER_ENABLED
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Display options: \n " ) ;
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 " ) ;
2017-12-27 20:51:19 +01:00
OS : : get_singleton ( ) - > print ( " -t, --always-on-top Request an always-on-top window. \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " --resolution <W>x<H> Request window resolution. \n " ) ;
OS : : get_singleton ( ) - > print ( " --position <X>,<Y> Request window position. \n " ) ;
2017-09-12 11:40:18 -03:00
OS : : get_singleton ( ) - > print ( " --low-dpi Force low-DPI mode (macOS and Windows only). \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " --no-window Disable window creation (Windows only). Useful together with --script. \n " ) ;
2019-11-06 20:18:55 -06:00
OS : : get_singleton ( ) - > print ( " --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only). \n " ) ;
OS : : get_singleton ( ) - > print ( " --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only). \n " ) ;
2020-03-14 13:06:39 -03:00
OS : : get_singleton ( ) - > print ( " --single-window Use a single window (no separate subwindows). \n " ) ;
2020-05-19 23:34:26 +03:00
OS : : get_singleton ( ) - > print ( " --tablet-driver Tablet input driver ( " ) ;
for ( int i = 0 ; i < OS : : get_singleton ( ) - > get_tablet_driver_count ( ) ; i + + ) {
if ( i ! = 0 )
OS : : get_singleton ( ) - > print ( " , " ) ;
OS : : get_singleton ( ) - > print ( " '%s' " , OS : : get_singleton ( ) - > get_tablet_driver_name ( i ) . utf8 ( ) . get_data ( ) ) ;
}
OS : : get_singleton ( ) - > print ( " ) (Windows only). \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
2019-05-19 01:33:13 +02:00
# endif
2017-08-19 17:47:27 -03:00
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " Debug options: \n " ) ;
2017-06-21 11:09:30 +02:00
OS : : get_singleton ( ) - > print ( " -d, --debug Debug (local stdout debugger). \n " ) ;
2017-08-19 16:45:03 +02:00
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 " ) ;
2019-10-05 10:27:43 -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-03-16 09:37:43 +01:00
OS : : get_singleton ( ) - > print ( " --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007). \n " ) ;
2019-05-19 01:33:13 +02:00
# if defined(DEBUG_ENABLED) && !defined(SERVER_ENABLED)
OS : : get_singleton ( ) - > print ( " --debug-collisions Show collision shapes when running the scene. \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " --debug-navigation Show navigation polygons when running the scene. \n " ) ;
# endif
2017-06-21 11:09:30 +02: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 " ) ;
2017-08-30 12:40:35 +02:00
OS : : get_singleton ( ) - > print ( " --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script. \n " ) ;
2017-09-07 22:01:49 -03:00
OS : : get_singleton ( ) - > print ( " --disable-crash-handler Disable crash handler when supported by the platform code. \n " ) ;
2017-09-24 20:24:41 +02:00
OS : : get_singleton ( ) - > print ( " --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization. \n " ) ;
2018-03-21 08:46:05 +01:00
OS : : get_singleton ( ) - > print ( " --print-fps Print the frames per second to the stdout. \n " ) ;
2017-08-19 16:45:03 +02:00
OS : : get_singleton ( ) - > print ( " \n " ) ;
OS : : get_singleton ( ) - > print ( " Standalone tools: \n " ) ;
OS : : get_singleton ( ) - > print ( " -s, --script <script> Run a script. \n " ) ;
2018-05-31 00:23:23 +02:00
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
2020-01-07 13:29:02 +01: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 " ) ;
2020-01-08 14:22:50 +01:00
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 " ) ;
2020-01-07 13:29:02 +01:00
OS : : get_singleton ( ) - > print ( " --export-debug <preset> <path> Same as --export, but using the debug template. \n " ) ;
2020-01-08 14:22:50 +01:00
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 " ) ;
2017-09-24 11:32:05 +02:00
OS : : get_singleton ( ) - > print ( " --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found. \n " ) ;
2017-06-21 11:09:30 +02:00
OS : : get_singleton ( ) - > print ( " --no-docbase Disallow dumping the base types (used with --doctool). \n " ) ;
2020-01-13 13:55:54 +01:00
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 " ) ;
2017-08-19 16:45:03 +02:00
# ifdef DEBUG_METHODS_ENABLED
OS : : get_singleton ( ) - > print ( " --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings. \n " ) ;
# endif
2020-03-27 10:48:30 +01:00
OS : : get_singleton ( ) - > print ( " --test <test> Run a unit test [ " ) ;
2017-08-19 16:45:03 +02:00
const char * * test_names = tests_get_names ( ) ;
const char * comma = " " ;
while ( * test_names ) {
OS : : get_singleton ( ) - > print ( " %s'%s' " , comma , * test_names ) ;
test_names + + ;
comma = " , " ;
}
2020-03-27 10:48:30 +01:00
OS : : get_singleton ( ) - > print ( " ]. \n " ) ;
2014-02-09 22:10:30 -03:00
# endif
}
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
2017-01-02 23:03:46 -03:00
ClassDB : : init ( ) ;
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-08-07 17:17:31 +07:00
Thread : : _main_thread_id = Thread : : get_caller_id ( ) ;
2014-02-09 22:10:30 -03:00
2017-07-19 17:00:46 -03:00
globals = memnew ( ProjectSettings ) ;
2017-03-05 16:44:50 +01:00
input_map = memnew ( InputMap ) ;
2014-02-09 22:10:30 -03:00
2017-01-05 09:16:00 -03:00
register_core_settings ( ) ; //here globals is present
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
translation_server = memnew ( TranslationServer ) ;
performance = memnew ( Performance ) ;
2017-10-09 23:49:17 +02:00
ClassDB : : register_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
2019-07-01 13:58:57 +02: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
2017-03-05 16:44:50 +01:00
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 = " " ;
2020-05-19 23:34:26 +03:00
String tablet_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-11-06 20:18:55 -06:00
bool saw_vsync_via_compositor_override = 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
2020-03-03 10:36:29 -03:00
bool use_vsync = false ;
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 ) {
OS : : get_singleton ( ) - > print ( " Unknown audio driver '%s', aborting. \n Valid options are " , audio_driver . utf8 ( ) . get_data ( ) ) ;
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-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-03-03 10:36:29 -03: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 {
OS : : get_singleton ( ) - > print ( " Missing video driver argument, aborting. \n " ) ;
goto error ;
}
# ifndef SERVER_ENABLED
} 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 ;
2019-10-05 10:27:43 -03:00
} else if ( I - > get ( ) = = " --gpu-abort " ) { // force windowed window
Engine : : singleton - > abort_on_gpu_errors = true ;
2020-05-19 23:34:26 +03:00
} else if ( I - > get ( ) = = " --tablet-driver " ) {
if ( I - > next ( ) ) {
tablet_driver = I - > next ( ) - > get ( ) ;
bool found = false ;
for ( int i = 0 ; i < OS : : get_singleton ( ) - > get_tablet_driver_count ( ) ; i + + ) {
if ( tablet_driver = = OS : : get_singleton ( ) - > get_tablet_driver_name ( i ) ) {
found = true ;
}
}
if ( ! found ) {
OS : : get_singleton ( ) - > print ( " Unknown tablet driver '%s', aborting. \n " , tablet_driver . utf8 ( ) . get_data ( ) ) ;
goto error ;
}
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
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
2017-08-19 16:45:03 +02: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 ) {
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
2017-08-19 16:45:03 +02: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 ;
}
2019-05-19 01:33:13 +02:00
} else if ( I - > get ( ) = = " --low-dpi " ) { // force low DPI (macOS only)
2015-08-30 23:36:46 -03:00
2019-05-19 01:33:13 +02:00
force_lowdpi = true ;
} else if ( I - > get ( ) = = " --no-window " ) { // disable window creation (Windows only)
2017-12-27 20:51:19 +01:00
2019-05-19 01:33:13 +02:00
OS : : get_singleton ( ) - > set_no_window_mode ( true ) ;
2019-11-06 20:18:55 -06:00
} else if ( I - > get ( ) = = " --enable-vsync-via-compositor " ) {
2020-03-03 10:36:29 -03:00
window_vsync_via_compositor = true ;
2019-11-06 20:18:55 -06:00
saw_vsync_via_compositor_override = true ;
} else if ( I - > get ( ) = = " --disable-vsync-via-compositor " ) {
2020-03-03 10:36:29 -03:00
window_vsync_via_compositor = false ;
2019-11-06 20:18:55 -06:00
saw_vsync_via_compositor_override = true ;
2019-05-19 01:33:13 +02:00
# endif
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 ;
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 ;
2019-08-19 16:14:58 +02:00
# ifdef DEBUG_METHODS_ENABLED
} else if ( I - > get ( ) = = " --gdnative-generate-json-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 ;
// We still pass it to the main arguments since the argument handling itself is not done in this function
main_args . push_back ( I - > get ( ) ) ;
# endif
2020-01-08 14:22:50 +01:00
} else if ( I - > get ( ) = = " --export " | | I - > get ( ) = = " --export-debug " | | I - > get ( ) = = " --export-pack " ) { // Export project
2019-06-28 15:34:09 +03:00
editor = true ;
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 ( ) ) {
2017-01-13 12:51:14 -03:00
Engine : : get_singleton ( ) - > set_time_scale ( I - > next ( ) - > get ( ) . to_double ( ) ) ;
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 ;
2019-05-19 01:33:13 +02:00
# if defined(DEBUG_ENABLED) && !defined(SERVER_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 ;
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
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 ;
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 ) {
OS : : get_singleton ( ) - > print ( " Error: Command line arguments implied opening both editor and project manager, which is not possible. Aborting. \n " ) ;
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 ( ) ;
if ( remotefs ! = " " ) {
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 ) ;
}
2018-05-12 13:21:26 +02:00
if ( globals - > setup ( project_path , main_pack , upwards ) = = 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 " ;
2019-02-22 15:38:49 +01:00
OS : : get_singleton ( ) - > print ( " %s " , error_msg . ascii ( ) . get_data ( ) ) ;
2020-03-12 20:12:34 -03:00
DisplayServer : : 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 ( ) ;
2017-07-17 21:05:38 -03:00
GLOBAL_DEF ( " memory/limits/multithreaded_server/rid_pool_prealloc " , 60 ) ;
2018-10-05 11:43:53 -05: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 ) ;
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 " ) ) ;
GLOBAL_DEF ( " network/limits/debugger/max_queued_messages " , 2048 ) ;
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 " ) ) ;
GLOBAL_DEF ( " network/limits/debugger/max_errors_per_second " , 400 ) ;
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 " ) ) ;
GLOBAL_DEF ( " network/limits/debugger/max_warnings_per_second " , 400 ) ;
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
2017-11-26 14:58:07 -03:00
GLOBAL_DEF ( " logging/file_logging/enable_file_logging " , false ) ;
2020-07-04 16:59:49 +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).
GLOBAL_DEF ( " logging/file_logging/enable_file_logging.pc " , true ) ;
GLOBAL_DEF ( " logging/file_logging/log_path " , " user://logs/godot.log " ) ;
GLOBAL_DEF ( " logging/file_logging/max_log_files " , 5 ) ;
2018-10-05 11:43:53 -05:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " logging/file_logging/max_log_files " , PropertyInfo ( Variant : : INT , " logging/file_logging/max_log_files " , PROPERTY_HINT_RANGE , " 0,20,1,or_greater " ) ) ; //no negative numbers
2017-11-21 16:35:01 +07:00
if ( FileAccess : : get_create_func ( FileAccess : : ACCESS_USERDATA ) & & GLOBAL_GET ( " logging/file_logging/enable_file_logging " ) ) {
String base_path = GLOBAL_GET ( " logging/file_logging/log_path " ) ;
int max_files = GLOBAL_GET ( " logging/file_logging/max_log_files " ) ;
OS : : get_singleton ( ) - > add_logger ( memnew ( RotatedFileLogger ( base_path , max_files ) ) ) ;
}
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 ) {
2018-02-13 18:56:38 +01:00
// Determine if the project manager should be requested
2018-02-26 17:16:29 +01:00
project_manager = main_args . size ( ) = = 0 & & ! found_project ;
2018-02-13 18:56:38 +01:00
}
2014-02-09 22:10:30 -03:00
# endif
2018-02-26 17:16:29 +01:00
if ( main_args . size ( ) = = 0 & & String ( GLOBAL_DEF ( " application/run/main_scene " , " " ) ) = = " " ) {
# ifdef TOOLS_ENABLED
if ( ! editor & & ! project_manager ) {
# endif
OS : : get_singleton ( ) - > print ( " Error: Can't run project: no main scene defined. \n " ) ;
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 {
2016-06-05 01:19:42 -03:00
input_map - > load_from_globals ( ) ; //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
OS : : get_singleton ( ) - > set_cmdline ( execpath , main_args ) ;
2014-02-09 22:10:30 -03:00
2019-07-12 16:18:30 +03:00
GLOBAL_DEF ( " rendering/quality/driver/driver_name " , " Vulkan " ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/quality/driver/driver_name " , PropertyInfo ( Variant : : STRING , " rendering/quality/driver/driver_name " , PROPERTY_HINT_ENUM , " Vulkan,GLES2 " ) ) ;
2020-03-03 10:36:29 -03:00
if ( display_driver = = " " ) {
display_driver = GLOBAL_GET ( " rendering/quality/driver/driver_name " ) ;
2018-03-01 23:17:34 +02:00
}
2014-02-09 22:10:30 -03:00
2019-01-14 18:26:41 +01:00
// Assigning here even though it's GLES2-specific, to be sure that it appears in docs
GLOBAL_DEF ( " rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround " , false ) ;
2017-11-09 13:55:51 -03:00
GLOBAL_DEF ( " display/window/size/width " , 1024 ) ;
2018-10-02 14:51:24 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/width " , PropertyInfo ( Variant : : INT , " display/window/size/width " , PROPERTY_HINT_RANGE , " 0,7680,or_greater " ) ) ; // 8K resolution
2017-11-09 13:55:51 -03:00
GLOBAL_DEF ( " display/window/size/height " , 600 ) ;
2018-10-02 14:51:24 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/height " , PropertyInfo ( Variant : : INT , " display/window/size/height " , PROPERTY_HINT_RANGE , " 0,4320,or_greater " ) ) ; // 8K resolution
2017-11-09 13:55:51 -03:00
GLOBAL_DEF ( " display/window/size/resizable " , true ) ;
GLOBAL_DEF ( " display/window/size/borderless " , false ) ;
GLOBAL_DEF ( " display/window/size/fullscreen " , false ) ;
2017-12-27 20:51:19 +01:00
GLOBAL_DEF ( " display/window/size/always_on_top " , false ) ;
2017-11-09 13:55:51 -03:00
GLOBAL_DEF ( " display/window/size/test_width " , 0 ) ;
2018-10-02 14:51:24 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/test_width " , PropertyInfo ( Variant : : INT , " display/window/size/test_width " , PROPERTY_HINT_RANGE , " 0,7680,or_greater " ) ) ; // 8K resolution
2017-11-09 13:55:51 -03:00
GLOBAL_DEF ( " display/window/size/test_height " , 0 ) ;
2018-10-02 14:51:24 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " display/window/size/test_height " , PropertyInfo ( Variant : : INT , " display/window/size/test_height " , 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 ) {
2020-03-03 10:36:29 -03:00
window_size . width = GLOBAL_GET ( " display/window/size/width " ) ;
window_size . height = GLOBAL_GET ( " display/window/size/height " ) ;
2017-11-09 13:01:29 -03:00
if ( globals - > has_setting ( " display/window/size/test_width " ) & & globals - > has_setting ( " display/window/size/test_height " ) ) {
int tw = globals - > get ( " display/window/size/test_width " ) ;
2019-10-04 10:26:02 -03:00
if ( tw > 0 ) {
2020-03-03 10:36:29 -03:00
window_size . width = tw ;
2019-10-04 10:26:02 -03:00
}
int th = globals - > get ( " display/window/size/test_height " ) ;
if ( th > 0 ) {
2020-03-03 10:36:29 -03:00
window_size . height = th ;
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 " ) ) ) {
window_flags | = DisplayServer : : WINDOW_FLAG_ALWAYS_ON_TOP ;
}
2014-09-15 11:33:30 -03:00
}
2014-02-09 22:10:30 -03:00
2017-11-09 13:01:29 -03:00
if ( ! force_lowdpi ) {
OS : : get_singleton ( ) - > _allow_hidpi = GLOBAL_DEF ( " display/window/dpi/allow_hidpi " , false ) ;
}
2020-03-03 10:36:29 -03:00
use_vsync = GLOBAL_DEF_RST ( " display/window/vsync/use_vsync " , true ) ;
OS : : get_singleton ( ) - > _use_vsync = use_vsync ;
2018-06-25 18:17:19 +03:00
2019-11-06 20:18:55 -06:00
if ( ! saw_vsync_via_compositor_override ) {
// If one of the command line options to enable/disable vsync via the
// window compositor ("--enable-vsync-via-compositor" or
// "--disable-vsync-via-compositor") was present then it overrides the
// project setting.
2020-03-03 10:36:29 -03:00
window_vsync_via_compositor = GLOBAL_DEF ( " display/window/vsync/vsync_via_compositor " , false ) ;
2019-11-06 20:18:55 -06:00
}
2020-03-03 10:36:29 -03:00
OS : : get_singleton ( ) - > _vsync_via_compositor = window_vsync_via_compositor ;
2019-11-06 20:18:55 -06:00
2020-05-19 23:34:26 +03:00
if ( tablet_driver = = " " ) { // specified in project.godot
tablet_driver = GLOBAL_DEF_RST ( " display/window/tablet_driver " , OS : : get_singleton ( ) - > get_tablet_driver_name ( 0 ) ) ;
2020-05-05 14:16:02 +03:00
}
2020-05-19 23:34:26 +03:00
for ( int i = 0 ; i < OS : : get_singleton ( ) - > get_tablet_driver_count ( ) ; i + + ) {
if ( tablet_driver = = OS : : get_singleton ( ) - > get_tablet_driver_name ( i ) ) {
OS : : get_singleton ( ) - > set_current_tablet_driver ( OS : : get_singleton ( ) - > get_tablet_driver_name ( i ) ) ;
break ;
}
}
if ( tablet_driver = = " " ) {
OS : : get_singleton ( ) - > set_current_tablet_driver ( OS : : get_singleton ( ) - > get_tablet_driver_name ( 0 ) ) ;
}
2020-05-05 14:16:02 +03:00
2020-03-03 10:36:29 -03:00
/* todo restore
2019-02-20 14:37:25 +01:00
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);
2020-03-03 10:36:29 -03:00
*/
2017-07-19 17:00:46 -03:00
GLOBAL_DEF ( " rendering/quality/intended_usage/framebuffer_allocation " , 2 ) ;
GLOBAL_DEF ( " rendering/quality/intended_usage/framebuffer_allocation.mobile " , 3 ) ;
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
Engine : : get_singleton ( ) - > _pixel_snap = GLOBAL_DEF ( " rendering/quality/2d/use_pixel_snap " , false ) ;
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 ) {
rtm = GLOBAL_DEF ( " rendering/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 ) {
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
}
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-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 ) ) {
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
}
2017-08-19 16:45:03 +02:00
if ( audio_driver = = " " ) { // specified in project.godot
2020-03-03 10:36:29 -03:00
audio_driver = GLOBAL_DEF_RST ( " audio/driver " , AudioDriverManager : : get_driver ( 0 ) - > get_name ( ) ) ;
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
}
{
2017-07-17 21:05:38 -03:00
String orientation = GLOBAL_DEF ( " display/window/handheld/orientation " , " landscape " ) ;
2014-02-09 22:10:30 -03:00
2020-05-14 16:41:43 +02:00
if ( orientation = = " portrait " ) {
2020-03-03 10:36:29 -03:00
window_orientation = DisplayServer : : SCREEN_PORTRAIT ;
2020-05-14 16:41:43 +02:00
} else if ( orientation = = " reverse_landscape " ) {
2020-03-03 10:36:29 -03:00
window_orientation = DisplayServer : : SCREEN_REVERSE_LANDSCAPE ;
2020-05-14 16:41:43 +02:00
} else if ( orientation = = " reverse_portrait " ) {
2020-03-03 10:36:29 -03:00
window_orientation = DisplayServer : : SCREEN_REVERSE_PORTRAIT ;
2020-05-14 16:41:43 +02:00
} else if ( orientation = = " sensor_landscape " ) {
2020-03-03 10:36:29 -03:00
window_orientation = DisplayServer : : SCREEN_SENSOR_LANDSCAPE ;
2020-05-14 16:41:43 +02:00
} else if ( orientation = = " sensor_portrait " ) {
2020-03-03 10:36:29 -03:00
window_orientation = DisplayServer : : SCREEN_SENSOR_PORTRAIT ;
2020-05-14 16:41:43 +02:00
} else if ( orientation = = " sensor " ) {
2020-03-03 10:36:29 -03:00
window_orientation = DisplayServer : : SCREEN_SENSOR ;
2020-05-14 16:41:43 +02:00
} else {
2020-03-03 10:36:29 -03:00
window_orientation = DisplayServer : : SCREEN_LANDSCAPE ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
}
2018-01-23 06:01:31 +09:00
Engine : : get_singleton ( ) - > set_iterations_per_second ( GLOBAL_DEF ( " physics/common/physics_fps " , 60 ) ) ;
2019-06-12 20:37:51 -07:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " physics/common/physics_fps " , PropertyInfo ( Variant : : INT , " physics/common/physics_fps " , PROPERTY_HINT_RANGE , " 1,120,1,or_greater " ) ) ;
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 ) ) ;
2018-10-05 11:43:53 -05:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " debug/settings/fps/force_fps " , PropertyInfo ( Variant : : INT , " debug/settings/fps/force_fps " , PROPERTY_HINT_RANGE , " 0,120,1,or_greater " ) ) ;
2017-01-05 09:16:00 -03:00
2018-03-21 08:46:05 +01:00
GLOBAL_DEF ( " debug/settings/stdout/print_fps " , 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 ) ;
2018-10-05 11:43:53 -05: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 ) ) ;
2019-05-09 22:40:20 +02:00
OS : : get_singleton ( ) - > set_low_processor_usage_mode_sleep_usec ( GLOBAL_DEF ( " application/run/low_processor_mode_sleep_usec " , 6900 ) ) ; // Roughly 144 FPS
2018-10-05 11:43:53 -05:00
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 ) ;
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-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
}
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 ) {
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 ) ) ;
2017-08-22 17:21:41 +02:00
if ( p_main_tid_override ) {
Thread : : _main_thread_id = p_main_tid_override ;
}
2014-02-09 22:10:30 -03:00
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
/* Iniitalize Display Server */
{
String rendering_driver ; // temp broken
Error err ;
display_server = DisplayServer : : create ( display_driver_idx , rendering_driver , window_mode , window_flags , window_size , err ) ;
if ( err ! = OK ) {
//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
}
display_server = DisplayServer : : create ( display_driver_idx , rendering_driver , window_mode , window_flags , window_size , err ) ;
if ( err = = OK ) {
break ;
}
}
}
if ( ! display_server ) {
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
2020-03-03 10:36:29 -03:00
/* Initialize Visual Server */
2020-03-27 15:21:27 -03:00
rendering_server = memnew ( RenderingServerRaster ) ;
2020-03-03 10:36:29 -03:00
if ( OS : : get_singleton ( ) - > get_render_thread_mode ( ) ! = OS : : RENDER_THREAD_UNSAFE ) {
2020-03-27 15:21:27 -03:00
rendering_server = memnew ( RenderingServerWrapMT ( rendering_server , 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-06-14 18:06:48 +01:00
rendering_server - > set_render_loop_enabled ( ! disable_render_loop ) ;
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 " ) ;
# ifdef JAVASCRIPT_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 ( ) ;
2015-09-03 23:24:55 -03:00
MAIN_PRINT ( " Main: Load Remaps " ) ;
2017-07-17 21:05:38 -03:00
Color clear = GLOBAL_DEF ( " rendering/environment/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!
2017-07-17 21:05:38 -03:00
String boot_logo_path = GLOBAL_DEF ( " application/boot_splash/image " , String ( ) ) ;
bool boot_logo_scale = GLOBAL_DEF ( " application/boot_splash/fullsize " , true ) ;
2019-06-13 22:37:19 +02:00
bool boot_logo_filter = GLOBAL_DEF ( " application/boot_splash/use_filter " , true ) ;
2017-07-19 17:00:46 -03:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/boot_splash/image " , PropertyInfo ( Variant : : STRING , " application/boot_splash/image " , 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
2015-09-03 23:24:55 -03:00
boot_logo_path = boot_logo_path . strip_edges ( ) ;
2018-08-24 09:35:07 +02:00
if ( boot_logo_path ! = String ( ) ) {
2017-05-17 07:36:47 -03:00
boot_logo . instance ( ) ;
2019-02-12 21:10:08 +01:00
Error load_err = ImageLoader : : load_image ( boot_logo_path , boot_logo ) ;
2020-05-14 16:41:43 +02:00
if ( load_err ) {
2019-11-06 17:03:04 +01:00
ERR_PRINT ( " Non-existing or invalid boot splash at ' " + boot_logo_path + " '. Loading default splash. " ) ;
2020-05-14 16:41:43 +02:00
}
2015-04-12 17:55:01 -03:00
}
2014-02-09 22:10:30 -03:00
2018-09-14 21:00:24 +02:00
Color boot_bg_color = GLOBAL_DEF ( " application/boot_splash/bg_color " , boot_splash_bg_color ) ;
2017-05-17 07:36:47 -03:00
if ( boot_logo . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
OS : : get_singleton ( ) - > _msec_splash = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
2020-03-27 15:21:27 -03: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 " ) ;
2020-03-27 15:21:27 -03: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
2017-05-17 07:36:47 -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
# endif
2014-02-09 22:10:30 -03:00
}
2016-04-08 01:30:00 +02:00
MAIN_PRINT ( " Main: DCC " ) ;
2020-03-27 15:21:27 -03:00
RenderingServer : : get_singleton ( ) - > set_default_clear_color ( GLOBAL_DEF ( " rendering/environment/default_clear_color " , Color ( 0.3 , 0.3 , 0.3 ) ) ) ;
2016-04-08 01:30:00 +02:00
MAIN_PRINT ( " Main: END " ) ;
2017-07-17 21:05:38 -03:00
GLOBAL_DEF ( " application/config/icon " , String ( ) ) ;
2017-07-19 17:00:46 -03:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/config/icon " , PropertyInfo ( Variant : : STRING , " application/config/icon " , PROPERTY_HINT_FILE , " *.png,*.webp " ) ) ;
2014-02-09 22:10:30 -03:00
2019-05-17 16:43:56 +03:00
GLOBAL_DEF ( " application/config/macos_native_icon " , String ( ) ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/config/macos_native_icon " , PropertyInfo ( Variant : : STRING , " application/config/macos_native_icon " , PROPERTY_HINT_FILE , " *.icns " ) ) ;
GLOBAL_DEF ( " application/config/windows_native_icon " , String ( ) ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " application/config/windows_native_icon " , PropertyInfo ( Variant : : STRING , " application/config/windows_native_icon " , PROPERTY_HINT_FILE , " *.ico " ) ) ;
2020-04-28 15:19:37 +02:00
Input * id = Input : : get_singleton ( ) ;
2018-02-24 03:04:30 +01:00
if ( id ) {
2018-05-10 14:26:28 +09: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
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: Load Remaps " ) ;
MAIN_PRINT ( " Main: Load Scene Types " ) ;
register_scene_types ( ) ;
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 ) ) ;
2017-07-19 17:00:46 -03: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 ( ) ) {
2019-06-11 15:43:37 -03: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
}
}
2014-02-09 22:10:30 -03:00
# ifdef TOOLS_ENABLED
2017-01-02 23:03:46 -03:00
ClassDB : : set_current_api ( ClassDB : : API_EDITOR ) ;
2014-02-09 22:10:30 -03:00
EditorNode : : register_editor_types ( ) ;
2016-10-01 22:04:10 +02:00
2017-01-02 23:03:46 -03:00
ClassDB : : set_current_api ( ClassDB : : API_CORE ) ;
2016-09-14 19:37:37 -03:00
2014-02-09 22:10:30 -03:00
# endif
2017-10-21 13:02:06 +02:00
MAIN_PRINT ( " Main: Load Modules, Physics, Drivers, Scripts " ) ;
2014-02-09 22:10:30 -03:00
2017-11-16 01:33:48 +01:00
register_platform_apis ( ) ;
2014-02-09 22:10:30 -03:00
register_module_types ( ) ;
2017-10-21 13:02:06 +02:00
2019-11-29 08:54:39 +02:00
camera_server = CameraServer : : create ( ) ;
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 ( ) ;
2014-02-09 22:10:30 -03:00
MAIN_PRINT ( " Main: Load Translations " ) ;
translation_server - > setup ( ) ; //register translations, load them, etc.
2017-03-05 16:44:50 +01:00
if ( locale ! = " " ) {
2014-02-09 22:10:30 -03:00
translation_server - > set_locale ( locale ) ;
}
translation_server - > load_translations ( ) ;
2017-06-28 17:00:18 -03:00
ResourceLoader : : load_translation_remaps ( ) ; //load remaps for resources
2014-02-09 22:10:30 -03:00
2017-12-14 15:33:54 -03:00
ResourceLoader : : load_path_remaps ( ) ;
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.
// If running on editor, dont load the textures because the editor
// 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 ;
locale = String ( ) ;
2014-02-09 22:10:30 -03:00
2017-01-02 23:03:46 -03:00
ClassDB : : set_current_api ( ClassDB : : API_NONE ) ; //no more api is 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 ;
2014-02-09 22:10:30 -03:00
String doc_tool ;
2016-12-16 19:12:22 +08:00
List < String > removal_docs ;
2019-10-29 01:42:57 +01:00
String positional_arg ;
2014-02-09 22:10:30 -03:00
String game_path ;
String script ;
String test ;
2020-01-08 14:22:50 +01:00
bool check_only = false ;
# ifdef TOOLS_ENABLED
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 ( ) ) ;
2018-02-11 00:03:31 +01:00
2014-02-09 22:10:30 -03:00
List < String > args = OS : : get_singleton ( ) - > get_cmdline_args ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < args . size ( ) ; i + + ) {
2015-11-01 17:50:44 +01:00
//parameters that do not have an argument to the right
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
2019-10-29 01:42:57 +01:00
} else if ( args [ i ] . length ( ) & & args [ i ] [ 0 ] ! = ' - ' & & positional_arg = = " " ) {
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
}
2015-09-16 15:51:19 -05:00
//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 ] ;
2017-06-21 11:09:30 +02:00
} else if ( args [ i ] = = " --test " ) {
2017-03-05 16:44:50 +01:00
test = args [ i + 1 ] ;
2018-02-16 19:40:22 +01:00
# ifdef TOOLS_ENABLED
} else if ( args [ i ] = = " --doctool " ) {
doc_tool = args [ i + 1 ] ;
2020-05-14 16:41:43 +02:00
for ( int j = i + 2 ; j < args . size ( ) ; j + + ) {
2018-02-16 19:40:22 +01:00
removal_docs . push_back ( args [ j ] ) ;
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
}
2014-02-09 22:10:30 -03:00
}
}
String main_loop_type ;
# ifdef TOOLS_ENABLED
2017-03-05 16:44:50 +01:00
if ( doc_tool ! = " " ) {
2019-06-01 16:42:22 +03:00
Engine : : get_singleton ( ) - > set_editor_hint ( true ) ; // Needed to instance editor-only classes for their default values
2017-09-12 17:42:36 -03:00
{
DirAccessRef da = DirAccess : : open ( doc_tool ) ;
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 ) ;
GLOBAL_DEF ( " mono/unhandled_exception_policy " , 0 ) ;
2020-06-18 12:05:44 +02:00
// From editor/csharp_project.cpp.
GLOBAL_DEF ( " mono/project/auto_update_project " , true ) ;
2020-04-20 17:57:38 +02:00
# endif
2014-02-09 22:10:30 -03:00
DocData doc ;
doc . generate ( doc_base ) ;
DocData 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 ;
if ( path . is_rel_path ( ) ) {
path = doc_tool . plus_file ( path ) ;
}
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 ) ;
da - > make_dir_recursive ( path ) ;
memdelete ( da ) ;
2017-09-12 17:42:36 -03:00
docsrc . load_classes ( path ) ;
2017-09-13 09:13:23 +02:00
print_line ( " Loading docs from: " + path ) ;
2017-09-12 17:42:36 -03:00
}
2014-02-09 22:10:30 -03:00
}
2017-09-12 17:42:36 -03:00
String index_path = doc_tool . 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 ) ;
da - > make_dir_recursive ( index_path ) ;
memdelete ( da ) ;
2017-09-12 17:42:36 -03:00
docsrc . load_classes ( index_path ) ;
checked_paths . insert ( index_path ) ;
2017-09-13 09:13:23 +02:00
print_line ( " Loading docs from: " + index_path ) ;
2017-09-12 17:42:36 -03:00
2018-04-22 19:36:01 +02:00
print_line ( " Merging docs... " ) ;
2017-09-12 17:42:36 -03:00
doc . merge_from ( docsrc ) ;
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 ( ) ) ;
2017-09-12 17:42:36 -03:00
DocData : : erase_classes ( E - > get ( ) ) ;
2016-12-16 19:12:22 +08:00
}
2018-04-22 19:36:01 +02:00
print_line ( " Generating new docs... " ) ;
2017-09-13 09:13:23 +02:00
doc . save_classes ( index_path , doc_data_classes ) ;
2014-02-09 22:10:30 -03:00
return false ;
}
2017-08-14 20:15:06 +07:00
if ( _export_preset ! = " " ) {
2019-10-29 01:42:57 +01:00
if ( positional_arg = = " " ) {
2020-01-08 14:22:50 +01:00
String err = " Command line includes export parameter option, but no destination path was given. \n " ;
2017-03-05 16:44:50 +01:00
err + = " Please specify the binary's file path to export to. Aborting export. " ;
2020-01-07 13:29:02 +01:00
ERR_PRINT ( err ) ;
2015-11-26 21:59:25 +01:00
return false ;
}
}
2020-01-08 14:22:50 +01:00
# endif
2015-11-26 21:59:25 +01:00
2017-07-17 21:05:38 -03:00
if ( script = = " " & & game_path = = " " & & String ( GLOBAL_DEF ( " application/run/main_scene " , " " ) ) ! = " " ) {
game_path = GLOBAL_DEF ( " application/run/main_scene " , " " ) ;
2014-02-09 22:10:30 -03:00
}
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 ) ;
2014-02-09 22:10:30 -03:00
} ;
2017-03-05 16:44:50 +01:00
if ( test ! = " " ) {
2019-09-26 14:56:27 +03:00
# ifdef TOOLS_ENABLED
2017-03-05 16:44:50 +01:00
main_loop = test_main ( test , args ) ;
2014-02-09 22:10:30 -03:00
2020-05-14 16:41:43 +02:00
if ( ! main_loop ) {
2014-02-09 22:10:30 -03:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-09 22:10:30 -03:00
# endif
2017-03-05 16:44:50 +01:00
} else if ( script ! = " " ) {
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 ( ) ) {
OS : : get_singleton ( ) - > set_exit_code ( 1 ) ;
}
2018-05-31 00:23:23 +02:00
return false ;
}
2020-03-06 22:57:02 +01:00
if ( script_res - > can_instance ( ) ) {
2017-03-05 16:44:50 +01:00
StringName instance_type = script_res - > get_instance_base_type ( ) ;
2017-01-02 23:03:46 -03:00
Object * obj = ClassDB : : instance ( 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
}
2020-03-06 22:57:02 +01:00
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
}
script_loop - > set_init_script ( script_res ) ;
2017-03-05 16:44:50 +01:00
main_loop = script_loop ;
2014-02-09 22:10:30 -03:00
} else {
return false ;
}
} else {
2017-07-17 21:05:38 -03:00
main_loop_type = GLOBAL_DEF ( " application/run/main_loop_type " , " " ) ;
2014-02-09 22:10:30 -03:00
}
2016-03-09 00:00:52 +01:00
2020-05-14 16:41:43 +02:00
if ( ! main_loop & & main_loop_type = = " " ) {
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 ) ) {
2020-03-03 10:36:29 -03:00
DisplayServer : : get_singleton ( ) - > alert ( " Error: MainLoop type doesn't exist: " + main_loop_type ) ;
2014-02-09 22:10:30 -03:00
return false ;
} else {
2017-01-02 23:03:46 -03:00
Object * ml = ClassDB : : instance ( 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
2020-03-28 21:56:50 +01:00
bool embed_subwindows = GLOBAL_DEF ( " display/window/subwindows/embed_subwindows " , false ) ;
if ( 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
2018-05-01 11:06:23 -03:00
if ( game_path ! = " " | | script ! = " " ) {
//autoload
2020-06-17 20:45:08 -03:00
Map < 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
2020-06-17 20:45:08 -03:00
for ( Map < 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 ;
2020-06-17 20:45:08 -03:00
for ( Map < 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 ;
n = ps - > instance ( ) ;
} 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
Object * obj = ClassDB : : instance ( ibt ) ;
2020-04-02 01:20:12 +02: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
}
}
}
for ( List < Node * > : : Element * E = to_add . front ( ) ; E ; E = E - > next ( ) ) {
sml - > get_root ( ) - > add_child ( E - > get ( ) ) ;
}
}
}
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 ) ;
2017-08-14 20:15:06 +07:00
if ( _export_preset ! = " " ) {
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
2019-09-06 22:51:27 -03:00
{
int directional_atlas_size = GLOBAL_GET ( " rendering/quality/directional_shadow/size " ) ;
2020-03-27 15:21:27 -03:00
RenderingServer : : get_singleton ( ) - > directional_shadow_atlas_set_size ( directional_atlas_size ) ;
2019-09-06 22:51:27 -03:00
}
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
2017-07-17 21:05:38 -03:00
String stretch_mode = GLOBAL_DEF ( " display/window/stretch/mode " , " disabled " ) ;
String stretch_aspect = GLOBAL_DEF ( " display/window/stretch/aspect " , " ignore " ) ;
Size2i stretch_size = Size2 ( GLOBAL_DEF ( " display/window/size/width " , 0 ) , GLOBAL_DEF ( " display/window/size/height " , 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 ) ;
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
2017-07-17 21:05:38 -03:00
int shadow_atlas_size = GLOBAL_GET ( " rendering/quality/shadow_atlas/size " ) ;
int shadow_atlas_q0_subdiv = GLOBAL_GET ( " rendering/quality/shadow_atlas/quadrant_0_subdiv " ) ;
int shadow_atlas_q1_subdiv = GLOBAL_GET ( " rendering/quality/shadow_atlas/quadrant_1_subdiv " ) ;
int shadow_atlas_q2_subdiv = GLOBAL_GET ( " rendering/quality/shadow_atlas/quadrant_2_subdiv " ) ;
int shadow_atlas_q3_subdiv = GLOBAL_GET ( " rendering/quality/shadow_atlas/quadrant_3_subdiv " ) ;
2016-11-09 23:55:06 -03:00
sml - > get_root ( ) - > set_shadow_atlas_size ( shadow_atlas_size ) ;
2017-03-05 16:44:50 +01:00
sml - > get_root ( ) - > set_shadow_atlas_quadrant_subdiv ( 0 , Viewport : : ShadowAtlasQuadrantSubdiv ( shadow_atlas_q0_subdiv ) ) ;
sml - > get_root ( ) - > set_shadow_atlas_quadrant_subdiv ( 1 , Viewport : : ShadowAtlasQuadrantSubdiv ( shadow_atlas_q1_subdiv ) ) ;
sml - > get_root ( ) - > set_shadow_atlas_quadrant_subdiv ( 2 , Viewport : : ShadowAtlasQuadrantSubdiv ( shadow_atlas_q2_subdiv ) ) ;
sml - > get_root ( ) - > set_shadow_atlas_quadrant_subdiv ( 3 , Viewport : : ShadowAtlasQuadrantSubdiv ( shadow_atlas_q3_subdiv ) ) ;
2014-02-09 22:10:30 -03:00
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 ) ;
2018-04-19 01:25:25 +02:00
bool font_oversampling = GLOBAL_DEF ( " rendering/quality/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
2019-06-24 22:24:07 -03:00
int texture_filter = GLOBAL_DEF ( " rendering/canvas_textures/default_texture_filter " , 1 ) ;
int texture_repeat = GLOBAL_DEF ( " rendering/canvas_textures/default_texture_repeat " , 0 ) ;
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 ) ) ;
2014-02-09 22:10:30 -03:00
} else {
2017-07-17 21:05:38 -03:00
GLOBAL_DEF ( " display/window/stretch/mode " , " disabled " ) ;
2020-07-02 17:15:11 -03: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 " ) ) ;
2017-07-17 21:05:38 -03:00
GLOBAL_DEF ( " display/window/stretch/aspect " , " ignore " ) ;
2017-08-09 10:53:38 +03: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 " ) ) ;
2019-02-25 16:53:33 +01:00
GLOBAL_DEF ( " display/window/stretch/shrink " , 1.0 ) ;
2020-02-24 15:20:53 -03: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 ) ) ;
2017-09-07 11:22:07 -03:00
GLOBAL_DEF ( " gui/common/snap_controls_to_pixels " , true ) ;
2018-04-19 01:25:25 +02:00
GLOBAL_DEF ( " rendering/quality/dynamic_fonts/use_oversampling " , true ) ;
2019-06-24 22:24:07 -03:00
GLOBAL_DEF ( " rendering/canvas_textures/default_texture_filter " , 1 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/canvas_textures/default_texture_filter " , PropertyInfo ( Variant : : INT , " rendering/canvas_textures/default_texture_filter " , PROPERTY_HINT_ENUM , " Nearest,Linear,MipmapLinear,MipmapNearest " ) ) ;
GLOBAL_DEF ( " rendering/canvas_textures/default_texture_repeat " , 0 ) ;
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " rendering/canvas_textures/default_texture_repeat " , PropertyInfo ( Variant : : INT , " rendering/canvas_textures/default_texture_repeat " , PROPERTY_HINT_ENUM , " Disable,Enable,Mirror " ) ) ;
2014-02-09 22:10:30 -03:00
}
2020-05-22 01:55:28 +02:00
# ifdef TOOLS_ENABLED
if ( editor ) {
bool editor_embed_subwindows = EditorSettings : : get_singleton ( ) - > get_setting ( " interface/editor/single_window_mode " ) ;
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 ;
2018-02-13 18:56:38 +01:00
if ( game_path ! = " " & & ! 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:// " ) ) {
2017-03-05 16:44:50 +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 ) {
2019-06-16 13:31:57 +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 ) {
2018-09-21 00:14:04 -03:00
if ( game_path ! = GLOBAL_GET ( " application/run/main_scene " ) | | ! editor_node - > has_scenes_in_session ( ) ) {
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 ) ;
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
2017-03-05 16:44:50 +01:00
if ( game_path ! = " " ) {
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 ( ) ) {
2017-03-05 16:44:50 +01:00
scene = scenedata - > instance ( ) ;
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() " ) ;
if ( mac_iconpath ! = " " ) {
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() " ) ;
if ( win_iconpath ! = " " ) {
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() " ) ;
2019-05-17 16:43:56 +03:00
if ( ( iconpath ! = " " ) & & ( ! hasicon ) ) {
2017-05-17 07:36:47 -03:00
Ref < Image > icon ;
2017-08-11 19:13:17 +02:00
icon . instance ( ) ;
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
2018-02-13 18:56:38 +01:00
if ( project_manager | | ( script = = " " & & test = = " " & & game_path = = " " & & ! editor ) ) {
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 ) ;
2018-12-18 14:17:43 +01:00
project_manager = true ;
2014-02-09 22:10:30 -03:00
}
2018-09-15 14:45:54 +02:00
if ( project_manager | | editor ) {
2020-05-01 09:34:23 -03:00
if ( DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_CONSOLE_WINDOW ) ) {
// Hide console window if requested (Windows-only).
bool hide_console = EditorSettings : : get_singleton ( ) - > get_setting ( " interface/editor/hide_console_window " ) ;
DisplayServer : : get_singleton ( ) - > console_set_visible ( ! hide_console ) ;
}
2019-07-19 15:29:57 +02:00
// Load SSL Certificates from Editor Settings (or builtin)
Crypto : : load_default_certificates ( EditorSettings : : get_singleton ( ) - > get_setting ( " network/ssl/editor_ssl_certificates " ) . operator String ( ) ) ;
}
2014-02-09 22:10:30 -03:00
# endif
}
2017-09-15 13:41:11 -03:00
if ( ! hasicon ) {
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
return true ;
}
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 ;
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 ;
2017-03-05 16:44:50 +01:00
static uint64_t idle_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
2017-03-05 16:44:50 +01:00
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
2017-03-05 16:44:50 +01:00
uint64_t ticks_elapsed = ticks - last_ticks ;
2014-02-09 22:10:30 -03:00
2018-02-11 00:03:31 +01:00
int physics_fps = Engine : : get_singleton ( ) - > get_iterations_per_second ( ) ;
float frame_slice = 1.0 / physics_fps ;
2017-08-30 12:40:35 +02:00
2018-05-09 08:11:43 +02:00
float time_scale = Engine : : get_singleton ( ) - > get_time_scale ( ) ;
2018-05-15 17:12:35 -03:00
MainFrameTime advance = main_timer_sync . advance ( frame_slice , physics_fps ) ;
double step = advance . idle_step ;
2018-05-09 08:11:43 +02:00
double scaled_step = step * time_scale ;
2015-04-14 22:05:14 -03:00
2017-07-15 01:23:10 -03:00
Engine : : get_singleton ( ) - > _frame_step = 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 ;
2017-03-05 16:44:50 +01:00
uint64_t idle_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 ) {
step - = ( advance . physics_steps - max_physics_steps ) * frame_slice ;
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
2017-09-30 16:19:07 +02:00
Engine : : get_singleton ( ) - > _in_physics = true ;
2016-09-01 18:58:52 -03:00
2018-02-11 00:03:31 +01:00
for ( int iters = 0 ; iters < advance . physics_steps ; + + iters ) {
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
2020-03-27 15:21:27 -03:00
PhysicsServer3D : : get_singleton ( ) - > sync ( ) ;
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
2017-03-05 16:44:50 +01:00
if ( OS : : get_singleton ( ) - > get_main_loop ( ) - > iteration ( frame_slice * time_scale ) ) {
exit = true ;
2014-02-09 22:10:30 -03:00
break ;
}
2020-03-27 15:21:27 -03:00
NavigationServer3D : : get_singleton_mut ( ) - > process ( frame_slice * 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
2020-03-27 15:21:27 -03:00
PhysicsServer3D : : get_singleton ( ) - > step ( frame_slice * time_scale ) ;
2015-05-26 01:05:08 -03:00
2020-03-27 15:21:27 -03:00
PhysicsServer2D : : get_singleton ( ) - > end_sync ( ) ;
PhysicsServer2D : : get_singleton ( ) - > step ( frame_slice * time_scale ) ;
2014-02-09 22:10:30 -03:00
message_queue - > flush ( ) ;
2017-10-21 21:28:08 +07:00
physics_process_ticks = MAX ( physics_process_ticks , OS : : get_singleton ( ) - > get_ticks_usec ( ) - physics_begin ) ; // keep the largest one for reference
physics_process_max = MAX ( OS : : get_singleton ( ) - > get_ticks_usec ( ) - physics_begin , physics_process_max ) ;
2017-09-30 16:19:07 +02:00
Engine : : get_singleton ( ) - > _physics_frames + + ;
2014-02-09 22:10:30 -03:00
}
2017-09-30 16:19:07 +02:00
Engine : : get_singleton ( ) - > _in_physics = false ;
2016-09-01 18:58:52 -03:00
2014-02-09 22:10:30 -03:00
uint64_t idle_begin = OS : : get_singleton ( ) - > get_ticks_usec ( ) ;
2019-03-09 17:06:37 +05:30
if ( OS : : get_singleton ( ) - > get_main_loop ( ) - > idle ( step * time_scale ) ) {
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-06-14 18:06:48 +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 ;
}
}
2017-03-05 16:44:50 +01:00
idle_process_ticks = OS : : get_singleton ( ) - > get_ticks_usec ( ) - idle_begin ;
idle_process_max = MAX ( idle_process_ticks , idle_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-02-27 03:30:20 +01:00
EngineDebugger : : get_singleton ( ) - > iteration ( frame_time , idle_process_ticks , physics_process_ticks , frame_slice ) ;
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 + + ;
2017-01-13 12:51:14 -03:00
Engine : : get_singleton ( ) - > _idle_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 ) {
print_line ( " Editor FPS: " + itos ( frames ) ) ;
}
} else if ( GLOBAL_GET ( " debug/settings/stdout/print_fps " ) | | print_fps ) {
print_line ( " Game FPS: " + itos ( frames ) ) ;
}
2014-02-09 22:10:30 -03:00
2017-03-05 16:44:50 +01:00
Engine : : get_singleton ( ) - > _fps = frames ;
2016-05-21 21:18:16 -03:00
performance - > set_process_time ( USEC_TO_SEC ( idle_process_max ) ) ;
2017-09-30 16:19:07 +02:00
performance - > set_physics_process_time ( USEC_TO_SEC ( physics_process_max ) ) ;
2017-03-05 16:44:50 +01:00
idle_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
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 ) {
ERR_FAIL_V_MSG ( true , " Command line option --build-solutions was passed, but no project is being edited. Aborting. " ) ;
}
2018-02-14 10:23:04 -05:00
if ( ! EditorNode : : get_singleton ( ) - > call_build ( ) ) {
2020-01-13 13:55:54 +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.
*/
2014-02-09 22:10:30 -03:00
void Main : : cleanup ( ) {
ERR_FAIL_COND ( ! _start_success ) ;
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
2020-04-16 23:52:00 -03:00
//clear global shader variables before scene and other graphics stuff is deinitialized.
rendering_server - > global_variables_clear ( ) ;
2014-02-25 09:31:47 -03:00
# ifdef TOOLS_ENABLED
EditorNode : : unregister_editor_types ( ) ;
# endif
2020-04-09 00:47:36 +10:00
if ( xr_server ) {
2017-10-08 00:51:17 +11:00
// cleanup now before we pull the rug from underneath...
2020-04-09 00:47:36 +10:00
memdelete ( xr_server ) ;
2017-10-08 00:51:17 +11:00
}
2018-09-03 14:06:35 +09:30
ImageLoader : : cleanup ( ) ;
2016-03-09 00:00:52 +01:00
unregister_driver_types ( ) ;
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 ( ) ;
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
}
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
}
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
String exec = OS : : get_singleton ( ) - > get_executable_path ( ) ;
2018-07-20 08:37:10 +02:00
List < String > args = OS : : get_singleton ( ) - > get_restart_on_exit_arguments ( ) ;
2018-07-19 18:58:15 -03:00
OS : : ProcessID pid = 0 ;
OS : : get_singleton ( ) - > execute ( exec , args , false , & pid ) ;
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 ( ) ;
}