diff options
author | reduz <reduzio@gmail.com> | 2021-07-20 21:36:56 -0300 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2021-07-22 19:37:47 +0200 |
commit | 75755beeee44c6e3807854d7dbb6a192f7183898 (patch) | |
tree | 21a90d5cd6d97191efb4f778a2ebba1aa47e4441 /core/io/resource_format_binary.cpp | |
parent | 5de991d57c44d68221c68cf4996831a3b6a3e9e1 (diff) | |
download | redot-engine-75755beeee44c6e3807854d7dbb6a192f7183898.tar.gz |
Implement textual ext/subresource IDs.
* Friendlier with version control.
* Generates pseudo unique IDs, to minimize conflicts when merging, but still
user readable (so, not UUID).
* Eventually will also allow to have more precisely named sub-resources in
imported files.
* This will allow better reloading on changes (including resources already
loaded) as well as better keeping track of changes on the DCC.
* Keeps backward compatibility with the old formats.
* Binary and text format version incremented to mark breakage in forward
compatibility.
Diffstat (limited to 'core/io/resource_format_binary.cpp')
-rw-r--r-- | core/io/resource_format_binary.cpp | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 0e9815245f..e889586afc 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -84,9 +84,10 @@ enum { OBJECT_EXTERNAL_RESOURCE = 1, OBJECT_INTERNAL_RESOURCE = 2, OBJECT_EXTERNAL_RESOURCE_INDEX = 3, - //version 2: added 64 bits support for float and int - //version 3: changed nodepath encoding - FORMAT_VERSION = 3, + // Version 2: added 64 bits support for float and int. + // Version 3: changed nodepath encoding. + // Version 4: new string ID for ext/subresources, breaks forward compat. + FORMAT_VERSION = 4, FORMAT_VERSION_CAN_RENAME_DEPS = 1, FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3, }; @@ -311,7 +312,14 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case OBJECT_INTERNAL_RESOURCE: { uint32_t index = f->get_32(); - String path = res_path + "::" + itos(index); + String path; + + if (using_named_scene_ids) { // New format. + ERR_FAIL_INDEX_V((int)index, internal_resources.size(), ERR_PARSE_ERROR); + path = internal_resources[index].path; + } else { + path += res_path + "::" + itos(index); + } //always use internal cache for loading internal resources if (!internal_index_cache.has(path)) { @@ -320,7 +328,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } else { r_v = internal_index_cache[path]; } - } break; case OBJECT_EXTERNAL_RESOURCE: { //old file format, still around for compatibility @@ -378,7 +385,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { ERR_FAIL_V(ERR_FILE_CORRUPT); } break; } - } break; case VARIANT_CALLABLE: { r_v = Callable(); @@ -659,15 +665,17 @@ Error ResourceLoaderBinary::load() { //maybe it is loaded already String path; - int subindex = 0; + String id; if (!main) { path = internal_resources[i].path; if (path.begins_with("local://")) { path = path.replace_first("local://", ""); - subindex = path.to_int(); + id = path; path = res_path + "::" + path; + + internal_resources.write[i].path = path; // Update path. } if (cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE) { @@ -722,7 +730,7 @@ Error ResourceLoaderBinary::load() { if (path != String() && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) { r->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); //if got here because the resource with same path has different type, replace it } - r->set_subindex(subindex); + r->set_scene_unique_id(id); } if (!main) { @@ -879,7 +887,11 @@ void ResourceLoaderBinary::open(FileAccess *p_f) { print_bl("type: " + type); importmd_ofs = f->get_64(); - for (int i = 0; i < 14; i++) { + uint32_t flags = f->get_32(); + if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_NAMED_SCENE_IDS) { + using_named_scene_ids = true; + } + for (int i = 0; i < 13; i++) { f->get_32(); //skip a few reserved fields } @@ -1269,11 +1281,7 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes) } } -void ResourceFormatSaverBinaryInstance::_write_variant(const Variant &p_property, const PropertyInfo &p_hint) { - write_variant(f, p_property, resource_set, external_resources, string_map, p_hint); -} - -void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) { +void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) { switch (p_property.get_type()) { case Variant::NIL: { f->store_32(VARIANT_NIL); @@ -1492,13 +1500,13 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX); f->store_32(external_resources[res]); } else { - if (!resource_set.has(res)) { + if (!resource_map.has(res)) { f->store_32(OBJECT_EMPTY); ERR_FAIL_MSG("Resource was not pre cached for the resource section, most likely due to circular reference."); } f->store_32(OBJECT_INTERNAL_RESOURCE); - f->store_32(res->get_subindex()); + f->store_32(resource_map[res]); //internal resource } @@ -1526,8 +1534,8 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia continue; */ - write_variant(f, E->get(), resource_set, external_resources, string_map); - write_variant(f, d[E->get()], resource_set, external_resources, string_map); + write_variant(f, E->get(), resource_map, external_resources, string_map); + write_variant(f, d[E->get()], resource_map, external_resources, string_map); } } break; @@ -1536,7 +1544,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia Array a = p_property; f->store_32(uint32_t(a.size())); for (int i = 0; i < a.size(); i++) { - write_variant(f, a[i], resource_set, external_resources, string_map); + write_variant(f, a[i], resource_map, external_resources, string_map); } } break; @@ -1816,7 +1824,8 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p save_unicode_string(f, p_resource->get_class()); f->store_64(0); //offset to import metadata - for (int i = 0; i < 14; i++) { + f->store_32(FORMAT_FLAG_NAMED_SCENE_IDS); + for (int i = 0; i < 13; i++) { f->store_32(0); // reserved } @@ -1886,37 +1895,43 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p // save internal resource table f->store_32(saved_resources.size()); //amount of internal resources Vector<uint64_t> ofs_pos; - Set<int> used_indices; + Set<String> used_unique_ids; for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { RES r = E->get(); if (r->get_path() == "" || r->get_path().find("::") != -1) { - if (r->get_subindex() != 0) { - if (used_indices.has(r->get_subindex())) { - r->set_subindex(0); //repeated + if (r->get_scene_unique_id() != "") { + if (used_unique_ids.has(r->get_scene_unique_id())) { + r->set_scene_unique_id(""); } else { - used_indices.insert(r->get_subindex()); + used_unique_ids.insert(r->get_scene_unique_id()); } } } } + Map<RES, int> resource_map; + int res_index = 0; for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { RES r = E->get(); if (r->get_path() == "" || r->get_path().find("::") != -1) { - if (r->get_subindex() == 0) { - int new_subindex = 1; - if (used_indices.size()) { - new_subindex = used_indices.back()->get() + 1; + if (r->get_scene_unique_id() == "") { + String new_id; + + while (true) { + new_id = r->get_class() + "_" + Resource::generate_scene_unique_id(); + if (!used_unique_ids.has(new_id)) { + break; + } } - r->set_subindex(new_subindex); - used_indices.insert(new_subindex); + r->set_scene_unique_id(new_id); + used_unique_ids.insert(new_id); } - save_unicode_string(f, "local://" + itos(r->get_subindex())); + save_unicode_string(f, "local://" + r->get_scene_unique_id()); if (takeover_paths) { - r->set_path(p_path + "::" + itos(r->get_subindex()), true); + r->set_path(p_path + "::" + r->get_scene_unique_id(), true); } #ifdef TOOLS_ENABLED r->set_edited(false); @@ -1926,6 +1941,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p } ofs_pos.push_back(f->get_position()); f->store_64(0); //offset in 64 bits + resource_map[r] = res_index++; } Vector<uint64_t> ofs_table; @@ -1941,7 +1957,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p for (List<Property>::Element *F = rd.properties.front(); F; F = F->next()) { Property &p = F->get(); f->store_32(p.name_idx); - _write_variant(p.value, F->get().pi); + write_variant(f, p.value, resource_map, external_resources, string_map, F->get().pi); } } |