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; 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 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 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 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 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; 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; 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 { 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; PathAndType pat;
Error err = _get_path_and_type(p_path, 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 bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) 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 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 Variant get_resource_metadata(const String &p_path) const;
virtual bool is_import_valid(const String &p_path) const override; 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; 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 { ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const {
int64_t uid = ResourceUID::INVALID_ID; 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; 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 { 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)) { if (p_type.is_empty() || handles_type(p_type)) {
get_recognized_extensions(p_extensions); get_recognized_extensions(p_extensions);
@ -1159,6 +1170,21 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
return ResourceUID::INVALID_ID; 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 ResourceLoader::_path_remap(const String &p_path, bool *r_translation_remapped) {
String new_path = p_path; 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_type(const String &p_path) const;
virtual String get_resource_script_class(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 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 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 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; } 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_type(const String &p_path);
static String get_resource_script_class(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 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 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 Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map);
static bool is_import_valid(const String &p_path); static bool is_import_valid(const String &p_path);

View file

@ -57,6 +57,7 @@
<return type="int" /> <return type="int" />
<param index="0" name="path" type="String" /> <param index="0" name="path" type="String" />
<description> <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> </description>
</method> </method>
<method name="_handles_type" qualifiers="virtual const"> <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) { 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. // Update scene if it is open.
for (int i = 0; i < file_changed_paths.size(); ++i) { 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); 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); 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) { 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); Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) { 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_type(const String &p_path) const override;
virtual String get_resource_script_class(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 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 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; virtual Error rename_dependencies(const String &p_path, const HashMap<String, String> &p_map) override;