Browse Source

Add create_id_for_path() to ResourceUID

kobewi 8 tháng trước cách đây
mục cha
commit
ff1f040893

+ 23 - 0
core/io/resource_uid.cpp

@@ -35,6 +35,7 @@
 #include "core/io/dir_access.h"
 #include "core/io/dir_access.h"
 #include "core/io/file_access.h"
 #include "core/io/file_access.h"
 #include "core/io/resource_loader.h"
 #include "core/io/resource_loader.h"
+#include "core/math/random_pcg.h"
 
 
 // These constants are off by 1, causing the 'z' and '9' characters never to be used.
 // These constants are off by 1, causing the 'z' and '9' characters never to be used.
 // This cannot be fixed without breaking compatibility; see GH-83843.
 // This cannot be fixed without breaking compatibility; see GH-83843.
@@ -121,10 +122,31 @@ ResourceUID::ID ResourceUID::create_id() {
 	}
 	}
 }
 }
 
 
+ResourceUID::ID ResourceUID::create_id_for_path(const String &p_path) {
+	ID id = INVALID_ID;
+	RandomPCG rng;
+
+	const String project_name = GLOBAL_GET("application/config/name");
+	rng.seed(project_name.hash64() * p_path.hash64() * FileAccess::get_md5(p_path).hash64());
+
+	while (true) {
+		int64_t num1 = rng.rand();
+		int64_t num2 = ((int64_t)rng.rand()) << 32;
+		id = (num1 | num2) & 0x7FFFFFFFFFFFFFFF;
+
+		MutexLock lock(mutex);
+		if (!unique_ids.has(id)) {
+			break;
+		}
+	}
+	return id;
+}
+
 bool ResourceUID::has_id(ID p_id) const {
 bool ResourceUID::has_id(ID p_id) const {
 	MutexLock l(mutex);
 	MutexLock l(mutex);
 	return unique_ids.has(p_id);
 	return unique_ids.has(p_id);
 }
 }
+
 void ResourceUID::add_id(ID p_id, const String &p_path) {
 void ResourceUID::add_id(ID p_id, const String &p_path) {
 	MutexLock l(mutex);
 	MutexLock l(mutex);
 	ERR_FAIL_COND(unique_ids.has(p_id));
 	ERR_FAIL_COND(unique_ids.has(p_id));
@@ -327,6 +349,7 @@ void ResourceUID::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
 	ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
 
 
 	ClassDB::bind_method(D_METHOD("create_id"), &ResourceUID::create_id);
 	ClassDB::bind_method(D_METHOD("create_id"), &ResourceUID::create_id);
+	ClassDB::bind_method(D_METHOD("create_id_for_path", "path"), &ResourceUID::create_id_for_path);
 
 
 	ClassDB::bind_method(D_METHOD("has_id", "id"), &ResourceUID::has_id);
 	ClassDB::bind_method(D_METHOD("has_id", "id"), &ResourceUID::has_id);
 	ClassDB::bind_method(D_METHOD("add_id", "id", "path"), &ResourceUID::add_id);
 	ClassDB::bind_method(D_METHOD("add_id", "id", "path"), &ResourceUID::add_id);

+ 1 - 0
core/io/resource_uid.h

@@ -70,6 +70,7 @@ public:
 	ID text_to_id(const String &p_text) const;
 	ID text_to_id(const String &p_text) const;
 
 
 	ID create_id();
 	ID create_id();
+	ID create_id_for_path(const String &p_path);
 	bool has_id(ID p_id) const;
 	bool has_id(ID p_id) const;
 	void add_id(ID p_id, const String &p_path);
 	void add_id(ID p_id, const String &p_path);
 	void set_id(ID p_id, const String &p_path);
 	void set_id(ID p_id, const String &p_path);

+ 7 - 0
doc/classes/ResourceUID.xml

@@ -26,6 +26,13 @@
 				In order for this UID to be registered, you must call [method add_id] or [method set_id].
 				In order for this UID to be registered, you must call [method add_id] or [method set_id].
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="create_id_for_path">
+			<return type="int" />
+			<param index="0" name="path" type="String" />
+			<description>
+				Like [method create_id], but the UID is seeded with the provided [param path] and project name. UIDs generated for that path will be always the same within the current project.
+			</description>
+		</method>
 		<method name="get_id_path" qualifiers="const">
 		<method name="get_id_path" qualifiers="const">
 			<return type="String" />
 			<return type="String" />
 			<param index="0" name="id" type="int" />
 			<param index="0" name="id" type="int" />

+ 8 - 8
editor/editor_file_system.cpp

@@ -905,7 +905,7 @@ bool EditorFileSystem::_update_scan_actions() {
 				if (existing_id != ResourceUID::INVALID_ID) {
 				if (existing_id != ResourceUID::INVALID_ID) {
 					const String old_path = ResourceUID::get_singleton()->get_id_path(existing_id);
 					const String old_path = ResourceUID::get_singleton()->get_id_path(existing_id);
 					if (old_path != new_file_path && FileAccess::exists(old_path)) {
 					if (old_path != new_file_path && FileAccess::exists(old_path)) {
-						const ResourceUID::ID new_id = ResourceUID::get_singleton()->create_id();
+						const ResourceUID::ID new_id = ResourceUID::get_singleton()->create_id_for_path(new_file_path);
 						ResourceUID::get_singleton()->add_id(new_id, new_file_path);
 						ResourceUID::get_singleton()->add_id(new_id, new_file_path);
 						ResourceSaver::set_uid(new_file_path, new_id);
 						ResourceSaver::set_uid(new_file_path, new_id);
 						WARN_PRINT(vformat("Duplicate UID detected for Resource at \"%s\".\nOld Resource path: \"%s\". The new file UID was changed automatically.", new_file_path, old_path));
 						WARN_PRINT(vformat("Duplicate UID detected for Resource at \"%s\".\nOld Resource path: \"%s\". The new file UID was changed automatically.", new_file_path, old_path));
@@ -916,7 +916,7 @@ bool EditorFileSystem::_update_scan_actions() {
 				} else if (ResourceLoader::should_create_uid_file(new_file_path)) {
 				} else if (ResourceLoader::should_create_uid_file(new_file_path)) {
 					Ref<FileAccess> f = FileAccess::open(new_file_path + ".uid", FileAccess::WRITE);
 					Ref<FileAccess> f = FileAccess::open(new_file_path + ".uid", FileAccess::WRITE);
 					if (f.is_valid()) {
 					if (f.is_valid()) {
-						ia.new_file->uid = ResourceUID::get_singleton()->create_id();
+						ia.new_file->uid = ResourceUID::get_singleton()->create_id_for_path(new_file_path);
 						f->store_line(ResourceUID::get_singleton()->id_to_text(ia.new_file->uid));
 						f->store_line(ResourceUID::get_singleton()->id_to_text(ia.new_file->uid));
 					}
 					}
 				}
 				}
@@ -1353,7 +1353,7 @@ void EditorFileSystem::_process_file_system(const ScannedDirectory *p_scan_dir,
 				Ref<FileAccess> f = FileAccess::open(path + ".uid", FileAccess::WRITE);
 				Ref<FileAccess> f = FileAccess::open(path + ".uid", FileAccess::WRITE);
 				if (f.is_valid()) {
 				if (f.is_valid()) {
 					if (fi->uid == ResourceUID::INVALID_ID) {
 					if (fi->uid == ResourceUID::INVALID_ID) {
-						fi->uid = ResourceUID::get_singleton()->create_id();
+						fi->uid = ResourceUID::get_singleton()->create_id_for_path(path);
 					} else {
 					} else {
 						WARN_PRINT(vformat("Missing .uid file for path \"%s\". The file was re-created from cache.", path));
 						WARN_PRINT(vformat("Missing .uid file for path \"%s\". The file was re-created from cache.", path));
 					}
 					}
@@ -2442,7 +2442,7 @@ void EditorFileSystem::update_files(const Vector<String> &p_script_paths) {
 				if (ResourceLoader::should_create_uid_file(file)) {
 				if (ResourceLoader::should_create_uid_file(file)) {
 					Ref<FileAccess> f = FileAccess::open(file + ".uid", FileAccess::WRITE);
 					Ref<FileAccess> f = FileAccess::open(file + ".uid", FileAccess::WRITE);
 					if (f.is_valid()) {
 					if (f.is_valid()) {
-						const ResourceUID::ID id = ResourceUID::get_singleton()->create_id();
+						const ResourceUID::ID id = ResourceUID::get_singleton()->create_id_for_path(file);
 						ResourceUID::get_singleton()->add_id(id, file);
 						ResourceUID::get_singleton()->add_id(id, file);
 						f->store_line(ResourceUID::get_singleton()->id_to_text(id));
 						f->store_line(ResourceUID::get_singleton()->id_to_text(id));
 						fi->uid = id;
 						fi->uid = id;
@@ -2630,7 +2630,7 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
 			}
 			}
 
 
 			if (uid == ResourceUID::INVALID_ID) {
 			if (uid == ResourceUID::INVALID_ID) {
-				uid = ResourceUID::get_singleton()->create_id();
+				uid = ResourceUID::get_singleton()->create_id_for_path(file);
 			}
 			}
 
 
 			f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); // Store in readable format.
 			f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); // Store in readable format.
@@ -2852,7 +2852,7 @@ Error EditorFileSystem::_reimport_file(const String &p_file, const HashMap<Strin
 	}
 	}
 
 
 	if (uid == ResourceUID::INVALID_ID) {
 	if (uid == ResourceUID::INVALID_ID) {
-		uid = ResourceUID::get_singleton()->create_id();
+		uid = ResourceUID::get_singleton()->create_id_for_path(p_file);
 	}
 	}
 
 
 	//finally, perform import!!
 	//finally, perform import!!
@@ -3541,14 +3541,14 @@ ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const
 		}
 		}
 
 
 		if (p_generate) {
 		if (p_generate) {
-			return ResourceUID::get_singleton()->create_id(); // Just create a new one, we will be notified of save anyway and fetch the right UID at that time, to keep things simple.
+			return ResourceUID::get_singleton()->create_id_for_path(p_path); // Just create a new one, we will be notified of save anyway and fetch the right UID at that time, to keep things simple.
 		} else {
 		} else {
 			return ResourceUID::INVALID_ID;
 			return ResourceUID::INVALID_ID;
 		}
 		}
 	} else if (fs->files[cpos]->uid != ResourceUID::INVALID_ID) {
 	} else if (fs->files[cpos]->uid != ResourceUID::INVALID_ID) {
 		return fs->files[cpos]->uid;
 		return fs->files[cpos]->uid;
 	} else if (p_generate) {
 	} else if (p_generate) {
-		return ResourceUID::get_singleton()->create_id(); // Just create a new one, we will be notified of save anyway and fetch the right UID at that time, to keep things simple.
+		return ResourceUID::get_singleton()->create_id_for_path(p_path); // Just create a new one, we will be notified of save anyway and fetch the right UID at that time, to keep things simple.
 	} else {
 	} else {
 		return ResourceUID::INVALID_ID;
 		return ResourceUID::INVALID_ID;
 	}
 	}

+ 1 - 1
editor/import/3d/resource_importer_scene.cpp

@@ -2930,7 +2930,7 @@ static Error convert_path_to_uid(ResourceUID::ID p_source_id, const String &p_ha
 			if (ResourceUID::get_singleton()->has_id(save_id)) {
 			if (ResourceUID::get_singleton()->has_id(save_id)) {
 				if (save_path != ResourceUID::get_singleton()->get_id_path(save_id)) {
 				if (save_path != ResourceUID::get_singleton()->get_id_path(save_id)) {
 					// The user has specified a path which does not match the default UID.
 					// The user has specified a path which does not match the default UID.
-					save_id = ResourceUID::get_singleton()->create_id();
+					save_id = ResourceUID::get_singleton()->create_id_for_path(save_path);
 				}
 				}
 			}
 			}
 			p_settings[p_path_key] = ResourceUID::get_singleton()->id_to_text(save_id);
 			p_settings[p_path_key] = ResourceUID::get_singleton()->id_to_text(save_id);