Universalize UID support in all resource types

Ensures all resource types support UIDs in a project.

This is required to fix:
* Scripts and many other resource types can't be referenced by UID and when refactored the references are lost.
* Path export properties can't use UID for unsupported types.
* Refactoring problems when files are moved outside the editor (this PR effectively fixes it).
* Editor properly refreshing paths if they changed externally while opened (as example, git update).
  This needs to be addressed in a subsequent PR, but this one effectively sets the prerequisites.

Resource types that do not support UID will get a .uid file appended to them (this includes .gd, .gdshader, .gdextension, etc. files).
This commit is contained in:
Juan 2024-09-23 10:42:18 +02:00 committed by Rémi Verschelde
parent 0f5f3bc954
commit d57846087b
No known key found for this signature in database
GPG Key ID: C3336907360768E1
11 changed files with 61 additions and 1 deletions

View File

@ -1577,6 +1577,10 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat
return loader.uid;
}
bool ResourceFormatLoaderBinary::has_custom_uid_support() const {
return true;
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////

View File

@ -118,6 +118,7 @@ public:
virtual String get_resource_script_class(const String &p_path) const override;
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const override;
virtual bool has_custom_uid_support() const override;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override;
virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) override;
};

View File

@ -387,6 +387,10 @@ ResourceUID::ID ResourceFormatImporter::get_resource_uid(const String &p_path) c
return pat.uid;
}
bool ResourceFormatImporter::has_custom_uid_support() const {
return true;
}
Error ResourceFormatImporter::get_resource_import_info(const String &p_path, StringName &r_type, ResourceUID::ID &r_uid, String &r_import_group_file) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);

View File

@ -70,6 +70,7 @@ public:
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const override;
virtual bool has_custom_uid_support() const override;
virtual Variant get_resource_metadata(const String &p_path) const;
virtual bool is_import_valid(const String &p_path) const override;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override;

View File

@ -112,10 +112,21 @@ String ResourceFormatLoader::get_resource_script_class(const String &p_path) con
ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const {
int64_t uid = ResourceUID::INVALID_ID;
GDVIRTUAL_CALL(_get_resource_uid, p_path, uid);
if (has_custom_uid_support()) {
GDVIRTUAL_CALL(_get_resource_uid, p_path, uid);
} else {
Ref<FileAccess> file = FileAccess::open(p_path + ".uid", FileAccess::READ);
if (file.is_valid()) {
uid = ResourceUID::get_singleton()->text_to_id(file->get_line());
}
}
return uid;
}
bool ResourceFormatLoader::has_custom_uid_support() const {
return GDVIRTUAL_IS_OVERRIDDEN(_get_resource_uid);
}
void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
if (p_type.is_empty() || handles_type(p_type)) {
get_recognized_extensions(p_extensions);
@ -1159,6 +1170,21 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
return ResourceUID::INVALID_ID;
}
bool ResourceLoader::has_custom_uid_support(const String &p_path) {
String local_path = _validate_local_path(p_path);
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) {
continue;
}
if (loader[i]->has_custom_uid_support()) {
return true;
}
}
return false;
}
String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_remapped) {
String new_path = p_path;

View File

@ -81,6 +81,7 @@ public:
virtual String get_resource_type(const String &p_path) const;
virtual String get_resource_script_class(const String &p_path) const;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual bool has_custom_uid_support() const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);
virtual bool is_import_valid(const String &p_path) const { return true; }
@ -238,6 +239,7 @@ public:
static String get_resource_type(const String &p_path);
static String get_resource_script_class(const String &p_path);
static ResourceUID::ID get_resource_uid(const String &p_path);
static bool has_custom_uid_support(const String &p_path);
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);
static bool is_import_valid(const String &p_path);

View File

@ -57,6 +57,7 @@
<return type="int" />
<param index="0" name="path" type="String" />
<description>
Should return the unique ID for the resource associated with the given path. If this method is not overridden, a [code].uid[/code] file is generated along with the resource file, containing the unique ID.
</description>
</method>
<method name="_handles_type" qualifiers="virtual const">

View File

@ -1259,6 +1259,15 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
}
}
}
if (fi->uid == ResourceUID::INVALID_ID && ResourceLoader::exists(path) && !ResourceLoader::has_custom_uid_support(path) && !FileAccess::exists(path + ".uid")) {
// Create a UID.
Ref<FileAccess> f = FileAccess::open(path + ".uid", FileAccess::WRITE);
if (f.is_valid()) {
fi->uid = ResourceUID::get_singleton()->create_id();
f->store_line(ResourceUID::get_singleton()->id_to_text(fi->uid));
}
}
}
if (fi->uid != ResourceUID::INVALID_ID) {

View File

@ -1446,6 +1446,13 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
}
}
if (p_item.is_file && FileAccess::exists(old_path + ".uid")) {
err = da->rename(old_path + ".uid", new_path + ".uid");
if (err != OK) {
EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + ".uid\n");
}
}
// Update scene if it is open.
for (int i = 0; i < file_changed_paths.size(); ++i) {
String new_item_path = p_item.is_file ? new_path : file_changed_paths[i].replace_first(old_path, new_path);

View File

@ -1526,6 +1526,10 @@ ResourceUID::ID ResourceFormatLoaderText::get_resource_uid(const String &p_path)
return loader.get_uid(f);
}
bool ResourceFormatLoaderText::has_custom_uid_support() const {
return true;
}
void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) {

View File

@ -155,6 +155,7 @@ public:
virtual String get_resource_type(const String &p_path) const override;
virtual String get_resource_script_class(const String &p_path) const override;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const override;
virtual bool has_custom_uid_support() const override;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false) override;
virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) override;