diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp index 06daaab6a20c..50f8007efae5 100644 --- a/core/variant/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -1789,7 +1789,7 @@ static String rtos_fix(double p_value) { } } -Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count) { +Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count, bool p_compat) { switch (p_variant.get_type()) { case Variant::NIL: { p_store_string_func(p_store_string_ud, "null"); @@ -2009,7 +2009,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } p_store_string_func(p_store_string_ud, "\"" + E.name + "\":"); - write(obj->get(E.name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count); + write(obj->get(E.name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat); } } @@ -2035,9 +2035,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, "{\n"); for (List::Element *E = keys.front(); E; E = E->next()) { - write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count); + write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat); p_store_string_func(p_store_string_ud, ": "); - write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count); + write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat); if (E->next()) { p_store_string_func(p_store_string_ud, ",\n"); } else { @@ -2096,7 +2096,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } else { p_store_string_func(p_store_string_ud, ", "); } - write(var, p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count); + write(var, p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud, p_recursion_count, p_compat); } p_store_string_func(p_store_string_ud, "]"); @@ -2110,7 +2110,16 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str case Variant::PACKED_BYTE_ARRAY: { p_store_string_func(p_store_string_ud, "PackedByteArray("); Vector data = p_variant; - if (data.size() > 0) { + if (p_compat) { + int len = data.size(); + const uint8_t *ptr = data.ptr(); + for (int i = 0; i < len; i++) { + if (i > 0) { + p_store_string_func(p_store_string_ud, ", "); + } + p_store_string_func(p_store_string_ud, itos(ptr[i])); + } + } else if (data.size() > 0) { p_store_string_func(p_store_string_ud, "\""); p_store_string_func(p_store_string_ud, CryptoCore::b64_encode_str(data.ptr(), data.size())); p_store_string_func(p_store_string_ud, "\""); @@ -2255,8 +2264,8 @@ static Error _write_to_str(void *ud, const String &p_string) { return OK; } -Error VariantWriter::write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud) { +Error VariantWriter::write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, bool p_compat) { r_string = String(); - return write(p_variant, _write_to_str, &r_string, p_encode_res_func, p_encode_res_ud); + return write(p_variant, _write_to_str, &r_string, p_encode_res_func, p_encode_res_ud, 0, p_compat); } diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h index 2f8974849f1e..b0ac07170da5 100644 --- a/core/variant/variant_parser.h +++ b/core/variant/variant_parser.h @@ -161,8 +161,8 @@ class VariantWriter { typedef Error (*StoreStringFunc)(void *ud, const String &p_string); typedef String (*EncodeResourceFunc)(void *ud, const Ref &p_resource); - static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count = 0); - static Error write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func = nullptr, void *p_encode_res_ud = nullptr); + static Error write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud, int p_recursion_count = 0, bool p_compat = true); + static Error write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func = nullptr, void *p_encode_res_ud = nullptr, bool p_compat = true); }; #endif // VARIANT_PARSER_H diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 98a12f14006e..f70a00a9f6ac 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -40,6 +40,7 @@ // Version 2: changed names for Basis, AABB, Vectors, etc. // Version 3: new string ID for ext/subresources, breaks forward compat. // Version 4: PackedByteArray is now stored as base64 encoded. +#define FORMAT_VERSION_COMPAT 3 #define FORMAT_VERSION 4 #define BINARY_FORMAT_VERSION 4 @@ -845,7 +846,7 @@ void ResourceLoaderText::set_translation_remapped(bool p_remapped) { } ResourceLoaderText::ResourceLoaderText() : - stream(false) {} + stream(false), format_version(FORMAT_VERSION) {} void ResourceLoaderText::get_dependencies(Ref p_f, List *p_dependencies, bool p_add_types) { open(p_f); @@ -954,13 +955,13 @@ Error ResourceLoaderText::rename_dependencies(Ref p_f, const String } if (is_scene) { - fw->store_line("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + uid_text + "]\n"); + fw->store_line("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(format_version) + uid_text + "]\n"); } else { String script_res_text; if (!script_class.is_empty()) { script_res_text = "script_class=\"" + script_class + "\" "; } - fw->store_line("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + uid_text + "]\n"); + fw->store_line("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(format_version) + uid_text + "]\n"); } } @@ -1063,13 +1064,15 @@ void ResourceLoaderText::open(Ref p_f, bool p_skip_first_tag) { } if (tag.fields.has("format")) { - int fmt = tag.fields["format"]; - if (fmt > FORMAT_VERSION) { + format_version = tag.fields["format"]; + if (format_version > FORMAT_VERSION) { error_text = "Saved with newer format version"; _printerr(); error = ERR_FILE_UNRECOGNIZED; return; } + } else { + format_version = FORMAT_VERSION; } if (tag.name == "gd_scene") { @@ -1970,6 +1973,12 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, _find_resources(v); } } break; + case Variant::PACKED_BYTE_ARRAY: { + // Balance between compatibility and performance. + if (use_compat && p_variant.operator PackedByteArray().size() > 64) { + use_compat = false; + } + } break; default: { } } @@ -2005,6 +2014,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Ref 1) { title += "load_steps=" + itos(load_steps) + " "; } - title += "format=" + itos(FORMAT_VERSION) + ""; + title += "format=" + itos(use_compat ? FORMAT_VERSION_COMPAT : FORMAT_VERSION) + ""; ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(local_path, true); @@ -2223,7 +2233,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Refstore_string(name.property_name_encode() + " = " + vars + "\n"); } } @@ -2287,14 +2297,14 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Refstore_string(" instance_placeholder="); - VariantWriter::write_to_string(instance_placeholder, vars, _write_resources, this); + VariantWriter::write_to_string(instance_placeholder, vars, _write_resources, this, use_compat); f->store_string(vars); } if (instance.is_valid()) { String vars; f->store_string(" instance="); - VariantWriter::write_to_string(instance, vars, _write_resources, this); + VariantWriter::write_to_string(instance, vars, _write_resources, this, use_compat); f->store_string(vars); } @@ -2302,7 +2312,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Refget_node_property_count(i); j++) { String vars; - VariantWriter::write_to_string(state->get_node_property_value(i, j), vars, _write_resources, this); + VariantWriter::write_to_string(state->get_node_property_value(i, j), vars, _write_resources, this, use_compat); f->store_string(String(state->get_node_property_name(i, j)).property_name_encode() + " = " + vars + "\n"); } @@ -2336,7 +2346,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const Refstore_string(connstr); if (binds.size()) { String vars; - VariantWriter::write_to_string(binds, vars, _write_resources, this); + VariantWriter::write_to_string(binds, vars, _write_resources, this, use_compat); f->store_string(" binds= " + vars); } @@ -2368,14 +2378,14 @@ Error ResourceLoaderText::set_uid(Ref p_f, ResourceUID::ID p_uid) { fw = FileAccess::open(local_path + ".uidren", FileAccess::WRITE); if (is_scene) { - fw->store_string("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]"); + fw->store_string("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(format_version) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]"); } else { String script_res_text; if (!script_class.is_empty()) { script_res_text = "script_class=\"" + script_class + "\" "; } - fw->store_string("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]"); + fw->store_string("[gd_resource type=\"" + res_type + "\" " + script_res_text + "load_steps=" + itos(resources_total) + " format=" + itos(format_version) + " uid=\"" + ResourceUID::get_singleton()->id_to_text(p_uid) + "\"]"); } uint8_t c = f->get_8(); diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h index c05b7a24e15e..41363fd9754e 100644 --- a/scene/resources/resource_format_text.h +++ b/scene/resources/resource_format_text.h @@ -54,6 +54,7 @@ class ResourceLoaderText { }; bool is_scene = false; + int format_version; String res_type; bool ignore_resource_parsing = false; @@ -178,6 +179,7 @@ class ResourceFormatSaverTextInstance { List> saved_resources; HashMap, String> external_resources; HashMap, String> internal_resources; + bool use_compat = true; struct ResourceSort { Ref resource;