From 8f49a492d8477c03c1ad0f1f6f89996e6fb0ad86 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 4 Jun 2025 23:49:19 +0200 Subject: [PATCH] Fix duplicating json assets to properly remap object IDs #3441 --- .../Content/Storage/JsonStorageProxy.cpp | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/Source/Engine/Content/Storage/JsonStorageProxy.cpp b/Source/Engine/Content/Storage/JsonStorageProxy.cpp index af19c67c0..3d837e61a 100644 --- a/Source/Engine/Content/Storage/JsonStorageProxy.cpp +++ b/Source/Engine/Content/Storage/JsonStorageProxy.cpp @@ -9,6 +9,10 @@ #include "Engine/Level/Types.h" #include "Engine/Debug/Exceptions/JsonParseException.h" #include "Engine/Profiler/ProfilerCPU.h" +#if USE_EDITOR +#include "Engine/Core/Collections/HashSet.h" +#include "Engine/Core/Collections/Dictionary.h" +#endif #include bool JsonStorageProxy::IsValidExtension(const StringView& extension) @@ -56,27 +60,31 @@ bool JsonStorageProxy::GetAssetInfo(const StringView& path, Guid& resultId, Stri #if USE_EDITOR -void ChangeIds(rapidjson_flax::Value& obj, rapidjson_flax::Document& document, const StringAnsi& srcId, const StringAnsi& dstId) +void FindObjectIds(const rapidjson_flax::Value& obj, const rapidjson_flax::Document& document, HashSet& ids, const char* parentName = nullptr) { if (obj.IsObject()) { - for (rapidjson_flax::Value::MemberIterator i = obj.MemberBegin(); i != obj.MemberEnd(); ++i) + for (rapidjson_flax::Value::ConstMemberIterator i = obj.MemberBegin(); i != obj.MemberEnd(); ++i) { - ChangeIds(i->value, document, srcId, dstId); + FindObjectIds(i->value, document, ids, i->name.GetString()); } } else if (obj.IsArray()) { for (rapidjson::SizeType i = 0; i < obj.Size(); i++) { - ChangeIds(obj[i], document, srcId, dstId); + FindObjectIds(obj[i], document, ids, parentName); } } - else if (obj.IsString()) + else if (obj.IsString() && obj.GetStringLength() == 32) { - if (StringUtils::Compare(srcId.Get(), obj.GetString()) == 0) + if (parentName && StringUtils::Compare(parentName, "ID") == 0) { - obj.SetString(dstId.Get(), document.GetAllocator()); + auto value = JsonTools::GetGuid(obj); + if (value.IsValid()) + { + ids.Add(value); + } } } } @@ -91,9 +99,7 @@ bool JsonStorageProxy::ChangeId(const StringView& path, const Guid& newId) // Load file Array fileData; if (File::ReadAllBytes(path, fileData)) - { return false; - } // Parse data rapidjson_flax::Document document; @@ -107,33 +113,35 @@ bool JsonStorageProxy::ChangeId(const StringView& path, const Guid& newId) return false; } - // Try get asset metadata + // Get all IDs inside the file + HashSet ids; + FindObjectIds(document, document, ids); + + // Remap into a unique IDs + Dictionary remap; + remap.EnsureCapacity(ids.Count()); + for (const auto& id : ids) + remap.Add(id.Item, Guid::New()); + + // Remap asset ID using the provided value auto idNode = document.FindMember("ID"); if (idNode == document.MemberEnd()) - { return true; - } + remap[JsonTools::GetGuid(idNode->value)] = newId; - // Change IDs - auto oldIdStr = idNode->value.GetString(); - auto newIdStr = newId.ToString(Guid::FormatType::N).ToStringAnsi(); - ChangeIds(document, document, oldIdStr, newIdStr); + // Change IDs of asset and objects inside asset + JsonTools::ChangeIds(document, remap); // Save to file rapidjson_flax::StringBuffer buffer; PrettyJsonWriter writer(buffer); document.Accept(writer.GetWriter()); if (File::WriteAllBytes(path, (byte*)buffer.GetString(), (int32)buffer.GetSize())) - { return true; - } return false; - #else - LOG(Warning, "Editing cooked content is invalid."); return true; - #endif }