Fix slow editor load on large projects (v2)

This commit is contained in:
Hilderin 2024-08-16 21:55:03 -04:00
parent 2be730a05b
commit 21f7c8a25f
10 changed files with 233 additions and 127 deletions

View file

@ -507,7 +507,7 @@ bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) con
for (int i = 0; i < importers.size(); i++) {
if (importers[i]->get_importer_name() == pat.importer) {
if (!importers[i]->are_import_settings_valid(p_path)) { //importer thinks this is not valid
if (!importers[i]->are_import_settings_valid(p_path, pat.metadata)) { //importer thinks this is not valid
return false;
}
}

View file

@ -153,7 +153,7 @@ public:
virtual void import_threaded_end() {}
virtual Error import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) { return ERR_UNAVAILABLE; }
virtual bool are_import_settings_valid(const String &p_path) const { return true; }
virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const { return true; }
virtual String get_import_settings_string() const { return String(); }
};

View file

@ -294,7 +294,6 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
if (!err) {
return status.st_mtime;
} else {
WARN_PRINT("Failed to get modified time for: " + p_file);
return 0;
}
}

View file

@ -445,7 +445,6 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
}
}
print_verbose("Failed to get modified time for: " + p_file);
return 0;
}

View file

@ -282,6 +282,21 @@ void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_sca
}
for (const String &scan_file : p_scan_dir->files) {
// Optimization to skip the ResourceLoader::get_resource_type for files
// that are not scripts. Some loader get_resource_type methods read the file
// which can be very slow on large projects.
String ext = scan_file.get_extension().to_lower();
bool is_script = false;
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
if (ScriptServer::get_language(i)->get_extension() == ext) {
is_script = true;
break;
}
}
if (!is_script) {
continue; // Not a script.
}
String path = p_scan_dir->full_path.path_join(scan_file);
String type = ResourceLoader::get_resource_type(path);
@ -371,6 +386,11 @@ void EditorFileSystem::_scan_filesystem() {
fc.script_class_name = split[7].get_slice("<>", 0);
fc.script_class_extends = split[7].get_slice("<>", 1);
fc.script_class_icon_path = split[7].get_slice("<>", 2);
fc.import_md5 = split[7].get_slice("<>", 3);
String dest_paths = split[7].get_slice("<>", 4);
if (!dest_paths.is_empty()) {
fc.import_dest_paths = dest_paths.split("<*>");
}
String deps = split[8].strip_edges();
if (deps.length()) {
@ -463,12 +483,33 @@ void EditorFileSystem::_thread_func(void *_userdata) {
sd->_scan_filesystem();
}
bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_imported_files) {
if (!reimport_on_missing_imported_files && p_only_imported_files) {
return false;
bool EditorFileSystem::_is_test_for_reimport_needed(const String &p_path, uint64_t p_last_modification_time, uint64_t p_modification_time, uint64_t p_last_import_modification_time, uint64_t p_import_modification_time, const Vector<String> &p_import_dest_paths) {
// The idea here is to trust the cache. If the last modification times in the cache correspond
// to the last modification times of the files on disk, it means the files have not changed since
// the last import, and the files in .godot/imported (p_import_dest_paths) should all be valid.
if (p_last_modification_time != p_modification_time) {
return true;
}
if (p_last_import_modification_time != p_import_modification_time) {
return true;
}
if (reimport_on_missing_imported_files) {
for (const String &path : p_import_dest_paths) {
if (!FileAccess::exists(path)) {
return true;
}
}
}
return false;
}
if (!FileAccess::exists(p_path + ".import")) {
bool EditorFileSystem::_test_for_reimport(const String &p_path, const String &p_expected_import_md5) {
if (p_expected_import_md5.is_empty()) {
// Marked as reimportation needed.
return true;
}
String new_md5 = FileAccess::get_md5(p_path + ".import");
if (p_expected_import_md5 != new_md5) {
return true;
}
@ -489,7 +530,7 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
int lines = 0;
String error_text;
List<String> to_check;
Vector<String> to_check;
String importer_name;
String source_file = "";
@ -498,6 +539,7 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
String dest_md5 = "";
int version = 0;
bool found_uid = false;
Variant meta;
while (true) {
assign = Variant();
@ -522,8 +564,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
to_check.push_back(value);
} else if (assign == "files") {
Array fa = value;
for (int i = 0; i < fa.size(); i++) {
to_check.push_back(fa[i]);
for (const Variant &check_path : fa) {
to_check.push_back(check_path);
}
} else if (assign == "importer_version") {
version = value;
@ -531,12 +573,12 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
importer_name = value;
} else if (assign == "uid") {
found_uid = true;
} else if (!p_only_imported_files) {
if (assign == "source_file") {
source_file = value;
} else if (assign == "dest_files") {
dest_files = value;
}
} else if (assign == "source_file") {
source_file = value;
} else if (assign == "dest_files") {
dest_files = value;
} else if (assign == "metadata") {
meta = value;
}
} else if (next_tag.name != "remap" && next_tag.name != "deps") {
@ -544,33 +586,40 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
}
}
if (!ResourceFormatImporter::get_singleton()->are_import_settings_valid(p_path)) {
// Reimport settings are out of sync with project settings, reimport.
return true;
}
if (importer_name == "keep" || importer_name == "skip") {
return false; //keep mode, do not reimport
return false; // Keep mode, do not reimport.
}
if (!found_uid) {
return true; //UID not found, old format, reimport.
return true; // UID not found, old format, reimport.
}
// Imported files are gone, reimport.
for (const String &E : to_check) {
if (!FileAccess::exists(E)) {
return true;
}
}
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
if (importer.is_null()) {
return true; // the importer has possibly changed, try to reimport.
return true; // The importer has possibly changed, try to reimport.
}
if (importer->get_format_version() > version) {
return true; // version changed, reimport
return true; // Version changed, reimport.
}
// Read the md5's from a separate file (so the import parameters aren't dependent on the file version
if (!importer->are_import_settings_valid(p_path, meta)) {
// Reimport settings are out of sync with project settings, reimport.
return true;
}
// Read the md5's from a separate file (so the import parameters aren't dependent on the file version).
String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_path);
Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err);
if (md5s.is_null()) { // No md5's stored for this resource
if (md5s.is_null()) { // No md5's stored for this resource.
return true;
}
@ -588,50 +637,101 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
break;
} else if (err != OK) {
ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import.md5:" + itos(lines) + "' error '" + error_text + "'.");
return false; // parse error
return false; // Parse error.
}
if (!assign.is_empty()) {
if (!p_only_imported_files) {
if (assign == "source_md5") {
source_md5 = value;
} else if (assign == "dest_md5") {
dest_md5 = value;
if (assign == "source_md5") {
source_md5 = value;
} else if (assign == "dest_md5") {
dest_md5 = value;
}
}
}
// Check source md5 matching.
if (!source_file.is_empty() && source_file != p_path) {
return true; // File was moved, reimport.
}
if (source_md5.is_empty()) {
return true; // Lacks md5, so just reimport.
}
String md5 = FileAccess::get_md5(p_path);
if (md5 != source_md5) {
return true;
}
if (!dest_files.is_empty() && !dest_md5.is_empty()) {
md5 = FileAccess::get_multiple_md5(dest_files);
if (md5 != dest_md5) {
return true;
}
}
return false; // Nothing changed.
}
Vector<String> EditorFileSystem::_get_import_dest_paths(const String &p_path) {
Error err;
Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
if (f.is_null()) { // No import file, reimport.
return Vector<String>();
}
VariantParser::StreamFile stream;
stream.f = f;
String assign;
Variant value;
VariantParser::Tag next_tag;
int lines = 0;
String error_text;
Vector<String> dest_paths;
String importer_name;
while (true) {
assign = Variant();
next_tag.fields.clear();
next_tag.name = String();
err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
if (err == ERR_FILE_EOF) {
break;
} else if (err != OK) {
ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import:" + itos(lines) + "' error '" + error_text + "'.");
// Parse error, skip and let user attempt manual reimport to avoid reimport loop.
return Vector<String>();
}
if (!assign.is_empty()) {
if (assign == "valid" && value.operator bool() == false) {
// Invalid import (failed previous import), skip and let user attempt manual reimport to avoid reimport loop.
return Vector<String>();
}
if (assign.begins_with("path")) {
dest_paths.push_back(value);
} else if (assign == "files") {
Array fa = value;
for (const Variant &dest_path : fa) {
dest_paths.push_back(dest_path);
}
} else if (assign == "importer") {
importer_name = value;
}
} else if (next_tag.name != "remap" && next_tag.name != "deps") {
break;
}
}
//imported files are gone, reimport
for (const String &E : to_check) {
if (!FileAccess::exists(E)) {
return true;
}
if (importer_name == "keep" || importer_name == "skip") {
return Vector<String>();
}
//check source md5 matching
if (!p_only_imported_files) {
if (!source_file.is_empty() && source_file != p_path) {
return true; //file was moved, reimport
}
if (source_md5.is_empty()) {
return true; //lacks md5, so just reimport
}
String md5 = FileAccess::get_md5(p_path);
if (md5 != source_md5) {
return true;
}
if (dest_files.size() && !dest_md5.is_empty()) {
md5 = FileAccess::get_multiple_md5(dest_files);
if (md5 != dest_md5) {
return true;
}
}
}
return false; //nothing changed
return dest_paths;
}
bool EditorFileSystem::_scan_import_support(const Vector<String> &reimports) {
@ -774,20 +874,9 @@ bool EditorFileSystem::_update_scan_actions() {
ERR_CONTINUE(idx == -1);
String full_path = ia.dir->get_file_path(idx);
bool need_reimport = _test_for_reimport(full_path, false);
// Workaround GH-94416 for the Android editor for now.
// `import_mt` seems to always be 0 and force a reimport on any fs scan.
#ifndef ANDROID_ENABLED
if (!need_reimport && FileAccess::exists(full_path + ".import")) {
uint64_t import_mt = ia.dir->get_file_import_modified_time(idx);
if (import_mt != FileAccess::get_modified_time(full_path + ".import")) {
need_reimport = true;
}
}
#endif
bool need_reimport = _test_for_reimport(full_path, ia.dir->files[idx]->import_md5);
if (need_reimport) {
//must reimport
// Must reimport.
reimports.push_back(full_path);
Vector<String> dependencies = _get_dependencies(full_path);
for (const String &dep : dependencies) {
@ -797,10 +886,14 @@ bool EditorFileSystem::_update_scan_actions() {
}
}
} else {
//must not reimport, all was good
//update modified times, to avoid reimport
// Must not reimport, all was good.
// Update modified times, md5 and destination paths, to avoid reimport.
ia.dir->files[idx]->modified_time = FileAccess::get_modified_time(full_path);
ia.dir->files[idx]->import_modified_time = FileAccess::get_modified_time(full_path + ".import");
if (ia.dir->files[idx]->import_md5.is_empty()) {
ia.dir->files[idx]->import_md5 = FileAccess::get_md5(full_path + ".import");
}
ia.dir->files[idx]->import_dest_paths = _get_import_dest_paths(full_path);
}
fs_changed = true;
@ -1029,26 +1122,36 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
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");
}
uint64_t import_mt = FileAccess::get_modified_time(path + ".import");
if (fc && fc->modification_time == mt && fc->import_modification_time == import_mt && !_test_for_reimport(path, true)) {
if (fc) {
fi->type = fc->type;
fi->resource_script_class = fc->resource_script_class;
fi->uid = fc->uid;
fi->deps = fc->deps;
fi->modified_time = fc->modification_time;
fi->import_modified_time = fc->import_modification_time;
fi->modified_time = mt;
fi->import_modified_time = import_mt;
fi->import_md5 = fc->import_md5;
fi->import_dest_paths = fc->import_dest_paths;
fi->import_valid = fc->import_valid;
fi->script_class_name = fc->script_class_name;
fi->import_group_file = fc->import_group_file;
fi->script_class_extends = fc->script_class_extends;
fi->script_class_icon_path = fc->script_class_icon_path;
if (revalidate_import_files && !ResourceFormatImporter::get_singleton()->are_import_settings_valid(path)) {
// Ensures backward compatibility when the project is loaded for the first time with the added import_md5
// and import_dest_paths properties in the file cache.
if (fc->import_md5.is_empty()) {
fi->import_md5 = FileAccess::get_md5(path + ".import");
fi->import_dest_paths = _get_import_dest_paths(path);
}
// The method _is_test_for_reimport_needed checks if the files were modified and ensures that
// all the destination files still exist without reading the .import file.
// If something is different, we will queue a test for reimportation that will check
// the md5 of all files and import settings and, if necessary, execute a reimportation.
if (_is_test_for_reimport_needed(path, fc->modification_time, mt, fc->import_modification_time, import_mt, fi->import_dest_paths) ||
(revalidate_import_files && !ResourceFormatImporter::get_singleton()->are_import_settings_valid(path))) {
ItemAction ia;
ia.action = ItemAction::ACTION_FILE_TEST_REIMPORT;
ia.dir = p_dir;
@ -1075,6 +1178,8 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path);
fi->modified_time = 0;
fi->import_modified_time = 0;
fi->import_md5 = "";
fi->import_dest_paths = Vector<String>();
fi->import_valid = (fi->type == "TextFile" || fi->type == "OtherFile") ? true : ResourceLoader::is_import_valid(path);
ItemAction ia;
@ -1089,9 +1194,11 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
fi->type = fc->type;
fi->resource_script_class = fc->resource_script_class;
fi->uid = fc->uid;
fi->modified_time = fc->modification_time;
fi->modified_time = mt;
fi->deps = fc->deps;
fi->import_modified_time = 0;
fi->import_md5 = "";
fi->import_dest_paths = Vector<String>();
fi->import_valid = true;
fi->script_class_name = fc->script_class_name;
fi->script_class_extends = fc->script_class_extends;
@ -1126,6 +1233,8 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
fi->deps = _get_dependencies(path);
fi->modified_time = mt;
fi->import_modified_time = 0;
fi->import_md5 = "";
fi->import_dest_paths = Vector<String>();
fi->import_valid = true;
// Files in dep_update_list are forced for rescan to update dependencies. They don't need other updates.
@ -1269,6 +1378,8 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanPr
String path = cd.path_join(fi->file);
fi->modified_time = FileAccess::get_modified_time(path);
fi->import_modified_time = 0;
fi->import_md5 = "";
fi->import_dest_paths = Vector<String>();
fi->type = ResourceLoader::get_resource_type(path);
fi->resource_script_class = ResourceLoader::get_resource_script_class(path);
if (fi->type == "" && textfile_extensions.has(ext)) {
@ -1323,26 +1434,13 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, ScanPr
String path = cd.path_join(p_dir->files[i]->file);
if (import_extensions.has(p_dir->files[i]->file.get_extension().to_lower())) {
//check here if file must be imported or not
// Check here if file must be imported or not.
// Same logic as in _process_file_system, the last modifications dates
// needs to be trusted to prevent reading all the .import files and the md5
// each time the user switch back to Godot.
uint64_t mt = FileAccess::get_modified_time(path);
bool reimport = false;
if (mt != p_dir->files[i]->modified_time) {
reimport = true; //it was modified, must be reimported.
} else if (!FileAccess::exists(path + ".import")) {
reimport = true; //no .import file, obviously reimport
} else {
uint64_t import_mt = FileAccess::get_modified_time(path + ".import");
if (import_mt != p_dir->files[i]->import_modified_time) {
reimport = true;
} else if (_test_for_reimport(path, true)) {
reimport = true;
}
}
if (reimport) {
uint64_t import_mt = FileAccess::get_modified_time(path + ".import");
if (_is_test_for_reimport_needed(path, p_dir->files[i]->modified_time, mt, p_dir->files[i]->import_modified_time, import_mt, p_dir->files[i]->import_dest_paths)) {
ItemAction ia;
ia.action = ItemAction::ACTION_FILE_TEST_REIMPORT;
ia.dir = p_dir;
@ -1625,7 +1723,7 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir,
cache_string.append(itos(file_info->import_modified_time));
cache_string.append(itos(file_info->import_valid));
cache_string.append(file_info->import_group_file);
cache_string.append(String("<>").join({ file_info->script_class_name, file_info->script_class_extends, file_info->script_class_icon_path }));
cache_string.append(String("<>").join({ file_info->script_class_name, file_info->script_class_extends, file_info->script_class_icon_path, file_info->import_md5, String("<*>").join(file_info->import_dest_paths) }));
cache_string.append(String("<>").join(file_info->deps));
p_file->store_line(String("::").join(cache_string));
@ -2166,6 +2264,8 @@ void EditorFileSystem::update_files(const Vector<String> &p_script_paths) {
fi->file = file_name;
fi->import_modified_time = 0;
fi->import_valid = (type == "TextFile" || type == "OtherFile") ? true : ResourceLoader::is_import_valid(file);
fi->import_md5 = "";
fi->import_dest_paths = Vector<String>();
if (idx == fs->files.size()) {
fs->files.push_back(fi);
@ -2441,6 +2541,8 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
//update modified times, to avoid reimport
fs->files[cpos]->modified_time = FileAccess::get_modified_time(file);
fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(file + ".import");
fs->files[cpos]->import_md5 = FileAccess::get_md5(file + ".import");
fs->files[cpos]->import_dest_paths = dest_paths;
fs->files[cpos]->deps = _get_dependencies(file);
fs->files[cpos]->uid = uid;
fs->files[cpos]->type = importer->get_resource_type();
@ -2542,11 +2644,13 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin
if (p_update_file_system) {
fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import");
fs->files[cpos]->import_md5 = FileAccess::get_md5(p_file + ".import");
fs->files[cpos]->import_dest_paths = Vector<String>();
fs->files[cpos]->deps.clear();
fs->files[cpos]->type = "";
fs->files[cpos]->import_valid = false;
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
}
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
return OK;
}
Ref<ResourceImporter> importer;
@ -2712,6 +2816,8 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin
// Update modified times, to avoid reimport.
fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import");
fs->files[cpos]->import_md5 = FileAccess::get_md5(p_file + ".import");
fs->files[cpos]->import_dest_paths = dest_paths;
fs->files[cpos]->deps = _get_dependencies(p_file);
fs->files[cpos]->type = importer->get_resource_type();
fs->files[cpos]->uid = uid;

View file

@ -60,6 +60,8 @@ class EditorFileSystemDirectory : public Object {
ResourceUID::ID uid = ResourceUID::INVALID_ID;
uint64_t modified_time = 0;
uint64_t import_modified_time = 0;
String import_md5;
Vector<String> import_dest_paths;
bool import_valid = false;
String import_group_file;
Vector<String> deps;
@ -206,6 +208,8 @@ class EditorFileSystem : public Node {
ResourceUID::ID uid = ResourceUID::INVALID_ID;
uint64_t modification_time = 0;
uint64_t import_modification_time = 0;
String import_md5;
Vector<String> import_dest_paths;
Vector<String> deps;
bool import_valid = false;
String import_group_file;
@ -264,7 +268,9 @@ class EditorFileSystem : public Node {
Error _reimport_file(const String &p_file, const HashMap<StringName, Variant> &p_custom_options = HashMap<StringName, Variant>(), const String &p_custom_importer = String(), Variant *generator_parameters = nullptr, bool p_update_file_system = true);
Error _reimport_group(const String &p_group_file, const Vector<String> &p_files);
bool _test_for_reimport(const String &p_path, bool p_only_imported_files);
bool _test_for_reimport(const String &p_path, const String &p_expected_import_md5);
bool _is_test_for_reimport_needed(const String &p_path, uint64_t p_last_modification_time, uint64_t p_modification_time, uint64_t p_last_import_modification_time, uint64_t p_import_modification_time, const Vector<String> &p_import_dest_paths);
Vector<String> _get_import_dest_paths(const String &p_path);
bool reimport_on_missing_imported_files;

View file

@ -431,22 +431,20 @@ String ResourceImporterLayeredTexture::get_import_settings_string() const {
return s;
}
bool ResourceImporterLayeredTexture::are_import_settings_valid(const String &p_path) const {
bool ResourceImporterLayeredTexture::are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const {
//will become invalid if formats are missing to import
Dictionary meta = ResourceFormatImporter::get_singleton()->get_resource_metadata(p_path);
if (!meta.has("vram_texture")) {
if (!p_meta.has("vram_texture")) {
return false;
}
bool vram = meta["vram_texture"];
bool vram = p_meta["vram_texture"];
if (!vram) {
return true; //do not care about non vram
}
Vector<String> formats_imported;
if (meta.has("imported_formats")) {
formats_imported = meta["imported_formats"];
if (p_meta.has("imported_formats")) {
formats_imported = p_meta["imported_formats"];
}
int index = 0;

View file

@ -114,7 +114,7 @@ public:
virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
virtual bool are_import_settings_valid(const String &p_path) const override;
virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const override;
virtual String get_import_settings_string() const override;
void set_mode(Mode p_mode) { mode = p_mode; }

View file

@ -740,10 +740,8 @@ String ResourceImporterTexture::get_import_settings_string() const {
return s;
}
bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) const {
Dictionary meta = ResourceFormatImporter::get_singleton()->get_resource_metadata(p_path);
if (meta.has("has_editor_variant")) {
bool ResourceImporterTexture::are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const {
if (p_meta.has("has_editor_variant")) {
String imported_path = ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_path);
if (!FileAccess::exists(imported_path)) {
return false;
@ -760,19 +758,19 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) co
}
}
if (!meta.has("vram_texture")) {
if (!p_meta.has("vram_texture")) {
return false;
}
bool vram = meta["vram_texture"];
bool vram = p_meta["vram_texture"];
if (!vram) {
return true; // Do not care about non-VRAM.
}
// Will become invalid if formats are missing to import.
Vector<String> formats_imported;
if (meta.has("imported_formats")) {
formats_imported = meta["imported_formats"];
if (p_meta.has("imported_formats")) {
formats_imported = p_meta["imported_formats"];
}
int index = 0;

View file

@ -104,7 +104,7 @@ public:
void update_imports();
virtual bool are_import_settings_valid(const String &p_path) const override;
virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const override;
virtual String get_import_settings_string() const override;
ResourceImporterTexture(bool p_singleton = false);