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_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; String cd = p_dir->get_path(); //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); 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("project.godot"))) // skip if another project inside this continue; if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) // 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.get_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->import_modified_time = 0; 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); } if (import_extensions.has(ext)) { //if it can be imported, and it was added, it needs to be reimported print_line("REIMPORT: file was not found before, reimport"); print_line("at dir: " + p_dir->get_path() + " file: " + f); for (int i = 0; i < p_dir->files.size(); i++) { print_line(itos(i) + ": " + p_dir->files[i]->file); } ItemAction ia; ia.action = ItemAction::ACTION_FILE_REIMPORT; 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 (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) { //check here if file must be imported or not String path = cd.plus_file(p_dir->files[i]->file); uint64_t mt = FileAccess::get_modified_time(path); bool reimport = false; if (mt != p_dir->files[i]->modified_time) { print_line("REIMPORT: modified time changed, reimport"); reimport = true; //it was modified, must be reimported. } else if (!FileAccess::exists(path + ".import")) { print_line("REIMPORT: no .import exists, reimport"); reimport = true; //no .import file, obviously reimport } else { uint64_t import_mt = FileAccess::get_modified_time(path + ".import"); //print_line(itos(import_mt) + " vs " + itos(p_dir->files[i]->import_modified_time)); if (import_mt != p_dir->files[i]->import_modified_time) { print_line("REIMPORT: import modified changed, reimport"); reimport = true; } else if (!_check_missing_imported_files(path)) { print_line("REIMPORT: imported files removed"); reimport = true; } } if (reimport) { ItemAction ia; ia.action = ItemAction::ACTION_FILE_REIMPORT; ia.dir = p_dir; ia.file = p_dir->files[i]->file; scan_actions.push_back(ia); } } EditorResourcePreview::get_singleton()->check_for_invalidation(p_dir->get_file_path(i)); } 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); } }
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("project.godot"))) // skip if another project inside this continue; if (FileAccess::exists(cd.plus_file(f).plus_file(".gdignore"))) // skip if another project inside this continue; dirs.push_back(f); } else { files.push_back(f); } } da->list_dir_end(); dirs.sort_custom<NaturalNoCaseComparator>(); files.sort_custom<NaturalNoCaseComparator>(); 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) { String d = da->get_current_dir(); if (d == cd || !d.begins_with(cd)) { da->change_dir(cd); //avoid recursion } else { 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("Cannot 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().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 (import_extensions.has(ext)) { //is imported uint64_t import_mt = 0; if (FileAccess::exists(path + ".import")) { import_mt = FileAccess::get_modified_time(path + ".import"); } if (fc && fc->modification_time == mt && fc->import_modification_time == import_mt && _check_missing_imported_files(path)) { fi->type = fc->type; fi->deps = fc->deps; fi->modified_time = fc->modification_time; fi->import_modified_time = fc->import_modification_time; if (fc->type == String()) { fi->type = ResourceLoader::get_resource_type(path); //there is also the chance that file type changed due to reimport, must probably check this somehow here (or kind of note it for next time in another file?) //note: I think this should not happen any longer.. } } else { if (!fc) { print_line("REIMPORT BECAUSE: not previously found"); } else if (fc->modification_time != mt) { print_line("REIMPORT BECAUSE: modified resource time " + itos(fc->modification_time) + " vs " + itos(mt)); } else if (fc->import_modification_time != import_mt) { print_line("REIMPORT BECAUSE: modified .import time" + itos(fc->import_modification_time) + " vs " + itos(import_mt)); } else { print_line("REIMPORT BECAUSE: missing imported files"); } fi->type = ResourceFormatImporter::get_singleton()->get_resource_type(path); //fi->deps = ResourceLoader::get_dependencies(path); pointless because it will be reimported, but.. print_line("import extension tried resource type for " + path + " and its " + fi->type); fi->modified_time = 0; fi->import_modified_time = 0; ItemAction ia; ia.action = ItemAction::ACTION_FILE_REIMPORT; ia.dir = p_dir; ia.file = E->get(); scan_actions.push_back(ia); } } else { if (fc && fc->modification_time == mt) { //not imported, so just update type if changed fi->type = fc->type; fi->modified_time = fc->modification_time; fi->deps = fc->deps; fi->import_modified_time = 0; } else { //new or modified time fi->type = ResourceLoader::get_resource_type(path); fi->deps = _get_dependencies(path); print_line("regular import tried resource type for " + path + " and its " + fi->type); fi->modified_time = mt; fi->import_modified_time = 0; } } p_dir->files.push_back(fi); p_progress.update(idx, total); } }