Entity Section API draft

This commit is contained in:
Curle 2023-03-12 12:05:01 +00:00
parent 33b27fc9a1
commit cc5400587c
2 changed files with 137 additions and 4 deletions

View File

@ -18,12 +18,13 @@ namespace SE {
explicit IDContainer(uint64_t v) : id(v) {} explicit IDContainer(uint64_t v) : id(v) {}
// Check if the ID is valid (non-zero) // Check if the ID is valid (non-zero)
__inline bool Valid() const { return id != 0; } __inline virtual bool Valid() const { return id != 0; }
// Set this ID to be invalid (zero). // Set this ID to be invalid (zero).
__inline void Invalidate() { id = 0; } __inline virtual void Invalidate() { id = 0; }
// Check for in/equality against another ID. // Check for in/equality against another ID.
__inline bool operator==(IDContainer const& other) const { return id == other.id; } __inline virtual bool operator==(IDContainer const& other) const { return id == other.id; }
__inline bool operator!=(IDContainer const& other) const { return id != other.id; } __inline virtual bool operator!=(IDContainer const& other) const { return id != other.id; }
__inline virtual bool operator<(IDContainer const& other) const { return id < other.id; }
uint64_t id; uint64_t id;
}; };

View File

@ -0,0 +1,132 @@
#pragma once
#include <vector>
#include <map>
namespace SE {
// Forward declaration, see inc/entity/Entity.h
class Entity;
/**
* A section is a collection of Entities with linked runtime.
* ie. a game level could have one giant linked Section.
* a cell of an open-world game could represent one Region,
* and rooms of a BSP level could represent one Region.
*/
class EntitySection {
/**
* The possible statuses for this Section.
* Entities are not valid until the Loaded status is reached.
*/
enum class Status {
Failed = -1, // An error occurred during loading.
Unloaded = 0, // The Section is present, but none of the data is populated.
Loading, // The Section is being loaded with data.
Loaded, // The Section is present and contains valid data.
Unloading // The Section is present but preparing to unload.
};
/**
* Request the deletion of an entity, after ie. destruction or death.
*/
struct PendingRemoval {
PendingRemoval(Entity* entity, bool destroy)
: entity(entity), destroy(destroy) {}
Entity* entity = nullptr;
bool destroy = false;
};
public:
EntitySection();
EntitySection(EntitySection const& section);
EntitySection(EntitySection&& section);
~EntitySection();
EntitySection& operator=(EntitySection const& section);
EntitySection& operator=(EntitySection&& section);
// Get the ID of this Section
inline EntitySectionID GetID() const { return id; }
// Whether or not this Section was generated, without being loaded from disk.
inline bool IsTransient() const { return isTransient; }
// TODO: Contexts?
void Load();
void Unload();
// Check that everything went properly, and update state accordingly.
bool UpdateState();
// Whether there are any pending entity removals or additions.
inline bool HasPendingEntityChanges() const { return (entitiesPendingLoading.size() + entitiesPendingRemoval.size()) > 0; }
bool IsLoading() const { return status == Status::Loading; }
inline bool IsLoaded() const { return status == Status::Loaded; }
inline bool IsUnloaded() const { return status == Status::Unloaded; }
inline bool LoadingFailed() const { return status == Status::Failed; }
// Get the total number of entities in the section
inline size_t GetEntityCount() const { return entities.size(); }
// Get all entities in the region.
inline std::vector<Entity*> const& GetEntities() const { return entities; }
// Get a specific entity by its' ID.
inline Entity* GetEntity(const EntityID& eID) const {
auto i = entityLookup.find(eID);
return (i != entityLookup.end()) ? i->second : nullptr;
}
// Check whether this region contains the specified entity.
inline bool ContainsEntity(const EntityID& eID) const { return GetEntity(eID) != nullptr; }
// Add all of the specified entities to the region.
// Transfers ownership if already present.
// This operation takes time, but is guaranteed to be finished by the start of the next frame.
void AddEntities(const std::vector<Entity*>& entities);
// Add an entity to the region.
// Transfers ownership if already present.
void AddEntity(Entity* entity);
// Queue an entity for removal from this region.
// Transfers ownership to the caller.
// This operation takes time, and no guarantee is given for completion.
Entity* RemoveEntity(const EntityID& eID);
// Queue an entity for unloading from this region.
// This operation takes time, and no guarantee is given for completion.
void DestroyEntity(const EntityID& eID);
private:
// A callback for when an entity's state changes (ie. when loading)
void EntityStateUpdated(Entity* entity);
// TODO: Process Loading, Unloading, Entity Shutdown, Entity Removal, Entity Loading.
private:
EntitySectionID id = UUID::Generate();
Status status = Status::Unloaded;
// Transient = created on-the-fly, rather than existing on disk.
bool const isTransient = false;
// The list of every entity in the Section, including those that are not yet loaded, or those that are due to be unloaded.
std::vector<Entity*> entities;
// A fast map for looking up entities by ID.
std::map<EntityID, Entity*> entityLookup;
// The list of entities that are currently being initialized to be put into the Section.
std::vector<Entity*> entitiesLoading;
// The list of entities that are waiting to be loaded.
std::vector<Entity*> entitiesPendingLoading;
// The list of entities that are waiting to be removed.
std::vector<Entity*> entitiesPendingRemoval;
};
}