From 88773e71e557b1d43afe4b31fd75754688049bc4 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 14 Sep 2025 14:25:19 +0200 Subject: [PATCH] Fix warning when cloning actor from prefab that is not a root #3578 --- Source/Engine/Level/Actor.cpp | 21 +++++++++++++++------ Source/Engine/Scripting/Scripting.cpp | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp index 0c0a98e14..b119797e7 100644 --- a/Source/Engine/Level/Actor.cpp +++ b/Source/Engine/Level/Actor.cpp @@ -1124,9 +1124,10 @@ void Actor::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) } else if (!parent && parentId.IsValid()) { + Guid tmpId; if (_prefabObjectID.IsValid()) LOG(Warning, "Missing parent actor {0} for \'{1}\', prefab object {2}", parentId, ToString(), _prefabObjectID); - else + else if (!modifier->IdsMapping.TryGet(parentId, tmpId) || tmpId.IsValid()) // Skip warning if object was mapped to empty id (intentionally ignored) LOG(Warning, "Missing parent actor {0} for \'{1}\'", parentId, ToString()); } } @@ -1694,7 +1695,7 @@ bool Actor::ToBytes(const Array& actors, MemoryWriteStream& output) } // Collect object ids that exist in the serialized data to allow references mapping later - Array ids(Math::RoundUpToPowerOf2(actors.Count() * 2)); + Array ids(actors.Count()); for (int32 i = 0; i < actors.Count(); i++) { // By default we collect actors and scripts (they are ManagedObjects recognized by the id) @@ -1997,19 +1998,27 @@ Actor* Actor::Clone() // Remap object ids into a new ones auto modifier = Cache::ISerializeModifier.Get(); - for (int32 i = 0; i < actors->Count(); i++) + for (const Actor* actor : *actors.Value) { - auto actor = actors->At(i); if (!actor) continue; modifier->IdsMapping.Add(actor->GetID(), Guid::New()); - for (int32 j = 0; j < actor->Scripts.Count(); j++) + for (const Script* script : actor->Scripts) { - const auto script = actor->Scripts[j]; if (script) modifier->IdsMapping.Add(script->GetID(), Guid::New()); } } + if (HasPrefabLink() && HasParent() && !IsPrefabRoot()) + { + // When cloning actor that is part of prefab (but not as whole), ignore the prefab hierarchy + Actor* parent = GetParent(); + do + { + modifier->IdsMapping.Add(parent->GetPrefabObjectID(), Guid::Empty); + parent = parent->GetParent(); + } while (parent && !parent->IsPrefabRoot()); + } // Deserialize objects Array output; diff --git a/Source/Engine/Scripting/Scripting.cpp b/Source/Engine/Scripting/Scripting.cpp index db6867d34..e042b4633 100644 --- a/Source/Engine/Scripting/Scripting.cpp +++ b/Source/Engine/Scripting/Scripting.cpp @@ -904,6 +904,8 @@ ScriptingObject* Scripting::FindObject(Guid id, const MClass* type) if (idsMapping) { idsMapping->TryGet(id, id); + if (!id.IsValid()) + return nullptr; // Skip warning if object was mapped to empty id (intentionally ignored) } // Try to find it