void EditorFileSystem::_load_type_cache(){ GLOBAL_LOCK_FUNCTION #if 0 //this is not good, removed for now as it interferes with metadata stored in files String project=Globals::get_singleton()->get_resource_path(); FileAccess *f =FileAccess::open(project+"/types.cache",FileAccess::READ); if (!f) { WARN_PRINT("Can't open types.cache."); return; } file_type_cache.clear(); while(!f->eof_reached()) { String path=f->get_line(); if (f->eof_reached()) break; String type=f->get_line(); file_type_cache[path]=type; } memdelete(f); #endif }
void FindInFiles::_scan_file(String fpath) { FileAccess *f = FileAccess::open(fpath, FileAccess::READ); if (f == NULL) { print_verbose(String("Cannot open file ") + fpath); return; } int line_number = 0; while (!f->eof_reached()) { // line number starts at 1 ++line_number; int begin = 0; int end = 0; String line = f->get_line(); while (find_next(line, _pattern, end, _match_case, _whole_words, begin, end)) { emit_signal(SIGNAL_RESULT_FOUND, fpath, line_number, begin, end, line); } } f->close(); }
void FindInFiles::_scan_file(String fpath) { FileAccess *f = FileAccess::open(fpath, FileAccess::READ); if (f == NULL) { print_line(String("Cannot open file ") + fpath); return; } int line_number = 0; while (!f->eof_reached()) { // line number starts at 1 ++line_number; int begin = 0; int end = 0; String line = f->get_line(); // Find all occurrences in the current line while (true) { begin = _match_case ? line.find(_pattern, end) : line.findn(_pattern, end); if (begin == -1) break; end = begin + _pattern.length(); if (_whole_words) { if (begin > 0 && is_text_char(line[begin - 1])) { continue; } if (end < line.size() && is_text_char(line[end])) { continue; } } emit_signal(SIGNAL_RESULT_FOUND, fpath, line_number, begin, end, line); } } f->close(); }
Error Font::create_from_fnt(const String& p_string) { //fnt format used by angelcode bmfont //http://www.angelcode.com/products/bmfont/ FileAccess *f = FileAccess::open(p_string,FileAccess::READ); if (!f) { ERR_EXPLAIN("Can't open font: "+p_string); ERR_FAIL_V(ERR_FILE_NOT_FOUND); } clear(); while(true) { String line=f->get_line(); int delimiter=line.find(" "); String type=line.substr(0,delimiter); int pos = delimiter+1; Map<String,String> keys; while (pos < line.size() && line[pos]==' ') pos++; while(pos<line.size()) { int eq = line.find("=",pos); if (eq==-1) break; String key=line.substr(pos,eq-pos); int end=-1; String value; if (line[eq+1]=='"') { end=line.find("\"",eq+2); if (end==-1) break; value=line.substr(eq+2,end-1-eq-1); pos=end+1; } else { end=line.find(" ",eq+1); if (end==-1) end=line.size(); value=line.substr(eq+1,end-eq); pos=end; } while (pos<line.size() && line[pos]==' ') pos++; keys[key]=value; } if (type=="info") { if (keys.has("face")) set_name(keys["face"]); //if (keys.has("size")) // font->set_height(keys["size"].to_int()); } else if (type=="common") { if (keys.has("lineHeight")) set_height(keys["lineHeight"].to_int()); if (keys.has("base")) set_ascent(keys["base"].to_int()); } else if (type=="page") { if (keys.has("file")) { String file = keys["file"]; file=p_string.get_base_dir()+"/"+file; Ref<Texture> tex = ResourceLoader::load(file); if (tex.is_null()) { ERR_PRINT("Can't load font texture!"); } else { add_texture(tex); } } } else if (type=="char") { CharType idx=0; if (keys.has("id")) idx=keys["id"].to_int(); Rect2 rect; if (keys.has("x")) rect.pos.x=keys["x"].to_int(); if (keys.has("y")) rect.pos.y=keys["y"].to_int(); if (keys.has("width")) rect.size.width=keys["width"].to_int(); if (keys.has("height")) rect.size.height=keys["height"].to_int(); Point2 ofs; if (keys.has("xoffset")) ofs.x=keys["xoffset"].to_int(); if (keys.has("yoffset")) ofs.y=keys["yoffset"].to_int(); int texture=0; if (keys.has("page")) texture=keys["page"].to_int(); int advance=-1; if (keys.has("xadvance")) advance=keys["xadvance"].to_int(); add_char(idx,texture,rect,ofs,advance); } else if (type=="kerning") { CharType first=0,second=0; int k=0; if (keys.has("first")) first=keys["first"].to_int(); if (keys.has("second")) second=keys["second"].to_int(); if (keys.has("amount")) k=keys["amount"].to_int(); add_kerning_pair(first,second,-k); } if (f->eof_reached()) break; } memdelete(f); return OK; }
void EditorFileSystem::_scan_filesystem() { ERR_FAIL_COND(!scanning || new_filesystem); //read .fscache String cpath; sources_changed.clear(); file_cache.clear(); String project=Globals::get_singleton()->get_resource_path(); String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache"); FileAccess *f =FileAccess::open(fscache,FileAccess::READ); if (f) { //read the disk cache while(!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l==String()) continue; if (l.begins_with("::")) { Vector<String> split = l.split("::"); ERR_CONTINUE( split.size() != 3); String name = split[1]; cpath=name; } else { Vector<String> split = l.split("::"); ERR_CONTINUE( split.size() != 5); String name = split[0]; String file; file=name; name=cpath.plus_file(name); FileCache fc; fc.type=split[1]; fc.modification_time=split[2].to_int64(); String meta = split[3].strip_edges(); fc.meta.enabled=false; if (meta.find("<>")!=-1){ Vector<String> spl = meta.split("<>"); int sc = spl.size()-1; if (sc%3==0){ fc.meta.enabled=true; fc.meta.import_editor=spl[0]; fc.meta.sources.resize(sc/3); for(int i=0;i<fc.meta.sources.size();i++) { fc.meta.sources[i].path=spl[1+i*3+0]; fc.meta.sources[i].md5=spl[1+i*3+1]; fc.meta.sources[i].modified_time=spl[1+i*3+2].to_int64(); } } } String deps = split[4].strip_edges(); if (deps.length()) { Vector<String> dp = deps.split("<>"); for(int i=0;i<dp.size();i++) { String path=dp[i]; fc.meta.deps.push_back(path); } } file_cache[name]=fc; } } f->close(); memdelete(f); } EditorProgressBG scan_progress("efs","ScanFS",1000); ScanProgress sp; sp.low=0; sp.hi=1; sp.progress=&scan_progress; new_filesystem = memnew( EditorFileSystemDirectory ); new_filesystem->parent=NULL; DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); d->change_dir("res://"); _scan_new_dir(new_filesystem,d,sp); file_cache.clear(); //clear caches, no longer needed memdelete(d); //save back the findings // String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache"); f=FileAccess::open(fscache,FileAccess::WRITE); _save_filesystem_cache(new_filesystem,f); f->close(); memdelete(f); scanning=false; }
RES ResourceFormatLoaderTheme::load(const String &p_path, const String& p_original_path, Error *r_error) { if (r_error) *r_error=ERR_CANT_OPEN; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); ERR_EXPLAIN("Unable to open theme file: "+p_path); ERR_FAIL_COND_V(err,RES()); String base_path = p_path.get_base_dir(); Ref<Theme> theme( memnew( Theme ) ); Map<StringName,Variant> library; if (r_error) *r_error=ERR_FILE_CORRUPT; bool reading_library=false; int line=0; while(!f->eof_reached()) { String l = f->get_line().strip_edges(); line++; int comment = l.find(";"); if (comment!=-1) l=l.substr(0,comment); if (l=="") continue; if (l.begins_with("[")) { if (l=="[library]") { reading_library=true; } else if (l=="[theme]") { reading_library=false; } else { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Unknown section type: '"+l+"'."); ERR_FAIL_V(RES()); } continue; } int eqpos = l.find("="); if (eqpos==-1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected '='."); ERR_FAIL_V(RES()); } String right=l.substr(eqpos+1,l.length()).strip_edges(); if (right=="") { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected value after '='."); ERR_FAIL_V(RES()); } Variant value; if (right.is_valid_integer()) { //is number value = right.to_int(); } else if (right.is_valid_html_color()) { //is html color value = Color::html(right); } else if (right.begins_with("@")) { //reference String reference = right.substr(1,right.length()); if (!library.has(reference)) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid reference to '"+reference+"'."); ERR_FAIL_V(RES()); } value=library[reference]; } else if (right.begins_with("default")) { //use default //do none } else { //attempt to parse a constructor int popenpos = right.find("("); if (popenpos==-1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor syntax: "+right); ERR_FAIL_V(RES()); } int pclosepos = right.find_last(")"); if (pclosepos==-1) { ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor parameter syntax: "+right); ERR_FAIL_V(RES()); } String type = right.substr(0,popenpos); String param = right.substr(popenpos+1,pclosepos-popenpos-1); if (type=="icon") { String path; if (param.is_abs_path()) path=param; else path=base_path+"/"+param; Ref<Texture> texture = ResourceLoader::load(path); if (!texture.is_valid()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Couldn't find icon at path: "+path); ERR_FAIL_V(RES()); } value=texture; } else if (type=="sbox") { String path; if (param.is_abs_path()) path=param; else path=base_path+"/"+param; Ref<StyleBox> stylebox = ResourceLoader::load(path); if (!stylebox.is_valid()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Couldn't find stylebox at path: "+path); ERR_FAIL_V(RES()); } value=stylebox; } else if (type=="sboxt") { Vector<String> params = param.split(","); if (params.size()!=5 && params.size()!=9) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid param count for sboxt(): '"+right+"'."); ERR_FAIL_V(RES()); } String path=params[0]; if (!param.is_abs_path()) path=base_path+"/"+path; Ref<Texture> tex = ResourceLoader::load(path); if (tex.is_null()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Could not open texture for sboxt at path: '"+params[0]+"'."); ERR_FAIL_V(RES()); } Ref<StyleBoxTexture> sbtex( memnew(StyleBoxTexture) ); sbtex->set_texture(tex); for(int i=0; i<4; i++) { if (!params[i+1].is_valid_integer()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid expand margin parameter for sboxt #"+itos(i+1) +", expected integer constant, got: '"+params[i+1]+"'."); ERR_FAIL_V(RES()); } int margin = params[i+1].to_int(); sbtex->set_expand_margin_size(Margin(i),margin); } if (params.size()==9) { for(int i=0; i<4; i++) { if (!params[i+5].is_valid_integer()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid expand margin parameter for sboxt #"+itos(i+5) +", expected integer constant, got: '"+params[i+5]+"'."); ERR_FAIL_V(RES()); } int margin = params[i+5].to_int(); sbtex->set_margin_size(Margin(i),margin); } } value = sbtex; } else if (type=="sboxf") { Vector<String> params = param.split(","); if (params.size()<2) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid param count for sboxf(): '"+right+"'."); ERR_FAIL_V(RES()); } Ref<StyleBoxFlat> sbflat( memnew(StyleBoxFlat) ); if (!params[0].is_valid_integer()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected integer numeric constant for parameter 0 (border size)."); ERR_FAIL_V(RES()); } sbflat->set_border_size(params[0].to_int()); if (!params[0].is_valid_integer()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected integer numeric constant for parameter 0 (border size)."); ERR_FAIL_V(RES()); } int left = MIN( params.size()-1, 3 ); int ccodes=0; for(int i=0; i<left; i++) { if (params[i+1].is_valid_html_color()) ccodes++; else break; } Color normal; Color bright; Color dark; if (ccodes<1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected at least 1, 2 or 3 html color codes."); ERR_FAIL_V(RES()); } else if (ccodes==1) { normal=Color::html(params[1]); bright=Color::html(params[1]); dark=Color::html(params[1]); } else if (ccodes==2) { normal=Color::html(params[1]); bright=Color::html(params[2]); dark=Color::html(params[2]); } else { normal=Color::html(params[1]); bright=Color::html(params[2]); dark=Color::html(params[3]); } sbflat->set_dark_color(dark); sbflat->set_light_color(bright); sbflat->set_bg_color(normal); if (params.size()==ccodes+5) { //margins for(int i=0; i<4; i++) { if (!params[i+ccodes+1].is_valid_integer()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid expand margin parameter for sboxf #"+itos(i+ccodes+1) +", expected integer constant, got: '"+params[i+ccodes+1]+"'."); ERR_FAIL_V(RES()); } // int margin = params[i+ccodes+1].to_int(); //sbflat->set_margin_size(Margin(i),margin); } } else if (params.size()!=ccodes+1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid amount of margin parameters for sboxt."); ERR_FAIL_V(RES()); } value=sbflat; } else { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor type: '"+type+"'."); ERR_FAIL_V(RES()); } } //parse left and do something with it String left= l.substr(0,eqpos); if (reading_library) { left=left.strip_edges(); if (!left.is_valid_identifier()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": <LibraryItem> is not a valid identifier."); ERR_FAIL_V(RES()); } if (library.has(left)) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Already in library: '"+left+"'."); ERR_FAIL_V(RES()); } library[left]=value; } else { int pointpos = left.find("."); if (pointpos==-1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected 'control.item=..' assign syntax."); ERR_FAIL_V(RES()); } String control=left.substr(0,pointpos).strip_edges(); if (!control.is_valid_identifier()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": <Control> is not a valid identifier."); ERR_FAIL_V(RES()); } String item=left.substr(pointpos+1,left.size()).strip_edges(); if (!item.is_valid_identifier()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": <Item> is not a valid identifier."); ERR_FAIL_V(RES()); } if (value.get_type()==Variant::NIL) { //try to use exiting if (Theme::get_default()->has_stylebox(item,control)) value=Theme::get_default()->get_stylebox(item,control); else if (Theme::get_default()->has_font(item,control)) value=Theme::get_default()->get_font(item,control); else if (Theme::get_default()->has_icon(item,control)) value=Theme::get_default()->get_icon(item,control); else if (Theme::get_default()->has_color(item,control)) value=Theme::get_default()->get_color(item,control); else if (Theme::get_default()->has_constant(item,control)) value=Theme::get_default()->get_constant(item,control); else { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Default not present for: '"+control+"."+item+"'."); ERR_FAIL_V(RES()); } } if (value.get_type()==Variant::OBJECT) { Ref<Resource> res = value; if (!res.is_valid()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid resource (NULL)."); ERR_FAIL_V(RES()); } if (res->cast_to<StyleBox>()) { theme->set_stylebox(item,control,res); } else if (res->cast_to<Font>()) { theme->set_font(item,control,res); } else if (res->cast_to<Font>()) { theme->set_font(item,control,res); } else if (res->cast_to<Texture>()) { theme->set_icon(item,control,res); } else { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid resource type."); ERR_FAIL_V(RES()); } } else if (value.get_type()==Variant::COLOR) { theme->set_color(item,control,value); } else if (value.get_type()==Variant::INT) { theme->set_constant(item,control,value); } else { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Couldn't even determine what this setting is! what did you do!?"); ERR_FAIL_V(RES()); } } } f->close(); memdelete(f); if (r_error) *r_error=OK; return theme; }
void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { type_list.clear(); ClassDB::get_class_list(&type_list); ScriptServer::get_global_class_list(&type_list); type_list.sort_custom<StringName::AlphCompare>(); recent->clear(); FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ); if (f) { TreeItem *root = recent->create_item(); while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l != String()) { TreeItem *ti = recent->create_item(root); ti->set_text(0, l); ti->set_icon(0, _get_editor_icon(l)); } } memdelete(f); } favorites->clear(); f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::READ); favorite_list.clear(); if (f) { while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l != String()) { favorite_list.push_back(l); } } memdelete(f); } _update_favorite_list(); // Restore valid window bounds or pop up at default size. if (EditorSettings::get_singleton()->has_setting("interface/dialogs/create_new_node_bounds")) { popup(EditorSettings::get_singleton()->get("interface/dialogs/create_new_node_bounds")); } else { Size2 popup_size = Size2(900, 700) * editor_get_scale(); Size2 window_size = get_viewport_rect().size; popup_size.x = MIN(window_size.x * 0.8, popup_size.x); popup_size.y = MIN(window_size.y * 0.8, popup_size.y); popup_centered(popup_size); } if (p_dont_clear) { search_box->select_all(); } else { search_box->clear(); } search_box->grab_focus(); _update_search(); bool enable_rl = EditorSettings::get_singleton()->get("docks/scene_tree/draw_relationship_lines"); Color rl_color = EditorSettings::get_singleton()->get("docks/scene_tree/relationship_line_color"); if (enable_rl) { search_options->add_constant_override("draw_relationship_lines", 1); search_options->add_color_override("relationship_line_color", rl_color); } else { search_options->add_constant_override("draw_relationship_lines", 0); } is_replace_mode = p_replace_mode; if (p_replace_mode) { set_title(vformat(TTR("Change %s Type"), base_type)); get_ok()->set_text(TTR("Change")); } else { set_title(vformat(TTR("Create New %s"), base_type)); get_ok()->set_text(TTR("Create")); } }
RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_original_path) { if (p_path.extension()=="cube") { // open as cubemap txture CubeMap* ptr = memnew(CubeMap); Ref<CubeMap> cubemap( ptr ); Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); if (err) { ERR_FAIL_COND_V( err, RES() ); } String base_path=p_path.substr( 0, p_path.find_last("/")+1 ); for(int i=0;i<6;i++) { String file = f->get_line().strip_edges(); Image image; Error err = ImageLoader::load_image(base_path+file,&image); if (err) { memdelete(f); ERR_FAIL_COND_V( err, RES() ); } if (i==0) { //cubemap->create(image.get_width(),image.get_height(),image.get_format(),Texture::FLAGS_DEFAULT|Texture::FLAG_CUBEMAP); } static const CubeMap::Side cube_side[6]= { CubeMap::SIDE_LEFT, CubeMap::SIDE_RIGHT, CubeMap::SIDE_BOTTOM, CubeMap::SIDE_TOP, CubeMap::SIDE_FRONT, CubeMap::SIDE_BACK }; cubemap->set_side(cube_side[i],image); } memdelete(f); cubemap->set_name(p_path.get_file()); return cubemap; } else { // simple image ImageTexture* ptr = memnew(ImageTexture); Ref<ImageTexture> texture( ptr ); uint64_t begtime; double total; Image image; if (debug_load_times) begtime=OS::get_singleton()->get_ticks_usec(); Error err = ImageLoader::load_image(p_path,&image); if (!err && debug_load_times) { double total=(double)(OS::get_singleton()->get_ticks_usec()-begtime)/1000000.0; print_line("IMAGE: "+itos(image.get_width())+"x"+itos(image.get_height())); print_line(" -load: "+rtos(total)); } ERR_EXPLAIN("Failed loading image: "+p_path); ERR_FAIL_COND_V(err, RES()); #ifdef DEBUG_ENABLED #ifdef TOOLS_ENABLED if (max_texture_size && (image.get_width() > max_texture_size || image.get_height() > max_texture_size)) { if (bool(Globals::get_singleton()->get("debug/max_texture_size_alert"))) { OS::get_singleton()->alert("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+".","BAD ARTIST, NO COOKIE!"); } ERR_EXPLAIN("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+"."); ERR_FAIL_V(RES()); } #endif #endif uint32_t flags=0; if (bool(GLOBAL_DEF("texture_import/filter",true))) flags|=Texture::FLAG_FILTER; if (bool(GLOBAL_DEF("texture_import/gen_mipmaps",true))) flags|=Texture::FLAG_MIPMAPS; if (bool(GLOBAL_DEF("texture_import/repeat",true))) flags|=Texture::FLAG_REPEAT; if (debug_load_times) begtime=OS::get_singleton()->get_ticks_usec(); //print_line("img: "+p_path+" flags: "+itos(flags)); texture->create_from_image( image,flags ); texture->set_name(p_path.get_file()); if (debug_load_times) { total=(double)(OS::get_singleton()->get_ticks_usec()-begtime)/1000000.0; print_line(" -make texture: "+rtos(total)); } return RES( texture ); } }
void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_select_type) { type_list.clear(); ClassDB::get_class_list(&type_list); ScriptServer::get_global_class_list(&type_list); type_list.sort_custom<StringName::AlphCompare>(); recent->clear(); FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::READ); if (f) { TreeItem *root = recent->create_item(); while (!f->eof_reached()) { String l = f->get_line().strip_edges(); String name = l.split(" ")[0]; if (ClassDB::class_exists(name) || ScriptServer::is_global_class(name)) { TreeItem *ti = recent->create_item(root); ti->set_text(0, l); ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(l, base_type)); } } memdelete(f); } favorites->clear(); f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::READ); favorite_list.clear(); if (f) { while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l != String()) { favorite_list.push_back(l); } } memdelete(f); } _save_and_update_favorite_list(); // Restore valid window bounds or pop up at default size. Rect2 saved_size = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "create_new_node", Rect2()); if (saved_size != Rect2()) { popup(saved_size); } else { popup_centered_clamped(Size2(900, 700) * EDSCALE, 0.8); } if (p_dont_clear) { search_box->select_all(); } else { search_box->clear(); } search_box->grab_focus(); _update_search(); is_replace_mode = p_replace_mode; if (p_replace_mode) { select_type(p_select_type); set_title(vformat(TTR("Change %s Type"), base_type)); get_ok()->set_text(TTR("Change")); } else { set_title(vformat(TTR("Create New %s"), base_type)); get_ok()->set_text(TTR("Create")); } }
void CreateDialog::popup_create(bool p_dontclear) { recent->clear(); FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent." + base_type), FileAccess::READ); if (f) { TreeItem *root = recent->create_item(); while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l != String()) { TreeItem *ti = recent->create_item(root); ti->set_text(0, l); if (has_icon(l, "EditorIcons")) { ti->set_icon(0, get_icon(l, "EditorIcons")); } else { ti->set_icon(0, get_icon("Object", "EditorIcons")); } } } memdelete(f); } favorites->clear(); f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites." + base_type), FileAccess::READ); favorite_list.clear(); if (f) { while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l != String()) { favorite_list.push_back(l); } } memdelete(f); } _update_favorite_list(); // Restore valid window bounds or pop up at default size. if (EditorSettings::get_singleton()->has("interface/dialogs/create_new_node_bounds")) { popup(EditorSettings::get_singleton()->get("interface/dialogs/create_new_node_bounds")); } else { popup_centered_ratio(); } if (p_dontclear) search_box->select_all(); else { search_box->clear(); } search_box->grab_focus(); _update_search(); }
void EditorFileSystem::_scan_filesystem() { ERR_FAIL_COND(!scanning || new_filesystem); //read .fscache String cpath; sources_changed.clear(); file_cache.clear(); String project = ProjectSettings::get_singleton()->get_resource_path(); String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_cache2"); FileAccess *f = FileAccess::open(fscache, FileAccess::READ); if (f) { //read the disk cache while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l == String()) continue; if (l.begins_with("::")) { Vector<String> split = l.split("::"); ERR_CONTINUE(split.size() != 3); String name = split[1]; cpath = name; } else { Vector<String> split = l.split("::"); ERR_CONTINUE(split.size() != 5); String name = split[0]; String file; file = name; name = cpath.plus_file(name); FileCache fc; fc.type = split[1]; fc.modification_time = split[2].to_int64(); fc.import_modification_time = split[3].to_int64(); String deps = split[4].strip_edges(); if (deps.length()) { Vector<String> dp = deps.split("<>"); for (int i = 0; i < dp.size(); i++) { String path = dp[i]; fc.deps.push_back(path); } } file_cache[name] = fc; } } f->close(); memdelete(f); } String update_cache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("filesystem_update2"); print_line("try to see fs update2"); if (FileAccess::exists(update_cache)) { print_line("it exists"); { FileAccessRef f = FileAccess::open(update_cache, FileAccess::READ); String l = f->get_line().strip_edges(); while (l != String()) { print_line("erased cache for: " + l + " " + itos(file_cache.has(l))); file_cache.erase(l); //erase cache for this, so it gets updated l = f->get_line().strip_edges(); } } DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); d->remove(update_cache); //bye bye update cache } EditorProgressBG scan_progress("efs", "ScanFS", 1000); ScanProgress sp; sp.low = 0; sp.hi = 1; sp.progress = &scan_progress; new_filesystem = memnew(EditorFileSystemDirectory); new_filesystem->parent = NULL; DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); d->change_dir("res://"); _scan_new_dir(new_filesystem, d, sp); file_cache.clear(); //clear caches, no longer needed memdelete(d); //save back the findings //String fscache = EditorSettings::get_singleton()->get_project_settings_path().plus_file("file_cache"); f = FileAccess::open(fscache, FileAccess::WRITE); _save_filesystem_cache(new_filesystem, f); f->close(); memdelete(f); scanning = false; }
void EditorResourcePreview::_thread() { //print_line("begin thread"); while (!exit) { //print_line("wait for semaphore"); preview_sem->wait(); preview_mutex->lock(); //print_line("blue team go"); if (queue.size()) { QueueItem item = queue.front()->get(); queue.pop_front(); if (cache.has(item.path)) { //already has it because someone loaded it, just let it know it's ready if (item.resource.is_valid()) { item.path += ":" + itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below) } _preview_ready(item.path, cache[item.path].preview, item.id, item.function, item.userdata); preview_mutex->unlock(); } else { preview_mutex->unlock(); Ref<Texture> texture; //print_line("pop from queue "+item.path); int thumbnail_size = EditorSettings::get_singleton()->get("file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; if (item.resource.is_valid()) { texture = _generate_preview(item, String()); //adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred _preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, item.id, item.function, item.userdata); } else { String temp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp"); String cache_base = Globals::get_singleton()->globalize_path(item.path).md5_text(); cache_base = temp_path.plus_file("resthumb-" + cache_base); //does not have it, try to load a cached thumbnail String file = cache_base + ".txt"; //print_line("cachetxt at "+file); FileAccess *f = FileAccess::open(file, FileAccess::READ); if (!f) { //print_line("generate because not cached"); //generate texture = _generate_preview(item, cache_base); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); int tsize = f->get_line().to_int64(); uint64_t last_modtime = f->get_line().to_int64(); bool cache_valid = true; if (tsize != thumbnail_size) { cache_valid = false; memdelete(f); } else if (last_modtime != modtime) { String last_md5 = f->get_line(); String md5 = FileAccess::get_md5(item.path); memdelete(f); if (last_md5 != md5) { cache_valid = false; } else { //update modified time f = FileAccess::open(file, FileAccess::WRITE); f->store_line(itos(modtime)); f->store_line(md5); memdelete(f); } } else { memdelete(f); } if (cache_valid) { texture = ResourceLoader::load(cache_base + ".png", "ImageTexture", true); if (!texture.is_valid()) { //well f**k cache_valid = false; } } if (!cache_valid) { texture = _generate_preview(item, cache_base); } } //print_line("notify of preview ready"); _preview_ready(item.path, texture, item.id, item.function, item.userdata); } } } else { preview_mutex->unlock(); } } }
void EditorFileSystem::_scan_scenes() { ERR_FAIL_COND(!scanning || scandir); //read .fscache HashMap<String,FileCache> file_cache; HashMap<String,DirCache> dir_cache; DirCache *dc=NULL; String cpath; sources_changed.clear(); String project=Globals::get_singleton()->get_resource_path(); FileAccess *f =FileAccess::open(project+"/.fscache",FileAccess::READ); if (f) { //read the disk cache while(!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l==String()) continue; if (l.begins_with("::")) { Vector<String> split = l.split("::"); ERR_CONTINUE( split.size() != 3); String name = split[1]; dir_cache[name]=DirCache(); dc=&dir_cache[name]; dc->modification_time=split[2].to_int64(); if (name!="res://") { cpath=name+"/"; int sp=name.find_last("/"); if (sp==5) sp=6; String pd = name.substr(0,sp); DirCache *dcp = dir_cache.getptr(pd); ERR_CONTINUE(!dcp); dcp->subdirs.insert(name.get_file()); } else { cpath=name; } } else { Vector<String> split = l.split("::"); ERR_CONTINUE( split.size() != 4); String name = split[0]; String file; if (!name.begins_with("res://")) { file=name; name=cpath+name; } else { file=name.get_file(); } FileCache fc; fc.type=split[1]; fc.modification_time=split[2].to_int64(); String meta = split[3].strip_edges(); fc.meta.enabled=false; if (meta.find("<>")!=-1){ Vector<String> spl = meta.split("<>"); int sc = spl.size()-1; if (sc%3==0){ fc.meta.enabled=true; fc.meta.import_editor=spl[0]; fc.meta.sources.resize(sc/3); for(int i=0;i<fc.meta.sources.size();i++) { fc.meta.sources[i].path=spl[1+i*3+0]; fc.meta.sources[i].md5=spl[1+i*3+1]; fc.meta.sources[i].modified_time=spl[1+i*3+2].to_int64(); } } } file_cache[name]=fc; ERR_CONTINUE(!dc); dc->files.insert(file); } } f->close(); memdelete(f); } total=0; DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); //da->change_dir( Globals::get_singleton()->get_resource_path() ); List<String> extensionsl; ResourceLoader::get_recognized_extensions_for_type("",&extensionsl); Set<String> extensions; for(List<String>::Element *E = extensionsl.front();E;E=E->next()) { extensions.insert(E->get()); } EditorProgressBG scan_progress("efs","ScanFS",100); md_count=0; scandir=_scan_dir(da,extensions,"",0,1,"",file_cache,dir_cache,scan_progress); memdelete(da); if (abort_scan && scandir) { memdelete(scandir); scandir=NULL; } //save back the findings f=FileAccess::open(project+"/.fscache",FileAccess::WRITE); _save_type_cache_fs(scandir,f); f->close(); memdelete(f); scanning=false; }
void EditorResourcePreview::_thread() { while (!exit) { preview_sem->wait(); preview_mutex->lock(); if (queue.size()) { QueueItem item = queue.front()->get(); queue.pop_front(); if (cache.has(item.path)) { //already has it because someone loaded it, just let it know it's ready String path = item.path; if (item.resource.is_valid()) { path += ":" + itos(cache[item.path].last_hash); //keep last hash (see description of what this is in condition below) } _preview_ready(path, cache[item.path].preview, cache[item.path].small_preview, item.id, item.function, item.userdata); preview_mutex->unlock(); } else { preview_mutex->unlock(); Ref<ImageTexture> texture; Ref<ImageTexture> small_texture; int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; if (item.resource.is_valid()) { _generate_preview(texture, small_texture, item, String()); //adding hash to the end of path (should be ID:<objid>:<hash>) because of 5 argument limit to call_deferred _preview_ready(item.path + ":" + itos(item.resource->hash_edited_version()), texture, small_texture, item.id, item.function, item.userdata); } else { String temp_path = EditorSettings::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(item.path).md5_text(); cache_base = temp_path.plus_file("resthumb-" + cache_base); //does not have it, try to load a cached thumbnail String file = cache_base + ".txt"; FileAccess *f = FileAccess::open(file, FileAccess::READ); if (!f) { // No cache found, generate _generate_preview(texture, small_texture, item, cache_base); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); int tsize = f->get_line().to_int64(); bool has_small_texture = f->get_line().to_int(); uint64_t last_modtime = f->get_line().to_int64(); bool cache_valid = true; if (tsize != thumbnail_size) { cache_valid = false; memdelete(f); } else if (last_modtime != modtime) { String last_md5 = f->get_line(); String md5 = FileAccess::get_md5(item.path); memdelete(f); if (last_md5 != md5) { cache_valid = false; } else { //update modified time f = FileAccess::open(file, FileAccess::WRITE); f->store_line(itos(modtime)); f->store_line(itos(has_small_texture)); f->store_line(md5); memdelete(f); } } else { memdelete(f); } if (cache_valid) { Ref<Image> img; img.instance(); Ref<Image> small_img; small_img.instance(); if (img->load(cache_base + ".png") != OK) { cache_valid = false; } else { texture.instance(); texture->create_from_image(img, Texture::FLAG_FILTER); if (has_small_texture) { if (small_img->load(cache_base + "_small.png") != OK) { cache_valid = false; } else { small_texture.instance(); small_texture->create_from_image(small_img, Texture::FLAG_FILTER); } } } } if (!cache_valid) { _generate_preview(texture, small_texture, item, cache_base); } } _preview_ready(item.path, texture, small_texture, item.id, item.function, item.userdata); } } } else { preview_mutex->unlock(); } } }
RES ResourceFormatLoaderImage::load(const String &p_path, const String& p_original_path, Error *r_error) { if (r_error) *r_error=ERR_CANT_OPEN; if (p_path.extension()=="cube") { // open as cubemap txture CubeMap* ptr = memnew(CubeMap); Ref<CubeMap> cubemap( ptr ); Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); if (err) { ERR_FAIL_COND_V( err, RES() ); } String base_path=p_path.substr( 0, p_path.find_last("/")+1 ); for(int i=0;i<6;i++) { String file = f->get_line().strip_edges(); Image image; Error err = ImageLoader::load_image(base_path+file,&image); if (err) { memdelete(f); ERR_FAIL_COND_V( err, RES() ); } if (i==0) { //cubemap->create(image.get_width(),image.get_height(),image.get_format(),Texture::FLAGS_DEFAULT|Texture::FLAG_CUBEMAP); } static const CubeMap::Side cube_side[6]= { CubeMap::SIDE_LEFT, CubeMap::SIDE_RIGHT, CubeMap::SIDE_BOTTOM, CubeMap::SIDE_TOP, CubeMap::SIDE_FRONT, CubeMap::SIDE_BACK }; cubemap->set_side(cube_side[i],image); } memdelete(f); cubemap->set_name(p_path.get_file()); if (r_error) *r_error=OK; return cubemap; } else { // simple image ImageTexture* ptr = memnew(ImageTexture); Ref<ImageTexture> texture( ptr ); uint64_t begtime; double total; Image image; if (debug_load_times) begtime=OS::get_singleton()->get_ticks_usec(); Error err = ImageLoader::load_image(p_path,&image); if (!err && debug_load_times) { double total=(double)(OS::get_singleton()->get_ticks_usec()-begtime)/1000000.0; print_line("IMAGE: "+itos(image.get_width())+"x"+itos(image.get_height())); print_line(" -load: "+rtos(total)); } ERR_EXPLAIN("Failed loading image: "+p_path); ERR_FAIL_COND_V(err, RES()); if (r_error) *r_error=ERR_FILE_CORRUPT; #ifdef DEBUG_ENABLED #ifdef TOOLS_ENABLED if (max_texture_size && (image.get_width() > max_texture_size || image.get_height() > max_texture_size)) { if (bool(Globals::get_singleton()->get("debug/max_texture_size_alert"))) { OS::get_singleton()->alert("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+".","BAD ARTIST, NO COOKIE!"); } ERR_EXPLAIN("Texture is too large: '"+p_path+"', at "+itos(image.get_width())+"x"+itos(image.get_height())+". Max allowed size is: "+itos(max_texture_size)+"x"+itos(max_texture_size)+"."); ERR_FAIL_V(RES()); } #endif #endif uint32_t flags=0; FileAccess *f2 = FileAccess::open(p_path+".flags",FileAccess::READ); Map<String,bool> flags_found; if (f2) { while(!f2->eof_reached()) { String l2 = f2->get_line(); int eqpos = l2.find("="); if (eqpos!=-1) { String flag=l2.substr(0,eqpos).strip_edges(); String val=l2.substr(eqpos+1,l2.length()).strip_edges().to_lower(); flags_found[flag]=(val=="true" || val=="1")?true:false; } } memdelete(f2); } if (flags_found.has("filter")) { if (flags_found["filter"]) flags|=Texture::FLAG_FILTER; } else if (bool(GLOBAL_DEF("image_loader/filter",true))) { flags|=Texture::FLAG_FILTER; } if (flags_found.has("gen_mipmaps")) { if (flags_found["gen_mipmaps"]) flags|=Texture::FLAG_MIPMAPS; } else if (bool(GLOBAL_DEF("image_loader/gen_mipmaps",true))) { flags|=Texture::FLAG_MIPMAPS; } if (flags_found.has("repeat")) { if (flags_found["repeat"]) flags|=Texture::FLAG_REPEAT; } else if (bool(GLOBAL_DEF("image_loader/repeat",true))) { flags|=Texture::FLAG_REPEAT; } if (flags_found.has("anisotropic")) { if (flags_found["anisotropic"]) flags|=Texture::FLAG_ANISOTROPIC_FILTER; } if (flags_found.has("tolinear")) { if (flags_found["tolinear"]) flags|=Texture::FLAG_CONVERT_TO_LINEAR; } if (flags_found.has("mirroredrepeat")) { if (flags_found["mirroredrepeat"]) flags|=Texture::FLAG_MIRRORED_REPEAT; } if (debug_load_times) begtime=OS::get_singleton()->get_ticks_usec(); //print_line("img: "+p_path+" flags: "+itos(flags)); texture->create_from_image( image,flags ); texture->set_name(p_path.get_file()); if (debug_load_times) { total=(double)(OS::get_singleton()->get_ticks_usec()-begtime)/1000000.0; print_line(" -make texture: "+rtos(total)); } if (r_error) *r_error=OK; return RES( texture ); } }
RES ResourceFormatLoaderShader::load(const String &p_path, const String& p_original_path, Error *r_error) { if (r_error) *r_error=ERR_FILE_CANT_OPEN; String fragment_code; String vertex_code; String light_code; int mode=-1; Error err; FileAccess *f = FileAccess::open(p_path,FileAccess::READ,&err); ERR_EXPLAIN("Unable to open shader file: "+p_path); ERR_FAIL_COND_V(err,RES()); String base_path = p_path.get_base_dir(); if (r_error) *r_error=ERR_FILE_CORRUPT; Ref<Shader> shader;//( memnew( Shader ) ); int line=0; while(!f->eof_reached()) { String l = f->get_line(); line++; if (mode<=0) { l = l.strip_edges(); int comment = l.find(";"); if (comment!=-1) l=l.substr(0,comment); } if (mode<1) vertex_code+="\n"; if (mode<2) fragment_code+="\n"; if (mode < 1 && l=="") continue; if (l.begins_with("[")) { l=l.strip_edges(); if (l=="[params]") { if (mode>=0) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Misplaced [params] section."); ERR_FAIL_V(RES()); } mode=0; } else if (l=="[vertex]") { if (mode>=1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Misplaced [vertex] section."); ERR_FAIL_V(RES()); } mode=1; } else if (l=="[fragment]") { if (mode>=2) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Misplaced [fragment] section."); ERR_FAIL_V(RES()); } mode=1; } else { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Unknown section type: '"+l+"'."); ERR_FAIL_V(RES()); } continue; } if (mode==0) { int eqpos = l.find("="); if (eqpos==-1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected '='."); ERR_FAIL_V(RES()); } String right=l.substr(eqpos+1,l.length()).strip_edges(); if (right=="") { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Expected value after '='."); ERR_FAIL_V(RES()); } Variant value; if (right=="true") { value = true; } else if (right=="false") { value = false; } else if (right.is_valid_float()) { //is number value = right.to_double(); } else if (right.is_valid_html_color()) { //is html color value = Color::html(right); } else { //attempt to parse a constructor int popenpos = right.find("("); if (popenpos==-1) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor syntax: "+right); ERR_FAIL_V(RES()); } int pclosepos = right.find_last(")"); if (pclosepos==-1) { ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor parameter syntax: "+right); ERR_FAIL_V(RES()); } String type = right.substr(0,popenpos); String param = right.substr(popenpos+1,pclosepos-popenpos-1).strip_edges(); if (type=="tex") { if (param=="") { value=RID(); } else { String path; if (param.is_abs_path()) path=param; else path=base_path+"/"+param; Ref<Texture> texture = ResourceLoader::load(path); if (!texture.is_valid()) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Couldn't find icon at path: "+path); ERR_FAIL_V(RES()); } value=texture; } } else if (type=="vec3") { if (param=="") { value=Vector3(); } else { Vector<String> params = param.split(","); if (params.size()!=3) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid param count for vec3(): '"+right+"'."); ERR_FAIL_V(RES()); } Vector3 v; for(int i=0;i<3;i++) v[i]=params[i].to_double(); value=v; } } else if (type=="xform") { if (param=="") { value=Transform(); } else { Vector<String> params = param.split(","); if (params.size()!=12) { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid param count for xform(): '"+right+"'."); ERR_FAIL_V(RES()); } Transform t; for(int i=0;i<9;i++) t.basis[i%3][i/3]=params[i].to_double(); for(int i=0;i<3;i++) t.origin[i]=params[i-9].to_double(); value=t; } } else { memdelete(f); ERR_EXPLAIN(p_path+":"+itos(line)+": Invalid constructor type: '"+type+"'."); ERR_FAIL_V(RES()); } } String left= l.substr(0,eqpos); // shader->set_param(left,value); } else if (mode==1) { vertex_code+=l; } else if (mode==2) { fragment_code+=l; } } shader->set_code(vertex_code,fragment_code,light_code); f->close(); memdelete(f); if (r_error) *r_error=OK; return shader; }
void CreateDialog::popup(bool p_dontclear) { recent->clear(); FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("create_recent." + base_type), FileAccess::READ); if (f) { TreeItem *root = recent->create_item(); while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l != String()) { TreeItem *ti = recent->create_item(root); ti->set_text(0, l); if (has_icon(l, "EditorIcons")) { ti->set_icon(0, get_icon(l, "EditorIcons")); } else { ti->set_icon(0, get_icon("Object", "EditorIcons")); } } } memdelete(f); } favorites->clear(); f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_path().plus_file("favorites." + base_type), FileAccess::READ); favorite_list.clear(); if (f) { while (!f->eof_reached()) { String l = f->get_line().strip_edges(); if (l != String()) { favorite_list.push_back(l); } } memdelete(f); } else { #if 0 // I think this was way too confusing if (base_type=="Node") { //harcode some favorites :D favorite_list.push_back("Panel"); favorite_list.push_back("Button"); favorite_list.push_back("Label"); favorite_list.push_back("LineEdit"); favorite_list.push_back("Node2D"); favorite_list.push_back("Sprite"); favorite_list.push_back("Camera2D"); favorite_list.push_back("Area2D"); favorite_list.push_back("CollisionShape2D"); favorite_list.push_back("Spatial"); favorite_list.push_back("Camera"); favorite_list.push_back("Area"); favorite_list.push_back("CollisionShape"); favorite_list.push_back("TestCube"); favorite_list.push_back("AnimationPlayer"); } #endif } _update_favorite_list(); popup_centered_ratio(); if (p_dontclear) search_box->select_all(); else { search_box->clear(); } search_box->grab_focus(); _update_search(); }