summaryrefslogtreecommitdiff
path: root/main/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main/main.cpp')
-rw-r--r--main/main.cpp1409
1 files changed, 1409 insertions, 0 deletions
diff --git a/main/main.cpp b/main/main.cpp
new file mode 100644
index 0000000000..48f16b303c
--- /dev/null
+++ b/main/main.cpp
@@ -0,0 +1,1409 @@
+/*************************************************************************/
+/* main.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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. */
+/*************************************************************************/
+#include "main.h"
+#include "os/os.h"
+#include "globals.h"
+#include "splash.h"
+#include "core/register_core_types.h"
+#include "scene/register_scene_types.h"
+#include "drivers/register_driver_types.h"
+#include "script/register_script_types.h"
+#include "servers/register_server_types.h"
+#include "modules/register_module_types.h"
+#include "script_debugger_local.h"
+#include "script_debugger_remote.h"
+#include "message_queue.h"
+#include "path_remap.h"
+#include "input_map.h"
+#include "io/resource_loader.h"
+#include "scene/main/scene_main_loop.h"
+
+#include "scene/io/scene_loader.h"
+#include "script_language.h"
+#include "io/resource_loader.h"
+
+#include "bin/tests/test_main.h"
+#include "os/dir_access.h"
+#include "core/io/ip.h"
+#include "scene/resources/packed_scene.h"
+#include "scene/main/viewport.h"
+
+#ifdef TOOLS_ENABLED
+#include "tools/editor/editor_node.h"
+#include "tools/editor/project_manager.h"
+#include "tools/editor/console.h"
+#endif
+
+#include "io/file_access_network.h"
+#include "tools/doc/doc_data.h"
+
+
+#include "servers/spatial_sound_server.h"
+#include "servers/spatial_sound_2d_server.h"
+#include "servers/physics_2d_server.h"
+
+
+#include "core/io/stream_peer_tcp.h"
+#include "core/os/thread.h"
+#include "core/io/file_access_pack.h"
+#include "core/io/file_access_zip.h"
+#include "translation.h"
+#include "version.h"
+
+#include "performance.h"
+
+static Globals *globals=NULL;
+static InputMap *input_map=NULL;
+static bool _start_success=false;
+static ScriptDebugger *script_debugger=NULL;
+
+static MessageQueue *message_queue=NULL;
+static Performance *performance = NULL;
+static PathRemap *path_remap;
+static PackedData *packed_data=NULL;
+static FileAccessNetworkClient *file_access_network_client=NULL;
+static TranslationServer *translation_server = NULL;
+
+static OS::VideoMode video_mode;
+static int video_driver_idx=-1;
+static int audio_driver_idx=-1;
+static String locale;
+
+static String unescape_cmdline(const String& p_str) {
+
+ return p_str.replace("%20"," ");
+}
+
+
+//#define DEBUG_INIT
+
+#ifdef DEBUG_INIT
+#define MAIN_PRINT(m_txt) print_line(m_txt)
+#else
+#define MAIN_PRINT(m_txt)
+#endif
+
+void Main::print_help(const char* p_binary) {
+
+ OS::get_singleton()->print(VERSION_FULL_NAME" (c) 2008-2010 Juan Linietsky, Ariel Manzur.\n");
+ OS::get_singleton()->print("Usage: %s [options] [scene]\n",p_binary);
+ OS::get_singleton()->print("Options:\n");
+ OS::get_singleton()->print("\t-path [dir] : Path to a game, containing engine.cfg\n");
+#ifdef TOOLS_ENABLED
+ OS::get_singleton()->print("\t-e,-editor : Bring up the editor instead of running the scene.\n");
+#endif
+ OS::get_singleton()->print("\t-test [test] : Run a test.\n");
+ OS::get_singleton()->print("\t\t(");
+ const char **test_names=tests_get_names();
+ const char* coma = "";
+ while(*test_names) {
+
+ OS::get_singleton()->print("%s%s", coma, *test_names);
+ test_names++;
+ coma = ", ";
+ }
+ OS::get_singleton()->print(")\n");
+
+ OS::get_singleton()->print("\t-r WIDTHxHEIGHT\t : Request Screen Resolution\n");
+ OS::get_singleton()->print("\t-f\t\t : Request Fullscreen\n");
+ OS::get_singleton()->print("\t-vd DRIVER\t : Video Driver (");
+ for (int i=0;i<OS::get_singleton()->get_video_driver_count();i++) {
+
+ if (i!=0)
+ OS::get_singleton()->print(", ");
+ OS::get_singleton()->print("%s",OS::get_singleton()->get_video_driver_name(i));
+ }
+ OS::get_singleton()->print(")\n");
+ OS::get_singleton()->print("\t-ad DRIVER\t : Audio Driver (");
+ for (int i=0;i<OS::get_singleton()->get_audio_driver_count();i++) {
+
+ if (i!=0)
+ OS::get_singleton()->print(", ");
+ OS::get_singleton()->print("%s",OS::get_singleton()->get_audio_driver_name(i));
+ }
+ OS::get_singleton()->print("\t-rthread <mode>\t : Render Thread Mode ('unsafe', 'safe', 'separate).");
+ OS::get_singleton()->print(")\n");
+ OS::get_singleton()->print("\t-s,-script [script] : Run a script.\n");
+ OS::get_singleton()->print("\t-d,-debug : Debug (local stdout debugger).\n");
+ OS::get_singleton()->print("\t-rdebug ADDRESS : Remote debug (<ip>:<port> host address).\n");
+ OS::get_singleton()->print("\t-fdelay [msec]: Simulate high CPU load (delay each frame by [msec]).\n");
+ OS::get_singleton()->print("\t-bp : breakpoint list as source::line comma separated pairs, no spaces (%%20,%%2C,etc instead).\n");
+ OS::get_singleton()->print("\t-v : Verbose stdout mode\n");
+ OS::get_singleton()->print("\t-lang [locale]: Use a specific locale\n");
+ OS::get_singleton()->print("\t-rfs <host/ip>[:<port>] : Remote FileSystem.\n");
+ OS::get_singleton()->print("\t-rfs_pass <password> : Password for Remote FileSystem.\n");
+#ifdef TOOLS_ENABLED
+ OS::get_singleton()->print("\t-doctool FILE: Dump the whole engine api to FILE in XML format. If FILE exists, it will be merged.\n");
+ OS::get_singleton()->print("\t-nodocbase: Disallow dump the base types (used with -doctool).\n");
+ OS::get_singleton()->print("\t-optimize FILE Save an optimized copy of scene to FILE.\n");
+ OS::get_singleton()->print("\t-optimize_preset [preset] Use a given preset for optimization.\n");
+ OS::get_singleton()->print("\t-export [target] Export the project using given export target.\n");
+#endif
+}
+
+
+Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phase) {
+
+ RID_OwnerBase::init_rid();
+
+ OS::get_singleton()->initialize_core();
+ ObjectTypeDB::init();
+
+ MAIN_PRINT("Main: Initialize CORE");
+
+ register_core_types();
+ register_core_driver_types();
+
+ MAIN_PRINT("Main: Initialize Globals");
+
+
+ Thread::_main_thread_id = Thread::get_caller_ID();
+
+ globals = memnew( Globals );
+ input_map = memnew( InputMap );
+
+
+ path_remap = memnew( PathRemap );
+ translation_server = memnew( TranslationServer );
+ performance = memnew( Performance );
+ globals->add_singleton(Globals::Singleton("Performance",performance));
+
+ MAIN_PRINT("Main: Parse CMDLine");
+
+ /* argument parsing and main creation */
+ List<String> args;
+ List<String> main_args;
+
+ for(int i=0;i<argc;i++) {
+
+ args.push_back(argv[i]);
+ }
+
+ List<String>::Element *I=args.front();
+
+ I=args.front();
+
+ while (I) {
+
+ I->get()=unescape_cmdline(I->get().strip_escapes());
+ I=I->next();
+ }
+
+ I=args.front();
+
+ video_mode = OS::get_singleton()->get_default_video_mode();
+
+ String video_driver="";
+ String audio_driver="";
+ String game_path=".";
+ String debug_mode;
+ String debug_host;
+ int rtm=-1;
+
+ String remotefs;
+ String remotefs_pass;
+
+ String screen = "";
+
+ List<String> pack_list;
+ Vector<String> breakpoints;
+ bool use_custom_res=true;
+ bool force_res=false;
+
+ I=args.front();
+
+ packed_data = PackedData::get_singleton();
+ if (!packed_data)
+ packed_data = memnew(PackedData);
+
+#ifdef MINIZIP_ENABLED
+ packed_data->add_pack_source(ZipArchive::get_singleton());
+#endif
+
+ bool editor=false;
+
+ while(I) {
+
+ List<String>::Element *N=I->next();
+
+ if (I->get() == "-noop") {
+
+ // no op
+ } else if (I->get()=="-h" || I->get()=="--help" || I->get()=="/?") { // resolution
+
+ goto error;
+
+
+ } else if (I->get()=="-r") { // resolution
+
+ if (I->next()) {
+
+ String vm=I->next()->get();
+
+ if (vm.find("x")==-1) { // invalid parameter format
+
+ goto error;
+
+
+ }
+
+ int w=vm.get_slice("x",0).to_int();
+ int h=vm.get_slice("x",1).to_int();
+
+ if (w==0 || h==0) {
+
+ goto error;
+
+ }
+
+ video_mode.width=w;
+ video_mode.height=h;
+ force_res=true;
+
+ N=I->next()->next();
+ } else {
+ goto error;
+
+
+ }
+
+ } else if (I->get()=="-vd") { // video driver
+
+ if (I->next()) {
+
+ video_driver=I->next()->get();
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+ } else if (I->get()=="-lang") { // language
+
+ if (I->next()) {
+
+ locale=I->next()->get();
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+ } else if (I->get()=="-rfs") { // language
+
+ if (I->next()) {
+
+ remotefs=I->next()->get();
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+ } else if (I->get()=="-rfs_pass") { // language
+
+ if (I->next()) {
+
+ remotefs_pass=I->next()->get();
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+ } else if (I->get()=="-rthread") { // language
+
+ if (I->next()) {
+
+ if (I->next()->get()=="safe")
+ rtm=OS::RENDER_THREAD_SAFE;
+ else if (I->next()->get()=="unsafe")
+ rtm=OS::RENDER_THREAD_UNSAFE;
+ else if (I->next()->get()=="separate")
+ rtm=OS::RENDER_SEPARATE_THREAD;
+
+
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+
+ } else if (I->get()=="-ad") { // video driver
+
+ if (I->next()) {
+
+ audio_driver=I->next()->get();
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+
+ } else if (I->get()=="-f") { // fullscreen
+
+ video_mode.fullscreen=true;
+ } else if (I->get()=="-e" || I->get()=="-editor") { // fonud editor
+
+ editor=true;
+
+ } else if (I->get()=="-nowindow") { // fullscreen
+
+ OS::get_singleton()->set_no_window_mode(true);
+ } else if (I->get()=="-v") { // fullscreen
+ OS::get_singleton()->_verbose_stdout=true;
+ } else if (I->get()=="-path") { // resolution
+
+ if (I->next()) {
+
+ String p = I->next()->get();
+ if (OS::get_singleton()->set_cwd(p)==OK) {
+ //nothing
+ } else {
+ game_path=I->next()->get(); //use game_path instead
+ }
+
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+ } else if (I->get()=="-bp") { // /breakpoints
+
+ if (I->next()) {
+
+ String bplist = I->next()->get();
+ breakpoints= bplist.split(",");
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+
+
+ } else if (I->get()=="-fdelay") { // resolution
+
+ if (I->next()) {
+
+ OS::get_singleton()->set_frame_delay(I->next()->get().to_int());
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+
+
+ } else if (I->get() == "-pack") {
+
+ if (I->next()) {
+
+ pack_list.push_back(I->next()->get());
+ N = I->next()->next();
+ } else {
+
+ goto error;
+ };
+
+ } else if (I->get()=="-debug" || I->get()=="-d") {
+ debug_mode="local";
+ } else if (I->get()=="-editor_scene") {
+
+ if (I->next()) {
+
+ Globals::get_singleton()->set("editor_scene",game_path=I->next()->get());
+ } else {
+ goto error;
+
+ }
+
+ } else if (I->get()=="-rdebug") {
+ if (I->next()) {
+
+ debug_mode="remote";
+ debug_host=I->next()->get();
+ if (debug_host.find(":")==-1) //wrong host
+ goto error;
+ N=I->next()->next();
+ } else {
+ goto error;
+
+ }
+ } else {
+
+ //test for game path
+ bool gpfound=false;
+
+ if (!I->get().begins_with("-") && game_path=="") {
+ DirAccess* da = DirAccess::open(I->get());
+ if (da!=NULL) {
+ game_path=I->get();
+ gpfound=true;
+ memdelete(da);
+ }
+
+ }
+
+ if (!gpfound) {
+ main_args.push_back(I->get());
+ }
+ }
+
+ I=N;
+ }
+
+
+
+ if (debug_mode == "remote") {
+
+ ScriptDebuggerRemote *sdr = memnew( ScriptDebuggerRemote );
+ uint16_t debug_port = GLOBAL_DEF("debug/remote_port",6007);
+ if (debug_host.find(":")!=-1) {
+ debug_port=debug_host.get_slice(":",1).to_int();
+ debug_host=debug_host.get_slice(":",0);
+ }
+ Error derr = sdr->connect_to_host(debug_host,debug_port);
+
+ if (derr!=OK) {
+ memdelete(sdr);
+ } else {
+ script_debugger=sdr;
+
+ }
+ } else if (debug_mode=="local") {
+
+ script_debugger = memnew( ScriptDebuggerLocal );
+ }
+
+
+ if (remotefs!="") {
+
+ file_access_network_client=memnew(FileAccessNetworkClient);
+ int port;
+ if (remotefs.find(":")!=-1) {
+ port=remotefs.get_slice(":",1).to_int();
+ remotefs=remotefs.get_slice(":",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);
+ }
+ if (script_debugger) {
+ //there is a debugger, parse breakpoints
+
+ for(int i=0;i<breakpoints.size();i++) {
+
+ String bp = breakpoints[i];
+ int sp=bp.find_last(":");
+ if (sp==-1) {
+ ERR_EXPLAIN("Invalid breakpoint: '"+bp+"', expected file:line format.");
+ ERR_CONTINUE(sp==-1);
+ }
+
+ script_debugger->insert_breakpoint(bp.substr(sp+1,bp.length()).to_int(),bp.substr(0,sp));
+ }
+ }
+
+
+#ifdef TOOLS_ENABLED
+ if (editor) {
+ packed_data->set_disabled(true);
+ globals->set_disable_platform_override(true);
+ }
+
+#endif
+
+
+ if (globals->setup(game_path)!=OK) {
+
+#ifdef TOOLS_ENABLED
+ editor=false;
+#else
+ OS::get_singleton()->print("error: Couldn't load game path '%s'\n",game_path.ascii().get_data());
+
+ goto error;
+#endif
+ }
+
+ if (editor) {
+ main_args.push_back("-editor");
+ use_custom_res=false;
+ }
+
+ OS::get_singleton()->set_cmdline(execpath, main_args);
+
+#ifdef TOOLS_ENABLED
+
+ if (main_args.size()==0 && (!Globals::get_singleton()->has("application/main_loop_type")) && (!Globals::get_singleton()->has("application/main_scene") || String(Globals::get_singleton()->get("application/main_scene"))==""))
+ use_custom_res=false; //project manager (run without arguments)
+
+#endif
+
+ input_map->load_from_globals();
+
+ if (video_driver=="") // specified in engine.cfg
+ video_driver=_GLOBAL_DEF("display/driver",Variant((const char*)OS::get_singleton()->get_video_driver_name(0)));
+
+ if (!force_res && use_custom_res && globals->has("display/width"))
+ video_mode.width=globals->get("display/width");
+ if (!force_res &&use_custom_res && globals->has("display/height"))
+ video_mode.height=globals->get("display/height");
+ if (use_custom_res && globals->has("display/fullscreen"))
+ video_mode.fullscreen=globals->get("display/fullscreen");
+
+
+
+ GLOBAL_DEF("display/width",video_mode.width);
+ GLOBAL_DEF("display/height",video_mode.height);
+ GLOBAL_DEF("display/fullscreen",video_mode.fullscreen);
+ if (rtm==-1) {
+ rtm=GLOBAL_DEF("render/thread_model",OS::RENDER_THREAD_SAFE);
+ }
+
+ if (rtm>=0 && rtm<3)
+ OS::get_singleton()->_render_thread_mode=OS::RenderThreadMode(rtm);
+
+
+
+ /* Determine Video Driver */
+
+ if (audio_driver=="") // specified in engine.cfg
+ audio_driver=GLOBAL_DEF("audio/driver",OS::get_singleton()->get_audio_driver_name(0));
+
+
+ for (int i=0;i<OS::get_singleton()->get_video_driver_count();i++) {
+
+ if (video_driver==OS::get_singleton()->get_video_driver_name(i)) {
+
+ video_driver_idx=i;
+ break;
+ }
+ }
+
+ if (video_driver_idx<0) {
+
+ OS::get_singleton()->alert( "Invalid Video Driver: "+video_driver );
+ video_driver_idx = 0;
+ //goto error;
+ }
+
+ for (int i=0;i<OS::get_singleton()->get_audio_driver_count();i++) {
+
+ if (audio_driver==OS::get_singleton()->get_audio_driver_name(i)) {
+
+ audio_driver_idx=i;
+ break;
+ }
+ }
+
+ if (audio_driver_idx<0) {
+
+ OS::get_singleton()->alert( "Invalid Audio Driver: "+audio_driver );
+ goto error;
+ }
+
+ {
+ String orientation = GLOBAL_DEF("display/orientation","landscape");
+
+ if (orientation=="portrait")
+ OS::get_singleton()->set_screen_orientation(OS::SCREEN_PORTRAIT);
+ else if (orientation=="reverse_landscape")
+ OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_LANDSCAPE);
+ else if (orientation=="reverse_portrait")
+ OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_PORTRAIT);
+ else if (orientation=="sensor_landscape")
+ OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_LANDSCAPE);
+ else if (orientation=="sensor_portrait")
+ OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_PORTRAIT);
+ else if (orientation=="sensor")
+ OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR);
+ else
+ OS::get_singleton()->set_screen_orientation(OS::SCREEN_LANDSCAPE);
+ }
+
+ OS::get_singleton()->set_iterations_per_second(GLOBAL_DEF("display/target_fps",60));
+
+ if (!OS::get_singleton()->_verbose_stdout) //overrided
+ OS::get_singleton()->_verbose_stdout=GLOBAL_DEF("debug/verbose_stdout",false);
+
+ message_queue = memnew( MessageQueue );
+
+ Globals::get_singleton()->register_global_defaults();
+
+ if (p_second_phase)
+ return setup2();
+
+ return OK;
+
+ error:
+
+ video_driver="";
+ audio_driver="";
+ game_path="";
+
+ args.clear();
+ main_args.clear();
+
+ print_help(execpath);
+
+
+ if (performance)
+ memdelete(performance);
+ if (input_map)
+ memdelete(input_map);
+ if (translation_server)
+ memdelete( translation_server );
+ if (globals)
+ memdelete(globals);
+ if (script_debugger)
+ memdelete(script_debugger);
+ if (packed_data)
+ memdelete(packed_data);
+ if (file_access_network_client)
+ memdelete(file_access_network_client);
+ unregister_core_types();
+
+ OS::get_singleton()->_cmdline.clear();
+
+ if (message_queue)
+ memdelete( message_queue);
+ OS::get_singleton()->finalize_core();
+ locale=String();
+
+ return ERR_INVALID_PARAMETER;
+}
+
+Error Main::setup2() {
+
+
+ OS::get_singleton()->initialize(video_mode,video_driver_idx,audio_driver_idx);
+
+ register_core_singletons();
+
+ MAIN_PRINT("Main: Setup Logo");
+
+ bool show_logo=true;
+#ifdef JAVASCRIPT_ENABLED
+ show_logo=false;
+#endif
+
+ if (show_logo) { //boot logo!
+ Image boot_logo=GLOBAL_DEF("application/boot_logo",Image());
+
+ if (!boot_logo.empty()) {
+ Color clear = GLOBAL_DEF("render/default_clear_color",Color(0.3,0.3,0.3));
+ VisualServer::get_singleton()->set_default_clear_color(clear);
+ Color boot_bg = GLOBAL_DEF("application/boot_bg_color", clear);
+ VisualServer::get_singleton()->set_boot_image(boot_logo, boot_bg);
+#ifndef TOOLS_ENABLED
+ //no tools, so free the boot logo (no longer needed)
+ Globals::get_singleton()->set("application/boot_logo",Image());
+#endif
+
+ } else {
+#ifndef NO_DEFAULT_BOOT_LOGO
+
+ MAIN_PRINT("Main: Create botsplash");
+ Image splash(boot_splash_png);
+
+ MAIN_PRINT("Main: ClearColor");
+ VisualServer::get_singleton()->set_default_clear_color(boot_splash_bg_color);
+ MAIN_PRINT("Main: Image");
+ VisualServer::get_singleton()->set_boot_image(splash, boot_splash_bg_color);
+#endif
+ MAIN_PRINT("Main: DCC");
+ VisualServer::get_singleton()->set_default_clear_color(GLOBAL_DEF("render/default_clear_color",Color(0.3,0.3,0.3)));
+ MAIN_PRINT("Main: END");
+ }
+
+ Image icon(app_icon_png);
+ OS::get_singleton()->set_icon(icon);
+ }
+ GLOBAL_DEF("application/icon",String());
+ Globals::get_singleton()->set_custom_property_info("application/icon",PropertyInfo(Variant::STRING,"application/icon",PROPERTY_HINT_FILE,"*.png,*.webp"));
+
+ MAIN_PRINT("Main: Load Remaps");
+
+ path_remap->load_remaps();
+
+ MAIN_PRINT("Main: Load Scene Types");
+
+ register_scene_types();
+ register_server_types();
+
+#ifdef TOOLS_ENABLED
+ EditorNode::register_editor_types();
+#endif
+
+ MAIN_PRINT("Main: Load Scripts, Modules, Drivers");
+
+ register_module_types();
+ register_script_types();
+ register_driver_types();
+
+ MAIN_PRINT("Main: Load Translations");
+
+ translation_server->setup(); //register translations, load them, etc.
+ if (locale!="") {
+
+ translation_server->set_locale(locale);
+ }
+ translation_server->load_translations();
+
+
+
+ _start_success=true;
+ locale=String();
+
+ MAIN_PRINT("Main: Done");
+
+ return OK;
+
+}
+
+
+
+bool Main::start() {
+
+ ERR_FAIL_COND_V(!_start_success,false);
+
+ bool editor=false;
+ String doc_tool;
+ String doc_header;
+ bool doc_base=true;
+ String game_path;
+ String script;
+ String test;
+ String screen;
+ String optimize;
+ String optimize_preset;
+ String _export_platform;
+ String _import;
+ String _import_script;
+ String dumpstrings;
+ bool noquit=false;
+ bool convert_old=false;
+ bool export_debug=false;
+ List<String> args = OS::get_singleton()->get_cmdline_args();
+ for (int i=0;i<args.size();i++) {
+
+
+ if (args[i]=="-doctool" && i <(args.size()-1)) {
+
+ doc_tool=args[i+1];
+ i++;
+ } else if (args[i]=="-docheader" && i <(args.size()-1)) {
+
+ doc_header=args[i+1];
+ i++;
+ }else if (args[i]=="-nodocbase") {
+
+ doc_base=false;
+ } else if ((args[i]=="-script" || args[i]=="-s") && i <(args.size()-1)) {
+
+ script=args[i+1];
+ i++;
+ } else if ((args[i]=="-level" || args[i]=="-l") && i <(args.size()-1)) {
+
+ OS::get_singleton()->_custom_level=args[i+1];
+ i++;
+ } else if (args[i]=="-test" && i <(args.size()-1)) {
+ test=args[i+1];
+ i++;
+ } else if (args[i]=="-optimize" && i <(args.size()-1)) {
+ optimize=args[i+1];
+ i++;
+ } else if (args[i]=="-optimize_preset" && i <(args.size()-1)) {
+ optimize_preset=args[i+1];
+ i++;
+ } else if (args[i]=="-export" && i <(args.size()-1)) {
+ editor=true; //needs editor
+ _export_platform=args[i+1];
+ i++;
+ } else if (args[i]=="-export_debug" && i <(args.size()-1)) {
+ editor=true; //needs editor
+ _export_platform=args[i+1];
+ export_debug=true;
+ i++;
+ } else if (args[i]=="-import" && i <(args.size()-1)) {
+ editor=true; //needs editor
+ _import=args[i+1];
+ i++;
+ } else if (args[i]=="-import_script" && i <(args.size()-1)) {
+ editor=true; //needs editor
+ _import_script=args[i+1];
+ i++;
+ } else if (args[i]=="-noquit" ) {
+ noquit=true;
+ } else if (args[i]=="-dumpstrings" && i <(args.size()-1)) {
+ editor=true; //needs editor
+ dumpstrings=args[i+1];
+ i++;
+ } else if (args[i]=="-editor" || args[i]=="-e") {
+ editor=true;
+ } else if (args[i]=="-convert_old") {
+ convert_old=true;
+ } else if (args[i].length() && args[i][0] != '-' && game_path == "") {
+
+ game_path=args[i];
+ }
+ }
+
+ print_line("editor: "+itos(editor));
+
+ if (editor)
+ Globals::get_singleton()->set("editor_active",true);
+
+
+ String main_loop_type;
+#ifdef TOOLS_ENABLED
+ if(doc_tool!="") {
+
+ DocData doc;
+ doc.generate(doc_base);
+
+ DocData docsrc;
+ if (docsrc.load(doc_tool)==OK) {
+ print_line("Doc exists. Merging..");
+ doc.merge_from(docsrc);
+ } else {
+ print_line("No Doc exists. Generating empty.");
+
+ }
+
+ if (doc_header.length())
+ doc.save_compressed_header(doc_header);
+ else
+ doc.save(doc_tool);
+
+ return false;
+ }
+
+ if (optimize!="")
+ editor=true; //need editor
+
+
+
+#endif
+
+ if(script=="" && game_path=="" && !editor && String(GLOBAL_DEF("application/main_scene",""))!="") {
+ game_path=GLOBAL_DEF("application/main_scene","");
+ }
+
+
+ MainLoop *main_loop=NULL;
+ if (editor) {
+ main_loop = memnew(SceneMainLoop);
+ };
+
+ if (test!="") {
+#ifdef DEBUG_ENABLED
+ main_loop = test_main(test,args);
+
+ if (!main_loop)
+ return false;
+
+#endif
+
+ } else if (script!="") {
+
+ Ref<Script> script_res = ResourceLoader::load(script);
+ ERR_EXPLAIN("Can't load script: "+script);
+ ERR_FAIL_COND_V(script_res.is_null(),false);
+
+ if( script_res->can_instance() /*&& script_res->inherits_from("SceneMainLoopScripted")*/) {
+
+
+ StringName instance_type=script_res->get_instance_base_type();
+ Object *obj = ObjectTypeDB::instance(instance_type);
+ MainLoop *script_loop = obj?obj->cast_to<MainLoop>():NULL;
+ if (!script_loop) {
+ if (obj)
+ memdelete(obj);
+ ERR_EXPLAIN("Can't load script '"+script+"', it does not inherit from a MainLoop type");
+ ERR_FAIL_COND_V(!script_loop,false);
+ }
+
+
+ script_loop->set_init_script(script_res);
+ main_loop=script_loop;
+ } else {
+
+ return false;
+ }
+
+ } else {
+ main_loop_type=GLOBAL_DEF("application/main_loop_type","");
+ }
+
+ if (!main_loop && main_loop_type=="")
+ main_loop_type="SceneMainLoop";
+
+ if (!main_loop) {
+ if (!ObjectTypeDB::type_exists(main_loop_type)) {
+ OS::get_singleton()->alert("godot: error: MainLoop type doesn't exist: "+main_loop_type);
+ return false;
+ } else {
+
+ Object *ml = ObjectTypeDB::instance(main_loop_type);
+ if (!ml) {
+ ERR_EXPLAIN("Can't instance MainLoop type");
+ ERR_FAIL_V(false);
+ }
+
+ main_loop=ml->cast_to<MainLoop>();
+ if (!main_loop) {
+
+ memdelete(ml);
+ ERR_EXPLAIN("Invalid MainLoop type");
+ ERR_FAIL_V(false);
+
+ }
+ }
+ }
+
+ if (main_loop->is_type("SceneMainLoop")) {
+
+ SceneMainLoop *sml = main_loop->cast_to<SceneMainLoop>();
+
+#ifdef TOOLS_ENABLED
+
+ EditorNode *editor_node=NULL;
+ if (editor) {
+
+ editor_node = memnew( EditorNode );
+ sml->get_root()->add_child(editor_node);
+
+ //root_node->set_editor(editor);
+ //startup editor
+
+ if (_export_platform!="") {
+
+ editor_node->export_platform(_export_platform,game_path,export_debug,"",true);
+ game_path=""; //no load anything
+ }
+ }
+#endif
+
+ if (!editor) {
+ //standard helpers that can be changed from main config
+
+ if (GLOBAL_DEF("display/stretch_2d",false).operator bool()) {
+
+ sml->get_root()->set_size_override(true,Size2(Globals::get_singleton()->get("display/width"),Globals::get_singleton()->get("display/height")));
+ sml->get_root()->set_size_override_stretch(true);
+ }
+
+ sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
+ String appname = Globals::get_singleton()->get("application/name");
+ appname = TranslationServer::get_singleton()->translate(appname);
+ OS::get_singleton()->set_window_title(appname);
+
+
+ } else {
+ GLOBAL_DEF("display/stretch_2d",false);
+ sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
+
+
+ }
+
+
+ if (game_path!="") {
+
+ String local_game_path=game_path.replace("\\","/");
+
+ if (!local_game_path.begins_with("res://")) {
+ bool absolute=(local_game_path.size()>1) && (local_game_path[0]=='/' || local_game_path[1]==':');
+
+ if (!absolute) {
+
+ int sep=local_game_path.find_last("/");
+
+ if (sep==-1) {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ local_game_path=da->get_current_dir()+"/"+local_game_path;
+ memdelete(da) ;
+ } else {
+
+ DirAccess *da = DirAccess::open(local_game_path.substr(0,sep));
+ if (da) {
+ local_game_path=da->get_current_dir()+"/"+local_game_path.substr(sep+1,local_game_path.length());;
+ memdelete(da);
+ }
+ }
+
+ }
+ }
+
+ local_game_path=Globals::get_singleton()->localize_path(local_game_path);
+
+#ifdef TOOLS_ENABLED
+ if (editor) {
+
+#ifdef OLD_SCENE_FORMAT_ENABLED
+ if (convert_old)
+ editor_node->set_convert_old_scene(true);
+#endif
+
+ if (_import!="") {
+
+ //editor_node->import_scene(_import,local_game_path,_import_script);
+ if (!noquit)
+ sml->quit();
+ game_path=""; //no load anything
+ } else {
+
+ Error serr = editor_node->load_scene(local_game_path);
+
+ if (serr==OK) {
+
+ if (optimize!="") {
+
+ editor_node->save_optimized_copy(optimize,optimize_preset);
+ if (!noquit)
+ sml->quit();
+ }
+
+ if (dumpstrings!="") {
+
+ editor_node->save_translatable_strings(dumpstrings);
+ if (!noquit)
+ sml->quit();
+ }
+ }
+ }
+
+ //editor_node->set_edited_scene(game);
+ } else {
+#endif
+
+ {
+ //autoload
+ List<PropertyInfo> props;
+ Globals::get_singleton()->get_property_list(&props);
+ for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
+
+ String s = E->get().name;
+ if (!s.begins_with("autoload/"))
+ continue;
+ String name = s.get_slice("/",1);
+ String path = Globals::get_singleton()->get(s);
+ RES res = ResourceLoader::load(path);
+ ERR_EXPLAIN("Can't autoload: "+path);
+ ERR_CONTINUE(res.is_null());
+ Node *n=NULL;
+ if (res->is_type("PackedScene")) {
+ Ref<PackedScene> ps = res;
+ n=ps->instance();
+ } else if (res->is_type("Script")) {
+ Ref<Script> s = res;
+ StringName ibt = s->get_instance_base_type();
+ ERR_EXPLAIN("Script does not inherit a Node: "+path);
+ ERR_CONTINUE( !ObjectTypeDB::is_type(ibt,"Node") );
+
+ Object *obj = ObjectTypeDB::instance(ibt);
+
+ ERR_EXPLAIN("Cannot instance node for autoload type: "+String(ibt));
+ ERR_CONTINUE( obj==NULL );
+
+ n = obj->cast_to<Node>();
+ n->set_script(s.get_ref_ptr());
+ }
+
+ ERR_EXPLAIN("Path in autoload not a node or script: "+path);
+ ERR_CONTINUE(!n);
+ n->set_name(name);
+ sml->get_root()->add_child(n);
+ }
+
+ }
+
+ Node *scene=NULL;
+ Ref<PackedScene> scenedata = ResourceLoader::load(local_game_path);
+ if (scenedata.is_valid())
+ scene=scenedata->instance();
+
+#ifdef OLD_SCENE_FORMAT_ENABLED
+
+ if (!scene) {
+ scene = SceneLoader::load(local_game_path,true);
+ }
+
+#endif
+
+ ERR_EXPLAIN("Failed loading scene: "+local_game_path);
+ ERR_FAIL_COND_V(!scene,false)
+ sml->get_root()->add_child(scene);
+
+ String iconpath = GLOBAL_DEF("application/icon","Variant()""");
+ if (iconpath!="") {
+ Image icon;
+ if (icon.load(iconpath)==OK)
+ OS::get_singleton()->set_icon(icon);
+ }
+
+
+ //singletons
+#ifdef TOOLS_ENABLED
+ }
+#endif
+ }
+
+#ifdef TOOLS_ENABLED
+
+ /*if (_export_platform!="") {
+
+ sml->quit();
+ }*/
+
+ /*
+ if (sml->get_root_node()) {
+
+ Console *console = memnew( Console );
+
+ sml->get_root_node()->cast_to<RootNode>()->set_console(console);
+ if (GLOBAL_DEF("console/visible_default",false).operator bool()) {
+
+ console->show();
+ } else {P
+
+ console->hide();
+ };
+ }
+*/
+ if (script=="" && test=="" && game_path=="" && !editor) {
+
+ ProjectManager *pmanager = memnew( ProjectManager );
+ sml->get_root()->add_child(pmanager);
+ }
+
+#endif
+ }
+
+ OS::get_singleton()->set_main_loop( main_loop );
+
+ return true;
+}
+
+uint64_t Main::last_ticks=0;
+float Main::time_accum=0;
+uint32_t Main::frames=0;
+uint32_t Main::frame=0;
+bool Main::force_redraw_requested = false;
+
+static uint64_t fixed_process_max=0;
+static uint64_t idle_process_max=0;
+
+
+bool Main::iteration() {
+
+ uint64_t ticks=OS::get_singleton()->get_ticks_usec();
+ uint64_t ticks_elapsed=ticks-last_ticks;
+
+ frame+=ticks_elapsed;
+
+ last_ticks=ticks;
+ double step=(double)ticks_elapsed / 1000000.0;
+
+ float frame_slice=1.0/OS::get_singleton()->get_iterations_per_second();
+
+ if (step>frame_slice*8)
+ step=frame_slice*8;
+
+ time_accum+=step;
+
+ bool exit=false;
+
+
+ int iters = 0;
+
+ while(time_accum>frame_slice) {
+
+ uint64_t fixed_begin = OS::get_singleton()->get_ticks_usec();
+
+ PhysicsServer::get_singleton()->sync();
+ PhysicsServer::get_singleton()->flush_queries();
+
+ Physics2DServer::get_singleton()->sync();
+ Physics2DServer::get_singleton()->flush_queries();
+
+ if (OS::get_singleton()->get_main_loop()->iteration( frame_slice )) {
+ exit=true;
+ break;
+ }
+
+ message_queue->flush();
+
+ PhysicsServer::get_singleton()->step(frame_slice);
+ Physics2DServer::get_singleton()->step(frame_slice);
+
+ time_accum-=frame_slice;
+ message_queue->flush();
+ //if (AudioServer::get_singleton())
+ // AudioServer::get_singleton()->update();
+
+ fixed_process_max=MAX(OS::get_singleton()->get_ticks_usec()-fixed_begin,fixed_process_max);
+ iters++;
+ }
+
+ uint64_t idle_begin = OS::get_singleton()->get_ticks_usec();
+
+ OS::get_singleton()->get_main_loop()->idle( step );
+ message_queue->flush();
+
+ if (SpatialSoundServer::get_singleton())
+ SpatialSoundServer::get_singleton()->update( step );
+ if (SpatialSound2DServer::get_singleton())
+ SpatialSound2DServer::get_singleton()->update( step );
+
+
+ if (OS::get_singleton()->can_draw()) {
+
+ if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
+ if (VisualServer::get_singleton()->has_changed()) {
+ VisualServer::get_singleton()->draw(); // flush visual commands
+ OS::get_singleton()->frames_drawn++;
+ }
+ } else {
+ VisualServer::get_singleton()->draw(); // flush visual commands
+ OS::get_singleton()->frames_drawn++;
+ force_redraw_requested = false;
+ }
+ } else {
+ VisualServer::get_singleton()->flush(); // flush visual commands
+
+ }
+
+ if (AudioServer::get_singleton())
+ AudioServer::get_singleton()->update();
+
+ for(int i=0;i<ScriptServer::get_language_count();i++) {
+ ScriptServer::get_language(i)->frame();
+ }
+
+ idle_process_max=MAX(OS::get_singleton()->get_ticks_usec()-idle_begin,idle_process_max);
+
+ if (script_debugger)
+ script_debugger->idle_poll();
+
+
+ // x11_delay_usec(10000);
+ frames++;
+
+ if (frame>1000000) {
+
+ if (GLOBAL_DEF("debug/print_fps", OS::get_singleton()->is_stdout_verbose())) {
+ print_line("FPS: "+itos(frames));
+ };
+
+ OS::get_singleton()->_fps=frames;
+ performance->set_process_time(idle_process_max/1000000.0);
+ performance->set_fixed_process_time(fixed_process_max/1000000.0);
+ idle_process_max=0;
+ fixed_process_max=0;
+
+ if (GLOBAL_DEF("debug/print_metrics", false)) {
+
+ //PerformanceMetrics::print();
+ };
+
+ frame%=1000000;
+ frames=0;
+ }
+
+ if (OS::get_singleton()->is_in_low_processor_usage_mode() || !OS::get_singleton()->can_draw())
+ OS::get_singleton()->delay_usec(25000); //apply some delay to force idle time
+ else {
+ uint32_t frame_delay = OS::get_singleton()->get_frame_delay();
+ if (frame_delay)
+ OS::get_singleton()->delay_usec( OS::get_singleton()->get_frame_delay()*1000 );
+ }
+
+ return exit;
+}
+
+void Main::force_redraw() {
+
+ force_redraw_requested = true;
+};
+
+
+void Main::cleanup() {
+
+ ERR_FAIL_COND(!_start_success);
+
+ if (script_debugger)
+ memdelete(script_debugger);
+
+ OS::get_singleton()->delete_main_loop();
+
+ OS::get_singleton()->_cmdline.clear();
+ OS::get_singleton()->_execpath="";
+ OS::get_singleton()->_local_clipboard="";
+
+ unregister_driver_types();
+ unregister_module_types();
+ unregister_scene_types();
+ unregister_server_types();
+ unregister_script_types();
+
+ OS::get_singleton()->finalize();
+
+ if (packed_data)
+ memdelete(packed_data);
+ if (file_access_network_client)
+ memdelete(file_access_network_client);
+ if (performance)
+ memdelete(performance);
+ if (input_map)
+ memdelete(input_map);
+ if (translation_server)
+ memdelete( translation_server );
+ if (path_remap)
+ memdelete(path_remap);
+ if (globals)
+ memdelete(globals);
+
+
+
+
+ memdelete( message_queue );
+
+ unregister_core_driver_types();
+ unregister_core_types();
+
+ //PerformanceMetrics::finish();
+ OS::get_singleton()->clear_last_error();
+ OS::get_singleton()->finalize_core();
+
+
+}
+