Make internal unique scene resource ID deterministic
Changes the Resource::generate_scene_unique_id() to be deterministic and seedable. Fixes #97110
This commit is contained in:
parent
d5aadc38b4
commit
abf9d24520
4 changed files with 27 additions and 11 deletions
|
@ -99,31 +99,42 @@ void Resource::set_path_cache(const String &p_path) {
|
||||||
GDVIRTUAL_CALL(_set_path_cache, p_path);
|
GDVIRTUAL_CALL(_set_path_cache, p_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static thread_local RandomPCG unique_id_gen(0, RandomPCG::DEFAULT_INC);
|
||||||
|
|
||||||
|
void Resource::seed_scene_unique_id(uint32_t p_seed) {
|
||||||
|
unique_id_gen.seed(p_seed);
|
||||||
|
}
|
||||||
|
|
||||||
String Resource::generate_scene_unique_id() {
|
String Resource::generate_scene_unique_id() {
|
||||||
// Generate a unique enough hash, but still user-readable.
|
// Generate a unique enough hash, but still user-readable.
|
||||||
// If it's not unique it does not matter because the saver will try again.
|
// If it's not unique it does not matter because the saver will try again.
|
||||||
OS::DateTime dt = OS::get_singleton()->get_datetime();
|
if (unique_id_gen.get_seed() == 0) {
|
||||||
uint32_t hash = hash_murmur3_one_32(OS::get_singleton()->get_ticks_usec());
|
OS::DateTime dt = OS::get_singleton()->get_datetime();
|
||||||
hash = hash_murmur3_one_32(dt.year, hash);
|
uint32_t hash = hash_murmur3_one_32(OS::get_singleton()->get_ticks_usec());
|
||||||
hash = hash_murmur3_one_32(dt.month, hash);
|
hash = hash_murmur3_one_32(dt.year, hash);
|
||||||
hash = hash_murmur3_one_32(dt.day, hash);
|
hash = hash_murmur3_one_32(dt.month, hash);
|
||||||
hash = hash_murmur3_one_32(dt.hour, hash);
|
hash = hash_murmur3_one_32(dt.day, hash);
|
||||||
hash = hash_murmur3_one_32(dt.minute, hash);
|
hash = hash_murmur3_one_32(dt.hour, hash);
|
||||||
hash = hash_murmur3_one_32(dt.second, hash);
|
hash = hash_murmur3_one_32(dt.minute, hash);
|
||||||
hash = hash_murmur3_one_32(Math::rand(), hash);
|
hash = hash_murmur3_one_32(dt.second, hash);
|
||||||
|
hash = hash_murmur3_one_32(Math::rand(), hash);
|
||||||
|
unique_id_gen.seed(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t random_num = unique_id_gen.rand();
|
||||||
|
|
||||||
static constexpr uint32_t characters = 5;
|
static constexpr uint32_t characters = 5;
|
||||||
static constexpr uint32_t char_count = ('z' - 'a');
|
static constexpr uint32_t char_count = ('z' - 'a');
|
||||||
static constexpr uint32_t base = char_count + ('9' - '0');
|
static constexpr uint32_t base = char_count + ('9' - '0');
|
||||||
String id;
|
String id;
|
||||||
for (uint32_t i = 0; i < characters; i++) {
|
for (uint32_t i = 0; i < characters; i++) {
|
||||||
uint32_t c = hash % base;
|
uint32_t c = random_num % base;
|
||||||
if (c < char_count) {
|
if (c < char_count) {
|
||||||
id += String::chr('a' + c);
|
id += String::chr('a' + c);
|
||||||
} else {
|
} else {
|
||||||
id += String::chr('0' + (c - char_count));
|
id += String::chr('0' + (c - char_count));
|
||||||
}
|
}
|
||||||
hash /= base;
|
random_num /= base;
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
|
|
@ -114,6 +114,7 @@ public:
|
||||||
virtual void set_path_cache(const String &p_path); // Set raw path without involving resource cache.
|
virtual void set_path_cache(const String &p_path); // Set raw path without involving resource cache.
|
||||||
_FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.contains("::") || path_cache.begins_with("local://"); }
|
_FORCE_INLINE_ bool is_built_in() const { return path_cache.is_empty() || path_cache.contains("::") || path_cache.begins_with("local://"); }
|
||||||
|
|
||||||
|
static void seed_scene_unique_id(uint32_t p_seed);
|
||||||
static String generate_scene_unique_id();
|
static String generate_scene_unique_id();
|
||||||
void set_scene_unique_id(const String &p_id);
|
void set_scene_unique_id(const String &p_id);
|
||||||
String get_scene_unique_id() const;
|
String get_scene_unique_id() const;
|
||||||
|
|
|
@ -2136,6 +2136,8 @@ static String _resource_get_class(Ref<Resource> p_resource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
|
Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
|
||||||
|
Resource::seed_scene_unique_id(p_path.hash());
|
||||||
|
|
||||||
Error err;
|
Error err;
|
||||||
Ref<FileAccess> f;
|
Ref<FileAccess> f;
|
||||||
if (p_flags & ResourceSaver::FLAG_COMPRESS) {
|
if (p_flags & ResourceSaver::FLAG_COMPRESS) {
|
||||||
|
|
|
@ -1708,6 +1708,8 @@ static String _resource_get_class(Ref<Resource> p_resource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
|
Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref<Resource> &p_resource, uint32_t p_flags) {
|
||||||
|
Resource::seed_scene_unique_id(p_path.hash()); // Seeding for save path should make it deterministic for importers.
|
||||||
|
|
||||||
if (p_path.ends_with(".tscn")) {
|
if (p_path.ends_with(".tscn")) {
|
||||||
packed_scene = p_resource;
|
packed_scene = p_resource;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue