Files
o3de/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h
T
2021-04-07 14:03:29 -07:00

161 lines
6.3 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Memory/PoolAllocator.h>
#include <AzCore/std/limits.h>
#include <AzCore/std/containers/queue.h>
#include <AzCore/std/containers/deque.h>
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
namespace AZ
{
class Entity;
class SerializeContext;
}
namespace AzFramework
{
class SpawnableEntitiesManager
: public SpawnableEntitiesInterface::Registrar
{
public:
AZ_RTTI(AzFramework::SpawnableEntitiesManager, "{6E14333F-128C-464C-94CA-A63B05A5E51C}");
enum class CommandQueueStatus : bool
{
HasCommandsLeft,
NoCommandLeft
};
~SpawnableEntitiesManager() override = default;
//
// The following functions are thread safe
//
void SpawnAllEntities(EntitySpawnTicket& ticket, EntitySpawnCallback completionCallback = {}) override;
void SpawnEntities(EntitySpawnTicket& ticket, AZStd::vector<size_t> entityIndices,
EntitySpawnCallback completionCallback = {}) override;
void DespawnAllEntities(EntitySpawnTicket& ticket, EntityDespawnCallback completionCallback = {}) override;
void ReloadSpawnable(EntitySpawnTicket& ticket, AZ::Data::Asset<Spawnable> spawnable,
ReloadSpawnableCallback completionCallback = {}) override;
void ListEntities(EntitySpawnTicket& ticket, ListEntitiesCallback listCallback) override;
void ClaimEntities(EntitySpawnTicket& ticket, ClaimEntitiesCallback listCallback) override;
void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback) override;
//
// The following function is thread safe but intended to be run from the main thread.
//
CommandQueueStatus ProcessQueue();
protected:
void* CreateTicket(AZ::Data::Asset<Spawnable>&& spawnable) override;
void DestroyTicket(void* ticket) override;
private:
struct Ticket
{
AZ_CLASS_ALLOCATOR(Ticket, AZ::ThreadPoolAllocator, 0);
static constexpr uint32_t Processing = AZStd::numeric_limits<uint32_t>::max();
AZStd::vector<AZ::Entity*> m_spawnedEntities;
AZStd::vector<size_t> m_spawnedEntityIndices;
AZ::Data::Asset<Spawnable> m_spawnable;
uint32_t m_nextTicketId{ 0 }; //!< Next id for this ticket.
uint32_t m_currentTicketId{ 0 }; //!< The id for the command that should be executed.
bool m_loadAll{ true };
};
struct SpawnAllEntitiesCommand
{
EntitySpawnCallback m_completionCallback;
EntitySpawnTicket* m_ticket;
uint32_t m_ticketId;
};
struct SpawnEntitiesCommand
{
AZStd::vector<size_t> m_entityIndices;
EntitySpawnCallback m_completionCallback;
EntitySpawnTicket* m_ticket;
uint32_t m_ticketId;
};
struct DespawnAllEntitiesCommand
{
EntityDespawnCallback m_completionCallback;
EntitySpawnTicket* m_ticket;
uint32_t m_ticketId;
};
struct ReloadSpawnableCommand
{
AZ::Data::Asset<Spawnable> m_spawnable;
ReloadSpawnableCallback m_completionCallback;
EntitySpawnTicket* m_ticket;
uint32_t m_ticketId;
};
struct ListEntitiesCommand
{
ListEntitiesCallback m_listCallback;
EntitySpawnTicket* m_ticket;
uint32_t m_ticketId;
};
struct ClaimEntitiesCommand
{
ClaimEntitiesCallback m_listCallback;
EntitySpawnTicket* m_ticket;
uint32_t m_ticketId;
};
struct BarrierCommand
{
BarrierCallback m_completionCallback;
EntitySpawnTicket* m_ticket;
uint32_t m_ticketId;
};
struct DestroyTicketCommand
{
Ticket* m_ticket;
uint32_t m_ticketId;
};
using Requests = AZStd::variant<SpawnAllEntitiesCommand, SpawnEntitiesCommand, DespawnAllEntitiesCommand, ReloadSpawnableCommand,
ListEntitiesCommand, ClaimEntitiesCommand, BarrierCommand, DestroyTicketCommand>;
AZ::Entity* SpawnSingleEntity(const AZ::Entity& entityTemplate, AZ::SerializeContext& serializeContext);
bool ProcessRequest(SpawnAllEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(SpawnEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(DespawnAllEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(ReloadSpawnableCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(ListEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(ClaimEntitiesCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(BarrierCommand& request, AZ::SerializeContext& serializeContext);
bool ProcessRequest(DestroyTicketCommand& request, AZ::SerializeContext& serializeContext);
[[nodiscard]] static bool IsEqualTicket(const EntitySpawnTicket* lhs, const EntitySpawnTicket* rhs);
[[nodiscard]] static bool IsEqualTicket(const Ticket* lhs, const EntitySpawnTicket* rhs);
[[nodiscard]] static bool IsEqualTicket(const EntitySpawnTicket* lhs, const Ticket* rhs);
[[nodiscard]] static bool IsEqualTicket(const Ticket* lhs, const Ticket* rhs);
AZStd::deque<Requests> m_delayedQueue; //!< Requests that were processed before, but couldn't be completed.
AZStd::queue<Requests> m_pendingRequestQueue;
AZStd::mutex m_pendingRequestQueueMutex;
};
} // namespace AzFramework