Fixed existing spawnable unit tests to work with entity alias changes.

Signed-off-by: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com>
This commit is contained in:
AMZN-koppersr
2021-10-26 13:33:02 -07:00
parent 15ea380d39
commit 66df146554
2 changed files with 43 additions and 63 deletions
@@ -303,18 +303,11 @@ namespace AzFramework
AZ::Entity* SpawnableEntitiesManager::CloneSingleEntity(const AZ::Entity& entityTemplate, AZ::Entity* SpawnableEntitiesManager::CloneSingleEntity(const AZ::Entity& entityTemplate,
EntityIdMap& templateToCloneMap, AZ::SerializeContext& serializeContext) EntityIdMap& templateToCloneMap, AZ::SerializeContext& serializeContext)
{ {
if (!entityTemplate.GetComponents().empty()) // If the same ID gets remapped more than once, preserve the original remapping instead of overwriting it.
{ constexpr bool allowDuplicateIds = false;
// If the same ID gets remapped more than once, preserve the original remapping instead of overwriting it.
constexpr bool allowDuplicateIds = false;
return AZ::IdUtils::Remapper<AZ::EntityId, allowDuplicateIds>::CloneObjectAndGenerateNewIdsAndFixRefs( return AZ::IdUtils::Remapper<AZ::EntityId, allowDuplicateIds>::CloneObjectAndGenerateNewIdsAndFixRefs(
&entityTemplate, templateToCloneMap, &serializeContext); &entityTemplate, templateToCloneMap, &serializeContext);
}
else
{
return nullptr;
}
} }
AZ::Entity* SpawnableEntitiesManager::CloneSingleAliasedEntity( AZ::Entity* SpawnableEntitiesManager::CloneSingleAliasedEntity(
@@ -468,9 +461,8 @@ namespace AzFramework
if (aliasIt == aliasEnd || aliasIt->m_sourceIndex != i) if (aliasIt == aliasEnd || aliasIt->m_sourceIndex != i)
{ {
AZ::Entity* clone = spawnedEntities.emplace_back(
CloneSingleEntity(*entitiesToSpawn[i], ticket.m_entityIdReferenceMap, *request.m_serializeContext); CloneSingleEntity(*entitiesToSpawn[i], ticket.m_entityIdReferenceMap, *request.m_serializeContext));
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(i); spawnedEntityIndices.push_back(i);
} }
else else
@@ -483,21 +475,9 @@ namespace AzFramework
AZ::Entity* clone = CloneSingleAliasedEntity( AZ::Entity* clone = CloneSingleAliasedEntity(
*entitiesToSpawn[i], *aliasIt, ticket.m_entityIdReferenceMap, previousEntity, *entitiesToSpawn[i], *aliasIt, ticket.m_entityIdReferenceMap, previousEntity,
*request.m_serializeContext); *request.m_serializeContext);
// Not all alias operations create a new instance. It's also possible for an empty entity to be left behind, previousEntity = clone;
// in which case it's also filtered out as the entity component framework doesn't handle these gracefully. spawnedEntities.emplace_back(clone);
if (clone) spawnedEntityIndices.push_back(i);
{
if (!clone->GetComponents().empty())
{
previousEntity = clone;
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(i);
}
else
{
delete clone;
}
}
++aliasIt; ++aliasIt;
} while (aliasIt != aliasEnd && aliasIt->m_sourceIndex == i); } while (aliasIt != aliasEnd && aliasIt->m_sourceIndex == i);
} }
@@ -519,8 +499,13 @@ namespace AzFramework
// Add to the game context, now the entities are active // Add to the game context, now the entities are active
for (auto it = newEntitiesBegin; it != newEntitiesEnd; ++it) for (auto it = newEntitiesBegin; it != newEntitiesEnd; ++it)
{ {
(*it)->SetSpawnTicketId(request.m_ticketId); AZ::Entity* clone = (*it);
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it); // The entity component framework doesn't handle entities without TransformComponent safely.
if (!clone->GetComponents().empty())
{
clone->SetSpawnTicketId(request.m_ticketId);
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
}
} }
// Let other systems know about newly spawned entities for any post-processing after adding to the scene/game context. // Let other systems know about newly spawned entities for any post-processing after adding to the scene/game context.
@@ -585,10 +570,8 @@ namespace AzFramework
RefreshEntityIdMapping( RefreshEntityIdMapping(
entitiesToSpawn[index].get()->GetId(), ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned); entitiesToSpawn[index].get()->GetId(), ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
AZ::Entity* clone = spawnedEntities.push_back(
CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext); CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext));
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
spawnedEntities.push_back(clone);
spawnedEntityIndices.push_back(index); spawnedEntityIndices.push_back(index);
} }
} }
@@ -612,9 +595,8 @@ namespace AzFramework
if (aliasIt == aliasEnd) if (aliasIt == aliasEnd)
{ {
AZ::Entity* clone = spawnedEntities.emplace_back(
CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext); CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext));
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(index); spawnedEntityIndices.push_back(index);
} }
else else
@@ -627,22 +609,10 @@ namespace AzFramework
AZ::Entity* clone = CloneSingleAliasedEntity( AZ::Entity* clone = CloneSingleAliasedEntity(
*entitiesToSpawn[index], *aliasIt, ticket.m_entityIdReferenceMap, previousEntity, *entitiesToSpawn[index], *aliasIt, ticket.m_entityIdReferenceMap, previousEntity,
*request.m_serializeContext); *request.m_serializeContext);
// Not all alias operations create a new instance. It's also possible for an empty entity to be left previousEntity = clone;
// behind, in which case it's also filtered out as the entity component framework doesn't handle these spawnedEntities.emplace_back(clone);
// gracefully. spawnedEntityIndices.push_back(index);
if (clone)
{
if (!clone->GetComponents().empty())
{
previousEntity = clone;
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(index);
}
else
{
delete clone;
}
}
++aliasIt; ++aliasIt;
} while (aliasIt != aliasEnd && aliasIt->m_sourceIndex == index); } while (aliasIt != aliasEnd && aliasIt->m_sourceIndex == index);
} }
@@ -663,8 +633,13 @@ namespace AzFramework
// Add to the game context, now the entities are active // Add to the game context, now the entities are active
for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it) for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it)
{ {
(*it)->SetSpawnTicketId(request.m_ticketId); AZ::Entity* clone = (*it);
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it); // The entity component framework doesn't handle entities without TransformComponent safely.
if (!clone->GetComponents().empty())
{
clone->SetSpawnTicketId(request.m_ticketId);
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
}
} }
if (request.m_completionCallback) if (request.m_completionCallback)
@@ -965,13 +940,18 @@ namespace AzFramework
{ {
for (AZ::Entity* entity : request.m_ticket->m_spawnedEntities) for (AZ::Entity* entity : request.m_ticket->m_spawnedEntities)
{ {
if (entity != nullptr) if (entity != nullptr && !entity->GetComponents().empty())
{ {
// Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager. // Setting it to 0 is needed to avoid the infinite loop between GameEntityContext and SpawnableEntitiesManager.
entity->SetSpawnTicketId(0); entity->SetSpawnTicketId(0);
GameEntityContextRequestBus::Broadcast( GameEntityContextRequestBus::Broadcast(
&GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId());
} }
else
{
// Entities without components wouldn't have been send to the GameEntityContext.
delete entity;
}
} }
delete request.m_ticket; delete request.m_ticket;
@@ -403,7 +403,7 @@ namespace UnitTest
static constexpr size_t NumEntities = 4; static constexpr size_t NumEntities = 4;
FillSpawnable(NumEntities); FillSpawnable(NumEntities);
AZStd::vector<size_t> indices = { 0, 2, 3, 1 }; AZStd::vector<uint32_t> indices = { 0, 2, 3, 1 };
size_t spawnedEntitiesCount = 0; size_t spawnedEntitiesCount = 0;
auto callback = [&spawnedEntitiesCount](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) auto callback = [&spawnedEntitiesCount](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
@@ -423,7 +423,7 @@ namespace UnitTest
static constexpr size_t NumEntities = 1; static constexpr size_t NumEntities = 1;
FillSpawnable(NumEntities); FillSpawnable(NumEntities);
AZStd::vector<size_t> indices = { 0, 0 }; AZStd::vector<uint32_t> indices = { 0, 0 };
size_t spawnedEntitiesCount = 0; size_t spawnedEntitiesCount = 0;
auto callback = auto callback =
@@ -444,7 +444,7 @@ namespace UnitTest
static constexpr size_t NumEntities = 4; static constexpr size_t NumEntities = 4;
FillSpawnable(NumEntities); FillSpawnable(NumEntities);
AZStd::vector<size_t> indices = { 0, 2, 3, 1 }; AZStd::vector<uint32_t> indices = { 0, 2, 3, 1 };
size_t spawnedEntitiesCount = 0; size_t spawnedEntitiesCount = 0;
auto callback = auto callback =
@@ -467,7 +467,7 @@ namespace UnitTest
FillSpawnable(NumEntities); FillSpawnable(NumEntities);
CreateSingleParent(); CreateSingleParent();
AZStd::vector<size_t> indices = { 0, 1, 2, 3 }; AZStd::vector<uint32_t> indices = { 0, 1, 2, 3 };
AZStd::vector<AZ::EntityId> parents; AZStd::vector<AZ::EntityId> parents;
auto callback = [&parents](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities) auto callback = [&parents](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
@@ -499,7 +499,7 @@ namespace UnitTest
FillSpawnable(NumEntities); FillSpawnable(NumEntities);
CreateSingleParent(); CreateSingleParent();
AZStd::vector<size_t> indices = { 0, 1, 2, 3 }; AZStd::vector<uint32_t> indices = { 0, 1, 2, 3 };
AZStd::vector<AZ::EntityId> parents; AZStd::vector<AZ::EntityId> parents;
auto callback = auto callback =