PageRenderTime 8ms CodeModel.GetById 2ms app.highlight 129ms RepoModel.GetById 1ms app.codeStats 1ms

/main/main.cpp

https://github.com/zzyclark/godot
C++ | 1450 lines | 982 code | 399 blank | 69 comment | 316 complexity | 38e2785cc95018546c4a8005f5e62d8f MD5 | raw file
   1/*************************************************************************/
   2/*  main.cpp                                                             */
   3/*************************************************************************/
   4/*                       This file is part of:                           */
   5/*                           GODOT ENGINE                                */
   6/*                    http://www.godotengine.org                         */
   7/*************************************************************************/
   8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                 */
   9/*                                                                       */
  10/* Permission is hereby granted, free of charge, to any person obtaining */
  11/* a copy of this software and associated documentation files (the       */
  12/* "Software"), to deal in the Software without restriction, including   */
  13/* without limitation the rights to use, copy, modify, merge, publish,   */
  14/* distribute, sublicense, and/or sell copies of the Software, and to    */
  15/* permit persons to whom the Software is furnished to do so, subject to */
  16/* the following conditions:                                             */
  17/*                                                                       */
  18/* The above copyright notice and this permission notice shall be        */
  19/* included in all copies or substantial portions of the Software.       */
  20/*                                                                       */
  21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
  22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
  23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
  25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
  26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
  27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
  28/*************************************************************************/
  29#include "main.h"
  30#include "os/os.h"
  31#include "globals.h"
  32#include "splash.h"
  33#include "core/register_core_types.h"
  34#include "scene/register_scene_types.h"
  35#include "drivers/register_driver_types.h"
  36#include "servers/register_server_types.h"
  37#include "modules/register_module_types.h"
  38#include "script_debugger_local.h"
  39#include "script_debugger_remote.h"
  40#include "message_queue.h"
  41#include "path_remap.h"
  42#include "input_map.h"
  43#include "io/resource_loader.h"
  44#include "scene/main/scene_main_loop.h"
  45
  46#include "scene/io/scene_loader.h"
  47#include "script_language.h"
  48#include "io/resource_loader.h"
  49
  50#include "bin/tests/test_main.h"
  51#include "os/dir_access.h"
  52#include "core/io/ip.h"
  53#include "scene/resources/packed_scene.h"
  54#include "scene/main/viewport.h"
  55
  56#ifdef TOOLS_ENABLED
  57#include "tools/editor/editor_node.h"
  58#include "tools/editor/project_manager.h"
  59#include "tools/editor/console.h"
  60#endif
  61
  62#include "io/file_access_network.h"
  63#include "tools/doc/doc_data.h"
  64
  65
  66#include "servers/spatial_sound_server.h"
  67#include "servers/spatial_sound_2d_server.h"
  68#include "servers/physics_2d_server.h"
  69
  70
  71#include "core/io/stream_peer_tcp.h"
  72#include "core/os/thread.h"
  73#include "core/io/file_access_pack.h"
  74#include "core/io/file_access_zip.h"
  75#include "translation.h"
  76#include "version.h"
  77
  78#include "performance.h"
  79
  80static Globals *globals=NULL;
  81static InputMap *input_map=NULL;
  82static bool _start_success=false;
  83static ScriptDebugger *script_debugger=NULL;
  84
  85static MessageQueue *message_queue=NULL;
  86static Performance *performance = NULL;
  87static PathRemap *path_remap;
  88static PackedData *packed_data=NULL;
  89static FileAccessNetworkClient *file_access_network_client=NULL;
  90static TranslationServer *translation_server = NULL;
  91
  92static OS::VideoMode video_mode;
  93static int video_driver_idx=-1;
  94static int audio_driver_idx=-1;
  95static String locale;
  96
  97static String unescape_cmdline(const String& p_str) {
  98
  99	return p_str.replace("%20"," ");
 100}
 101
 102
 103//#define DEBUG_INIT
 104
 105#ifdef DEBUG_INIT
 106#define MAIN_PRINT(m_txt) print_line(m_txt)
 107#else
 108#define MAIN_PRINT(m_txt)
 109#endif
 110
 111void Main::print_help(const char* p_binary) {
 112
 113	OS::get_singleton()->print(VERSION_FULL_NAME" (c) 2008-2010 Juan Linietsky, Ariel Manzur.\n");
 114	OS::get_singleton()->print("Usage: %s [options] [scene]\n",p_binary);
 115	OS::get_singleton()->print("Options:\n");
 116	OS::get_singleton()->print("\t-path [dir] : Path to a game, containing engine.cfg\n");
 117#ifdef TOOLS_ENABLED
 118	OS::get_singleton()->print("\t-e,-editor : Bring up the editor instead of running the scene.\n");
 119#endif
 120	OS::get_singleton()->print("\t-test [test] : Run a test.\n");
 121	OS::get_singleton()->print("\t\t(");
 122	const char **test_names=tests_get_names();
 123	const char* coma = "";
 124	while(*test_names) {
 125	
 126		OS::get_singleton()->print("%s%s", coma, *test_names);
 127		test_names++;
 128		coma = ", ";
 129	}
 130	OS::get_singleton()->print(")\n");
 131	
 132	OS::get_singleton()->print("\t-r WIDTHxHEIGHT\t : Request Screen Resolution\n");
 133	OS::get_singleton()->print("\t-f\t\t : Request Fullscreen\n");
 134	OS::get_singleton()->print("\t-vd DRIVER\t : Video Driver (");
 135	for (int i=0;i<OS::get_singleton()->get_video_driver_count();i++) {
 136		
 137		if (i!=0)
 138			OS::get_singleton()->print(", ");
 139		OS::get_singleton()->print("%s",OS::get_singleton()->get_video_driver_name(i));
 140	}
 141	OS::get_singleton()->print(")\n");
 142	OS::get_singleton()->print("\t-ad DRIVER\t : Audio Driver (");
 143	for (int i=0;i<OS::get_singleton()->get_audio_driver_count();i++) {
 144		
 145		if (i!=0)
 146			OS::get_singleton()->print(", ");
 147		OS::get_singleton()->print("%s",OS::get_singleton()->get_audio_driver_name(i));
 148	}
 149	OS::get_singleton()->print("\t-rthread <mode>\t : Render Thread Mode ('unsafe', 'safe', 'separate).");
 150	OS::get_singleton()->print(")\n");
 151	OS::get_singleton()->print("\t-s,-script [script] : Run a script.\n");	
 152	OS::get_singleton()->print("\t-d,-debug : Debug (local stdout debugger).\n");
 153	OS::get_singleton()->print("\t-rdebug ADDRESS : Remote debug (<ip>:<port> host address).\n");
 154	OS::get_singleton()->print("\t-fdelay [msec]: Simulate high CPU load (delay each frame by [msec]).\n");
 155	OS::get_singleton()->print("\t-bp : breakpoint list as source::line comma separated pairs, no spaces (%%20,%%2C,etc instead).\n");
 156	OS::get_singleton()->print("\t-v : Verbose stdout mode\n");
 157	OS::get_singleton()->print("\t-lang [locale]: Use a specific locale\n");
 158	OS::get_singleton()->print("\t-rfs <host/ip>[:<port>] : Remote FileSystem.\n");
 159	OS::get_singleton()->print("\t-rfs_pass <password> : Password for Remote FileSystem.\n");
 160#ifdef TOOLS_ENABLED
 161	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");
 162	OS::get_singleton()->print("\t-nodocbase: Disallow dump the base types (used with -doctool).\n");
 163	OS::get_singleton()->print("\t-optimize FILE Save an optimized copy of scene to FILE.\n");
 164	OS::get_singleton()->print("\t-optimize_preset [preset] Use a given preset for optimization.\n");
 165	OS::get_singleton()->print("\t-export [target] Export the project using given export target.\n");
 166#endif
 167}
 168
 169
 170Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phase) {
 171
 172	RID_OwnerBase::init_rid();
 173
 174	OS::get_singleton()->initialize_core();
 175	ObjectTypeDB::init();
 176
 177	MAIN_PRINT("Main: Initialize CORE");
 178
 179	register_core_types();
 180	register_core_driver_types();
 181
 182	MAIN_PRINT("Main: Initialize Globals");
 183
 184
 185	Thread::_main_thread_id = Thread::get_caller_ID();
 186
 187	globals = memnew( Globals );
 188	input_map = memnew( InputMap );
 189
 190
 191	path_remap = memnew( PathRemap );
 192	translation_server = memnew( TranslationServer );
 193	performance = memnew( Performance );
 194	globals->add_singleton(Globals::Singleton("Performance",performance));
 195
 196	MAIN_PRINT("Main: Parse CMDLine");
 197
 198	/* argument parsing and main creation */
 199	List<String> args;
 200	List<String> main_args;
 201	
 202	for(int i=0;i<argc;i++) {
 203
 204		args.push_back(String::utf8(argv[i]));
 205	}
 206
 207	List<String>::Element *I=args.front();
 208
 209	I=args.front();
 210
 211	while (I) {
 212
 213		I->get()=unescape_cmdline(I->get().strip_escapes());
 214//		print_line("CMD: "+I->get());
 215		I=I->next();
 216	}
 217
 218	I=args.front();
 219	
 220	video_mode = OS::get_singleton()->get_default_video_mode();
 221
 222	String video_driver="";
 223	String audio_driver="";
 224	String game_path=".";
 225	String debug_mode;
 226	String debug_host;
 227	String main_pack;
 228	int rtm=-1;
 229
 230	String remotefs;
 231	String remotefs_pass;
 232
 233	String screen = "";
 234
 235	List<String> pack_list;
 236	Vector<String> breakpoints;
 237	bool use_custom_res=true;
 238	bool force_res=false;
 239
 240	I=args.front();
 241
 242	packed_data = PackedData::get_singleton();
 243	if (!packed_data)
 244		packed_data = memnew(PackedData);
 245
 246#ifdef MINIZIP_ENABLED
 247	packed_data->add_pack_source(ZipArchive::get_singleton());
 248#endif
 249
 250	bool editor=false;
 251
 252	while(I) {
 253
 254		List<String>::Element *N=I->next();
 255
 256		if (I->get() == "-noop") {
 257
 258			// no op
 259		} else if (I->get()=="-h" || I->get()=="--help" || I->get()=="/?") { // resolution
 260			
 261			goto error;
 262			
 263			
 264		} else if (I->get()=="-r") { // resolution
 265		
 266			if (I->next()) {
 267			
 268				String vm=I->next()->get();
 269				
 270				if (vm.find("x")==-1) { // invalid parameter format
 271				
 272					goto error;
 273					
 274				
 275				}
 276				
 277				int w=vm.get_slice("x",0).to_int();
 278				int h=vm.get_slice("x",1).to_int();
 279				
 280				if (w==0 || h==0) {
 281				
 282					goto error;
 283					
 284				}
 285				
 286				video_mode.width=w;
 287				video_mode.height=h;
 288				force_res=true;
 289				
 290				N=I->next()->next();
 291			} else {
 292				goto error;
 293				
 294			
 295			}
 296			
 297		} else if (I->get()=="-vd") { // video driver
 298		
 299			if (I->next()) {
 300			
 301				video_driver=I->next()->get();
 302				N=I->next()->next();
 303			} else {
 304				goto error;
 305				
 306			}
 307		} else if (I->get()=="-lang") { // language
 308
 309			if (I->next()) {
 310
 311				locale=I->next()->get();
 312				N=I->next()->next();
 313			} else {
 314				goto error;
 315
 316			}
 317		} else if (I->get()=="-rfs") { // language
 318
 319			if (I->next()) {
 320
 321				remotefs=I->next()->get();
 322				N=I->next()->next();
 323			} else {
 324				goto error;
 325
 326			}
 327		} else if (I->get()=="-rfs_pass") { // language
 328
 329			if (I->next()) {
 330
 331				remotefs_pass=I->next()->get();
 332				N=I->next()->next();
 333			} else {
 334				goto error;
 335
 336			}
 337		} else if (I->get()=="-rthread") { // language
 338
 339			if (I->next()) {
 340
 341				if (I->next()->get()=="safe")
 342					rtm=OS::RENDER_THREAD_SAFE;
 343				else if (I->next()->get()=="unsafe")
 344					rtm=OS::RENDER_THREAD_UNSAFE;
 345				else if (I->next()->get()=="separate")
 346					rtm=OS::RENDER_SEPARATE_THREAD;
 347
 348
 349				N=I->next()->next();
 350			} else {
 351				goto error;
 352
 353			}
 354
 355		} else if (I->get()=="-ad") { // video driver
 356		
 357			if (I->next()) {
 358			
 359				audio_driver=I->next()->get();
 360				N=I->next()->next();
 361			} else {
 362				goto error;
 363				
 364			}
 365			
 366		} else if (I->get()=="-f") { // fullscreen
 367		
 368			video_mode.fullscreen=true;
 369		} else if (I->get()=="-e" || I->get()=="-editor") { // fonud editor
 370
 371			editor=true;
 372
 373		} else if (I->get()=="-nowindow") { // fullscreen
 374
 375			OS::get_singleton()->set_no_window_mode(true);
 376		} else if (I->get()=="-v") { // fullscreen
 377			OS::get_singleton()->_verbose_stdout=true;
 378		} else if (I->get()=="-path") { // resolution
 379		
 380			if (I->next()) {
 381			
 382				String p = I->next()->get();
 383				if (OS::get_singleton()->set_cwd(p)==OK) {
 384					//nothing
 385				} else {
 386					game_path=I->next()->get(); //use game_path instead
 387				}
 388
 389				N=I->next()->next();
 390			} else {
 391				goto error;
 392				
 393			}
 394		} else if (I->get()=="-bp") { // /breakpoints
 395
 396			if (I->next()) {
 397
 398				String bplist = I->next()->get();
 399				breakpoints= bplist.split(",");
 400				N=I->next()->next();
 401			} else {
 402				goto error;
 403
 404			}
 405
 406
 407		} else if (I->get()=="-fdelay") { // resolution
 408
 409			if (I->next()) {
 410
 411				OS::get_singleton()->set_frame_delay(I->next()->get().to_int());
 412				N=I->next()->next();
 413			} else {
 414				goto error;
 415
 416			}
 417
 418
 419		} else if (I->get() == "-pack") {
 420
 421			if (I->next()) {
 422
 423				pack_list.push_back(I->next()->get());
 424				N = I->next()->next();
 425			} else {
 426
 427				goto error;
 428			};
 429
 430		} else if (I->get() == "-main_pack") {
 431
 432			if (I->next()) {
 433
 434				main_pack=I->next()->get();
 435				N = I->next()->next();
 436			} else {
 437
 438				goto error;
 439			};
 440
 441		} else if (I->get()=="-debug" || I->get()=="-d") {
 442			debug_mode="local";
 443		} else if (I->get()=="-editor_scene") {
 444
 445			if (I->next()) {
 446
 447				Globals::get_singleton()->set("editor_scene",game_path=I->next()->get());
 448			} else {
 449				goto error;
 450
 451			}
 452
 453		} else if (I->get()=="-rdebug") {
 454			if (I->next()) {
 455
 456				debug_mode="remote";
 457				debug_host=I->next()->get();
 458				if (debug_host.find(":")==-1) //wrong host
 459					goto error;
 460				N=I->next()->next();
 461			} else {
 462				goto error;
 463
 464			}
 465		} else {
 466
 467			//test for game path
 468			bool gpfound=false;
 469
 470			if (!I->get().begins_with("-") && game_path=="") {
 471				DirAccess* da = DirAccess::open(I->get());
 472				if (da!=NULL) {
 473					game_path=I->get();
 474					gpfound=true;
 475					memdelete(da);
 476				}
 477
 478			}
 479
 480			if (!gpfound) {
 481				main_args.push_back(I->get());
 482			}
 483		}
 484			
 485		I=N;
 486	}
 487
 488
 489
 490	if (debug_mode == "remote") {
 491
 492		ScriptDebuggerRemote *sdr = memnew( ScriptDebuggerRemote );
 493		uint16_t debug_port = GLOBAL_DEF("debug/remote_port",6007);
 494		if (debug_host.find(":")!=-1) {
 495		    debug_port=debug_host.get_slice(":",1).to_int();
 496		    debug_host=debug_host.get_slice(":",0);
 497		}
 498		Error derr = sdr->connect_to_host(debug_host,debug_port);
 499
 500		if (derr!=OK) {
 501			memdelete(sdr);
 502		} else {
 503			script_debugger=sdr;
 504
 505		}
 506	} else if (debug_mode=="local") {
 507
 508		script_debugger = memnew( ScriptDebuggerLocal );
 509	}
 510
 511
 512	if (remotefs!="") {
 513
 514		file_access_network_client=memnew(FileAccessNetworkClient);
 515		int port;
 516		if (remotefs.find(":")!=-1) {
 517			port=remotefs.get_slice(":",1).to_int();
 518			remotefs=remotefs.get_slice(":",0);
 519		} else {
 520			port=6010;
 521		}
 522
 523		Error err = file_access_network_client->connect(remotefs,port,remotefs_pass);
 524		if (err) {
 525			OS::get_singleton()->printerr("Could not connect to remotefs: %s:%i\n",remotefs.utf8().get_data(),port);
 526			goto error;
 527		}
 528
 529		FileAccess::make_default<FileAccessNetwork>(FileAccess::ACCESS_RESOURCES);
 530	}
 531	if (script_debugger) {
 532		//there is a debugger, parse breakpoints
 533
 534		for(int i=0;i<breakpoints.size();i++) {
 535
 536			String bp = breakpoints[i];
 537			int sp=bp.find_last(":");
 538			if (sp==-1) {
 539				ERR_EXPLAIN("Invalid breakpoint: '"+bp+"', expected file:line format.");
 540				ERR_CONTINUE(sp==-1);
 541			}
 542
 543			script_debugger->insert_breakpoint(bp.substr(sp+1,bp.length()).to_int(),bp.substr(0,sp));
 544		}
 545	}
 546
 547
 548#ifdef TOOLS_ENABLED
 549	if (editor) {
 550		packed_data->set_disabled(true);
 551		globals->set_disable_platform_override(true);
 552	}
 553
 554#endif
 555
 556
 557	if (globals->setup(game_path,main_pack)!=OK) {
 558		
 559#ifdef TOOLS_ENABLED
 560		editor=false;
 561#else
 562		OS::get_singleton()->print("error: Couldn't load game path '%s'\n",game_path.ascii().get_data());
 563
 564		goto error;
 565#endif
 566	}
 567
 568	if (editor) {
 569		main_args.push_back("-editor");
 570		use_custom_res=false;
 571	}
 572
 573	OS::get_singleton()->set_cmdline(execpath, main_args);
 574
 575#ifdef TOOLS_ENABLED
 576
 577	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"))==""))
 578		use_custom_res=false; //project manager (run without arguments)
 579
 580#endif
 581
 582	input_map->load_from_globals();
 583
 584	if (video_driver=="") // specified in engine.cfg
 585		video_driver=_GLOBAL_DEF("display/driver",Variant((const char*)OS::get_singleton()->get_video_driver_name(0)));
 586
 587	if (!force_res && use_custom_res && globals->has("display/width"))
 588		video_mode.width=globals->get("display/width");
 589	if (!force_res &&use_custom_res && globals->has("display/height"))
 590		video_mode.height=globals->get("display/height");
 591	if (use_custom_res && globals->has("display/fullscreen"))
 592		video_mode.fullscreen=globals->get("display/fullscreen");
 593	if (use_custom_res && globals->has("display/resizable"))
 594		video_mode.resizable=globals->get("display/resizable");
 595
 596
 597
 598	GLOBAL_DEF("display/width",video_mode.width);
 599	GLOBAL_DEF("display/height",video_mode.height);
 600	GLOBAL_DEF("display/fullscreen",video_mode.fullscreen);
 601	GLOBAL_DEF("display/resizable",video_mode.resizable);
 602	if (rtm==-1) {
 603		rtm=GLOBAL_DEF("render/thread_model",OS::RENDER_THREAD_SAFE);
 604	}
 605
 606	if (rtm>=0 && rtm<3)
 607		OS::get_singleton()->_render_thread_mode=OS::RenderThreadMode(rtm);
 608
 609
 610
 611	/* Determine Video Driver */
 612
 613	if (audio_driver=="") // specified in engine.cfg
 614		audio_driver=GLOBAL_DEF("audio/driver",OS::get_singleton()->get_audio_driver_name(0));
 615		
 616	
 617	for (int i=0;i<OS::get_singleton()->get_video_driver_count();i++) {
 618
 619		if (video_driver==OS::get_singleton()->get_video_driver_name(i)) {
 620		
 621			video_driver_idx=i;
 622			break;
 623		}
 624	}
 625
 626	if (video_driver_idx<0) {
 627	
 628		OS::get_singleton()->alert( "Invalid Video Driver: "+video_driver );
 629		video_driver_idx = 0;
 630		//goto error;
 631	}
 632
 633	for (int i=0;i<OS::get_singleton()->get_audio_driver_count();i++) {
 634	
 635		if (audio_driver==OS::get_singleton()->get_audio_driver_name(i)) {
 636		
 637			audio_driver_idx=i;
 638			break;
 639		}
 640	}
 641
 642	if (audio_driver_idx<0) {
 643	
 644		OS::get_singleton()->alert( "Invalid Audio Driver: "+audio_driver );
 645		goto error;
 646	}
 647
 648	{
 649		String orientation = GLOBAL_DEF("display/orientation","landscape");
 650
 651		if (orientation=="portrait")
 652			OS::get_singleton()->set_screen_orientation(OS::SCREEN_PORTRAIT);
 653		else if (orientation=="reverse_landscape")
 654			OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_LANDSCAPE);
 655		else if (orientation=="reverse_portrait")
 656			OS::get_singleton()->set_screen_orientation(OS::SCREEN_REVERSE_PORTRAIT);
 657		else if (orientation=="sensor_landscape")
 658			OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_LANDSCAPE);
 659		else if (orientation=="sensor_portrait")
 660			OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR_PORTRAIT);
 661		else if (orientation=="sensor")
 662			OS::get_singleton()->set_screen_orientation(OS::SCREEN_SENSOR);
 663		else
 664			OS::get_singleton()->set_screen_orientation(OS::SCREEN_LANDSCAPE);
 665	}
 666
 667	OS::get_singleton()->set_iterations_per_second(GLOBAL_DEF("physics/fixed_fps",60));
 668	OS::get_singleton()->set_target_fps(GLOBAL_DEF("application/target_fps",0));
 669
 670	if (!OS::get_singleton()->_verbose_stdout) //overrided
 671		OS::get_singleton()->_verbose_stdout=GLOBAL_DEF("debug/verbose_stdout",false);
 672
 673	message_queue = memnew( MessageQueue );
 674
 675	Globals::get_singleton()->register_global_defaults();
 676
 677	if (p_second_phase)
 678		return setup2();
 679
 680	return OK;
 681
 682	error:
 683	
 684	video_driver="";	
 685	audio_driver="";
 686	game_path="";
 687		
 688	args.clear(); 
 689	main_args.clear();
 690	
 691	print_help(execpath);
 692	
 693
 694	if (performance)
 695		memdelete(performance);
 696	if (input_map)
 697		memdelete(input_map);
 698	if (translation_server)
 699		memdelete( translation_server );
 700	if (globals)
 701		memdelete(globals);
 702	if (script_debugger)
 703		memdelete(script_debugger);
 704	if (packed_data)
 705		memdelete(packed_data);
 706	if (file_access_network_client)
 707		memdelete(file_access_network_client);
 708	unregister_core_types();
 709	
 710	OS::get_singleton()->_cmdline.clear();
 711
 712	if (message_queue)
 713		memdelete( message_queue);
 714	OS::get_singleton()->finalize_core();
 715	locale=String();
 716	
 717	return ERR_INVALID_PARAMETER;
 718}
 719
 720Error Main::setup2() {
 721
 722
 723	OS::get_singleton()->initialize(video_mode,video_driver_idx,audio_driver_idx);
 724
 725	register_core_singletons();
 726
 727	MAIN_PRINT("Main: Setup Logo");
 728
 729	bool show_logo=true;
 730#ifdef JAVASCRIPT_ENABLED
 731	show_logo=false;
 732#endif
 733
 734	if (show_logo) { //boot logo!
 735		Image boot_logo=GLOBAL_DEF("application/boot_logo",Image());
 736
 737		if (!boot_logo.empty()) {
 738			Color clear = GLOBAL_DEF("render/default_clear_color",Color(0.3,0.3,0.3));
 739			VisualServer::get_singleton()->set_default_clear_color(clear);
 740			Color boot_bg = GLOBAL_DEF("application/boot_bg_color", clear);
 741			VisualServer::get_singleton()->set_boot_image(boot_logo, boot_bg);
 742#ifndef TOOLS_ENABLED
 743			//no tools, so free the boot logo (no longer needed)
 744			Globals::get_singleton()->set("application/boot_logo",Image());
 745#endif
 746
 747		} else {
 748#ifndef NO_DEFAULT_BOOT_LOGO
 749
 750			MAIN_PRINT("Main: Create botsplash");
 751			Image splash(boot_splash_png);
 752
 753			MAIN_PRINT("Main: ClearColor");
 754			VisualServer::get_singleton()->set_default_clear_color(boot_splash_bg_color);
 755			MAIN_PRINT("Main: Image");
 756			VisualServer::get_singleton()->set_boot_image(splash, boot_splash_bg_color);
 757#endif
 758			MAIN_PRINT("Main: DCC");
 759			VisualServer::get_singleton()->set_default_clear_color(GLOBAL_DEF("render/default_clear_color",Color(0.3,0.3,0.3)));
 760			MAIN_PRINT("Main: END");
 761		}
 762
 763		Image icon(app_icon_png);
 764		OS::get_singleton()->set_icon(icon);
 765	}
 766	GLOBAL_DEF("application/icon",String());
 767	Globals::get_singleton()->set_custom_property_info("application/icon",PropertyInfo(Variant::STRING,"application/icon",PROPERTY_HINT_FILE,"*.png,*.webp"));
 768
 769	MAIN_PRINT("Main: Load Remaps");
 770
 771	path_remap->load_remaps();
 772
 773	MAIN_PRINT("Main: Load Scene Types");
 774
 775	register_scene_types();
 776	register_server_types();
 777
 778#ifdef TOOLS_ENABLED
 779	EditorNode::register_editor_types();
 780#endif
 781
 782	MAIN_PRINT("Main: Load Scripts, Modules, Drivers");
 783
 784	register_module_types();
 785	register_driver_types();
 786
 787	MAIN_PRINT("Main: Load Translations");
 788
 789	translation_server->setup(); //register translations, load them, etc.
 790	if (locale!="") {
 791
 792		translation_server->set_locale(locale);
 793	}
 794	translation_server->load_translations();
 795
 796
 797
 798	_start_success=true;
 799	locale=String();
 800
 801	MAIN_PRINT("Main: Done");
 802
 803	return OK;
 804
 805}
 806
 807
 808
 809bool Main::start() {
 810
 811	ERR_FAIL_COND_V(!_start_success,false);
 812
 813	bool editor=false;
 814	String doc_tool;
 815	bool doc_base=true;
 816	String game_path;
 817	String script;
 818	String test;
 819	String screen;
 820	String optimize;
 821	String optimize_preset;
 822	String _export_platform;
 823	String _import;
 824	String _import_script;
 825	String dumpstrings;
 826	bool noquit=false;
 827	bool convert_old=false;
 828	bool export_debug=false;
 829	List<String> args = OS::get_singleton()->get_cmdline_args();
 830	for (int i=0;i<args.size();i++) {
 831		
 832
 833		if (args[i]=="-doctool" && i <(args.size()-1)) {
 834
 835			doc_tool=args[i+1];
 836			i++;
 837		}else if (args[i]=="-nodocbase") {
 838
 839			doc_base=false;
 840		} else if ((args[i]=="-script" || args[i]=="-s") && i <(args.size()-1)) {
 841		
 842			script=args[i+1];
 843			i++;
 844		} else if ((args[i]=="-level" || args[i]=="-l") && i <(args.size()-1)) {
 845
 846			OS::get_singleton()->_custom_level=args[i+1];
 847			i++;
 848		} else if (args[i]=="-test" && i <(args.size()-1)) {
 849			test=args[i+1];
 850			i++;
 851		} else if (args[i]=="-optimize" && i <(args.size()-1)) {
 852			optimize=args[i+1];
 853			i++;
 854		} else if (args[i]=="-optimize_preset" && i <(args.size()-1)) {
 855			optimize_preset=args[i+1];
 856			i++;
 857		} else if (args[i]=="-export" && i <(args.size()-1)) {
 858			editor=true; //needs editor
 859			_export_platform=args[i+1];
 860			i++;
 861		} else if (args[i]=="-export_debug" && i <(args.size()-1)) {
 862			editor=true; //needs editor
 863			_export_platform=args[i+1];
 864			export_debug=true;
 865			i++;
 866		} else if (args[i]=="-import" && i <(args.size()-1)) {
 867			editor=true; //needs editor
 868			_import=args[i+1];
 869			i++;
 870		} else if (args[i]=="-import_script" && i <(args.size()-1)) {
 871			editor=true; //needs editor
 872			_import_script=args[i+1];
 873			i++;
 874		} else if (args[i]=="-noquit" ) {
 875			noquit=true;
 876		} else if (args[i]=="-dumpstrings" && i <(args.size()-1)) {
 877			editor=true; //needs editor
 878			dumpstrings=args[i+1];
 879			i++;
 880		} else if (args[i]=="-editor" || args[i]=="-e") {
 881			editor=true;
 882		} else if (args[i]=="-convert_old") {
 883			convert_old=true;
 884		} else if (args[i].length() && args[i][0] != '-' && game_path == "") {
 885
 886			game_path=args[i];
 887		}
 888	}
 889
 890	if (editor)
 891		Globals::get_singleton()->set("editor_active",true);
 892
 893
 894	String main_loop_type;
 895#ifdef TOOLS_ENABLED
 896	if(doc_tool!="") {
 897
 898		DocData doc;
 899		doc.generate(doc_base);
 900
 901		DocData docsrc;
 902		if (docsrc.load(doc_tool)==OK) {
 903			print_line("Doc exists. Merging..");
 904			doc.merge_from(docsrc);
 905		} else {
 906			print_line("No Doc exists. Generating empty.");
 907
 908		}
 909
 910		doc.save(doc_tool);
 911
 912		return false;
 913	}
 914
 915	if (optimize!="")
 916		editor=true; //need editor
 917
 918
 919
 920#endif
 921
 922	if(script=="" && game_path=="" && !editor && String(GLOBAL_DEF("application/main_scene",""))!="") {
 923		game_path=GLOBAL_DEF("application/main_scene","");
 924	}
 925
 926
 927	MainLoop *main_loop=NULL;
 928	if (editor) {
 929		main_loop = memnew(SceneMainLoop);
 930	};
 931
 932	if (test!="") {
 933#ifdef DEBUG_ENABLED
 934		main_loop = test_main(test,args);
 935
 936		if (!main_loop)
 937			return false;
 938
 939#endif
 940
 941	} else if (script!="") {
 942
 943		Ref<Script> script_res = ResourceLoader::load(script);
 944		ERR_EXPLAIN("Can't load script: "+script);
 945		ERR_FAIL_COND_V(script_res.is_null(),false);
 946		
 947		if( script_res->can_instance() /*&& script_res->inherits_from("SceneMainLoopScripted")*/) {
 948		
 949
 950			StringName instance_type=script_res->get_instance_base_type();
 951			Object *obj = ObjectTypeDB::instance(instance_type);
 952			MainLoop *script_loop = obj?obj->cast_to<MainLoop>():NULL;
 953			if (!script_loop) {
 954				if (obj)
 955					memdelete(obj);
 956				ERR_EXPLAIN("Can't load script '"+script+"', it does not inherit from a MainLoop type");
 957				ERR_FAIL_COND_V(!script_loop,false);
 958			}
 959
 960
 961			script_loop->set_init_script(script_res);
 962			main_loop=script_loop;
 963		} else {
 964
 965			return false;
 966		}
 967
 968	} else {
 969		main_loop_type=GLOBAL_DEF("application/main_loop_type","");
 970	}
 971	
 972	if (!main_loop && main_loop_type=="")
 973		main_loop_type="SceneMainLoop";
 974	
 975	if (!main_loop) {
 976		if (!ObjectTypeDB::type_exists(main_loop_type)) {
 977			OS::get_singleton()->alert("godot: error: MainLoop type doesn't exist: "+main_loop_type);
 978			return false;
 979		} else {
 980
 981			Object *ml = ObjectTypeDB::instance(main_loop_type);
 982			if (!ml) {
 983				ERR_EXPLAIN("Can't instance MainLoop type");
 984				ERR_FAIL_V(false);
 985			}
 986
 987			main_loop=ml->cast_to<MainLoop>();
 988			if (!main_loop) {
 989				
 990				memdelete(ml);
 991				ERR_EXPLAIN("Invalid MainLoop type");
 992				ERR_FAIL_V(false);
 993				
 994			}
 995		}
 996	}
 997
 998	if (main_loop->is_type("SceneMainLoop")) {
 999		
1000		SceneMainLoop *sml = main_loop->cast_to<SceneMainLoop>();
1001
1002#ifdef TOOLS_ENABLED
1003
1004		EditorNode *editor_node=NULL;
1005		if (editor) {
1006
1007			editor_node = memnew( EditorNode );			
1008			sml->get_root()->add_child(editor_node);
1009
1010			//root_node->set_editor(editor);
1011			//startup editor
1012
1013			if (_export_platform!="") {
1014
1015				editor_node->export_platform(_export_platform,game_path,export_debug,"",true);
1016				game_path=""; //no load anything
1017			}
1018		}
1019#endif
1020
1021		if (!editor) {
1022			//standard helpers that can be changed from main config
1023
1024			String stretch_mode = GLOBAL_DEF("display/stretch_mode","disabled");
1025			String stretch_aspect = GLOBAL_DEF("display/stretch_aspect","ignore");
1026			Size2i stretch_size = Size2(GLOBAL_DEF("display/width",0),GLOBAL_DEF("display/height",0));
1027
1028			SceneMainLoop::StretchMode sml_sm=SceneMainLoop::STRETCH_MODE_DISABLED;
1029			if (stretch_mode=="2d")
1030				sml_sm=SceneMainLoop::STRETCH_MODE_2D;
1031			else if (stretch_mode=="viewport")
1032				sml_sm=SceneMainLoop::STRETCH_MODE_VIEWPORT;
1033
1034			SceneMainLoop::StretchAspect sml_aspect=SceneMainLoop::STRETCH_ASPECT_IGNORE;
1035			if (stretch_aspect=="keep")
1036				sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP;
1037			else if (stretch_aspect=="keep_width")
1038				sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP_WIDTH;
1039			else if (stretch_aspect=="keep_height")
1040				sml_aspect=SceneMainLoop::STRETCH_ASPECT_KEEP_HEIGHT;
1041
1042			sml->set_screen_stretch(sml_sm,sml_aspect,stretch_size);
1043
1044			sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
1045			String appname = Globals::get_singleton()->get("application/name");
1046			appname = TranslationServer::get_singleton()->translate(appname);
1047			OS::get_singleton()->set_window_title(appname);
1048
1049
1050		} else {
1051			GLOBAL_DEF("display/stretch_mode","disabled");
1052			Globals::get_singleton()->set_custom_property_info("display/stretch_mode",PropertyInfo(Variant::STRING,"display/stretch_mode",PROPERTY_HINT_ENUM,"disabled,2d,viewport"));
1053			GLOBAL_DEF("display/stretch_aspect","ignore");
1054			Globals::get_singleton()->set_custom_property_info("display/stretch_aspect",PropertyInfo(Variant::STRING,"display/stretch_aspect",PROPERTY_HINT_ENUM,"ignore,keep,keep_width,keep_height"));
1055			sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
1056
1057
1058		}
1059
1060
1061		if (game_path!="") {
1062
1063			String local_game_path=game_path.replace("\\","/");
1064
1065			if (!local_game_path.begins_with("res://")) {
1066				bool absolute=(local_game_path.size()>1) && (local_game_path[0]=='/' || local_game_path[1]==':');
1067
1068				if (!absolute) {
1069
1070					if (Globals::get_singleton()->is_using_datapack()) {
1071
1072						local_game_path="res://"+local_game_path;
1073
1074					} else {
1075						int sep=local_game_path.find_last("/");
1076
1077						if (sep==-1) {
1078							DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
1079							local_game_path=da->get_current_dir()+"/"+local_game_path;
1080							memdelete(da)						;
1081						} else {
1082
1083							DirAccess *da = DirAccess::open(local_game_path.substr(0,sep));
1084							if (da) {
1085								local_game_path=da->get_current_dir()+"/"+local_game_path.substr(sep+1,local_game_path.length());;
1086								memdelete(da);
1087							}
1088						}
1089					}
1090
1091				}
1092			}
1093
1094			local_game_path=Globals::get_singleton()->localize_path(local_game_path);
1095
1096#ifdef TOOLS_ENABLED
1097			if (editor) {
1098
1099#ifdef OLD_SCENE_FORMAT_ENABLED
1100				if (convert_old)
1101					editor_node->set_convert_old_scene(true);
1102#endif
1103
1104				if (_import!="") {
1105
1106					//editor_node->import_scene(_import,local_game_path,_import_script);
1107					if (!noquit)
1108						sml->quit();
1109					game_path=""; //no load anything
1110				} else {
1111
1112					Error serr = editor_node->load_scene(local_game_path);
1113
1114					if (serr==OK) {
1115
1116						if (optimize!="") {
1117
1118							editor_node->save_optimized_copy(optimize,optimize_preset);
1119							if (!noquit)
1120								sml->quit();
1121						}
1122
1123						if (dumpstrings!="") {
1124
1125							editor_node->save_translatable_strings(dumpstrings);
1126							if (!noquit)
1127								sml->quit();
1128						}
1129					}
1130				}
1131
1132				//editor_node->set_edited_scene(game);
1133			} else {
1134#endif
1135
1136				{
1137					//autoload
1138					List<PropertyInfo> props;
1139					Globals::get_singleton()->get_property_list(&props);
1140					for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
1141
1142						String s = E->get().name;
1143						if (!s.begins_with("autoload/"))
1144							continue;
1145						String name = s.get_slice("/",1);
1146						String path = Globals::get_singleton()->get(s);
1147						RES res = ResourceLoader::load(path);
1148						ERR_EXPLAIN("Can't autoload: "+path);
1149						ERR_CONTINUE(res.is_null());
1150						Node *n=NULL;
1151						if (res->is_type("PackedScene")) {
1152							Ref<PackedScene> ps = res;
1153							n=ps->instance();
1154						} else if (res->is_type("Script")) {
1155							Ref<Script> s = res;
1156							StringName ibt = s->get_instance_base_type();
1157							ERR_EXPLAIN("Script does not inherit a Node: "+path);
1158							ERR_CONTINUE( !ObjectTypeDB::is_type(ibt,"Node") );
1159
1160							Object *obj = ObjectTypeDB::instance(ibt);
1161
1162							ERR_EXPLAIN("Cannot instance node for autoload type: "+String(ibt));
1163							ERR_CONTINUE( obj==NULL );
1164
1165							n = obj->cast_to<Node>();
1166							n->set_script(s.get_ref_ptr());
1167						}
1168
1169						ERR_EXPLAIN("Path in autoload not a node or script: "+path);
1170						ERR_CONTINUE(!n);
1171						n->set_name(name);
1172						sml->get_root()->add_child(n);
1173					}
1174
1175				}
1176
1177				Node *scene=NULL;
1178				Ref<PackedScene> scenedata = ResourceLoader::load(local_game_path);
1179				if (scenedata.is_valid())
1180					scene=scenedata->instance();
1181
1182#ifdef OLD_SCENE_FORMAT_ENABLED
1183
1184				if (!scene) {
1185					scene = SceneLoader::load(local_game_path,true);
1186				}
1187
1188#endif
1189
1190				ERR_EXPLAIN("Failed loading scene: "+local_game_path);
1191				ERR_FAIL_COND_V(!scene,false)
1192				sml->get_root()->add_child(scene);
1193
1194				String iconpath = GLOBAL_DEF("application/icon","Variant()""");
1195				if (iconpath!="") {
1196					Image icon;
1197					if (icon.load(iconpath)==OK)
1198						OS::get_singleton()->set_icon(icon);
1199				}
1200
1201
1202				//singletons
1203#ifdef TOOLS_ENABLED
1204			}
1205#endif
1206		}
1207
1208#ifdef TOOLS_ENABLED
1209
1210		/*if (_export_platform!="") {
1211
1212			sml->quit();
1213		}*/
1214
1215		/*
1216		if (sml->get_root_node()) {
1217
1218			Console *console = memnew( Console );
1219
1220			sml->get_root_node()->cast_to<RootNode>()->set_console(console);
1221			if (GLOBAL_DEF("console/visible_default",false).operator bool()) {
1222
1223				console->show();
1224			} else {P
1225
1226				console->hide();
1227			};
1228		}
1229*/
1230		if (script=="" && test=="" && game_path=="" && !editor) {
1231
1232			ProjectManager *pmanager = memnew( ProjectManager );
1233			sml->get_root()->add_child(pmanager);
1234		}
1235
1236#endif
1237	}
1238
1239	OS::get_singleton()->set_main_loop( main_loop );
1240
1241	return true;
1242}
1243
1244uint64_t Main::last_ticks=0;
1245uint64_t Main::target_ticks=0;
1246float Main::time_accum=0;
1247uint32_t Main::frames=0;
1248uint32_t Main::frame=0;
1249bool Main::force_redraw_requested = false;
1250
1251static uint64_t fixed_process_max=0;
1252static uint64_t idle_process_max=0;
1253
1254
1255bool Main::iteration() {
1256
1257	uint64_t ticks=OS::get_singleton()->get_ticks_usec();
1258	uint64_t ticks_elapsed=ticks-last_ticks;
1259
1260	frame+=ticks_elapsed;
1261
1262	last_ticks=ticks;
1263	double step=(double)ticks_elapsed / 1000000.0;
1264
1265	float frame_slice=1.0/OS::get_singleton()->get_iterations_per_second();
1266
1267	if (step>frame_slice*8)
1268		step=frame_slice*8;
1269
1270	time_accum+=step;
1271
1272	bool exit=false;
1273
1274
1275	int iters = 0;
1276
1277	while(time_accum>frame_slice) {
1278
1279		uint64_t fixed_begin = OS::get_singleton()->get_ticks_usec();
1280
1281		PhysicsServer::get_singleton()->sync();
1282		PhysicsServer::get_singleton()->flush_queries();
1283
1284		Physics2DServer::get_singleton()->sync();
1285		Physics2DServer::get_singleton()->flush_queries();
1286
1287		if (OS::get_singleton()->get_main_loop()->iteration( frame_slice )) {
1288			exit=true;
1289			break;
1290		}
1291
1292		message_queue->flush();
1293
1294		PhysicsServer::get_singleton()->step(frame_slice);
1295		Physics2DServer::get_singleton()->step(frame_slice);
1296
1297		time_accum-=frame_slice;
1298		message_queue->flush();
1299		//if (AudioServer::get_singleton())
1300		//	AudioServer::get_singleton()->update();
1301
1302		fixed_process_max=MAX(OS::get_singleton()->get_ticks_usec()-fixed_begin,fixed_process_max);
1303		iters++;
1304	}
1305
1306	uint64_t idle_begin = OS::get_singleton()->get_ticks_usec();
1307
1308	OS::get_singleton()->get_main_loop()->idle( step );
1309	message_queue->flush();
1310
1311	if (SpatialSoundServer::get_singleton())
1312		SpatialSoundServer::get_singleton()->update( step );
1313	if (SpatialSound2DServer::get_singleton())
1314		SpatialSound2DServer::get_singleton()->update( step );
1315
1316
1317	if (OS::get_singleton()->can_draw()) {
1318
1319		if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) {
1320			if (VisualServer::get_singleton()->has_changed()) {
1321				VisualServer::get_singleton()->draw(); // flush visual commands
1322				OS::get_singleton()->frames_drawn++;
1323			}
1324		} else {
1325			VisualServer::get_singleton()->draw(); // flush visual commands
1326			OS::get_singleton()->frames_drawn++;
1327			force_redraw_requested = false;
1328		}
1329	} else {
1330		VisualServer::get_singleton()->flush(); // flush visual commands
1331	}
1332
1333	if (AudioServer::get_singleton())
1334		AudioServer::get_singleton()->update();
1335
1336	for(int i=0;i<ScriptServer::get_language_count();i++) {
1337		ScriptServer::get_language(i)->frame();
1338	}
1339
1340	idle_process_max=MAX(OS::get_singleton()->get_ticks_usec()-idle_begin,idle_process_max);
1341
1342	if (script_debugger)
1343		script_debugger->idle_poll();
1344
1345
1346	//	x11_delay_usec(10000);
1347	frames++;
1348
1349	if (frame>1000000) {
1350
1351		if (GLOBAL_DEF("debug/print_fps", OS::get_singleton()->is_stdout_verbose())) {
1352			print_line("FPS: "+itos(frames));
1353		};
1354
1355		OS::get_singleton()->_fps=frames;
1356		performance->set_process_time(idle_process_max/1000000.0);
1357		performance->set_fixed_process_time(fixed_process_max/1000000.0);
1358		idle_process_max=0;
1359		fixed_process_max=0;
1360
1361		if (GLOBAL_DEF("debug/print_metrics", false)) {
1362
1363			//PerformanceMetrics::print();
1364		};
1365
1366		frame%=1000000;
1367		frames=0;
1368	}
1369
1370	if (OS::get_singleton()->is_in_low_processor_usage_mode() || !OS::get_singleton()->can_draw())
1371		OS::get_singleton()->delay_usec(25000); //apply some delay to force idle time
1372	else {
1373		uint32_t frame_delay = OS::get_singleton()->get_frame_delay();
1374		if (frame_delay)
1375			OS::get_singleton()->delay_usec( OS::get_singleton()->get_frame_delay()*1000 );
1376	}
1377
1378	int taret_fps = OS::get_singleton()->get_target_fps();
1379	if (taret_fps>0) {
1380		uint64_t time_step = 1000000L/taret_fps;
1381		target_ticks += time_step;
1382		uint64_t current_ticks = OS::get_singleton()->get_ticks_usec();
1383		if (current_ticks<target_ticks) OS::get_singleton()->delay_usec(target_ticks-current_ticks);
1384		current_ticks = OS::get_singleton()->get_ticks_usec();
1385		target_ticks = MIN(MAX(target_ticks,current_ticks-time_step),current_ticks+time_step);
1386	}
1387
1388	return exit;
1389}
1390
1391void Main::force_redraw() {
1392
1393	force_redraw_requested = true;
1394};
1395
1396
1397void Main::cleanup() {
1398
1399	ERR_FAIL_COND(!_start_success);
1400
1401	if (script_debugger)
1402		memdelete(script_debugger);
1403
1404	OS::get_singleton()->delete_main_loop();
1405
1406	OS::get_singleton()->_cmdline.clear();
1407	OS::get_singleton()->_execpath="";
1408	OS::get_singleton()->_local_clipboard="";
1409
1410#ifdef TOOLS_ENABLED
1411	EditorNode::unregister_editor_types();
1412#endif
1413
1414	unregister_driver_types();	
1415	unregister_module_types();
1416	unregister_scene_types();	
1417	unregister_server_types();
1418
1419	OS::get_singleton()->finalize();
1420				
1421	if (packed_data)
1422		memdelete(packed_data);
1423	if (file_access_network_client)
1424		memdelete(file_access_network_client);
1425	if (performance)
1426		memdelete(performance);
1427	if (input_map)
1428		memdelete(input_map);
1429	if (translation_server)
1430		memdelete( translation_server );
1431	if (path_remap)
1432		memdelete(path_remap);
1433	if (globals)
1434		memdelete(globals);
1435
1436
1437
1438
1439	memdelete( message_queue );
1440
1441	unregister_core_driver_types();
1442	unregister_core_types();
1443
1444	//PerformanceMetrics::finish();
1445	OS::get_singleton()->clear_last_error();
1446	OS::get_singleton()->finalize_core();
1447
1448
1449}
1450