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,
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(
&entityTemplate, templateToCloneMap, &serializeContext);
}
else
{
return nullptr;
}
return AZ::IdUtils::Remapper<AZ::EntityId, allowDuplicateIds>::CloneObjectAndGenerateNewIdsAndFixRefs(
&entityTemplate, templateToCloneMap, &serializeContext);
}
AZ::Entity* SpawnableEntitiesManager::CloneSingleAliasedEntity(
@@ -468,9 +461,8 @@ namespace AzFramework
if (aliasIt == aliasEnd || aliasIt->m_sourceIndex != i)
{
AZ::Entity* clone =
CloneSingleEntity(*entitiesToSpawn[i], ticket.m_entityIdReferenceMap, *request.m_serializeContext);
spawnedEntities.emplace_back(clone);
spawnedEntities.emplace_back(
CloneSingleEntity(*entitiesToSpawn[i], ticket.m_entityIdReferenceMap, *request.m_serializeContext));
spawnedEntityIndices.push_back(i);
}
else
@@ -483,21 +475,9 @@ namespace AzFramework
AZ::Entity* clone = CloneSingleAliasedEntity(
*entitiesToSpawn[i], *aliasIt, ticket.m_entityIdReferenceMap, previousEntity,
*request.m_serializeContext);
// Not all alias operations create a new instance. It's also possible for an empty entity to be left behind,
// in which case it's also filtered out as the entity component framework doesn't handle these gracefully.
if (clone)
{
if (!clone->GetComponents().empty())
{
previousEntity = clone;
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(i);
}
else
{
delete clone;
}
}
previousEntity = clone;
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(i);
++aliasIt;
} while (aliasIt != aliasEnd && aliasIt->m_sourceIndex == i);
}
@@ -519,8 +499,13 @@ namespace AzFramework
// Add to the game context, now the entities are active
for (auto it = newEntitiesBegin; it != newEntitiesEnd; ++it)
{
(*it)->SetSpawnTicketId(request.m_ticketId);
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
AZ::Entity* clone = (*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.
@@ -585,10 +570,8 @@ namespace AzFramework
RefreshEntityIdMapping(
entitiesToSpawn[index].get()->GetId(), ticket.m_entityIdReferenceMap, ticket.m_previouslySpawned);
AZ::Entity* clone =
CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext);
AZ_Assert(clone != nullptr, "Failed to clone spawnable entity.");
spawnedEntities.push_back(clone);
spawnedEntities.push_back(
CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext));
spawnedEntityIndices.push_back(index);
}
}
@@ -612,9 +595,8 @@ namespace AzFramework
if (aliasIt == aliasEnd)
{
AZ::Entity* clone =
CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext);
spawnedEntities.emplace_back(clone);
spawnedEntities.emplace_back(
CloneSingleEntity(*entitiesToSpawn[index], ticket.m_entityIdReferenceMap, *request.m_serializeContext));
spawnedEntityIndices.push_back(index);
}
else
@@ -627,22 +609,10 @@ namespace AzFramework
AZ::Entity* clone = CloneSingleAliasedEntity(
*entitiesToSpawn[index], *aliasIt, ticket.m_entityIdReferenceMap, previousEntity,
*request.m_serializeContext);
// Not all alias operations create a new instance. It's also possible for an empty entity to be left
// behind, in which case it's also filtered out as the entity component framework doesn't handle these
// gracefully.
if (clone)
{
if (!clone->GetComponents().empty())
{
previousEntity = clone;
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(index);
}
else
{
delete clone;
}
}
previousEntity = clone;
spawnedEntities.emplace_back(clone);
spawnedEntityIndices.push_back(index);
++aliasIt;
} while (aliasIt != aliasEnd && aliasIt->m_sourceIndex == index);
}
@@ -663,8 +633,13 @@ namespace AzFramework
// Add to the game context, now the entities are active
for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it)
{
(*it)->SetSpawnTicketId(request.m_ticketId);
GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it);
AZ::Entity* clone = (*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)
@@ -965,13 +940,18 @@ namespace AzFramework
{
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);
GameEntityContextRequestBus::Broadcast(
&GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId());
}
else
{
// Entities without components wouldn't have been send to the GameEntityContext.
delete entity;
}
}
delete request.m_ticket;
@@ -403,7 +403,7 @@ namespace UnitTest
static constexpr size_t NumEntities = 4;
FillSpawnable(NumEntities);
AZStd::vector<size_t> indices = { 0, 2, 3, 1 };
AZStd::vector<uint32_t> indices = { 0, 2, 3, 1 };
size_t spawnedEntitiesCount = 0;
auto callback = [&spawnedEntitiesCount](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
@@ -423,7 +423,7 @@ namespace UnitTest
static constexpr size_t NumEntities = 1;
FillSpawnable(NumEntities);
AZStd::vector<size_t> indices = { 0, 0 };
AZStd::vector<uint32_t> indices = { 0, 0 };
size_t spawnedEntitiesCount = 0;
auto callback =
@@ -444,7 +444,7 @@ namespace UnitTest
static constexpr size_t NumEntities = 4;
FillSpawnable(NumEntities);
AZStd::vector<size_t> indices = { 0, 2, 3, 1 };
AZStd::vector<uint32_t> indices = { 0, 2, 3, 1 };
size_t spawnedEntitiesCount = 0;
auto callback =
@@ -467,7 +467,7 @@ namespace UnitTest
FillSpawnable(NumEntities);
CreateSingleParent();
AZStd::vector<size_t> indices = { 0, 1, 2, 3 };
AZStd::vector<uint32_t> indices = { 0, 1, 2, 3 };
AZStd::vector<AZ::EntityId> parents;
auto callback = [&parents](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
@@ -499,7 +499,7 @@ namespace UnitTest
FillSpawnable(NumEntities);
CreateSingleParent();
AZStd::vector<size_t> indices = { 0, 1, 2, 3 };
AZStd::vector<uint32_t> indices = { 0, 1, 2, 3 };
AZStd::vector<AZ::EntityId> parents;
auto callback =