Add support for loading prefab instance if the root was changed or deleted
#2050
This commit is contained in:
@@ -94,8 +94,8 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
||||
LOG(Warning, "Waiting for prefab asset be loaded failed. {0}", prefab->ToString());
|
||||
return nullptr;
|
||||
}
|
||||
const int32 objectsCount = prefab->ObjectsCount;
|
||||
if (objectsCount == 0)
|
||||
const int32 dataCount = prefab->ObjectsCount;
|
||||
if (dataCount == 0)
|
||||
{
|
||||
LOG(Warning, "Prefab has no objects. {0}", prefab->ToString());
|
||||
return nullptr;
|
||||
@@ -107,7 +107,7 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
||||
|
||||
// Prepare
|
||||
CollectionPoolCache<ActorsCache::SceneObjectsListType>::ScopeCache sceneObjects = ActorsCache::SceneObjectsListCache.Get();
|
||||
sceneObjects->Resize(objectsCount);
|
||||
sceneObjects->Resize(dataCount);
|
||||
CollectionPoolCache<ISerializeModifier, Cache::ISerializeModifierClearCallback>::ScopeCache modifier = Cache::ISerializeModifier.Get();
|
||||
modifier->EngineBuild = prefab->DataEngineBuild;
|
||||
modifier->IdsMapping.EnsureCapacity(prefab->ObjectsIds.Count() * 4);
|
||||
@@ -126,7 +126,7 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
||||
// Deserialize prefab objects
|
||||
auto prevIdMapping = Scripting::ObjectsLookupIdMapping.Get();
|
||||
Scripting::ObjectsLookupIdMapping.Set(&modifier.Value->IdsMapping);
|
||||
for (int32 i = 0; i < objectsCount; i++)
|
||||
for (int32 i = 0; i < dataCount; i++)
|
||||
{
|
||||
auto& stream = data[i];
|
||||
SceneObject* obj = SceneObjectsFactory::Spawn(context, stream);
|
||||
@@ -145,7 +145,7 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
||||
SceneObjectsFactory::SynchronizeNewPrefabInstances(context, prefabSyncData);
|
||||
Scripting::ObjectsLookupIdMapping.Set(&modifier.Value->IdsMapping);
|
||||
}
|
||||
for (int32 i = 0; i < objectsCount; i++)
|
||||
for (int32 i = 0; i < dataCount; i++)
|
||||
{
|
||||
auto& stream = data[i];
|
||||
SceneObject* obj = sceneObjects->At(i);
|
||||
@@ -154,20 +154,29 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
||||
}
|
||||
Scripting::ObjectsLookupIdMapping.Set(prevIdMapping);
|
||||
|
||||
// Pick prefab root object
|
||||
if (sceneObjects->IsEmpty())
|
||||
// Synchronize prefab instances (prefab may have new objects added or some removed so deserialized instances need to synchronize with it)
|
||||
if (withSynchronization)
|
||||
{
|
||||
LOG(Warning, "No valid objects in prefab. {0}", prefab->ToString());
|
||||
return nullptr;
|
||||
// TODO: resave and force sync scenes during game cooking so this step could be skipped in game
|
||||
SceneObjectsFactory::SynchronizePrefabInstances(context, prefabSyncData);
|
||||
}
|
||||
|
||||
// Pick prefab root object
|
||||
Actor* root = nullptr;
|
||||
const Guid prefabRootObjectId = prefab->GetRootObjectId();
|
||||
for (int32 i = 0; i < objectsCount; i++)
|
||||
for (int32 i = 0; i < dataCount && !root; i++)
|
||||
{
|
||||
if (JsonTools::GetGuid(data[i], "ID") == prefabRootObjectId)
|
||||
{
|
||||
root = dynamic_cast<Actor*>(sceneObjects->At(i));
|
||||
break;
|
||||
}
|
||||
if (!root)
|
||||
{
|
||||
// Fallback to the first actor that has no parent
|
||||
for (int32 i = 0; i < sceneObjects->Count() && !root; i++)
|
||||
{
|
||||
SceneObject* obj = sceneObjects->At(i);
|
||||
if (obj && !obj->GetParent())
|
||||
root = dynamic_cast<Actor*>(obj);
|
||||
}
|
||||
}
|
||||
if (!root)
|
||||
@@ -176,13 +185,6 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Synchronize prefab instances (prefab may have new objects added or some removed so deserialized instances need to synchronize with it)
|
||||
if (withSynchronization)
|
||||
{
|
||||
// TODO: resave and force sync scenes during game cooking so this step could be skipped in game
|
||||
SceneObjectsFactory::SynchronizePrefabInstances(context, prefabSyncData);
|
||||
}
|
||||
|
||||
// Prepare parent linkage for prefab root actor
|
||||
if (root->_parent)
|
||||
root->_parent->Children.Remove(root);
|
||||
@@ -264,7 +266,7 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
||||
}
|
||||
|
||||
// Link objects to prefab (only deserialized from prefab data)
|
||||
for (int32 i = 0; i < objectsCount; i++)
|
||||
for (int32 i = 0; i < dataCount; i++)
|
||||
{
|
||||
auto& stream = data[i];
|
||||
SceneObject* obj = sceneObjects->At(i);
|
||||
|
||||
Reference in New Issue
Block a user