diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2023-01-09 23:08:18 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-01-09 23:08:18 +0100 |
commit | be4e9dfeab0cef7efb78d4ce891caed050a42b3b (patch) | |
tree | a1275192e0a72b83a5791d77b5256542362edbf3 /core/io/resource_format_binary.cpp | |
parent | fd990e24a851c83abdef581997d2f9bc16108d1c (diff) | |
parent | 07a964fce34bf72610db5d0a50c5c18adb974f97 (diff) | |
download | redot-engine-be4e9dfeab0cef7efb78d4ce891caed050a42b3b.tar.gz |
Merge pull request #69616 from reduz/change-uuid
Ability to change a resource UID from API
Diffstat (limited to 'core/io/resource_format_binary.cpp')
-rw-r--r-- | core/io/resource_format_binary.cpp | 122 |
1 files changed, 120 insertions, 2 deletions
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index ba6ad16ca8..45e1301930 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1045,10 +1045,10 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p #ifdef TOOLS_ENABLED // Silence a warning that can happen during the initial filesystem scan due to cache being regenerated. if (ResourceLoader::get_resource_uid(res_path) != er.uid) { - WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UUID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data()); + WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data()); } #else - WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UUID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data()); + WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data()); #endif } } @@ -2209,12 +2209,130 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const Ref<Re return OK; } +Error ResourceFormatSaverBinaryInstance::set_uid(const String &p_path, ResourceUID::ID p_uid) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'."); + + Ref<FileAccess> fw; + + local_path = p_path.get_base_dir(); + + uint8_t header[4]; + f->get_buffer(header, 4); + if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') { + // Compressed. + Ref<FileAccessCompressed> fac; + fac.instantiate(); + Error err = fac->open_after_magic(f); + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'."); + f = fac; + + Ref<FileAccessCompressed> facw; + facw.instantiate(); + facw->configure("RSCC"); + err = facw->open_internal(p_path + ".uidren", FileAccess::WRITE); + ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".uidren'."); + + fw = facw; + + } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') { + // Not a binary resource. + return ERR_FILE_UNRECOGNIZED; + } else { + fw = FileAccess::open(p_path + ".uidren", FileAccess::WRITE); + ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".uidren'."); + + uint8_t magich[4] = { 'R', 'S', 'R', 'C' }; + fw->store_buffer(magich, 4); + } + + big_endian = f->get_32(); + bool use_real64 = f->get_32(); + f->set_big_endian(big_endian != 0); //read big endian if saved as big endian +#ifdef BIG_ENDIAN_ENABLED + fw->store_32(!big_endian); +#else + fw->store_32(big_endian); +#endif + fw->set_big_endian(big_endian != 0); + fw->store_32(use_real64); //use real64 + + uint32_t ver_major = f->get_32(); + uint32_t ver_minor = f->get_32(); + uint32_t ver_format = f->get_32(); + + if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) { + fw.unref(); + + { + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + da->remove(p_path + ".uidren"); + } + + // Use the old approach. + + WARN_PRINT("This file is old, so it does not support UIDs, opening and resaving '" + p_path + "'."); + return ERR_UNAVAILABLE; + } + + if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) { + ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, + vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).", + local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH)); + } + + // Since we're not actually converting the file contents, leave the version + // numbers in the file untouched. + fw->store_32(ver_major); + fw->store_32(ver_minor); + fw->store_32(ver_format); + + save_ustring(fw, get_ustring(f)); //type + + fw->store_64(f->get_64()); //metadata offset + + uint32_t flags = f->get_32(); + flags |= ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS; + f->get_64(); // Skip previous UID + + fw->store_32(flags); + fw->store_64(p_uid); + + //rest of file + uint8_t b = f->get_8(); + while (!f->eof_reached()) { + fw->store_8(b); + b = f->get_8(); + } + + f.unref(); + + bool all_ok = fw->get_error() == OK; + + if (!all_ok) { + return ERR_CANT_CREATE; + } + + fw.unref(); + + Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + da->remove(p_path); + da->rename(p_path + ".uidren", p_path); + return OK; +} + Error ResourceFormatSaverBinary::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { String local_path = ProjectSettings::get_singleton()->localize_path(p_path); ResourceFormatSaverBinaryInstance saver; return saver.save(local_path, p_resource, p_flags); } +Error ResourceFormatSaverBinary::set_uid(const String &p_path, ResourceUID::ID p_uid) { + String local_path = ProjectSettings::get_singleton()->localize_path(p_path); + ResourceFormatSaverBinaryInstance saver; + return saver.set_uid(local_path, p_uid); +} + bool ResourceFormatSaverBinary::recognize(const Ref<Resource> &p_resource) const { return true; //all recognized } |