diff options
Diffstat (limited to 'main/main.cpp')
-rw-r--r-- | main/main.cpp | 199 |
1 files changed, 128 insertions, 71 deletions
diff --git a/main/main.cpp b/main/main.cpp index 9978be7ab7..ced8d7227a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -262,25 +262,20 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" -h, --help Display this help message.\n"); OS::get_singleton()->print(" --version Display the version string.\n"); OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n"); - OS::get_singleton()->print( - " --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n"); + 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"); #ifdef TOOLS_ENABLED OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n"); - OS::get_singleton()->print( - " -p, --project-manager Start the project manager, even if a project is auto-detected.\n"); + OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n"); #endif OS::get_singleton()->print(" -q, --quit Quit after the first iteration.\n"); - OS::get_singleton()->print( - " -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n"); - OS::get_singleton()->print( - " --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n"); + OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n"); + OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n"); OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n"); OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n"); - OS::get_singleton()->print( - " --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n"); + OS::get_singleton()->print(" --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"); @@ -321,12 +316,9 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n"); OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n"); OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n"); - OS::get_singleton()->print( - " --no-window Disable window creation (Windows only). Useful together with --script.\n"); - 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"); + OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n"); + 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"); OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n"); OS::get_singleton()->print(" --tablet-driver Tablet input driver ("); for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) { @@ -340,77 +332,131 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print("Debug options:\n"); OS::get_singleton()->print(" -d, --debug Debug (local stdout debugger).\n"); - OS::get_singleton()->print( - " -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n"); + OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n"); OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n"); - OS::get_singleton()->print( - " --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n"); - OS::get_singleton()->print( - " --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n"); + OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n"); + OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n"); #if defined(DEBUG_ENABLED) && !defined(SERVER_ENABLED) OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n"); OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n"); #endif - OS::get_singleton()->print( - " --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n"); - OS::get_singleton()->print( - " --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n"); - OS::get_singleton()->print( - " --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n"); - OS::get_singleton()->print( - " --disable-crash-handler Disable crash handler when supported by the platform code.\n"); - OS::get_singleton()->print( - " --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n"); + OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n"); + OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n"); + OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n"); + OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n"); + OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n"); OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n"); OS::get_singleton()->print("\n"); OS::get_singleton()->print("Standalone tools:\n"); OS::get_singleton()->print(" -s, --script <script> Run a script.\n"); - OS::get_singleton()->print( - " --check-only Only parse for errors and quit (use with --script).\n"); + OS::get_singleton()->print(" --check-only Only parse for errors and quit (use with --script).\n"); #ifdef TOOLS_ENABLED - OS::get_singleton()->print( - " --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg.\n"); - OS::get_singleton()->print( - " <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n"); + OS::get_singleton()->print(" --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg.\n"); + OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n"); OS::get_singleton()->print(" --export-debug <preset> <path> Same as --export, but using the debug template.\n"); - OS::get_singleton()->print( - " --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n"); - 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"); - OS::get_singleton()->print( - " --no-docbase Disallow dumping the base types (used with --doctool).\n"); - OS::get_singleton()->print( - " --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n"); + OS::get_singleton()->print(" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n"); + OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n"); + OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n"); + OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n"); #ifdef DEBUG_METHODS_ENABLED - OS::get_singleton()->print( - " --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n"); + OS::get_singleton()->print(" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n"); #endif #ifdef TESTS_ENABLED - OS::get_singleton()->print(" --test <test> Run a unit test ["); - 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 = ", "; - } - OS::get_singleton()->print("].\n"); + OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n"); #endif OS::get_singleton()->print("\n"); #endif } +#ifdef TESTS_ENABLED +// The order is the same as in `Main::setup()`, only core and some editor types +// are initialized here. This also combines `Main::setup2()` initialization. +Error Main::test_setup() { + OS::get_singleton()->initialize(); + + engine = memnew(Engine); + + ClassDB::init(); + + register_core_types(); + register_core_driver_types(); + + globals = memnew(ProjectSettings); + + GLOBAL_DEF("debug/settings/crash_handler/message", + String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); + + // From `Main::setup2()`. + preregister_module_types(); + preregister_server_types(); + + register_core_singletons(); + + register_server_types(); + register_scene_types(); + +#ifdef TOOLS_ENABLED + ClassDB::set_current_api(ClassDB::API_EDITOR); + EditorNode::register_editor_types(); + + ClassDB::set_current_api(ClassDB::API_CORE); +#endif + register_platform_apis(); + + register_module_types(); + register_driver_types(); + + ClassDB::set_current_api(ClassDB::API_NONE); + + _start_success = true; + + return OK; +} +// The order is the same as in `Main::cleanup()`. +void Main::test_cleanup() { + ERR_FAIL_COND(!_start_success); + + EngineDebugger::deinitialize(); + + ResourceLoader::remove_custom_loaders(); + ResourceSaver::remove_custom_savers(); + +#ifdef TOOLS_ENABLED + EditorNode::unregister_editor_types(); +#endif + unregister_driver_types(); + unregister_module_types(); + unregister_platform_apis(); + unregister_scene_types(); + unregister_server_types(); + + OS::get_singleton()->finalize(); + + if (globals) { + memdelete(globals); + } + if (engine) { + memdelete(engine); + } + + unregister_core_driver_types(); + unregister_core_types(); + + OS::get_singleton()->finalize_core(); +} +#endif + int Main::test_entrypoint(int argc, char *argv[], bool &tests_need_run) { #ifdef TESTS_ENABLED for (int x = 0; x < argc; x++) { - if (strncmp(argv[x], "--test", 6) == 0) { + if ((strncmp(argv[x], "--test", 6) == 0) && (strlen(argv[x]) == 6)) { tests_need_run = true; - OS::get_singleton()->initialize(); - StringName::setup(); + // TODO: need to come up with different test contexts. + // Not every test requires high-level functionality like `ClassDB`. + test_setup(); int status = test_main(argc, argv); - StringName::cleanup(); - // TODO: fix OS::singleton cleanup + test_cleanup(); return status; } } @@ -1111,14 +1157,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph 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")); + PROPERTY_HINT_ENUM, "Vulkan")); if (display_driver == "") { display_driver = GLOBAL_GET("rendering/quality/driver/driver_name"); } - // 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); - GLOBAL_DEF("display/window/size/width", 1024); ProjectSettings::get_singleton()->set_custom_property_info("display/window/size/width", PropertyInfo(Variant::INT, "display/window/size/width", @@ -1175,7 +1218,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } if (bool(GLOBAL_GET("display/window/size/always_on_top"))) { - window_flags |= DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP; + window_flags |= DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP_BIT; } } @@ -1762,7 +1805,6 @@ bool Main::start() { } } - String main_loop_type; #ifdef TOOLS_ENABLED if (doc_tool != "") { Engine::get_singleton()->set_editor_hint( @@ -1857,6 +1899,7 @@ bool Main::start() { if (editor) { main_loop = memnew(SceneTree); }; + String main_loop_type = GLOBAL_DEF("application/run/main_loop_type", "SceneTree"); if (script != "") { Ref<Script> script_res = ResourceLoader::load(script); @@ -1887,9 +1930,23 @@ bool Main::start() { } else { return false; } - - } else { - main_loop_type = GLOBAL_DEF("application/run/main_loop_type", ""); + } else { // Not based on script path. + if (!editor && !ClassDB::class_exists(main_loop_type) && ScriptServer::is_global_class(main_loop_type)) { + String script_path = ScriptServer::get_global_class_path(main_loop_type); + Ref<Script> script_res = ResourceLoader::load(script_path); + StringName script_base = ScriptServer::get_global_class_native_base(main_loop_type); + Object *obj = ClassDB::instance(script_base); + MainLoop *script_loop = Object::cast_to<MainLoop>(obj); + if (!script_loop) { + if (obj) { + memdelete(obj); + } + DisplayServer::get_singleton()->alert("Error: Invalid MainLoop script base type: " + script_base); + ERR_FAIL_V_MSG(false, vformat("The global class %s does not inherit from SceneTree or MainLoop.", main_loop_type)); + } + script_loop->set_init_script(script_res); + main_loop = script_loop; + } } if (!main_loop && main_loop_type == "") { |