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; }
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>()); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }