void EditorFileSystem::_scan_sources(EditorFileSystemDirectory *p_dir,EditorProgressBG *ep) { for(int i=0;i<p_dir->files.size();i++) { if (_check_meta_sources(p_dir->files[i].meta,ep)) { sources_changed.push_back(p_dir->get_file_path(i)); } } for(int i=0;i<p_dir->subdirs.size();i++) { _scan_sources(p_dir->get_subdir(i),ep); } }
void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir,const ScanProgress& p_progress) { uint64_t current_mtime = FileAccess::get_modified_time(p_dir->get_path()); bool updated_dir=false; //print_line("dir: "+p_dir->get_path()+" MODTIME: "+itos(p_dir->modified_time)+" CTIME: "+itos(current_mtime)); if (current_mtime!=p_dir->modified_time) { updated_dir=true; p_dir->modified_time=current_mtime; //ooooops, dir changed, see what's going on //first mark everything as veryfied for(int i=0;i<p_dir->files.size();i++) { p_dir->files[i]->verified=false; } for(int i=0;i<p_dir->subdirs.size();i++) { p_dir->get_subdir(i)->verified=false; } //then scan files and directories and check what's different DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); String cd = p_dir->get_path(); da->change_dir(cd); da->list_dir_begin(); while (true) { bool isdir; String f = da->get_next(&isdir); if (f=="") break; if (isdir) { if (f.begins_with(".")) //ignore hidden and . / .. continue; int idx = p_dir->find_dir_index(f); if (idx==-1) { if (FileAccess::exists(cd.plus_file(f).plus_file("engine.cfg"))) // skip if another project inside this continue; EditorFileSystemDirectory *efd = memnew( EditorFileSystemDirectory ); efd->parent=p_dir; efd->name=f; DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); d->change_dir(cd.plus_file(f)); _scan_new_dir(efd,d,p_progress.get_sub(1,1)); memdelete(d); ItemAction ia; ia.action=ItemAction::ACTION_DIR_ADD; ia.dir=p_dir; ia.file=f; ia.new_dir=efd; scan_actions.push_back(ia); } else { p_dir->subdirs[idx]->verified=true; } } else { String ext = f.extension().to_lower(); if (!valid_extensions.has(ext)) continue; //invalid int idx = p_dir->find_file_index(f); if (idx==-1) { //never seen this file, add actition to add it EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo ); fi->file=f; String path = cd.plus_file(fi->file); fi->modified_time=FileAccess::get_modified_time(path); fi->meta=_get_meta(path); fi->type=ResourceLoader::get_resource_type(path); { ItemAction ia; ia.action=ItemAction::ACTION_FILE_ADD; ia.dir=p_dir; ia.file=f; ia.new_file=fi; scan_actions.push_back(ia); } //take the chance and scan sources if (_check_meta_sources(fi->meta)) { ItemAction ia; ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; ia.dir=p_dir; ia.file=f; scan_actions.push_back(ia); } } else { p_dir->files[idx]->verified=true; } } } da->list_dir_end(); memdelete(da); } for(int i=0;i<p_dir->files.size();i++) { if (updated_dir && !p_dir->files[i]->verified) { //this file was removed, add action to remove it ItemAction ia; ia.action=ItemAction::ACTION_FILE_REMOVE; ia.dir=p_dir; ia.file=p_dir->files[i]->file; scan_actions.push_back(ia); continue; } if (_check_meta_sources(p_dir->files[i]->meta)) { ItemAction ia; ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; ia.dir=p_dir; ia.file=p_dir->files[i]->file; scan_actions.push_back(ia); } } for(int i=0;i<p_dir->subdirs.size();i++) { if (updated_dir && !p_dir->subdirs[i]->verified) { //this directory was removed, add action to remove it ItemAction ia; ia.action=ItemAction::ACTION_DIR_REMOVE; ia.dir=p_dir->subdirs[i]; scan_actions.push_back(ia); continue; } _scan_fs_changes(p_dir->get_subdir(i),p_progress); } }
void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess *da,const ScanProgress& p_progress) { List<String> dirs; List<String> files; String cd = da->get_current_dir(); p_dir->modified_time = FileAccess::get_modified_time(cd); da->list_dir_begin(); while (true) { bool isdir; String f = da->get_next(&isdir); if (f=="") break; if (isdir) { if (f.begins_with(".")) //ignore hidden and . / .. continue; if (FileAccess::exists(cd.plus_file(f).plus_file("engine.cfg"))) // skip if another project inside this continue; dirs.push_back(f); } else { files.push_back(f); } } da->list_dir_end(); dirs.sort(); files.sort(); int total = dirs.size()+files.size(); int idx=0; for (List<String>::Element *E=dirs.front();E;E=E->next(),idx++) { if (da->change_dir(E->get())==OK) { EditorFileSystemDirectory *efd = memnew( EditorFileSystemDirectory ); efd->parent=p_dir; efd->name=E->get(); _scan_new_dir(efd,da,p_progress.get_sub(idx,total)); int idx=0; for(int i=0;i<p_dir->subdirs.size();i++) { if (efd->name<p_dir->subdirs[i]->name) break; idx++; } if (idx==p_dir->subdirs.size()) { p_dir->subdirs.push_back(efd); } else { p_dir->subdirs.insert(idx,efd); } da->change_dir(".."); } else { ERR_PRINTS("Can't go into subdir: "+E->get()); } p_progress.update(idx,total); } for (List<String>::Element*E=files.front();E;E=E->next(),idx++) { String ext = E->get().extension().to_lower(); if (!valid_extensions.has(ext)) continue; //invalid EditorFileSystemDirectory::FileInfo *fi = memnew( EditorFileSystemDirectory::FileInfo ); fi->file=E->get(); String path = cd.plus_file(fi->file); FileCache *fc = file_cache.getptr(path); uint64_t mt = FileAccess::get_modified_time(path); if (fc && fc->modification_time == mt) { fi->meta=fc->meta; fi->type=fc->type; fi->modified_time=fc->modification_time; } else { fi->meta=_get_meta(path); fi->type=ResourceLoader::get_resource_type(path); fi->modified_time=mt; } if (fi->meta.enabled) { if (_check_meta_sources(fi->meta)) { ItemAction ia; ia.action=ItemAction::ACTION_FILE_SOURCES_CHANGED; ia.dir=p_dir; ia.file=E->get(); scan_actions.push_back(ia); } } p_dir->files.push_back(fi); p_progress.update(idx,total); } }
EditorFileSystem::DirItem* EditorFileSystem::_scan_dir(DirAccess *da,Set<String> &extensions,String p_name,float p_from,float p_range,const String& p_path,HashMap<String,FileCache> &file_cache,HashMap<String,DirCache> &dir_cache,EditorProgressBG& p_prog) { if (abort_scan) return NULL; if (p_path!=String()) { if (FileAccess::exists(("res://"+p_path).plus_file("engine.cfg"))) { return NULL; } } List<String> dirs; List<String> files; Set<String> pngs; String path=p_path; if (path.ends_with("/")) path=path.substr(0,path.length()-1); String global_path = Globals::get_singleton()->get_resource_path().plus_file(path); path="res://"+path; uint64_t mtime = FileAccess::get_modified_time(global_path); DirCache *dc = dir_cache.getptr(path); if (false && dc && dc->modification_time==mtime) { //use the cached files, since directory did not change for (Set<String>::Element *E=dc->subdirs.front();E;E=E->next()) { dirs.push_back(E->get()); } for (Set<String>::Element *E=dc->files.front();E;E=E->next()) { files.push_back(E->get()); } } else { //use the filesystem, some files may have changed Error err = da->change_dir(global_path); if (err!=OK) { print_line("Can't change to: "+path); ERR_FAIL_COND_V(err!=OK,NULL); } da->list_dir_begin(); while (true) { bool isdir; String f = da->get_next(&isdir); if (f=="") break; if (isdir) { dirs.push_back(f); } else { String ext = f.extension().to_lower(); if (extensions.has(ext)) files.push_back(f); } } da->list_dir_end(); files.sort(); dirs.sort(); } //print_line(da->get_current_dir()+": dirs: "+itos(dirs.size())+" files:"+itos(files.size()) ); //find subdirs Vector<DirItem*> subdirs; //String current = da->get_current_dir(); float idx=0; for (List<String>::Element *E=dirs.front();E;E=E->next(),idx+=1.0) { String d = E->get(); if (d.begins_with(".")) //ignore hidden and . / .. continue; //ERR_CONTINUE( da->change_dir(d)!= OK ); DirItem *sdi = _scan_dir(da,extensions,d,p_from+(idx/dirs.size())*p_range,p_range/dirs.size(),p_path+d+"/",file_cache,dir_cache,p_prog); if (sdi) { subdirs.push_back(sdi); } //da->change_dir(current); } if (subdirs.empty() && files.empty()) { total=p_from+p_range; p_prog.step(total*100); return NULL; //give up, nothing to do here } DirItem *di = memnew( DirItem ); di->path=path; di->name=p_name; di->dirs=subdirs; di->modified_time=mtime; //add files for (List<String>::Element *E=files.front();E;E=E->next()) { SceneItem * si = memnew( SceneItem ); si->file=E->get(); si->path="res://"+p_path+si->file; FileCache *fc = file_cache.getptr(si->path); uint64_t mt = FileAccess::get_modified_time(si->path); if (fc && fc->modification_time == mt) { si->meta=fc->meta; si->type=fc->type; si->modified_time=fc->modification_time; } else { si->meta=_get_meta(si->path); si->type=ResourceLoader::get_resource_type(si->path); si->modified_time=mt; } if (si->meta.enabled) { md_count++; if (_check_meta_sources(si->meta)) { sources_changed.push_back(si->path); } } di->files.push_back(si); } total=p_from+p_range; p_prog.step(total*100); return di; }