diff --git a/Code/Framework/AzCore/AzCore/Component/Entity.cpp b/Code/Framework/AzCore/AzCore/Component/Entity.cpp index 00c1895261..4f55c360cd 100644 --- a/Code/Framework/AzCore/AzCore/Component/Entity.cpp +++ b/Code/Framework/AzCore/AzCore/Component/Entity.cpp @@ -655,6 +655,16 @@ namespace AZ m_stateEvent.Signal(oldState, m_state); } + void Entity::SetSpawnTicketId(u32 spawnTicketId) + { + m_spawnTicketId = AZStd::move(spawnTicketId); + } + + u32 Entity::GetSpawnTicketId() const + { + return m_spawnTicketId; + } + void Entity::OnNameChanged() const { EBUS_EVENT_ID(GetId(), EntityBus, OnEntityNameChanged, m_name); diff --git a/Code/Framework/AzCore/AzCore/Component/Entity.h b/Code/Framework/AzCore/AzCore/Component/Entity.h index 7ec63a56ac..97cec50946 100644 --- a/Code/Framework/AzCore/AzCore/Component/Entity.h +++ b/Code/Framework/AzCore/AzCore/Component/Entity.h @@ -133,6 +133,9 @@ namespace AZ //! @return The state of the entity. For example, the entity has been initialized, the entity is active, and so on. State GetState() const { return m_state; } + u32 GetSpawnTicketId() const; + void SetSpawnTicketId(u32); + //! Connects an entity state event handler to the entity. //! All state changes will be signaled through this event. //! @param handler reference to the EntityStateEvent handler to attach to the entities state event. @@ -411,6 +414,8 @@ namespace AZ //! A user-friendly name for the entity. This makes error messages easier to read. AZStd::string m_name; + u32 m_spawnTicketId = 0; + //! The state of the entity. State m_state; diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp index 694ed83765..f2571c7549 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "GameEntityContextComponent.h" @@ -290,10 +290,21 @@ namespace AzFramework isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); if (isPrefabSystemEnabled) { - SpawnedEntityTicketMapperInterface* spawnedEntityTicketMapperInterface = - AZ::Interface::Get(); - AZ_Assert(spawnedEntityTicketMapperInterface != nullptr, "SpawnedEntityTicketMapperInterface is not found."); - spawnedEntityTicketMapperInterface->RemoveSpawnedEntity(currentEntity->GetId()); + if (currentEntity->GetSpawnTicketId() > 0) + { + SpawnableEntitiesDefinition* spawnableEntitiesInterface = SpawnableEntitiesInterface::Get(); + AZ_Assert(spawnableEntitiesInterface != nullptr, "SpawnableEntitiesInterface is not found."); + spawnableEntitiesInterface->GetEntitySpawnTicket( + currentEntity->GetSpawnTicketId(), + [spawnableEntitiesInterface, currentEntity](EntitySpawnTicket* entitySpawnTicket) + { + if (entitySpawnTicket != nullptr) + { + spawnableEntitiesInterface->DespawnEntity(currentEntity->GetId(), *entitySpawnTicket); + } + }); + return; + } } if (currentEntity->GetState() == AZ::Entity::State::Active) diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp index 617eb3a0b9..53bffd0d26 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp @@ -227,10 +227,16 @@ namespace AzFramework EntitySpawnTicket::EntitySpawnTicket(EntitySpawnTicket&& rhs) : m_payload(rhs.m_payload) - , m_id(rhs.m_id) { + auto manager = SpawnableEntitiesInterface::Get(); + AZ_Assert(manager, "SpawnableEntitiesInterface has no implementation."); rhs.m_payload = nullptr; + Id previousId = m_id; + m_id = rhs.m_id; rhs.m_id = 0; + AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex); + manager->m_entitySpawnTicketMap.erase(previousId); + manager->m_entitySpawnTicketMap.insert_or_assign(rhs.m_id, this); } EntitySpawnTicket::EntitySpawnTicket(AZ::Data::Asset spawnable) @@ -240,6 +246,8 @@ namespace AzFramework AZStd::pair result = manager->CreateTicket(AZStd::move(spawnable)); m_id = result.first; m_payload = result.second; + AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex); + manager->m_entitySpawnTicketMap.insert_or_assign(m_id, this); } EntitySpawnTicket::~EntitySpawnTicket() @@ -250,6 +258,8 @@ namespace AzFramework AZ_Assert(manager, "Attempting to destroy an entity spawn ticket while the SpawnableEntitiesInterface has no implementation."); manager->DestroyTicket(m_payload); m_payload = nullptr; + AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex); + manager->m_entitySpawnTicketMap.erase(m_id); m_id = 0; } } @@ -258,17 +268,23 @@ namespace AzFramework { if (this != &rhs) { + auto manager = SpawnableEntitiesInterface::Get(); + AZ_Assert(manager, "Attempting to destroy an entity spawn ticket while the SpawnableEntitiesInterface has no implementation."); if (m_payload) { - auto manager = SpawnableEntitiesInterface::Get(); - AZ_Assert(manager, "Attempting to destroy an entity spawn ticket while the SpawnableEntitiesInterface has no implementation."); manager->DestroyTicket(m_payload); } + + Id previousId = m_id; m_id = rhs.m_id; rhs.m_id = 0; m_payload = rhs.m_payload; rhs.m_payload = nullptr; + + AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex); + manager->m_entitySpawnTicketMap.erase(previousId); + manager->m_entitySpawnTicketMap.insert_or_assign(m_id, this); } return *this; } diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index 2ce4158229..91b2eafc54 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -140,7 +140,7 @@ namespace AzFramework public: friend class SpawnableEntitiesDefinition; - using Id = uint64_t; + using Id = uint32_t; EntitySpawnTicket() = default; EntitySpawnTicket(const EntitySpawnTicket&) = delete; @@ -162,6 +162,7 @@ namespace AzFramework using EntitySpawnCallback = AZStd::function; using EntityPreInsertionCallback = AZStd::function; using EntityDespawnCallback = AZStd::function; + using GetEntitySpawnTicketCallback = AZStd::function; using ReloadSpawnableCallback = AZStd::function; using ListEntitiesCallback = AZStd::function; using ListIndicesEntitiesCallback = AZStd::function; @@ -206,12 +207,21 @@ namespace AzFramework struct DespawnAllEntitiesOptionalArgs final { //! Callback that's called when despawning entities has completed. This can be triggered from a different thread than the one that - //! made the function call to despawn. The returned list of entities contains all the newly created entities. + //! made the function call to despawn. EntityDespawnCallback m_completionCallback; //! The priority at which this call will be executed. SpawnablePriority m_priority { SpawnablePriority_Default }; }; + struct DespawnEntityOptionalArgs final + { + //! Callback that's called when despawning entity has completed. This can be triggered from a different thread than the one that + //! made the function call to despawn. + EntityDespawnCallback m_completionCallback; + //! The priority at which this call will be executed. + SpawnablePriority m_priority{ SpawnablePriority_Default }; + }; + struct ReloadSpawnableOptionalArgs final { //! Callback that's called when respawning entities has completed. This can be triggered from a different thread than the one that @@ -235,12 +245,6 @@ namespace AzFramework SpawnablePriority m_priority{ SpawnablePriority_Default }; }; - struct ClaimEntityOptionalArgs final - { - //! The priority at which this call will be executed. - SpawnablePriority m_priority{ SpawnablePriority_Default }; - }; - struct BarrierOptionalArgs final { //! The priority at which this call will be executed. @@ -283,9 +287,18 @@ namespace AzFramework EntitySpawnTicket& ticket, AZStd::vector entityIndices, SpawnEntitiesOptionalArgs optionalArgs = {}) = 0; //! Removes all entities in the provided list from the environment. //! @param ticket The ticket previously used to spawn entities with. - //! @param priority The priority at which this call will be executed. //! @param optionalArgs Optional additional arguments, see DespawnAllEntitiesOptionalArgs. virtual void DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs = {}) = 0; + //! Removes the entity with the provided id from the spawned list of entities. + //! @param entityId the id of entity to despawn. + //! @param ticket The ticket previously used to spawn entities with. + //! @param optionalArgs Optional additional arguments, see DespawnEntityOptionalArgs. + virtual void DespawnEntity(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs = {}) = 0; + //! Gets the EntitySpawnTicket associated with the entitySpawnTicketId. + //! @param entitySpawnTicketId the id of EntitySpawnTicket to get. + //! @param getEntitySpawnTicketCallback The callback to execute upon fetching the ticket. + virtual void GetEntitySpawnTicket( + EntitySpawnTicket::Id entitySpawnTicketId, GetEntitySpawnTicketCallback getEntitySpawnTicketCallback) = 0; //! Removes all entities in the provided list from the environment and reconstructs the entities from the provided spawnable. //! @param ticket Holds the information on the entities to reload. //! @param priority The priority at which this call will be executed. @@ -320,8 +333,6 @@ namespace AzFramework virtual void ClaimEntities( EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback, ClaimEntitiesOptionalArgs optionalArgs = {}) = 0; - virtual void ClaimEntity(AZ::EntityId entityId, void* ticket, ClaimEntityOptionalArgs optionalArgs = {}) = 0; - //! Blocks until all operations made on the provided ticket before the barrier call have completed. //! @param ticket The ticket to monitor. //! @param completionCallback Required callback that will be called as soon as the barrier has been reached. @@ -355,6 +366,9 @@ namespace AzFramework { return reinterpret_cast(ticket->m_payload); } + + AZStd::unordered_map m_entitySpawnTicketMap; + AZStd::mutex m_entitySpawnTicketMapMutex; }; using SpawnableEntitiesInterface = AZ::Interface; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp index 92d461819b..c75a5fe834 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -21,13 +21,13 @@ namespace AzFramework { template - void SpawnableEntitiesManager::QueueRequest(Ticket* ticket, SpawnablePriority priority, T&& request) + void SpawnableEntitiesManager::QueueRequest(EntitySpawnTicket& ticket, SpawnablePriority priority, T&& request) { - request.m_ticket = ticket; + request.m_ticket = &GetTicketPayload(ticket); Queue& queue = priority <= m_highPriorityThreshold ? m_highPriorityQueue : m_regularPriorityQueue; { AZStd::scoped_lock queueLock(queue.m_pendingRequestMutex); - request.m_requestId = ticket->m_nextRequestId++; + request.m_requestId = GetTicketPayload(ticket).m_nextRequestId++; queue.m_pendingRequest.push(AZStd::move(request)); } } @@ -56,7 +56,7 @@ namespace AzFramework optionalArgs.m_serializeContext == nullptr ? m_defaultSerializeContext : optionalArgs.m_serializeContext; queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback); queueEntry.m_preInsertionCallback = AZStd::move(optionalArgs.m_preInsertionCallback); - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } void SpawnableEntitiesManager::SpawnEntities( @@ -72,7 +72,7 @@ namespace AzFramework queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback); queueEntry.m_preInsertionCallback = AZStd::move(optionalArgs.m_preInsertionCallback); queueEntry.m_referencePreviouslySpawnedEntities = optionalArgs.m_referencePreviouslySpawnedEntities; - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } void SpawnableEntitiesManager::DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs) @@ -82,7 +82,36 @@ namespace AzFramework DespawnAllEntitiesCommand queueEntry; queueEntry.m_ticketId = ticket.GetId(); queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback); - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); + } + + void SpawnableEntitiesManager::DespawnEntity(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs) + { + AZ_Assert(ticket.IsValid(), "Ticket provided to DespawnEntity hasn't been initialized."); + + DespawnEntityCommand queueEntry; + queueEntry.m_ticketId = ticket.GetId(); + queueEntry.m_entityId = entityId; + queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); + } + + void SpawnableEntitiesManager::GetEntitySpawnTicket( + EntitySpawnTicket::Id entitySpawnTicketId, GetEntitySpawnTicketCallback getEntitySpawnTicketCallback) + { + if (entitySpawnTicketId == 0) + { + AZ_Error("Spawnable", false, "Ticket id provided to GetEntitySpawnTicket is invalid."); + return; + } + + auto entitySpawnTicketIterator = m_entitySpawnTicketMap.find(entitySpawnTicketId); + if (entitySpawnTicketIterator == m_entitySpawnTicketMap.end()) + { + AZ_Error("Spawnable", false, "The EntitySpawnTicket corresponding to id '%lu' cannot be found", entitySpawnTicketId); + return; + } + getEntitySpawnTicketCallback(entitySpawnTicketIterator->second); } void SpawnableEntitiesManager::ReloadSpawnable( @@ -96,7 +125,7 @@ namespace AzFramework queueEntry.m_serializeContext = optionalArgs.m_serializeContext == nullptr ? m_defaultSerializeContext : optionalArgs.m_serializeContext; queueEntry.m_completionCallback = AZStd::move(optionalArgs.m_completionCallback); - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } void SpawnableEntitiesManager::ListEntities( @@ -108,7 +137,7 @@ namespace AzFramework ListEntitiesCommand queueEntry; queueEntry.m_ticketId = ticket.GetId(); queueEntry.m_listCallback = AZStd::move(listCallback); - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } void SpawnableEntitiesManager::ListIndicesAndEntities( @@ -120,7 +149,7 @@ namespace AzFramework ListIndicesEntitiesCommand queueEntry; queueEntry.m_ticketId = ticket.GetId(); queueEntry.m_listCallback = AZStd::move(listCallback); - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } void SpawnableEntitiesManager::ClaimEntities( @@ -132,18 +161,7 @@ namespace AzFramework ClaimEntitiesCommand queueEntry; queueEntry.m_ticketId = ticket.GetId(); queueEntry.m_listCallback = AZStd::move(listCallback); - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); - } - - void SpawnableEntitiesManager::ClaimEntity( - AZ::EntityId entityId, void* ticket, - ClaimEntityOptionalArgs optionalArgs) - { - AZ_Assert(ticket == nullptr, "Ticket provided to ClaimEntity is invalid."); - - ClaimEntityCommand queueEntry; - queueEntry.m_entityId = entityId; - QueueRequest(reinterpret_cast(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } void SpawnableEntitiesManager::Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs) @@ -154,7 +172,7 @@ namespace AzFramework BarrierCommand queueEntry; queueEntry.m_ticketId = ticket.GetId(); queueEntry.m_completionCallback = AZStd::move(completionCallback); - QueueRequest(&GetTicketPayload(ticket), optionalArgs.m_priority, AZStd::move(queueEntry)); + QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } auto SpawnableEntitiesManager::ProcessQueue(CommandQueuePriority priority) -> CommandQueueStatus @@ -234,12 +252,13 @@ namespace AzFramework return queue.m_delayed.empty() ? CommandQueueStatus::NoCommandsLeft : CommandQueueStatus::HasCommandsLeft; } - AZStd::pair SpawnableEntitiesManager::CreateTicket(AZ::Data::Asset&& spawnable) + AZStd::pair SpawnableEntitiesManager::CreateTicket(AZ::Data::Asset&& spawnable) { - static AZStd::atomic_uint64_t idCounter { 1 }; + static AZStd::atomic_uint32_t idCounter { 1 }; auto result = aznew Ticket(); result->m_spawnable = AZStd::move(spawnable); + return AZStd::make_pair(idCounter++, result); } @@ -351,7 +370,7 @@ namespace AzFramework for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it) { GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it); - m_spawnedEntityTicketMapper.AddSpawnedEntity((*it)->GetId(), &ticket); + (*it)->SetSpawnTicketId(request.m_ticketId); } // Let other systems know about newly spawned entities for any post-processing after adding to the scene/game context. @@ -433,7 +452,7 @@ namespace AzFramework for (auto it = ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount; it != ticket.m_spawnedEntities.end(); ++it) { GameEntityContextRequestBus::Broadcast(&GameEntityContextRequestBus::Events::AddGameEntity, *it); - m_spawnedEntityTicketMapper.AddSpawnedEntity((*it)->GetId(), &ticket); + (*it)->SetSpawnTicketId(request.m_ticketId); } if (request.m_completionCallback) @@ -460,6 +479,7 @@ namespace AzFramework { if (entity != nullptr) { + entity->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); } @@ -482,6 +502,39 @@ namespace AzFramework } } + bool SpawnableEntitiesManager::ProcessRequest(DespawnEntityCommand& request) + { + Ticket& ticket = *request.m_ticket; + if (request.m_requestId == ticket.m_currentRequestId) + { + AZStd::vector& spawnedEntities = request.m_ticket->m_spawnedEntities; + for (auto entityIterator = spawnedEntities.begin(); entityIterator != spawnedEntities.end(); ++entityIterator) + { + if (*entityIterator != nullptr && (*entityIterator)->GetId() == request.m_entityId) + { + (*entityIterator)->SetSpawnTicketId(0); + GameEntityContextRequestBus::Broadcast( + &GameEntityContextRequestBus::Events::DestroyGameEntity, (*entityIterator)->GetId()); + AZStd::iter_swap(entityIterator, spawnedEntities.rbegin()); + spawnedEntities.pop_back(); + break; + } + } + + if (request.m_completionCallback) + { + request.m_completionCallback(request.m_ticketId); + } + + ticket.m_currentRequestId++; + return true; + } + else + { + return false; + } + } + bool SpawnableEntitiesManager::ProcessRequest(ReloadSpawnableCommand& request) { Ticket& ticket = *request.m_ticket; @@ -495,6 +548,7 @@ namespace AzFramework { if (entity != nullptr) { + entity->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); } @@ -622,29 +676,6 @@ namespace AzFramework } } - bool SpawnableEntitiesManager::ProcessRequest(ClaimEntityCommand& request) - { - Ticket* ticket = request.m_ticket; - if (request.m_requestId == ticket->m_currentRequestId) - { - AZStd::vector& spawnedEntities = ticket->m_spawnedEntities; - for (auto entityIterator = spawnedEntities.begin(); entityIterator != spawnedEntities.end(); ++entityIterator) - { - if ((*entityIterator)->GetId() == request.m_entityId) - { - AZStd::iter_swap(entityIterator, spawnedEntities.rbegin()); - spawnedEntities.pop_back(); - return true; - } - } - return true; - } - else - { - return false; - } - } - bool SpawnableEntitiesManager::ProcessRequest(BarrierCommand& request) { Ticket& ticket = *request.m_ticket; @@ -672,6 +703,7 @@ namespace AzFramework { if (entity != nullptr) { + entity->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); } diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h index e5a0760010..5445360d64 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h @@ -16,7 +16,6 @@ #include #include #include -#include namespace AZ { @@ -58,6 +57,9 @@ namespace AzFramework void SpawnEntities( EntitySpawnTicket& ticket, AZStd::vector entityIndices, SpawnEntitiesOptionalArgs optionalArgs = {}) override; void DespawnAllEntities(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs = {}) override; + void DespawnEntity(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs = {}) override; + void GetEntitySpawnTicket( + EntitySpawnTicket::Id entitySpawnTicketId, GetEntitySpawnTicketCallback getEntitySpawnTicketCallback) override; void ReloadSpawnable( EntitySpawnTicket& ticket, AZ::Data::Asset spawnable, ReloadSpawnableOptionalArgs optionalArgs = {}) override; @@ -67,8 +69,6 @@ namespace AzFramework EntitySpawnTicket& ticket, ListIndicesEntitiesCallback listCallback, ListEntitiesOptionalArgs optionalArgs = {}) override; void ClaimEntities( EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback, ClaimEntitiesOptionalArgs optionalArgs = {}) override; - void ClaimEntity( - AZ::EntityId entityId, void* ticket, ClaimEntityOptionalArgs optionalArgs = {}) override; void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) override; @@ -135,6 +135,14 @@ namespace AzFramework EntitySpawnTicket::Id m_ticketId; uint32_t m_requestId; }; + struct DespawnEntityCommand + { + EntityDespawnCallback m_completionCallback; + Ticket* m_ticket; + EntitySpawnTicket::Id m_ticketId; + uint32_t m_requestId; + AZ::EntityId m_entityId; + }; struct ReloadSpawnableCommand { AZ::Data::Asset m_spawnable; @@ -165,12 +173,6 @@ namespace AzFramework EntitySpawnTicket::Id m_ticketId; uint32_t m_requestId; }; - struct ClaimEntityCommand - { - Ticket* m_ticket; - uint32_t m_requestId; - AZ::EntityId m_entityId; - }; struct BarrierCommand { BarrierCallback m_completionCallback; @@ -185,8 +187,16 @@ namespace AzFramework }; using Requests = AZStd::variant< - SpawnAllEntitiesCommand, SpawnEntitiesCommand, DespawnAllEntitiesCommand, ReloadSpawnableCommand, ListEntitiesCommand, - ListIndicesEntitiesCommand, ClaimEntitiesCommand, ClaimEntityCommand, BarrierCommand, DestroyTicketCommand>; + SpawnAllEntitiesCommand, + SpawnEntitiesCommand, + DespawnAllEntitiesCommand, + DespawnEntityCommand, + ReloadSpawnableCommand, + ListEntitiesCommand, + ListIndicesEntitiesCommand, + ClaimEntitiesCommand, + BarrierCommand, + DestroyTicketCommand>; struct Queue { @@ -196,7 +206,7 @@ namespace AzFramework }; template - void QueueRequest(Ticket* ticket, SpawnablePriority priority, T&& request); + void QueueRequest(EntitySpawnTicket& ticket, SpawnablePriority priority, T&& request); AZStd::pair CreateTicket(AZ::Data::Asset&& spawnable) override; void DestroyTicket(void* ticket) override; @@ -208,11 +218,11 @@ namespace AzFramework bool ProcessRequest(SpawnAllEntitiesCommand& request); bool ProcessRequest(SpawnEntitiesCommand& request); bool ProcessRequest(DespawnAllEntitiesCommand& request); + bool ProcessRequest(DespawnEntityCommand& request); bool ProcessRequest(ReloadSpawnableCommand& request); bool ProcessRequest(ListEntitiesCommand& request); bool ProcessRequest(ListIndicesEntitiesCommand& request); bool ProcessRequest(ClaimEntitiesCommand& request); - bool ProcessRequest(ClaimEntityCommand& request); bool ProcessRequest(BarrierCommand& request); bool ProcessRequest(DestroyTicketCommand& request); @@ -234,8 +244,6 @@ namespace AzFramework //! SpawnablePriority_Default which gives users a bit of room to fine tune the priorities as this value can be configured //! through the Settings Registry under the key "/O3DE/AzFramework/Spawnables/HighPriorityThreshold". SpawnablePriority m_highPriorityThreshold { 64 }; - private: - SpawnedEntityTicketMapper m_spawnedEntityTicketMapper; }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(AzFramework::SpawnableEntitiesManager::CommandQueuePriority); diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapper.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapper.cpp deleted file mode 100644 index 3a6b40f5a9..0000000000 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapper.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include - -namespace AzFramework -{ - SpawnedEntityTicketMapper::SpawnedEntityTicketMapper() - { - spawnableEntitiesInterface = SpawnableEntitiesInterface::Get(); - AZ_Assert(spawnableEntitiesInterface != nullptr, "SpawnableEntitiesInterface is not found."); - - AZ::Interface::Register(this); - } - - SpawnedEntityTicketMapper::~SpawnedEntityTicketMapper() - { - AZ::Interface::Unregister(this); - } - - void SpawnedEntityTicketMapper::RemoveSpawnedEntity(AZ::EntityId entityId) - { - auto spawnedGameEntitiesIterator = m_spawnedEntities.find(entityId); - if (spawnedGameEntitiesIterator != m_spawnedEntities.end()) - { - spawnableEntitiesInterface->ClaimEntity( - spawnedGameEntitiesIterator->first, spawnedGameEntitiesIterator->second); - m_spawnedEntities.erase(entityId); - } - } - - void SpawnedEntityTicketMapper::AddSpawnedEntity(AZ::EntityId entityId, void* ticket) - { - m_spawnedEntities.emplace(entityId, ticket); - } - -} - diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapper.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapper.h deleted file mode 100644 index 45e701db4e..0000000000 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapper.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include - -namespace AzFramework -{ - class SpawnedEntityTicketMapper - : public SpawnedEntityTicketMapperInterface - { - public: - AZ_RTTI(SpawnedEntityTicketMapper, "{5C803604-E949-44F4-94A4-F835E5794C77}", SpawnedEntityTicketMapperInterface); - - SpawnedEntityTicketMapper(); - ~SpawnedEntityTicketMapper(); - - //! Removes the entityId from the spawned entities map if present. - //! @param entityId The id of the entity to remove. - void RemoveSpawnedEntity(AZ::EntityId entityId) override; - - //! Adds the entityId,ticket pair to the spawned entities map. - //! @param entityId The id of the entity to add. - //! @param ticket The ticket pointer to add. - void AddSpawnedEntity(AZ::EntityId entityId, void* ticket) override; - private: - SpawnableEntitiesDefinition* spawnableEntitiesInterface = nullptr; - AZStd::unordered_map m_spawnedEntities; - }; -} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapperInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapperInterface.h deleted file mode 100644 index 8f0bd96dbe..0000000000 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnedEntityTicketMapperInterface.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include - -namespace AzFramework -{ - class SpawnedEntityTicketMapperInterface - { - public: - AZ_RTTI(SpawnedEntityTicketMapperInterface, "{D407E96B-635C-44F2-B089-084EBAB8B036}"); - - virtual void RemoveSpawnedEntity(AZ::EntityId entityId) = 0; - virtual void AddSpawnedEntity(AZ::EntityId entityId, void* ticket) = 0; - }; -} diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index b486596e2a..87cf29ffec 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -294,9 +294,6 @@ set(FILES Spawnable/SpawnableMonitor.cpp Spawnable/SpawnableSystemComponent.h Spawnable/SpawnableSystemComponent.cpp - Spawnable/SpawnedEntityTicketMapper.h - Spawnable/SpawnedEntityTicketMapper.cpp - Spawnable/SpawnedEntityTicketMapperInterface.h Terrain/TerrainDataRequestBus.h Terrain/TerrainDataRequestBus.cpp Thermal/ThermalInfo.h