diff --git a/Code/Framework/AzCore/AzCore/Component/Entity.cpp b/Code/Framework/AzCore/AzCore/Component/Entity.cpp index 2e92873238..0fe201d448 100644 --- a/Code/Framework/AzCore/AzCore/Component/Entity.cpp +++ b/Code/Framework/AzCore/AzCore/Component/Entity.cpp @@ -649,6 +649,16 @@ namespace AZ m_stateEvent.Signal(oldState, m_state); } + void Entity::SetSpawnTicketId(u32 spawnTicketId) + { + m_spawnTicketId = 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 356533f268..c2bde375bb 100644 --- a/Code/Framework/AzCore/AzCore/Component/Entity.h +++ b/Code/Framework/AzCore/AzCore/Component/Entity.h @@ -133,6 +133,14 @@ 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; } + //! Gets the ticket id used to spawn the entity. + //! @return the ticket id used to spawn the entity. If entity is not spawned, the id will be 0. + u32 GetSpawnTicketId() const; + + //! Sets the ticket id used to spawn the entity. The ticket id in the entity will remain 0 unless it's set using this function. + //! @param spawnTicketId the ticket id used to spawn the entity. + void SetSpawnTicketId(u32 spawnTicketId); + //! 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. @@ -410,6 +418,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/GameEntityContextBus.h b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h index b5ca37df6e..f8e4dfa98b 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h @@ -91,15 +91,6 @@ namespace AzFramework */ virtual void DestroyGameEntity(const AZ::EntityId& /*id*/) = 0; - /** - * Destroys an entity only in slice mode (when prefabs are disabled). This request is only added as a stop-gap solution - * to prevent the editor from crashing when prefabs are enabled and must only be called through the BehaviorContext binding - * for 'DestroyGameEntity'. No code should be written to directly call this method. This will be removed soon. - * - * @param id The ID of the entity to destroy. - */ - virtual void DestroyGameEntityOnlyInSliceMode(const AZ::EntityId& /*id*/) = 0; - /** * Destroys an entity and all of its descendants. * The entity and its descendants are immediately deactivated and will be @@ -108,15 +99,6 @@ namespace AzFramework */ virtual void DestroyGameEntityAndDescendants(const AZ::EntityId& /*id*/) = 0; - /** - * Destroys an entity and its descendants only in slice mode (when prefabs are disabled). This request is only added as a stop-gap - * solution to prevent the editor from crashing when prefabs are enabled and must only be called through the BehaviorContext - * binding for 'DestroyGameEntityAndDescendants'.No code should be written to directly call this method. This will be removed soon. - * - * @param id The ID of the entity to destroy. - */ - virtual void DestroyGameEntityAndDescendantsOnlyInSliceMode(const AZ::EntityId& /*id*/) = 0; - /** * Activates the game entity. * @param id The ID of the entity to activate. diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp index a97281b9c1..aa7e03577a 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.cpp @@ -11,9 +11,10 @@ #include #include #include +#include #include #include -#include +#include #include "GameEntityContextComponent.h" @@ -47,9 +48,9 @@ namespace AzFramework ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Event("CreateGameEntity", &GameEntityContextRequestBus::Events::CreateGameEntityForBehaviorContext) ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) - ->Event("DestroyGameEntity", &GameEntityContextRequestBus::Events::DestroyGameEntityOnlyInSliceMode) + ->Event("DestroyGameEntity", &GameEntityContextRequestBus::Events::DestroyGameEntity) ->Event( - "DestroyGameEntityAndDescendants", &GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendantsOnlyInSliceMode) + "DestroyGameEntityAndDescendants", &GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants) ->Event("ActivateGameEntity", &GameEntityContextRequestBus::Events::ActivateGameEntity) ->Event("DeactivateGameEntity", &GameEntityContextRequestBus::Events::DeactivateGameEntity) ->Attribute(AZ::ScriptCanvasAttributes::DeactivatesInputEntity, true) @@ -249,23 +250,6 @@ namespace AzFramework DestroyGameEntityInternal(id, false); } - void GameEntityContextComponent::DestroyGameEntityOnlyInSliceMode(const AZ::EntityId& id) - { - bool isPrefabSystemEnabled = false; - AzFramework::ApplicationRequests::Bus::BroadcastResult( - isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); - if (!isPrefabSystemEnabled) - { - DestroyGameEntityInternal(id, false); - } - else - { - AZ_Error( - "GameEntityContextComponent", false, - "Destroying a game entity is temporarily disabled until the Spawnable system can support this."); - } - } - //========================================================================= // GameEntityContextComponent::DestroyGameEntityAndDescendantsById //========================================================================= @@ -274,24 +258,6 @@ namespace AzFramework DestroyGameEntityInternal(id, true); } - - void GameEntityContextComponent::DestroyGameEntityAndDescendantsOnlyInSliceMode(const AZ::EntityId& id) - { - bool isPrefabSystemEnabled = false; - AzFramework::ApplicationRequests::Bus::BroadcastResult( - isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); - if (!isPrefabSystemEnabled) - { - DestroyGameEntityInternal(id, true); - } - else - { - AZ_Error( - "GameEntityContextComponent", false, - "Destroying a game entity and its descendants is temporarily disabled until the Spawnable system can support this."); - } - } - //========================================================================= // GameEntityContextComponent::DestroyGameEntityInternal //========================================================================= @@ -319,6 +285,28 @@ namespace AzFramework EBUS_EVENT_RESULT(currentEntity, AZ::ComponentApplicationBus, FindEntity, *entityIdIter); if (currentEntity) { + bool isPrefabSystemEnabled = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult( + isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); + if (isPrefabSystemEnabled) + { + if (currentEntity->GetSpawnTicketId() > 0) + { + SpawnableEntitiesDefinition* spawnableEntitiesInterface = SpawnableEntitiesInterface::Get(); + AZ_Assert(spawnableEntitiesInterface != nullptr, "SpawnableEntitiesInterface is not found."); + spawnableEntitiesInterface->RetrieveEntitySpawnTicket( + currentEntity->GetSpawnTicketId(), + [spawnableEntitiesInterface, currentEntity](EntitySpawnTicket* entitySpawnTicket) + { + if (entitySpawnTicket != nullptr) + { + spawnableEntitiesInterface->DespawnEntity(currentEntity->GetId(), *entitySpawnTicket); + } + }); + return; + } + } + if (currentEntity->GetState() == AZ::Entity::State::Active) { // Deactivate the entity, we'll destroy it as soon as it is safe. diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h index b9a4ea0da1..f837bed14e 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h @@ -90,11 +90,6 @@ namespace AzFramework } private: - ////////////////////////////////////////////////////////////////////////// - // GameEntityContextRequestBus - void DestroyGameEntityOnlyInSliceMode(const AZ::EntityId&) override; - void DestroyGameEntityAndDescendantsOnlyInSliceMode(const AZ::EntityId&) override; - ///////////////////////////////////////////////////////////////////////// AzFramework::EntityVisibilityBoundsUnionSystem m_entityVisibilityBoundsUnionSystem; }; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp index 75fca39574..171d626b27 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp @@ -283,8 +283,12 @@ namespace AzFramework : 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; rhs.m_id = 0; + AZStd::scoped_lock lock(manager->m_entitySpawnTicketMapMutex); + manager->m_entitySpawnTicketMap.insert_or_assign(rhs.m_id, this); } EntitySpawnTicket::EntitySpawnTicket(AZ::Data::Asset spawnable) @@ -294,6 +298,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() @@ -304,6 +310,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; } } @@ -312,17 +320,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 6901fc7116..74a17020df 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -154,7 +154,7 @@ namespace AzFramework public: friend class SpawnableEntitiesDefinition; - using Id = uint64_t; + using Id = uint32_t; EntitySpawnTicket() = default; EntitySpawnTicket(const EntitySpawnTicket&) = delete; @@ -176,6 +176,7 @@ namespace AzFramework using EntitySpawnCallback = AZStd::function; using EntityPreInsertionCallback = AZStd::function; using EntityDespawnCallback = AZStd::function; + using RetrieveEntitySpawnTicketCallback = AZStd::function; using ReloadSpawnableCallback = AZStd::function; using ListEntitiesCallback = AZStd::function; using ListIndicesEntitiesCallback = AZStd::function; @@ -220,12 +221,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 @@ -291,9 +301,17 @@ 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 callback The callback to execute upon retrieving the ticket. + virtual void RetrieveEntitySpawnTicket(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback) = 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. @@ -361,6 +379,9 @@ namespace AzFramework { return reinterpret_cast(ticket->m_payload); } + + AZStd::unordered_map m_entitySpawnTicketMap; + AZStd::recursive_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 5fa072a451..ef7351aabb 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -85,6 +85,35 @@ namespace AzFramework 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::RetrieveEntitySpawnTicket(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback) + { + if (entitySpawnTicketId == 0) + { + AZ_Assert(false, "Ticket id provided to RetrieveEntitySpawnTicket is invalid."); + return; + } + + AZStd::scoped_lock lock(m_entitySpawnTicketMapMutex); + auto entitySpawnTicketIterator = m_entitySpawnTicketMap.find(entitySpawnTicketId); + if (entitySpawnTicketIterator == m_entitySpawnTicketMap.end()) + { + AZ_Assert(false, "The EntitySpawnTicket corresponding to id '%lu' cannot be found", entitySpawnTicketId); + return; + } + callback(entitySpawnTicketIterator->second); + } + void SpawnableEntitiesManager::ReloadSpawnable( EntitySpawnTicket& ticket, AZ::Data::Asset spawnable, ReloadSpawnableOptionalArgs optionalArgs) { @@ -223,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); } @@ -339,6 +369,7 @@ 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); } @@ -420,6 +451,7 @@ 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); } @@ -447,8 +479,10 @@ namespace AzFramework { if (entity != nullptr) { + // Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager. + entity->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( - &GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants, entity->GetId()); + &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); } } @@ -469,6 +503,40 @@ 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) + { + // Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager. + (*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; @@ -482,8 +550,10 @@ namespace AzFramework { if (entity != nullptr) { + // Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager. + entity->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( - &GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants, entity->GetId()); + &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); } } @@ -636,8 +706,10 @@ namespace AzFramework { if (entity != nullptr) { + // Setting it to 0 is needed to avoid the infite loop between GameEntityContext and SpawnableEntitiesManager. + entity->SetSpawnTicketId(0); GameEntityContextRequestBus::Broadcast( - &GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants, entity->GetId()); + &GameEntityContextRequestBus::Events::DestroyGameEntity, entity->GetId()); } } delete request.m_ticket; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h index 69985f8aa9..c3de5be003 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h @@ -57,6 +57,8 @@ 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 RetrieveEntitySpawnTicket(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback) override; void ReloadSpawnable( EntitySpawnTicket& ticket, AZ::Data::Asset spawnable, ReloadSpawnableOptionalArgs optionalArgs = {}) override; @@ -132,6 +134,14 @@ namespace AzFramework EntitySpawnTicket::Id m_ticketId; uint32_t m_requestId; }; + struct DespawnEntityCommand + { + EntityDespawnCallback m_completionCallback; + Ticket* m_ticket; + AZ::EntityId m_entityId; + EntitySpawnTicket::Id m_ticketId; + uint32_t m_requestId; + }; struct ReloadSpawnableCommand { AZ::Data::Asset m_spawnable; @@ -176,8 +186,16 @@ namespace AzFramework }; using Requests = AZStd::variant< - SpawnAllEntitiesCommand, SpawnEntitiesCommand, DespawnAllEntitiesCommand, ReloadSpawnableCommand, ListEntitiesCommand, - ListIndicesEntitiesCommand, ClaimEntitiesCommand, BarrierCommand, DestroyTicketCommand>; + SpawnAllEntitiesCommand, + SpawnEntitiesCommand, + DespawnAllEntitiesCommand, + DespawnEntityCommand, + ReloadSpawnableCommand, + ListEntitiesCommand, + ListIndicesEntitiesCommand, + ClaimEntitiesCommand, + BarrierCommand, + DestroyTicketCommand>; struct Queue { @@ -199,6 +217,7 @@ 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); diff --git a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h index a5df7af4c3..a437545adf 100644 --- a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h @@ -40,6 +40,11 @@ namespace AzFramework MOCK_METHOD2(DespawnAllEntities, void(EntitySpawnTicket& ticket, DespawnAllEntitiesOptionalArgs optionalArgs)); + MOCK_METHOD3(DespawnEntity, void(AZ::EntityId entityId, EntitySpawnTicket& ticket, DespawnEntityOptionalArgs optionalArgs)); + + MOCK_METHOD2( + RetrieveEntitySpawnTicket, void(EntitySpawnTicket::Id entitySpawnTicketId, RetrieveEntitySpawnTicketCallback callback)); + MOCK_METHOD3( ReloadSpawnable, void(EntitySpawnTicket& ticket, AZ::Data::Asset spawnable, ReloadSpawnableOptionalArgs optionalArgs));