Vector<Vector3> ConcavePolygonShape::_gen_debug_mesh_lines() { Set<DrawEdge> edges; PoolVector<Vector3> data=get_faces(); int datalen=data.size(); ERR_FAIL_COND_V( (datalen%3)!=0,Vector<Vector3>() ); PoolVector<Vector3>::Read r=data.read(); for(int i=0;i<datalen;i+=3) { for(int j=0;j<3;j++) { DrawEdge de(r[i+j],r[i+((j+1)%3)]); edges.insert(de); } } Vector<Vector3> points; points.resize(edges.size()*2); int idx=0; for (Set<DrawEdge>::Element*E=edges.front();E;E=E->next()) { points[idx+0]=E->get().a; points[idx+1]=E->get().b; idx+=2; } return points; }
void VisualScriptPropertySelector::get_visual_node_names(const String &root_filter, const Set<String> &filter, bool &found, TreeItem *const root, LineEdit *const search_box) { Map<String, TreeItem *> path_cache; List<String> fnodes; VisualScriptLanguage::singleton->get_registered_node_names(&fnodes); for (List<String>::Element *E = fnodes.front(); E; E = E->next()) { if (!E->get().begins_with(root_filter)) { continue; } Vector<String> path = E->get().split("/"); bool is_filter = false; for (Set<String>::Element *F = filter.front(); F; F = F->next()) { if (path.size() >= 2 && path[1].findn(F->get()) != -1) { is_filter = true; break; } } if (is_filter) { continue; } if (search_box->get_text() != String() && E->get().findn(search_box->get_text()) == -1) { continue; } TreeItem *item = search_options->create_item(root); VisualScriptOperator *vnode_operator = Object::cast_to<VisualScriptOperator>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); String type_name; if (vnode_operator != NULL) { String type; if (path.size() >= 2) { type = path[1]; } type_name = type.capitalize() + " "; } VisualScriptFunctionCall *vnode_function_call = Object::cast_to<VisualScriptFunctionCall>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); if (vnode_function_call != NULL) { String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type()); type_name = basic_type.capitalize() + " "; } Vector<String> desc = path[path.size() - 1].replace("(", "( ").replace(")", " )").replace(",", ", ").split(" "); for (int i = 0; i < desc.size(); i++) { desc.write[i] = desc[i].capitalize(); if (desc[i].ends_with(",")) { desc.write[i] = desc[i].replace(",", ", "); } } item->set_text(0, type_name + String("").join(desc)); item->set_icon(0, get_icon("VisualScript", "EditorIcons")); item->set_selectable(0, true); item->set_metadata(0, E->get()); item->set_selectable(0, true); item->set_metadata(1, "visualscript"); item->set_selectable(1, false); item->set_selectable(2, false); item->set_metadata(2, connecting); } }
static Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) { Set<String> file_paths; // check children for (int i = 0; i < p_dir->get_file_count(); i++) { String file_name = p_dir->get_file(i); String file_type = p_dir->get_file_type(i); if (file_type != "GDNativeLibrary") { continue; } Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i)); if (lib.is_valid() && lib->is_singleton()) { file_paths.insert(p_dir->get_file_path(i)); } } // check subdirectories for (int i = 0; i < p_dir->get_subdir_count(); i++) { Set<String> paths = get_gdnative_singletons(p_dir->get_subdir(i)); for (Set<String>::Element *E = paths.front(); E; E = E->next()) { file_paths.insert(E->get()); } } return file_paths; }
void RotatedFileLogger::clear_old_backups() { int max_backups = max_files - 1; // -1 for the current file String basename = base_path.get_file().get_basename(); String extension = "." + base_path.get_extension(); DirAccess *da = DirAccess::open(base_path.get_base_dir()); if (!da) { return; } da->list_dir_begin(); String f = da->get_next(); Set<String> backups; while (f != String()) { if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path.get_file()) { backups.insert(f); } f = da->get_next(); } da->list_dir_end(); if (backups.size() > max_backups) { // since backups are appended with timestamp and Set iterates them in sorted order, // first backups are the oldest int to_delete = backups.size() - max_backups; for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) { da->remove(E->get()); } } memdelete(da); }
void ProjectExportDialog::_update_feature_list() { Ref<EditorExportPreset> current = EditorExport::get_singleton()->get_export_preset(presets->get_current()); ERR_FAIL_COND(current.is_null()); Set<String> fset; List<String> features; current->get_platform()->get_platform_features(&features); current->get_platform()->get_preset_features(current, &features); String custom = current->get_custom_features(); Vector<String> custom_list = custom.split(","); for (int i = 0; i < custom_list.size(); i++) { String f = custom_list[i].strip_edges(); if (f != String()) { features.push_back(f); } } for (List<String>::Element *E = features.front(); E; E = E->next()) { fset.insert(E->get()); } custom_feature_display->clear(); for (Set<String>::Element *E = fset.front(); E; E = E->next()) { String f = E->get(); if (E->next()) { f += ", "; } custom_feature_display->add_text(f); } }
void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) { if (!efsd) return; for(int i=0;i<efsd->get_subdir_count();i++) { _fill_owners(efsd->get_subdir(i)); } for(int i=0;i<efsd->get_file_count();i++) { Vector<String> deps = efsd->get_file_deps(i); //print_line(":::"+efsd->get_file_path(i)); Set<String> met; for(int j=0;j<deps.size();j++) { if (files.has(deps[j])) { met.insert(deps[j]); } } if (!met.size()) continue; exist=true; Ref<Texture> icon; String type=efsd->get_file_type(i); if (!has_icon(type,TTR("EditorIcons"))) { icon=get_icon("Object","EditorIcons"); } else { icon=get_icon(type,"EditorIcons"); } for(Set<String>::Element *E=met.front();E;E=E->next()) { String which = E->get(); if (!files[which]) { TreeItem *ti=owners->create_item(owners->get_root()); ti->set_text(0,which.get_file()); files[which]=ti; } TreeItem *ti=owners->create_item(files[which]); ti->set_text(0,efsd->get_file_path(i)); ti->set_icon(0,icon); } } }
void Theme::get_type_list(List<StringName> *p_list) const { Set<StringName> types; const StringName *key=NULL; while((key=icon_map.next(key))) { types.insert(*key); } key=NULL; while((key=style_map.next(key))) { types.insert(*key); } key=NULL; while((key=font_map.next(key))) { types.insert(*key); } key=NULL; while((key=color_map.next(key))) { types.insert(*key); } key=NULL; while((key=constant_map.next(key))) { types.insert(*key); } for(Set<StringName>::Element *E=types.front(); E; E=E->next()) { p_list->push_back(E->get()); } }
void NativeScript::get_script_method_list(List<MethodInfo> *p_list) const { NativeScriptDesc *script_data = get_script_desc(); if (!script_data) return; Set<MethodInfo> methods; while (script_data) { for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) { methods.insert(E->get().info); } script_data = script_data->base_data; } for (Set<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { p_list->push_back(E->get()); } }
void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_for_script) { if (!bool(EditorSettings::get_singleton()->get("external_editor/use_external_editor"))) return; Set<Ref<Script> > scripts; Node *base = get_tree()->get_edited_scene_root(); if (base) { _find_changed_scripts_for_external_editor(base,base,scripts); } for (Set<Ref<Script> >::Element *E=scripts.front();E;E=E->next()) { Ref<Script> script = E->get(); if (p_for_script.is_valid() && p_for_script!=script) continue; if (script->get_path()=="" || script->get_path().find("local://")!=-1 || script->get_path().find("::")!=-1) { continue; //internal script, who cares, though weird } uint64_t last_date = script->get_last_modified_time(); uint64_t date = FileAccess::get_modified_time(script->get_path()); if (last_date!=date) { Ref<Script> rel_script = ResourceLoader::load(script->get_path(),script->get_type(),true); ERR_CONTINUE(!rel_script.is_valid()); script->set_source_code( rel_script->get_source_code() ); script->set_last_modified_time( rel_script->get_last_modified_time() ); script->update_exports(); } } }
void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags) { // TODO right now there is no way to stop the export process with an error ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); ERR_FAIL_NULL(TOOLS_DOMAIN); ERR_FAIL_NULL(GDMono::get_singleton()->get_editor_tools_assembly()); if (FileAccess::exists(GodotSharpDirs::get_project_sln_path())) { String build_config = p_debug ? "Debug" : "Release"; String scripts_metadata_path = GodotSharpDirs::get_res_metadata_dir().plus_file("scripts_metadata." + String(p_debug ? "debug" : "release")); Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path); ERR_FAIL_COND(metadata_err != OK); ERR_FAIL_COND(!_add_file(scripts_metadata_path, scripts_metadata_path)); // Turn export features into defines Vector<String> godot_defines; for (Set<String>::Element *E = p_features.front(); E; E = E->next()) { godot_defines.push_back(E->get()); } ERR_FAIL_COND(!GodotSharpBuilds::build_project_blocking(build_config, godot_defines)); // Add dependency assemblies Map<String, String> dependencies; String project_dll_name = ProjectSettings::get_singleton()->get("application/config/name"); if (project_dll_name.empty()) { project_dll_name = "UnnamedProject"; } String project_dll_src_dir = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config); String project_dll_src_path = project_dll_src_dir.plus_file(project_dll_name + ".dll"); dependencies.insert(project_dll_name, project_dll_src_path); { MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain"); ERR_FAIL_NULL(export_domain); _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain); _GDMONO_SCOPE_DOMAIN_(export_domain); GDMonoAssembly *scripts_assembly = NULL; bool load_success = GDMono::get_singleton()->load_assembly_from(project_dll_name, project_dll_src_path, &scripts_assembly, /* refonly: */ true); ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name); ERR_FAIL_COND(!load_success); Vector<String> search_dirs; GDMonoAssembly::fill_search_dirs(search_dirs, build_config); Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies); ERR_FAIL_COND(depend_error != OK); } for (Map<String, String>::Element *E = dependencies.front(); E; E = E->next()) { String depend_src_path = E->value(); String depend_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(depend_src_path.get_file()); ERR_FAIL_COND(!_add_file(depend_src_path, depend_dst_path)); } } // Mono specific export template extras (data dir) GDMonoClass *export_class = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Editor", "GodotSharpExport"); ERR_FAIL_NULL(export_class); GDMonoMethod *export_begin_method = export_class->get_method("_ExportBegin", 4); ERR_FAIL_NULL(export_begin_method); MonoArray *features = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), p_features.size()); int i = 0; for (const Set<String>::Element *E = p_features.front(); E; E = E->next()) { MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get()); mono_array_set(features, MonoString *, i, boxed); i++; } MonoBoolean debug = p_debug; MonoString *path = GDMonoMarshal::mono_string_from_godot(p_path); uint32_t flags = p_flags; void *args[4] = { features, &debug, path, &flags }; MonoException *exc = NULL; export_begin_method->invoke_raw(NULL, args, &exc); if (exc) { GDMonoUtils::debug_print_unhandled_exception(exc); ERR_FAIL(); } }
MainLoop * test() { /* HashMap<int,int> int_map; for (int i=0;i<68000;i++) { int num=(int)Math::random(0,1024); int_map[i]=num; } */ { // static const int size = 16; Image img; img.create(default_mouse_cursor_xpm); { for (int i=0; i<8; i++) { Image mipmap; //img.make_mipmap(mipmap); img = mipmap; if (img.get_width() <= 4) break; }; }; }; #if 0 Set<int> set; print_line("Begin Insert"); for (int i=0;i<1100;i++) { int num=i;//(int)Math::random(0,1024); // print_line("inserting "+itos(num)); set.insert( num ); } /* for (int i=0;i<400;i++) { int num=(int)Math::random(0,1024); set.erase(num); } */ //set.print_tree(); for(Set<int>::Element *I=set.front();I;I=I->next()) { print_line("inserted "+itos(I->get())+" prev is "+itos(I->prev()?I->prev()->get():-100)); } print_line("depth is "+itos(set.calculate_depth())); print_line("Insert Success"); #endif return NULL; }
Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const { Set<StringName> exported; if (FileAccess::exists("res://engine.cfg")) exported.insert("res://engine.cfg"); if (EditorImportExport::get_singleton()->get_export_filter()!=EditorImportExport::EXPORT_SELECTED) { String filter; if (EditorImportExport::get_singleton()->get_export_filter()==EditorImportExport::EXPORT_ALL) { _add_filter_to_list(exported,"*"); } else { _add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported); _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); } } else { Map<String,Map<String,String> > remapped_paths; Set<String> scene_extensions; Set<String> resource_extensions; { List<String> l; // SceneLoader::get_recognized_extensions(&l); // for(List<String>::Element *E=l.front();E;E=E->next()) { // // scene_extensions.insert(E->get()); // } ResourceLoader::get_recognized_extensions_for_type("",&l); for(List<String>::Element *E=l.front();E;E=E->next()) { resource_extensions.insert(E->get()); } } List<StringName> toexport; EditorImportExport::get_singleton()->get_export_file_list(&toexport); print_line("TO EXPORT: "+itos(toexport.size())); for (List<StringName>::Element *E=toexport.front();E;E=E->next()) { print_line("DEP: "+String(E->get())); exported.insert(E->get()); if (p_bundles && EditorImportExport::get_singleton()->get_export_file_action(E->get())==EditorImportExport::ACTION_BUNDLE) { print_line("NO BECAUSE OF BUNDLE!"); continue; //no dependencies needed to be copied } List<String> testsubs; testsubs.push_back(E->get()); while(testsubs.size()) { //recursive subdep search! List<String> deplist; ResourceLoader::get_dependencies(testsubs.front()->get(),&deplist); testsubs.pop_front(); List<String> subdeps; for (List<String>::Element *F=deplist.front();F;F=F->next()) { StringName dep = F->get(); if (exported.has(dep) || EditorImportExport::get_singleton()->get_export_file_action(dep)!=EditorImportExport::ACTION_NONE) continue; //dependency added or to be added print_line(" SUBDEP: "+String(dep)); exported.insert(dep); testsubs.push_back(dep); } } } _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); } Vector<StringName> ret; ret.resize(exported.size()); int idx=0; for(Set<StringName>::Element *E=exported.front();E;E=E->next()) { ret[idx++]=E->get(); } SortArray<StringName,__EESortDepCmp> sort; //some platforms work better if this is sorted sort.sort(ret.ptr(),ret.size()); return ret; }
void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); if (!obj) return; typedef Pair<PropertyInfo, Variant> PropertyDesc; List<PropertyDesc> properties; if (ScriptInstance *si = obj->get_script_instance()) { if (!si->get_script().is_null()) { Set<StringName> members; si->get_script()->get_members(&members); for (Set<StringName>::Element *E = members.front(); E; E = E->next()) { Variant m; if (si->get(E->get(), m)) { PropertyInfo pi(m.get_type(), String("Members/") + E->get()); properties.push_back(PropertyDesc(pi, m)); } } Map<StringName, Variant> constants; si->get_script()->get_constants(&constants); for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { PropertyInfo pi(E->value().get_type(), (String("Constants/") + E->key())); properties.push_back(PropertyDesc(pi, E->value())); } } } if (Node *node = Object::cast_to<Node>(obj)) { PropertyInfo pi(Variant::NODE_PATH, String("Node/path")); properties.push_front(PropertyDesc(pi, node->get_path())); } else if (Resource *res = Object::cast_to<Resource>(obj)) { if (Script *s = Object::cast_to<Script>(res)) { Map<StringName, Variant> constants; s->get_constants(&constants); for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) { PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key()); properties.push_front(PropertyDesc(pi, E->value())); } } } List<PropertyInfo> pinfo; obj->get_property_list(&pinfo, true); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) { properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name))); } } Array send_props; for (int i = 0; i < properties.size(); i++) { const PropertyInfo &pi = properties[i].first; Variant &var = properties[i].second; WeakRef *ref = Object::cast_to<WeakRef>(var); if (ref) { var = ref->get_ref(); } RES res = var; Array prop; prop.push_back(pi.name); prop.push_back(pi.type); //only send information that can be sent.. int len = 0; //test how big is this to encode encode_variant(var, NULL, len); if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG); prop.push_back(""); prop.push_back(pi.usage); prop.push_back(Variant()); } else { prop.push_back(pi.hint); if (res.is_null()) prop.push_back(pi.hint_string); else prop.push_back(String("RES:") + res->get_path()); prop.push_back(pi.usage); prop.push_back(var); } send_props.push_back(prop); } packet_peer_stream->put_var("message:inspect_object"); packet_peer_stream->put_var(3); packet_peer_stream->put_var(p_id); packet_peer_stream->put_var(obj->get_class()); packet_peer_stream->put_var(send_props); }
void EditorPropertyRootMotion::_node_assign() { NodePath current = get_edited_object()->get(get_edited_property()); AnimationTree *atree = Object::cast_to<AnimationTree>(get_edited_object()); if (!atree->has_node(atree->get_animation_player())) { EditorNode::get_singleton()->show_warning(TTR("AnimationTree has no path set to an AnimationPlayer")); return; } AnimationPlayer *player = Object::cast_to<AnimationPlayer>(atree->get_node(atree->get_animation_player())); if (!player) { EditorNode::get_singleton()->show_warning(TTR("Path to AnimationPlayer is invalid")); return; } Node *base = player->get_node(player->get_root()); if (!base) { EditorNode::get_singleton()->show_warning(TTR("Animation player has no valid root node path, so unable to retrieve track names.")); return; } Set<String> paths; { List<StringName> animations; player->get_animation_list(&animations); for (List<StringName>::Element *E = animations.front(); E; E = E->next()) { Ref<Animation> anim = player->get_animation(E->get()); for (int i = 0; i < anim->get_track_count(); i++) { paths.insert(anim->track_get_path(i)); } } } filters->clear(); TreeItem *root = filters->create_item(); Map<String, TreeItem *> parenthood; for (Set<String>::Element *E = paths.front(); E; E = E->next()) { NodePath path = E->get(); TreeItem *ti = NULL; String accum; for (int i = 0; i < path.get_name_count(); i++) { String name = path.get_name(i); if (accum != String()) { accum += "/"; } accum += name; if (!parenthood.has(accum)) { if (ti) { ti = filters->create_item(ti); } else { ti = filters->create_item(root); } parenthood[accum] = ti; ti->set_text(0, name); ti->set_selectable(0, false); ti->set_editable(0, false); if (base->has_node(accum)) { Node *node = base->get_node(accum); if (has_icon(node->get_class(), "EditorIcons")) { ti->set_icon(0, get_icon(node->get_class(), "EditorIcons")); } else { ti->set_icon(0, get_icon("Node", "EditorIcons")); } } } else { ti = parenthood[accum]; } } Node *node = NULL; if (base->has_node(accum)) { node = base->get_node(accum); } if (!node) continue; //no node, cant edit if (path.get_subname_count()) { String concat = path.get_concatenated_subnames(); Skeleton *skeleton = Object::cast_to<Skeleton>(node); if (skeleton && skeleton->find_bone(concat) != -1) { //path in skeleton String bone = concat; int idx = skeleton->find_bone(bone); List<String> bone_path; while (idx != -1) { bone_path.push_front(skeleton->get_bone_name(idx)); idx = skeleton->get_bone_parent(idx); } accum += ":"; for (List<String>::Element *F = bone_path.front(); F; F = F->next()) { if (F != bone_path.front()) { accum += "/"; } accum += F->get(); if (!parenthood.has(accum)) { ti = filters->create_item(ti); parenthood[accum] = ti; ti->set_text(0, F->get()); ti->set_selectable(0, true); ti->set_editable(0, false); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, accum); } else { ti = parenthood[accum]; } } ti->set_selectable(0, true); ti->set_text(0, concat); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, path); if (path == current) { ti->select(0); } } else { //just a property ti = filters->create_item(ti); ti->set_text(0, concat); ti->set_selectable(0, true); ti->set_metadata(0, path); if (path == current) { ti->select(0); } } } else { if (ti) { //just a node, likely call or animation track ti->set_selectable(0, true); ti->set_metadata(0, path); if (path == current) { ti->select(0); } } } } filters->ensure_cursor_is_visible(); filter_dialog->popup_centered_ratio(); }
void AnimationTreeEditor::_edit_filters() { filter_dialog->popup_centered_ratio(); filter->clear(); Set<String> npb; _find_paths_for_filter(edited_node,npb); TreeItem *root = filter->create_item(); filter->set_hide_root(true); Map<String,TreeItem*> pm; Node *base = anim_tree->get_node( anim_tree->get_base_path() ); for(Set<String>::Element *E=npb.front();E;E=E->next()) { TreeItem *parent=root; String descr=E->get(); if (base) { NodePath np = E->get(); if (np.get_property()!=StringName()) { Node *n = base->get_node(np); Skeleton *s = n->cast_to<Skeleton>(); if (s) { String skelbase = E->get().substr(0,E->get().find(":")); int bidx = s->find_bone(np.get_property()); if (bidx!=-1) { int bparent = s->get_bone_parent(bidx); // if (bparent!=-1) { String bpn = skelbase+":"+s->get_bone_name(bparent); if (pm.has(bpn)) { parent=pm[bpn]; descr=np.get_property(); } } else { if (pm.has(skelbase)) { parent=pm[skelbase]; } } } } } } TreeItem *it = filter->create_item(parent); it->set_cell_mode(0,TreeItem::CELL_MODE_CHECK); it->set_text(0,descr); it->set_metadata(0,NodePath(E->get())); it->set_editable(0,true); if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ONESHOT) { it->set_checked(0, anim_tree->oneshot_node_is_path_filtered(edited_node,E->get())); } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) { it->set_checked(0, anim_tree->blend2_node_is_path_filtered(edited_node,E->get())); } pm[E->get()]=it; } }
void FileSystemDock::_files_list_rmb_select(int p_item,const Vector2& p_pos) { Vector<String> filenames; bool all_scenes=true; bool all_can_reimport=true; Set<String> types; for(int i=0;i<files->get_item_count();i++) { if (!files->is_selected(i)) continue; String path = files->get_item_metadata(i); if (files->get_item_text(i)=="..") { // no operate on .. return; } if (path.ends_with("/")) { //no operate on dirs return; } EditorFileSystemDirectory *efsd=NULL; int pos; efsd = EditorFileSystem::get_singleton()->find_file(path,&pos); if (efsd) { if (!efsd->get_file_meta(pos)) { all_can_reimport=false; } else { Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(path); if (rimd.is_valid()) { String editor=rimd->get_editor(); if (editor.begins_with("texture_")) { //compatibility fix for old texture format editor="texture"; } types.insert(editor); } else { all_can_reimport=false; } } } else { all_can_reimport=false; } filenames.push_back(path); if (EditorFileSystem::get_singleton()->get_file_type(path)!="PackedScene") all_scenes=false; } if (filenames.size()==0) return; file_options->clear(); file_options->set_size(Size2(1,1)); file_options->add_item(TTR("Open"),FILE_OPEN); if (all_scenes) { file_options->add_item(TTR("Instance"),FILE_INSTANCE); } file_options->add_separator(); if (filenames.size()==1) { file_options->add_item(TTR("Edit Dependencies.."),FILE_DEPENDENCIES); file_options->add_item(TTR("View Owners.."),FILE_OWNERS); file_options->add_separator(); } if (filenames.size()==1) { file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH); file_options->add_item(TTR("Rename or Move.."),FILE_MOVE); } else { file_options->add_item(TTR("Move To.."),FILE_MOVE); } file_options->add_item(TTR("Delete"),FILE_REMOVE); //file_options->add_item(TTR("Info"),FILE_INFO); file_options->add_separator(); file_options->add_item(TTR("Show In File Manager"),FILE_SHOW_IN_EXPLORER); if (all_can_reimport && types.size()==1) { //all can reimport and are of the same type bool valid=true; Ref<EditorImportPlugin> rimp = EditorImportExport::get_singleton()->get_import_plugin_by_name(types.front()->get()); if (rimp.is_valid()) { if (filenames.size()>1 && !rimp->can_reimport_multiple_files()) { valid=false; } } else { valid=false; } if (valid) { file_options->add_separator(); file_options->add_item(TTR("Re-Import.."),FILE_REIMPORT); } } file_options->set_pos(files->get_global_pos() + p_pos); file_options->popup(); }
Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Set<Ref<ImageTexture> >& image_map) { // children first.. for(int i=0;i<p_node->get_child_count();i++) { Node *r = _fix_node(p_node->get_child(i),p_root,collision_map,p_flags,image_map); if (!r) { print_line("was erased.."); i--; //was erased } } String name = p_node->get_name(); bool isroot = p_node==p_root; if (!isroot && p_flags&SCENE_FLAG_REMOVE_NOIMP && _teststr(name,"noimp")) { memdelete(p_node); return NULL; } { List<PropertyInfo> pl; p_node->get_property_list(&pl); for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) { _find_resources(p_node->get(E->get().name),image_map); } } } if (p_flags&SCENE_FLAG_CREATE_BILLBOARDS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); bool bb=false; if ((_teststr(name,"bb"))) { bb=true; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) { bb=true; } if (bb) { mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true); if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } } } } if (p_flags&SCENE_FLAG_REMOVE_NOIMP && p_node->cast_to<AnimationPlayer>()) { //remove animations referencing non-importable nodes AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>(); List<StringName> anims; ap->get_animation_list(&anims); for(List<StringName>::Element *E=anims.front();E;E=E->next()) { Ref<Animation> anim=ap->get_animation(E->get()); ERR_CONTINUE(anim.is_null()); for(int i=0;i<anim->get_track_count();i++) { NodePath path = anim->track_get_path(i); for(int j=0;j<path.get_name_count();j++) { String node = path.get_name(j); if (_teststr(node,"noimp")) { anim->remove_track(i); i--; break; } } } } } if (p_flags&SCENE_FLAG_CREATE_IMPOSTORS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); String str; if ((_teststr(name,"imp"))) { str=name; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) { str=mi->get_mesh()->get_name(); } if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>(); String d=str.substr(str.find("imp")+3,str.length()); if (d!="") { if ((d[0]<'0' || d[0]>'9')) d=d.substr(1,d.length()); if (d.length() && d[0]>='0' && d[0]<='9') { float dist = d.to_double(); mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true); mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true); mi->set_draw_range_begin(dist); mi->set_draw_range_end(100000); mip->set_draw_range_begin(0); mip->set_draw_range_end(dist); if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } } } } } } if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); String str; if ((_teststr(name,"lod"))) { str=name; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) { str=mi->get_mesh()->get_name(); } if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>(); String d=str.substr(str.find("lod")+3,str.length()); if (d!="") { if ((d[0]<'0' || d[0]>'9')) d=d.substr(1,d.length()); if (d.length() && d[0]>='0' && d[0]<='9') { float dist = d.to_double(); mi->set_draw_range_begin(dist); mi->set_draw_range_end(100000); mip->set_draw_range_begin(0); mip->set_draw_range_end(dist); /*if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } }*/ } } } } if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); Node * col = mi->create_trimesh_collision_node(); ERR_FAIL_COND_V(!col,NULL); col->set_name(_fixstr(name,"colonly")); col->cast_to<Spatial>()->set_transform(mi->get_transform()); p_node->replace_by(col); memdelete(p_node); p_node=col; } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); mi->set_name(_fixstr(name,"col")); mi->create_trimesh_collision(); } else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID); BSP_Tree bsptree(faces); Ref<RoomBounds> area = memnew( RoomBounds ); area->set_bounds(faces); area->set_geometry_hint(faces); Room * room = memnew( Room ); room->set_name(_fixstr(name,"room")); room->set_transform(mi->get_transform()); room->set_room(area); p_node->replace_by(room); memdelete(p_node); p_node=room; } else if (p_flags&SCENE_FLAG_CREATE_ROOMS &&_teststr(name,"room")) { if (isroot) return p_node; Spatial *dummy = p_node->cast_to<Spatial>(); ERR_FAIL_COND_V(!dummy,NULL); Room * room = memnew( Room ); room->set_name(_fixstr(name,"room")); room->set_transform(dummy->get_transform()); p_node->replace_by(room); memdelete(p_node); p_node=room; room->compute_room_from_subtree(); } else if (p_flags&SCENE_FLAG_CREATE_PORTALS &&_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID); ERR_FAIL_COND_V(faces.size()==0,NULL); //step 1 compute the plane Set<Vector3> points; Plane plane; Vector3 center; for(int i=0;i<faces.size();i++) { Face3 f = faces.get(i); Plane p = f.get_plane(); plane.normal+=p.normal; plane.d+=p.d; for(int i=0;i<3;i++) { Vector3 v = f.vertex[i].snapped(0.01); if (!points.has(v)) { points.insert(v); center+=v; } } } plane.normal.normalize(); plane.d/=faces.size(); center/=points.size(); //step 2, create points Transform t; t.basis.from_z(plane.normal); t.basis.transpose(); t.origin=center; Vector<Point2> portal_points; for(Set<Vector3>::Element *E=points.front();E;E=E->next()) { Vector3 local = t.xform_inv(E->get()); portal_points.push_back(Point2(local.x,local.y)); } // step 3 bubbly sort points int swaps=0; do { swaps=0; for(int i=0;i<portal_points.size()-1;i++) { float a = portal_points[i].atan2(); float b = portal_points[i+1].atan2(); if (a>b) { SWAP( portal_points[i], portal_points[i+1] ); swaps++; } } } while(swaps); Portal *portal = memnew( Portal ); portal->set_shape(portal_points); portal->set_transform( mi->get_transform() * t); p_node->replace_by(portal); memdelete(p_node); p_node=portal; } else if (p_node->cast_to<MeshInstance>()) { //last attempt, maybe collision insde the mesh data MeshInstance *mi = p_node->cast_to<MeshInstance>(); Ref<Mesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(mesh->get_name(),"col")) { mesh->set_name( _fixstr(mesh->get_name(),"col") ); Ref<Shape> shape; if (collision_map.has(mesh)) { shape = collision_map[mesh]; } else { shape = mesh->create_trimesh_shape(); if (!shape.is_null()) collision_map[mesh]=shape; } if (!shape.is_null()) { #if 0 StaticBody* static_body = memnew( StaticBody ); ERR_FAIL_COND_V(!static_body,NULL); static_body->set_name( String(mesh->get_name()) + "_col" ); shape->set_name(static_body->get_name()); static_body->add_shape(shape); mi->add_child(static_body); if (mi->get_owner()) static_body->set_owner( mi->get_owner() ); #endif } } for(int i=0;i<mesh->get_surface_count();i++) { Ref<FixedMaterial> fm = mesh->surface_get_material(i); if (fm.is_valid()) { String name = fm->get_name(); if (_teststr(name,"alpha")) { fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); name=_fixstr(name,"alpha"); } if (_teststr(name,"vcol")) { fm->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); name=_fixstr(name,"vcol"); } fm->set_name(name); } } } } return p_node; }
Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) { Error err=OK; Ref<ResourceImportMetadata> from=p_from; String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0)); int animation_flags=p_from->get_option("animation_flags"); int scene_flags = from->get_option("flags"); EditorProgress progress("import","Import Scene",104); progress.step("Importing Scene..",2); bool merge = !bool(from->get_option("reimport")); from->set_source_md5(0,FileAccess::get_md5(src_path)); from->set_editor(get_name()); from->set_option("reimport",false); String target_res_path=p_dest_path.get_base_dir(); Map<Ref<Mesh>,Ref<Shape> > collision_map; Ref<ResourceImportMetadata> imd = memnew(ResourceImportMetadata); Set< Ref<ImageTexture> > imagemap; scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap); /// BEFORE ANYTHING, RUN SCRIPT progress.step("Running Custom Script..",2); String post_import_script_path = from->get_option("post_import_script"); Ref<EditorScenePostImport> post_import_script; if (post_import_script_path!="") { post_import_script_path = EditorImportPlugin::expand_source_path(post_import_script_path); Ref<Script> scr = ResourceLoader::load(post_import_script_path); if (!scr.is_valid()) { EditorNode::add_io_error("Couldn't load post-import script: '"+post_import_script_path); } else { post_import_script = Ref<EditorScenePostImport>( memnew( EditorScenePostImport ) ); post_import_script->set_script(scr.get_ref_ptr()); if (!post_import_script->get_script_instance()) { EditorNode::add_io_error("Invalid/Broken Script for Post-Import: '"+post_import_script_path); post_import_script.unref(); } } } if (post_import_script.is_valid()) { err = post_import_script->post_import(scene); if (err) { EditorNode::add_io_error("Error running Post-Import script: '"+post_import_script_path); return err; } } /// IMPORT IMAGES int idx=0; int image_format = from->get_option("texture_format"); int image_flags = from->get_option("texture_flags"); float image_quality = from->get_option("texture_quality"); for (Set< Ref<ImageTexture> >::Element *E=imagemap.front();E;E=E->next()) { //texture could be converted to something more useful for 3D, that could load individual mipmaps and stuff //but not yet.. Ref<ImageTexture> texture = E->get(); ERR_CONTINUE(!texture.is_valid()); String path = texture->get_path(); String fname= path.get_file(); String target_path = Globals::get_singleton()->localize_path(target_res_path.plus_file(fname)); progress.step("Import Img: "+fname,3+(idx)*100/imagemap.size()); idx++; if (path==target_path) { EditorNode::add_io_error("Can't import a file over itself: '"+target_path); continue; } if (!target_path.begins_with("res://")) { EditorNode::add_io_error("Couldn't localize path: '"+target_path+"' (already local)"); continue; } { target_path=target_path.basename()+".tex"; Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata ); print_line("flags: "+itos(image_flags)); imd->set_option("flags",image_flags); imd->set_option("format",image_format); imd->set_option("quality",image_quality); imd->set_option("atlas",false); imd->add_source(EditorImportPlugin::validate_source_path(path)); if (FileAccess::exists(target_path)) { Ref<ResourceImportMetadata> rimdex = ResourceLoader::load_import_metadata(target_path); if (rimdex.is_valid()) { //make sure the options are the same, otherwise re-import List<String> opts; imd->get_options(&opts); bool differ=false; for (List<String>::Element *E=opts.front();E;E=E->next()) { if (!(rimdex->get_option(E->get())==imd->get_option(E->get()))) { differ=true; break; } } if (!differ) { texture->set_path(target_path); continue; //already imported } } } Error err = EditorTextureImportPlugin::get_singleton(EditorTextureImportPlugin::MODE_TEXTURE_3D)->import(target_path,imd); } } /// BEFORE SAVING - MERGE if (merge) { progress.step("Merging..",103); FileAccess *fa = FileAccess::create(FileAccess::ACCESS_FILESYSTEM); if (fa->file_exists(p_dest_path)) { //try to merge Ref<PackedScene> s = ResourceLoader::load(p_dest_path); if (s.is_valid()) { Node *existing = s->instance(true); if (existing) { _merge_scenes(scene,existing); memdelete(scene); scene=existing; } } } memdelete(fa); } progress.step("Saving..",104); Ref<PackedScene> packer = memnew( PackedScene ); packer->pack(scene); packer->set_path(p_dest_path); packer->set_import_metadata(from); print_line("SAVING TO: "+p_dest_path); err = ResourceSaver::save(p_dest_path,packer); //EditorFileSystem::get_singleton()->update_resource(packer); memdelete(scene); /* scene->set_filename(p_dest_path); if (r_scene) { *r_scene=scene; } else { memdelete(scene); } String sp; if (p_post_import.is_valid() && !p_post_import->get_script().is_null()) { Ref<Script> scr = p_post_import->get_script(); if (scr.is_valid()) sp=scr->get_path(); } String op=_getrelpath(p_path,p_dest_path); */ return err; }
bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &anode) { if (updating || _filter_edit != anode) return false; NodePath player_path = anode->get_tree()->get_animation_player(); if (!anode->get_tree()->has_node(player_path)) { EditorNode::get_singleton()->show_warning(TTR("No animation player set, so unable to retrieve track names.")); return false; } AnimationPlayer *player = Object::cast_to<AnimationPlayer>(anode->get_tree()->get_node(player_path)); if (!player) { EditorNode::get_singleton()->show_warning(TTR("Player path set is invalid, so unable to retrieve track names.")); return false; } Node *base = player->get_node(player->get_root()); if (!base) { EditorNode::get_singleton()->show_warning(TTR("Animation player has no valid root node path, so unable to retrieve track names.")); return false; } updating = true; Set<String> paths; { List<StringName> animations; player->get_animation_list(&animations); for (List<StringName>::Element *E = animations.front(); E; E = E->next()) { Ref<Animation> anim = player->get_animation(E->get()); for (int i = 0; i < anim->get_track_count(); i++) { paths.insert(anim->track_get_path(i)); } } } filter_enabled->set_pressed(anode->is_filter_enabled()); filters->clear(); TreeItem *root = filters->create_item(); Map<String, TreeItem *> parenthood; for (Set<String>::Element *E = paths.front(); E; E = E->next()) { NodePath path = E->get(); TreeItem *ti = NULL; String accum; for (int i = 0; i < path.get_name_count(); i++) { String name = path.get_name(i); if (accum != String()) { accum += "/"; } accum += name; if (!parenthood.has(accum)) { if (ti) { ti = filters->create_item(ti); } else { ti = filters->create_item(root); } parenthood[accum] = ti; ti->set_text(0, name); ti->set_selectable(0, false); ti->set_editable(0, false); if (base->has_node(accum)) { Node *node = base->get_node(accum); if (has_icon(node->get_class(), "EditorIcons")) { ti->set_icon(0, get_icon(node->get_class(), "EditorIcons")); } else { ti->set_icon(0, get_icon("Node", "EditorIcons")); } } } else { ti = parenthood[accum]; } } Node *node = NULL; if (base->has_node(accum)) { node = base->get_node(accum); } if (!node) continue; //no node, cant edit if (path.get_subname_count()) { String concat = path.get_concatenated_subnames(); Skeleton *skeleton = Object::cast_to<Skeleton>(node); if (skeleton && skeleton->find_bone(concat) != -1) { //path in skeleton String bone = concat; int idx = skeleton->find_bone(bone); List<String> bone_path; while (idx != -1) { bone_path.push_front(skeleton->get_bone_name(idx)); idx = skeleton->get_bone_parent(idx); } accum += ":"; for (List<String>::Element *F = bone_path.front(); F; F = F->next()) { if (F != bone_path.front()) { accum += "/"; } accum += F->get(); if (!parenthood.has(accum)) { ti = filters->create_item(ti); parenthood[accum] = ti; ti->set_text(0, F->get()); ti->set_selectable(0, false); ti->set_editable(0, false); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); } else { ti = parenthood[accum]; } } ti->set_editable(0, true); ti->set_selectable(0, true); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, path); } else { //just a property ti = filters->create_item(ti); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); ti->set_editable(0, true); ti->set_selectable(0, true); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_metadata(0, path); } } else { if (ti) { //just a node, likely call or animation track ti->set_editable(0, true); ti->set_selectable(0, true); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_metadata(0, path); } } } updating = false; return true; }
Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { //figure out paths of files that will be exported Set<String> paths; Vector<String> path_remaps; if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_ALL_RESOURCES) { //find stuff _export_find_resources(EditorFileSystem::get_singleton()->get_filesystem(), paths); } else { bool scenes_only = p_preset->get_export_filter() == EditorExportPreset::EXPORT_SELECTED_SCENES; Vector<String> files = p_preset->get_files_to_export(); for (int i = 0; i < files.size(); i++) { if (scenes_only && ResourceLoader::get_resource_type(files[i]) != "PackedScene") continue; _export_find_dependencies(files[i], paths); } } _edit_filter_list(paths, p_preset->get_include_filter(), false); _edit_filter_list(paths, p_preset->get_exclude_filter(), true); Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins(); for (int i = 0; i < export_plugins.size(); i++) { export_plugins.write[i]->set_export_preset(p_preset); if (p_so_func) { for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { p_so_func(p_udata, export_plugins[i]->shared_objects[j]); } } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size()); } export_plugins.write[i]->_clear(); } FeatureContainers feature_containers = get_feature_containers(p_preset); Set<String> &features = feature_containers.features; PoolVector<String> &features_pv = feature_containers.features_pv; //store everything in the export medium int idx = 0; int total = paths.size(); for (Set<String>::Element *E = paths.front(); E; E = E->next()) { String path = E->get(); String type = ResourceLoader::get_resource_type(path); if (FileAccess::exists(path + ".import")) { //file is imported, replace by what it imports Ref<ConfigFile> config; config.instance(); Error err = config->load(path + ".import"); if (err != OK) { ERR_PRINTS("Could not parse: '" + path + "', not exported."); continue; } List<String> remaps; config->get_section_keys("remap", &remaps); Set<String> remap_features; for (List<String>::Element *F = remaps.front(); F; F = F->next()) { String remap = F->get(); String feature = remap.get_slice(".", 1); if (features.has(feature)) { remap_features.insert(feature); } } if (remap_features.size() > 1) { this->resolve_platform_feature_priorities(p_preset, remap_features); } err = OK; for (List<String>::Element *F = remaps.front(); F; F = F->next()) { String remap = F->get(); if (remap == "path") { String remapped_path = config->get_value("remap", remap); Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path); err = p_func(p_udata, remapped_path, array, idx, total); } else if (remap.begins_with("path.")) { String feature = remap.get_slice(".", 1); if (remap_features.has(feature)) { String remapped_path = config->get_value("remap", remap); Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path); err = p_func(p_udata, remapped_path, array, idx, total); } } } if (err != OK) { return err; } //also save the .import file Vector<uint8_t> array = FileAccess::get_file_as_array(path + ".import"); err = p_func(p_udata, path + ".import", array, idx, total); if (err != OK) { return err; } } else { bool do_export = true; for (int i = 0; i < export_plugins.size(); i++) { if (export_plugins[i]->get_script_instance()) { //script based export_plugins.write[i]->_export_file_script(path, type, features_pv); } else { export_plugins.write[i]->_export_file(path, type, features); } if (p_so_func) { for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { p_so_func(p_udata, export_plugins[i]->shared_objects[j]); } } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total); if (export_plugins[i]->extra_files[j].remap) { do_export = false; //if remap, do not path_remaps.push_back(path); path_remaps.push_back(export_plugins[i]->extra_files[j].path); } } if (export_plugins[i]->skipped) { do_export = false; } export_plugins.write[i]->_clear(); if (!do_export) break; //apologies, not exporting } //just store it as it comes if (do_export) { Vector<uint8_t> array = FileAccess::get_file_as_array(path); p_func(p_udata, path, array, idx, total); } } idx++; } //save config! Vector<String> custom_list; if (p_preset->get_custom_features() != String()) { Vector<String> tmp_custom_list = p_preset->get_custom_features().split(","); for (int i = 0; i < tmp_custom_list.size(); i++) { String f = tmp_custom_list[i].strip_edges(); if (f != String()) { custom_list.push_back(f); } } } ProjectSettings::CustomMap custom_map; if (path_remaps.size()) { if (1) { //new remap mode, use always as it's friendlier with multiple .pck exports for (int i = 0; i < path_remaps.size(); i += 2) { String from = path_remaps[i]; String to = path_remaps[i + 1]; String remap_file = "[remap]\n\npath=\"" + to.c_escape() + "\"\n"; CharString utf8 = remap_file.utf8(); Vector<uint8_t> new_file; new_file.resize(utf8.length()); for (int j = 0; j < utf8.length(); j++) { new_file.write[j] = utf8[j]; } p_func(p_udata, from + ".remap", new_file, idx, total); } } else { //old remap mode, will still work, but it's unused because it's not multiple pck export friendly custom_map["path_remap/remapped_paths"] = path_remaps; } } // Store icon and splash images directly, they need to bypass the import system and be loaded as images String icon = ProjectSettings::get_singleton()->get("application/config/icon"); String splash = ProjectSettings::get_singleton()->get("application/boot_splash/image"); if (icon != String() && FileAccess::exists(icon)) { Vector<uint8_t> array = FileAccess::get_file_as_array(icon); p_func(p_udata, icon, array, idx, total); } if (splash != String() && FileAccess::exists(splash) && icon != splash) { Vector<uint8_t> array = FileAccess::get_file_as_array(splash); p_func(p_udata, splash, array, idx, total); } String config_file = "project.binary"; String engine_cfb = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp" + config_file); ProjectSettings::get_singleton()->save_custom(engine_cfb, custom_map, custom_list); Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb); p_func(p_udata, "res://" + config_file, data, idx, total); return OK; }
Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base_path, Object*p_owner, List<String>* r_options, String &r_call_hint) { /* bugs: a[0].<complete> does not work functions should end in ( when completing virtuals, ask for full back */ //print_line( p_code.replace(String::chr(0xFFFF),"<cursor>")); GDParser p; Error err = p.parse(p_code,p_base_path); bool isfunction=false; Set<String> options; GDCompletionContext context; context._class=p.get_completion_class(); context.block=p.get_completion_block(); context.function=p.get_completion_function(); context.base=p_owner; context.base_path=p_base_path; switch(p.get_completion_type()) { case GDParser::COMPLETION_NONE: { print_line("No completion"); } break; case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: { print_line("Built in type constant"); List<StringName> constants; Variant::get_numeric_constants_for_type(p.get_completion_built_in_constant(),&constants); for(List<StringName>::Element *E=constants.front();E;E=E->next()) { options.insert(E->get().operator String()); } } break; case GDParser::COMPLETION_FUNCTION: isfunction=true; case GDParser::COMPLETION_IDENTIFIER: { _find_identifiers(context,p.get_completion_line(),isfunction,options); } break; case GDParser::COMPLETION_PARENT_FUNCTION: { print_line("parent function"); } break; case GDParser::COMPLETION_METHOD: isfunction=true; case GDParser::COMPLETION_INDEX: { const GDParser::Node *node = p.get_completion_node(); if (node->type!=GDParser::Node::TYPE_OPERATOR) break; GDCompletionIdentifier t; if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) { if (t.type==Variant::OBJECT && t.obj_type!=StringName()) { if (t.value.get_type()) { Object *obj=t.value; if (obj) { GDScript *scr = obj->cast_to<GDScript>(); while (scr) { if (!isfunction) { for (const Map<StringName,Variant>::Element *E=scr->get_constants().front();E;E=E->next()) { options.insert(E->key()); } } for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) { options.insert(E->key()); } if (scr->get_base().is_valid()) scr=scr->get_base().ptr(); else scr=NULL; } } } if (!isfunction) { ObjectTypeDB::get_integer_constant_list(t.obj_type,r_options); } List<MethodInfo> mi; ObjectTypeDB::get_method_list(t.obj_type,&mi); for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) { if (E->get().name.begins_with("_")) continue; if (E->get().arguments.size()) options.insert(E->get().name+"("); else options.insert(E->get().name+"()"); } } else { if (t.value.get_type()==Variant::NIL) { Variant::CallError ce; t.value=Variant::construct(t.type,NULL,0,ce); } if (!isfunction) { List<PropertyInfo> pl; t.value.get_property_list(&pl); for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { if (E->get().name.find("/")==-1) options.insert(E->get().name); } } List<MethodInfo> mi; t.value.get_method_list(&mi); for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) { if (E->get().arguments.size()) options.insert(E->get().name+"("); else options.insert(E->get().name+"()"); } } } } break; case GDParser::COMPLETION_CALL_ARGUMENTS: { _find_call_arguments(context,p.get_completion_node(),p.get_completion_line(),p.get_completion_argument_index(),options,r_call_hint); } break; } for(Set<String>::Element *E=options.front();E;E=E->next()) { r_options->push_back(E->get()); } return OK; }