virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {

		if (p_start_mode == START_MODE_RESUME_YIELD) {
			return 0; //resuming yield
		} else {
			//yield

			SceneTree *tree = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());
			if (!tree) {
				r_error_str = "Main Loop is not SceneTree";
				r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
				return 0;
			}

			Ref<VisualScriptFunctionState> state;
			state.instance();

			int ret = STEP_YIELD_BIT;
			switch (mode) {

				case VisualScriptYield::YIELD_RETURN:
					ret = STEP_EXIT_FUNCTION_BIT;
					break; //return the yield
				case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree, "idle_frame", Array()); break;
				case VisualScriptYield::YIELD_PHYSICS_FRAME: state->connect_to_signal(tree, "physics_frame", Array()); break;
				case VisualScriptYield::YIELD_WAIT: state->connect_to_signal(tree->create_timer(wait_time).ptr(), "timeout", Array()); break;
			}

			*p_working_mem = state;

			return ret;
		}
	}
Ref<TimerObject> NewTimer::wait_trigger(float p_time, Object *p_target, String p_method) {
    const String timer_key = "new_timer";
    MainLoop *main_loop = OS::get_singleton()->get_main_loop();
    SceneTree *tree = main_loop->cast_to<SceneTree>();
    ERR_FAIL_COND_V(tree == NULL, NULL);

    Viewport *viewport = tree->get_root();
    ERR_FAIL_COND_V(viewport == NULL, NULL);
    TimerNode *timerNode;
    if (timerNode == NULL) {
        timerNode = memnew(TimerNode);
        timerNode->set_name(timer_key);

        Vector<Variant> vector;
        vector.push_back(Variant(timerNode));

        tree->connect("idle_frame", this, "_add_node", vector, 0);

    }else {
        timerNode = viewport->get_node(timer_key)->cast_to<TimerNode>();
    }

    Ref<TimerObject> obj = memnew(TimerObject);
    obj->time = p_time;
    obj->target = p_target;
    obj->method = p_method;
    timerNode->timer_objs.push_back(obj);
    timerNode->check_queue();
    return obj;
}
Exemple #3
0
float Performance::_get_node_count() const {
	MainLoop *ml = OS::get_singleton()->get_main_loop();
	SceneTree *sml = Object::cast_to<SceneTree>(ml);
	if (!sml)
		return 0;
	return sml->get_node_count();
}
void NewTimer::_add_node(Object *node) {
    MainLoop *main_loop = OS::get_singleton()->get_main_loop();
    SceneTree *tree = main_loop->cast_to<SceneTree>();
    ERR_FAIL_COND(tree == NULL);

    tree->disconnect("idle_frame", this, "_add_node");
    tree->get_root()->add_child(node->cast_to<TimerNode>());
}
Exemple #5
0
float Performance::get_monitor(Monitor p_monitor) const {

	switch (p_monitor) {
		case TIME_FPS: return Engine::get_singleton()->get_frames_per_second();
		case TIME_PROCESS: return _process_time;
		case TIME_PHYSICS_PROCESS: return _physics_process_time;
		case MEMORY_STATIC: return Memory::get_mem_usage();
		case MEMORY_DYNAMIC: return MemoryPool::total_memory;
		case MEMORY_STATIC_MAX: return Memory::get_mem_max_usage();
		case MEMORY_DYNAMIC_MAX: return MemoryPool::max_memory;
		case MEMORY_MESSAGE_BUFFER_MAX: return MessageQueue::get_singleton()->get_max_buffer_usage();
		case OBJECT_COUNT: return ObjectDB::get_object_count();
		case OBJECT_RESOURCE_COUNT: return ResourceCache::get_cached_resource_count();
		case OBJECT_NODE_COUNT: {

			MainLoop *ml = OS::get_singleton()->get_main_loop();
			SceneTree *sml = Object::cast_to<SceneTree>(ml);
			if (!sml)
				return 0;
			return sml->get_node_count();
		};
		case RENDER_OBJECTS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_OBJECTS_IN_FRAME);
		case RENDER_VERTICES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_VERTICES_IN_FRAME);
		case RENDER_MATERIAL_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_MATERIAL_CHANGES_IN_FRAME);
		case RENDER_SHADER_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME);
		case RENDER_SURFACE_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME);
		case RENDER_DRAW_CALLS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_DRAW_CALLS_IN_FRAME);
		case RENDER_VIDEO_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VIDEO_MEM_USED);
		case RENDER_TEXTURE_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED);
		case RENDER_VERTEX_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VERTEX_MEM_USED);
		case RENDER_USAGE_VIDEO_MEM_TOTAL: return VS::get_singleton()->get_render_info(VS::INFO_USAGE_VIDEO_MEM_TOTAL);
		case PHYSICS_2D_ACTIVE_OBJECTS: return Physics2DServer::get_singleton()->get_process_info(Physics2DServer::INFO_ACTIVE_OBJECTS);
		case PHYSICS_2D_COLLISION_PAIRS: return Physics2DServer::get_singleton()->get_process_info(Physics2DServer::INFO_COLLISION_PAIRS);
		case PHYSICS_2D_ISLAND_COUNT: return Physics2DServer::get_singleton()->get_process_info(Physics2DServer::INFO_ISLAND_COUNT);
		case PHYSICS_3D_ACTIVE_OBJECTS: return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_ACTIVE_OBJECTS);
		case PHYSICS_3D_COLLISION_PAIRS: return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_COLLISION_PAIRS);
		case PHYSICS_3D_ISLAND_COUNT: return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_ISLAND_COUNT);
		case AUDIO_OUTPUT_LATENCY: return AudioServer::get_singleton()->get_output_latency();

		default: {}
	}

	return 0;
}
Exemple #6
0
Ref<ArrayMesh> Shape::get_debug_mesh() {

	if (debug_mesh_cache.is_valid())
		return debug_mesh_cache;

	Vector<Vector3> lines = _gen_debug_mesh_lines();

	debug_mesh_cache = Ref<ArrayMesh>(memnew(ArrayMesh));

	if (!lines.empty()) {
		//make mesh
		PoolVector<Vector3> array;
		array.resize(lines.size());
		{

			PoolVector<Vector3>::Write w = array.write();
			for (int i = 0; i < lines.size(); i++) {
				w[i] = lines[i];
			}
		}

		Array arr;
		arr.resize(Mesh::ARRAY_MAX);
		arr[Mesh::ARRAY_VERTEX] = array;

		SceneTree *st = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());

		debug_mesh_cache->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr);

		if (st) {
			debug_mesh_cache->surface_set_material(0, st->get_debug_collision_material());
		}
	}

	return debug_mesh_cache;
}
Exemple #7
0
void GridMap::_octant_update(const OctantKey &p_key) {
	ERR_FAIL_COND(!octant_map.has(p_key));
	Octant &g = *octant_map[p_key];
	if (!g.dirty)
		return;

	Ref<Mesh> mesh;

	_octant_clear_navmesh(p_key);
	PhysicsServer::get_singleton()->body_clear_shapes(g.static_body);

	if (g.collision_debug.is_valid()) {

		VS::get_singleton()->mesh_clear(g.collision_debug);
	}

	PoolVector<Vector3> col_debug;

	/*
	 * foreach item in this octant,
	 * set item's multimesh's instance count to number of cells which have this item
	 * and set said multimesh bounding box to one containing all cells which have this item
	 */
	for (Map<int, Octant::ItemInstances>::Element *E = g.items.front(); E; E = E->next()) {

		Octant::ItemInstances &ii = E->get();

		ii.multimesh->set_instance_count(ii.cells.size());

		Rect3 aabb;
		Rect3 mesh_aabb = ii.mesh.is_null() ? Rect3() : ii.mesh->get_aabb();

		Vector3 ofs(cell_size * 0.5 * int(center_x), cell_size * 0.5 * int(center_y), cell_size * 0.5 * int(center_z));

		//print_line("OCTANT, CELLS: "+itos(ii.cells.size()));
		int idx = 0;
		// foreach cell containing this item type
		for (Set<IndexKey>::Element *F = ii.cells.front(); F; F = F->next()) {
			IndexKey ik = F->get();
			Map<IndexKey, Cell>::Element *C = cell_map.find(ik);
			ERR_CONTINUE(!C);

			Vector3 cellpos = Vector3(ik.x, ik.y, ik.z);

			Transform xform;

			if (clip && ((clip_above && cellpos[clip_axis] > clip_floor) || (!clip_above && cellpos[clip_axis] < clip_floor))) {

				xform.basis.set_zero();

			} else {

				xform.basis.set_orthogonal_index(C->get().rot);
			}

			xform.set_origin(cellpos * cell_size + ofs);
			xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale));

			ii.multimesh->set_instance_transform(idx, xform);
			//ii.multimesh->set_instance_transform(idx,Transform()	);
			//ii.multimesh->set_instance_color(idx,Color(1,1,1,1));
			//print_line("MMINST: "+xform);

			if (idx == 0) {

				aabb = xform.xform(mesh_aabb);
			} else {

				aabb.merge_with(xform.xform(mesh_aabb));
			}

			// add the item's shape at given xform to octant's static_body
			if (ii.shape.is_valid()) {
				// add the item's shape
				PhysicsServer::get_singleton()->body_add_shape(g.static_body, ii.shape->get_rid(), xform);
				if (g.collision_debug.is_valid()) {
					ii.shape->add_vertices_to_array(col_debug, xform);
				}

				//print_line("PHIS x: "+xform);
			}

			// add the item's navmesh at given xform to GridMap's Navigation ancestor
			if (navigation) {
				if (ii.navmesh.is_valid()) {
					int nm_id = navigation->navmesh_create(ii.navmesh, xform, this);
					Octant::NavMesh nm;
					nm.id = nm_id;
					nm.xform = xform;
					g.navmesh_ids[ik] = nm;
				}
			}

			idx++;
		}

		//ii.multimesh->set_aabb(aabb);
	}

	if (col_debug.size()) {

		Array arr;
		arr.resize(VS::ARRAY_MAX);
		arr[VS::ARRAY_VERTEX] = col_debug;

		VS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, VS::PRIMITIVE_LINES, arr);
		SceneTree *st = SceneTree::get_singleton();
		if (st) {
			VS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid());
		}
	}

	g.dirty = false;
}
Exemple #8
0
void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) {

	ERR_FAIL_INDEX(ABS(p_x), 1 << 20);
	ERR_FAIL_INDEX(ABS(p_y), 1 << 20);
	ERR_FAIL_INDEX(ABS(p_z), 1 << 20);

	IndexKey key;
	key.x = p_x;
	key.y = p_y;
	key.z = p_z;

	OctantKey ok;
	ok.x = p_x / octant_size;
	ok.y = p_y / octant_size;
	ok.z = p_z / octant_size;
	ok.area = _find_area(key);

	if (cell_map.has(key)) {

		int prev_item = cell_map[key].item;

		OctantKey octantkey = ok;

		ERR_FAIL_COND(!octant_map.has(octantkey));
		Octant &g = *octant_map[octantkey];
		ERR_FAIL_COND(!g.items.has(prev_item));
		ERR_FAIL_COND(!g.items[prev_item].cells.has(key));

		g.items[prev_item].cells.erase(key);
		if (g.items[prev_item].cells.size() == 0) {
			VS::get_singleton()->free(g.items[prev_item].multimesh_instance);
			g.items.erase(prev_item);
		}
		if (g.items.empty()) {

			PhysicsServer::get_singleton()->free(g.static_body);
			if (g.collision_debug.is_valid()) {
				PhysicsServer::get_singleton()->free(g.collision_debug);
				PhysicsServer::get_singleton()->free(g.collision_debug_instance);
			}

			memdelete(&g);
			octant_map.erase(octantkey);
		} else {

			g.dirty = true;
		}
		cell_map.erase(key);

		_queue_dirty_map();
	}

	if (p_item < 0)
		return;

	OctantKey octantkey = ok;

	//add later
	if (!octant_map.has(octantkey)) {

		Octant *g = memnew(Octant);
		g->dirty = true;
		g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC);
		PhysicsServer::get_singleton()->body_attach_object_instance_ID(g->static_body, get_instance_ID());
		if (is_inside_world())
			PhysicsServer::get_singleton()->body_set_space(g->static_body, get_world()->get_space());

		SceneTree *st = SceneTree::get_singleton();

		if (st && st->is_debugging_collisions_hint()) {

			g->collision_debug = VisualServer::get_singleton()->mesh_create();
			g->collision_debug_instance = VisualServer::get_singleton()->instance_create();
			VisualServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug);
			if (is_inside_world()) {
				VisualServer::get_singleton()->instance_set_scenario(g->collision_debug_instance, get_world()->get_scenario());
				VisualServer::get_singleton()->instance_set_transform(g->collision_debug_instance, get_global_transform());
			}
		}

		octant_map[octantkey] = g;
	}

	Octant &g = *octant_map[octantkey];
	if (!g.items.has(p_item)) {

		Octant::ItemInstances ii;
		if (theme.is_valid() && theme->has_item(p_item)) {
			ii.mesh = theme->get_item_mesh(p_item);
			ii.shape = theme->get_item_shape(p_item);
			ii.navmesh = theme->get_item_navmesh(p_item);
		}
		ii.multimesh = Ref<MultiMesh>(memnew(MultiMesh));
		ii.multimesh->set_color_format(MultiMesh::COLOR_NONE);
		ii.multimesh->set_transform_format(MultiMesh::TRANSFORM_3D);
		ii.multimesh->set_mesh(ii.mesh);
		ii.multimesh_instance = VS::get_singleton()->instance_create();
		VS::get_singleton()->instance_set_base(ii.multimesh_instance, ii.multimesh->get_rid());

		g.items[p_item] = ii;
	}

	Octant::ItemInstances &ii = g.items[p_item];
	ii.cells.insert(key);
	g.dirty = true;

	_queue_dirty_map();

	cell_map[key] = Cell();
	Cell &c = cell_map[key];
	c.item = p_item;
	c.rot = p_rot;
}
Exemple #9
0
bool GridMap::_octant_update(const OctantKey &p_key) {
	ERR_FAIL_COND_V(!octant_map.has(p_key), false);
	Octant &g = *octant_map[p_key];
	if (!g.dirty)
		return false;

	//erase body shapes
	PhysicsServer::get_singleton()->body_clear_shapes(g.static_body);

	//erase body shapes debug
	if (g.collision_debug.is_valid()) {

		VS::get_singleton()->mesh_clear(g.collision_debug);
	}

	//erase navigation
	if (navigation) {
		for (Map<IndexKey, Octant::NavMesh>::Element *E = g.navmesh_ids.front(); E; E = E->next()) {
			navigation->navmesh_remove(E->get().id);
		}
		g.navmesh_ids.clear();
	}

	//erase multimeshes

	for (int i = 0; i < g.multimesh_instances.size(); i++) {

		VS::get_singleton()->free(g.multimesh_instances[i].instance);
		VS::get_singleton()->free(g.multimesh_instances[i].multimesh);
	}
	g.multimesh_instances.clear();

	if (g.cells.size() == 0) {
		//octant no longer needed
		_octant_clean_up(p_key);
		return true;
	}

	PoolVector<Vector3> col_debug;

	/*
	 * foreach item in this octant,
	 * set item's multimesh's instance count to number of cells which have this item
	 * and set said multimesh bounding box to one containing all cells which have this item
	 */

	Map<int, List<Pair<Transform, IndexKey> > > multimesh_items;

	for (Set<IndexKey>::Element *E = g.cells.front(); E; E = E->next()) {

		ERR_CONTINUE(!cell_map.has(E->get()));
		const Cell &c = cell_map[E->get()];

		if (!theme.is_valid() || !theme->has_item(c.item))
			continue;

		//print_line("OCTANT, CELLS: "+itos(ii.cells.size()));

		Vector3 cellpos = Vector3(E->get().x, E->get().y, E->get().z);
		Vector3 ofs(cell_size.x * 0.5 * int(center_x), cell_size.y * 0.5 * int(center_y), cell_size.z * 0.5 * int(center_z));

		Transform xform;

		if (clip && ((clip_above && cellpos[clip_axis] > clip_floor) || (!clip_above && cellpos[clip_axis] < clip_floor))) {

		} else {
		}

		xform.basis.set_orthogonal_index(c.rot);
		xform.set_origin(cellpos * cell_size + ofs);
		xform.basis.scale(Vector3(cell_scale, cell_scale, cell_scale));

		if (theme->get_item_mesh(c.item).is_valid()) {
			if (!multimesh_items.has(c.item)) {
				multimesh_items[c.item] = List<Pair<Transform, IndexKey> >();
			}

			Pair<Transform, IndexKey> p;
			p.first = xform;
			p.second = E->get();
			multimesh_items[c.item].push_back(p);
		}

		Vector<MeshLibrary::ShapeData> shapes = theme->get_item_shapes(c.item);
		// add the item's shape at given xform to octant's static_body
		for (int i = 0; i < shapes.size(); i++) {
			// add the item's shape
			if (!shapes[i].shape.is_valid())
				continue;
			PhysicsServer::get_singleton()->body_add_shape(g.static_body, shapes[i].shape->get_rid(), xform * shapes[i].local_transform);
			if (g.collision_debug.is_valid()) {
				shapes[i].shape->add_vertices_to_array(col_debug, xform * shapes[i].local_transform);
			}

			//print_line("PHIS x: "+xform);
		}

		// add the item's navmesh at given xform to GridMap's Navigation ancestor
		Ref<NavigationMesh> navmesh = theme->get_item_navmesh(c.item);
		if (navmesh.is_valid()) {
			Octant::NavMesh nm;
			nm.xform = xform;

			if (navigation) {
				nm.id = navigation->navmesh_create(navmesh, xform, this);
			} else {
				nm.id = -1;
			}
			g.navmesh_ids[E->get()] = nm;
		}
	}

	//update multimeshes
	for (Map<int, List<Pair<Transform, IndexKey> > >::Element *E = multimesh_items.front(); E; E = E->next()) {
		Octant::MultimeshInstance mmi;

		RID mm = VS::get_singleton()->multimesh_create();
		VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE);
		VS::get_singleton()->multimesh_set_mesh(mm, theme->get_item_mesh(E->key())->get_rid());

		int idx = 0;
		for (List<Pair<Transform, IndexKey> >::Element *F = E->get().front(); F; F = F->next()) {
			VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first);
#ifdef TOOLS_ENABLED

			Octant::MultimeshInstance::Item it;
			it.index = idx;
			it.transform = F->get().first;
			it.key = F->get().second;
			mmi.items.push_back(it);
#endif

			idx++;
		}

		RID instance = VS::get_singleton()->instance_create();
		VS::get_singleton()->instance_set_base(instance, mm);

		if (is_inside_tree()) {
			VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario());
			VS::get_singleton()->instance_set_transform(instance, get_global_transform());
		}

		mmi.multimesh = mm;
		mmi.instance = instance;

		g.multimesh_instances.push_back(mmi);
	}

	if (col_debug.size()) {

		Array arr;
		arr.resize(VS::ARRAY_MAX);
		arr[VS::ARRAY_VERTEX] = col_debug;

		VS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, VS::PRIMITIVE_LINES, arr);
		SceneTree *st = SceneTree::get_singleton();
		if (st) {
			VS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid());
		}
	}

	g.dirty = false;

	return false;
}
Exemple #10
0
void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) {

	ERR_FAIL_INDEX(ABS(p_x), 1 << 20);
	ERR_FAIL_INDEX(ABS(p_y), 1 << 20);
	ERR_FAIL_INDEX(ABS(p_z), 1 << 20);

	IndexKey key;
	key.x = p_x;
	key.y = p_y;
	key.z = p_z;

	OctantKey ok;
	ok.x = p_x / octant_size;
	ok.y = p_y / octant_size;
	ok.z = p_z / octant_size;

	if (p_item < 0) {
		//erase
		if (cell_map.has(key)) {
			OctantKey octantkey = ok;

			ERR_FAIL_COND(!octant_map.has(octantkey));
			Octant &g = *octant_map[octantkey];
			g.cells.erase(key);
			g.dirty = true;
			cell_map.erase(key);
			_queue_octants_dirty();
		}
		return;
	}

	OctantKey octantkey = ok;

	if (!octant_map.has(octantkey)) {
		//create octant because it does not exist
		Octant *g = memnew(Octant);
		g->dirty = true;
		g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC);
		PhysicsServer::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id());
		SceneTree *st = SceneTree::get_singleton();

		if (st && st->is_debugging_collisions_hint()) {

			g->collision_debug = VisualServer::get_singleton()->mesh_create();
			g->collision_debug_instance = VisualServer::get_singleton()->instance_create();
			VisualServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug);
		}

		octant_map[octantkey] = g;

		if (is_inside_world()) {
			_octant_enter_world(octantkey);
			_octant_transform(octantkey);
		}
	}

	Octant &g = *octant_map[octantkey];
	g.cells.insert(key);
	g.dirty = true;
	_queue_octants_dirty();

	Cell c;
	c.item = p_item;
	c.rot = p_rot;

	cell_map[key] = c;
}
Exemple #11
0
bool Main::start() {

	ERR_FAIL_COND_V(!_start_success,false);

	bool editor=false;
	String doc_tool;
	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;
	bool project_manager_request = false;
	List<String> args = OS::get_singleton()->get_cmdline_args();
	for (int i=0;i<args.size();i++) {
		//parameters that do not have an argument to the right
		if (args[i]=="-nodocbase") {
			doc_base=false;
		} else if (args[i]=="-noquit") {
			noquit=true;
		} else if (args[i]=="-convert_old") {
			convert_old=true;
		} else if (args[i]=="-editor" || args[i]=="-e") {
			editor=true;
		} else if (args[i] == "-pm" || args[i] == "-project_manager") {
			project_manager_request = true;
		} else if (args[i].length() && args[i][0] != '-' && game_path == "") {
			game_path=args[i];
		}
		//parameters that have an argument to the right
		else if (i < (args.size()-1)) {
			bool parsed_pair=true;
			if (args[i]=="-doctool") {
				doc_tool=args[i+1];
			} else if (args[i]=="-script" || args[i]=="-s") {
				script=args[i+1];
			} else if (args[i]=="-level" || args[i]=="-l") {
				OS::get_singleton()->_custom_level=args[i+1];
			} else if (args[i]=="-test") {
				test=args[i+1];
			} else if (args[i]=="-optimize") {
				optimize=args[i+1];
			} else if (args[i]=="-optimize_preset") {
				optimize_preset=args[i+1];
			} else if (args[i]=="-export") {
				editor=true; //needs editor
				_export_platform=args[i+1];
			} else if (args[i]=="-export_debug") {
				editor=true; //needs editor
				_export_platform=args[i+1];
				export_debug=true;
			} else if (args[i]=="-import") {
				editor=true; //needs editor
				_import=args[i+1];
			} else if (args[i]=="-import_script") {
				editor=true; //needs editor
				_import_script=args[i+1];
			} else if (args[i]=="-dumpstrings") {
				editor=true; //needs editor
				dumpstrings=args[i+1];
			} else {
				// The parameter does not match anything known, don't skip the next argument
				parsed_pair=false;
			}
			if (parsed_pair) {
				i++;
			}
		}
	}

	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.");

		}

		doc.save(doc_tool);

		return false;
	}

	if (optimize!="")
		editor=true; //need editor



#endif

	if (_export_platform!="") {
		if (game_path=="") {
			String err="Command line param ";
			err+=export_debug?"-export_debug":"-export";
			err+=" passed but no destination path given.\n";
			err+="Please specify the binary's file path to export to. Aborting export.";
			ERR_PRINT(err.utf8().get_data());
			return false;
		}
	}

	if(script=="" && game_path=="" && String(GLOBAL_DEF("application/main_scene",""))!="") {
		game_path=GLOBAL_DEF("application/main_scene","");
	}


	MainLoop *main_loop=NULL;
	if (editor) {
		main_loop = memnew(SceneTree);
	};

	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("SceneTreeScripted")*/) {


			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="SceneTree";

	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("SceneTree")) {

		SceneTree *sml = main_loop->cast_to<SceneTree>();

		if (debug_collisions) {
			sml->set_debug_collisions_hint(true);
		}
		if (debug_navigation) {
			sml->set_debug_navigation_hint(true);
		}
#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

			String stretch_mode = GLOBAL_DEF("display/stretch_mode","disabled");
			String stretch_aspect = GLOBAL_DEF("display/stretch_aspect","ignore");
			Size2i stretch_size = Size2(GLOBAL_DEF("display/width",0),GLOBAL_DEF("display/height",0));

			SceneTree::StretchMode sml_sm=SceneTree::STRETCH_MODE_DISABLED;
			if (stretch_mode=="2d")
				sml_sm=SceneTree::STRETCH_MODE_2D;
			else if (stretch_mode=="viewport")
				sml_sm=SceneTree::STRETCH_MODE_VIEWPORT;

			SceneTree::StretchAspect sml_aspect=SceneTree::STRETCH_ASPECT_IGNORE;
			if (stretch_aspect=="keep")
				sml_aspect=SceneTree::STRETCH_ASPECT_KEEP;
			else if (stretch_aspect=="keep_width")
				sml_aspect=SceneTree::STRETCH_ASPECT_KEEP_WIDTH;
			else if (stretch_aspect=="keep_height")
				sml_aspect=SceneTree::STRETCH_ASPECT_KEEP_HEIGHT;

			sml->set_screen_stretch(sml_sm,sml_aspect,stretch_size);

			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_mode","disabled");
			Globals::get_singleton()->set_custom_property_info("display/stretch_mode",PropertyInfo(Variant::STRING,"display/stretch_mode",PROPERTY_HINT_ENUM,"disabled,2d,viewport"));
			GLOBAL_DEF("display/stretch_aspect","ignore");
			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"));
			sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));


		}


		if (game_path!="" && !project_manager_request) {

			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) {

					if (Globals::get_singleton()->is_using_datapack()) {

						local_game_path="res://"+local_game_path;

					} else {
						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) {


				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();
						}
					}
				}
				OS::get_singleton()->set_context(OS::CONTEXT_EDITOR);

				//editor_node->set_edited_scene(game);
			} else {
#endif

				{
					//autoload
					List<PropertyInfo> props;
					Globals::get_singleton()->get_property_list(&props);

					//first pass, add the constants so they exist before any script is loaded
					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_slicec('/',1);
						String path = Globals::get_singleton()->get(s);
						bool global_var=false;
						if (path.begins_with("*")) {
							global_var=true;
						}

						if (global_var) {
							for(int i=0;i<ScriptServer::get_language_count();i++) {
								ScriptServer::get_language(i)->add_global_constant(name,Variant());
							}
						}

					}

					//second pass, load into global constants
					List<Node*> to_add;
					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_slicec('/',1);
						String path = Globals::get_singleton()->get(s);
						bool global_var=false;
						if (path.begins_with("*")) {
							global_var=true;
							path=path.substr(1,path.length()-1);
						}

						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();
							bool valid_type = ObjectTypeDB::is_type(ibt,"Node");
							ERR_EXPLAIN("Script does not inherit a Node: "+path);
							ERR_CONTINUE( !valid_type );

							Object *obj = ObjectTypeDB::instance(ibt);

							ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: "+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);

						//defer so references are all valid on _ready()
						//sml->get_root()->add_child(n);
						to_add.push_back(n);

						if (global_var) {
							for(int i=0;i<ScriptServer::get_language_count();i++) {
								ScriptServer::get_language(i)->add_global_constant(name,n);
							}
						}

					}

					for(List<Node*>::Element *E=to_add.front();E;E=E->next()) {

						sml->get_root()->add_child(E->get());
					}



				}

				Node *scene=NULL;
				Ref<PackedScene> scenedata = ResourceLoader::load(local_game_path);
				if (scenedata.is_valid())
					scene=scenedata->instance();

				ERR_EXPLAIN("Failed loading scene: "+local_game_path);
				ERR_FAIL_COND_V(!scene,false)
				//sml->get_root()->add_child(scene);
				sml->add_current_scene(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 (project_manager_request || (script=="" && test=="" && game_path=="" && !editor)) {

			ProjectManager *pmanager = memnew( ProjectManager );
			sml->get_root()->add_child(pmanager);
			OS::get_singleton()->set_context(OS::CONTEXT_PROJECTMAN);
		}

#endif
	}

	OS::get_singleton()->set_main_loop( main_loop );

	return true;
}