Improving entity manager and entity support for a simpler version, made some cleanup on the road to support serialization of world
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
#include <Entity/Entity.h>
|
||||
|
||||
DEFINE_ENTITY(Inert);
|
||||
+66
-27
@@ -1,68 +1,107 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <Core/Common/CoreUtils.h>
|
||||
#include <Core/Common/EnumUtils.h>
|
||||
#include <Core/Memory/Allocator.h>
|
||||
#include <Core/Memory/MemoryArena.h>
|
||||
#include <Engine/Class.h>
|
||||
#include <Entity/EntityManager.h>
|
||||
|
||||
#define DECLARE_ENTITY() \
|
||||
Entity* Base; \
|
||||
Entity* Base; \
|
||||
static const Class* Kind;
|
||||
|
||||
// Will register the class globally at launch
|
||||
#define DEFINE_ENTITY(entity) \
|
||||
constexpr Class entityKind##entity(#entity, sizeof(#entity) / sizeof(char)); \
|
||||
const Class* entity::Kind = &entityKind##entity;
|
||||
constexpr Class entityKind##entity = \
|
||||
MakeClass(ConstString(#entity), (uint8)Entity_Type::entity, sizeof(entity), alignof(entity), nullptr); \
|
||||
const Class* entity::Kind = &entityKind##entity;
|
||||
|
||||
#define DEFINE_ENTITY_SERIALIZED(entity, serialize_fct) \
|
||||
constexpr Class entityKind##entity = \
|
||||
MakeClass(ConstString(#entity), (uint8)Entity_Type::entity, sizeof(entity), alignof(entity), serialize_fct); \
|
||||
const Class* entity::Kind = &entityKind##entity;
|
||||
|
||||
struct EntityManager;
|
||||
using DerivedType = void*;
|
||||
using EntityID = uint64_t;
|
||||
|
||||
// clang-format off
|
||||
#define ENTITY_TYPE_LIST(X) X(Inert),
|
||||
|
||||
#define AS_ENUM(name) name
|
||||
enum class Entity_Type : uint8
|
||||
{
|
||||
ENTITY_TYPE_LIST(AS_ENUM)
|
||||
Count
|
||||
};
|
||||
#undef AS_ENUM
|
||||
|
||||
#define AS_STR(name) #name
|
||||
inline const char* kEntity_type_names[] = {
|
||||
ENTITY_TYPE_LIST(AS_STR)
|
||||
"Count"
|
||||
};
|
||||
|
||||
#define ENTITY(kind) ToUnderlying(Entity_Type::kind)
|
||||
// clang-format on
|
||||
|
||||
struct Entity final
|
||||
{
|
||||
EntityID ID;
|
||||
const Class* Kind;
|
||||
DerivedType Derived;
|
||||
float X, Y;
|
||||
index_t MeshInstance = indexMax;
|
||||
EntityID ID = 0;
|
||||
const Class* Kind = nullptr;
|
||||
DerivedType Derived = nullptr;
|
||||
float X = 0.0f;
|
||||
float Y = 0.0f;
|
||||
float Z = 0.0f;
|
||||
};
|
||||
|
||||
// Can reinterpret cast to this to have the offset of Base and Kind for any entity
|
||||
struct entity_template
|
||||
{
|
||||
DECLARE_ENTITY();
|
||||
};
|
||||
|
||||
struct Inert
|
||||
{
|
||||
DECLARE_ENTITY()
|
||||
|
||||
index_t MeshInstance = indexMax;
|
||||
};
|
||||
|
||||
//
|
||||
template <typename EntityType>
|
||||
concept EntityConcept = requires(EntityType entity) {
|
||||
requires std::same_as<decltype(entity.Kind), const Class*>;
|
||||
{ EntityType::Kind } -> std::convertible_to<const Class*>;
|
||||
requires std::same_as<decltype(entity.Base), Entity*>;
|
||||
};
|
||||
|
||||
template <typename EntityType>
|
||||
requires EntityConcept<EntityType>
|
||||
bool IsA(const Entity* entity)
|
||||
[[nodiscard]] bool IsA(const Entity* entity)
|
||||
{
|
||||
Assert(entity != nullptr);
|
||||
return entity->Kind == EntityType::Kind;
|
||||
}
|
||||
|
||||
template <typename EntityType>
|
||||
requires EntityConcept<EntityType>
|
||||
EntityType* MakeEntity(EntityManager& manager, float x, float y)
|
||||
[[nodiscard]] EntityType* MakeEntity(EntityManager& manager, float x, float y, float z)
|
||||
{
|
||||
auto* arena = manager.Arena;
|
||||
EntityType* result = ArenaPushStruct<EntityType>(arena);
|
||||
Entity base;
|
||||
base.X = x;
|
||||
base.Y = y;
|
||||
base.Derived = result;
|
||||
base.Kind = EntityType::Kind;
|
||||
manager.Entities.PushBack(base);
|
||||
EntityType result;
|
||||
Entity base;
|
||||
base.X = x;
|
||||
base.Y = y;
|
||||
base.Z = z;
|
||||
base.Kind = EntityType::Kind;
|
||||
|
||||
result->Base = manager.Entities.Back();
|
||||
|
||||
RegisterEntity(manager, &base);
|
||||
|
||||
return result;
|
||||
return (EntityType*)RegisterEntity(manager, &base, &result);
|
||||
}
|
||||
|
||||
template <typename EntityType>
|
||||
requires EntityConcept<EntityType>
|
||||
EntityType* DownCast(Entity* entity)
|
||||
[[nodiscard]] EntityType* DownCast(Entity* entity)
|
||||
{
|
||||
Assert(entity != nullptr);
|
||||
Assert(IsA<EntityType>(entity));
|
||||
return static_cast<EntityType*>(entity->Derived);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include <Entity/EntityManager.h>
|
||||
#include <Entity/EntityManager.h>
|
||||
|
||||
#include <Core/Common/EnumUtils.h>
|
||||
#include <Data/World.h>
|
||||
#include <Entity/Entity.h>
|
||||
#include <game.h>
|
||||
#include <Graphics/MeshRenderer.h>
|
||||
|
||||
EntityID EntityManager::ID = 0;
|
||||
@@ -12,7 +15,15 @@ void InitEntityManager(NonNullPtr<World> world)
|
||||
|
||||
newManager->Entities.Create(world->WorldArena JULIET_DEBUG_PARAM("Entities"));
|
||||
|
||||
newManager->Arena = ArenaAllocate({ .Name = "Entity Arena" });
|
||||
ArenaParams by_type_params{ .ReserveSize = Kilobytes(1),
|
||||
.CommitSize = Kilobytes(1),
|
||||
.Name = "" JULIET_DEBUG_ONLY(, .CanReserveMore = false) };
|
||||
for (uint8 i = 0; i < ENTITY(Count); ++i)
|
||||
{
|
||||
by_type_params.Name = kEntity_type_names[i];
|
||||
newManager->by_type[i].arena = ArenaAllocate(by_type_params);
|
||||
newManager->by_type[i].array = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ShutdownEntityManager()
|
||||
@@ -26,18 +37,40 @@ EntityManager& GetEntityManager()
|
||||
return *entityManager;
|
||||
}
|
||||
|
||||
void RegisterEntity(EntityManager& /*manager*/, Entity* entity)
|
||||
void Serialize(NonNullPtr<EntityManager> entityManager) {}
|
||||
|
||||
entity_template* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity)
|
||||
{
|
||||
entity->ID = EntityManager::ID++;
|
||||
base->ID = EntityManager::ID++;
|
||||
base->Derived = entity;
|
||||
|
||||
manager.Entities.PushBack(*base);
|
||||
|
||||
auto* ptr = (entity_template*)ArenaPushSize(manager.by_type[base->Kind->kind].arena, base->Kind->size_of, base->Kind->alignment,
|
||||
false JULIET_DEBUG_PARAM(kEntity_type_names[base->Kind->kind]));
|
||||
MemCopy(ptr, entity, base->Kind->size_of);
|
||||
manager.by_type[base->Kind->kind].count += 1;
|
||||
|
||||
ptr->Base = manager.Entities.Back();
|
||||
|
||||
if (manager.by_type[base->Kind->kind].array == nullptr)
|
||||
{
|
||||
manager.by_type[base->Kind->kind].array = ptr;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void UpdateEntityManager(EntityManager& manager)
|
||||
{
|
||||
for (Entity& ent : manager.Entities)
|
||||
// Todo : inert by definition dont move, but this is for test
|
||||
auto& by_type = manager.by_type[ENTITY(Inert)];
|
||||
for (index_t i = 0; i < by_type.count; ++i)
|
||||
{
|
||||
if (ent.MeshInstance != indexMax)
|
||||
Inert* inert = reinterpret_cast<Inert*>(by_type.array) + i;
|
||||
if (inert->MeshInstance != indexMax)
|
||||
{
|
||||
SetMeshInstanceTransform(ent.MeshInstance, MatrixTranslation(ent.X, ent.Y, 0.0f));
|
||||
SetMeshInstanceTransform(inert->MeshInstance, MatrixTranslation(inert->Base->X, inert->Base->Y, inert->Base->Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-12
@@ -1,24 +1,32 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <Core/Common/CoreTypes.h>
|
||||
#include <Core/Container/Vector.h>
|
||||
#include <game.h>
|
||||
|
||||
using EntityID = uint64_t;
|
||||
#include <Entity/Entity.h>
|
||||
|
||||
struct Entity;
|
||||
struct World;
|
||||
|
||||
struct typed_entity_array
|
||||
{
|
||||
Arena* arena;
|
||||
entity_template* array;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
struct EntityManager
|
||||
{
|
||||
static EntityID ID;
|
||||
|
||||
Arena* Arena;
|
||||
|
||||
// TODO: Should be a pool
|
||||
VectorArena<Entity, 1024> Entities;
|
||||
VectorArena<Entity, 100'000> Entities;
|
||||
|
||||
typed_entity_array by_type[ENTITY(Count)];
|
||||
};
|
||||
|
||||
void InitEntityManager(NonNullPtr<World> world);
|
||||
void ShutdownEntityManager();
|
||||
EntityManager& GetEntityManager();
|
||||
void RegisterEntity(EntityManager& manager, Entity* entity);
|
||||
void UpdateEntityManager(EntityManager& manager);
|
||||
void InitEntityManager(NonNullPtr<World> world);
|
||||
void ShutdownEntityManager();
|
||||
EntityManager& GetEntityManager();
|
||||
void Serialize(NonNullPtr<EntityManager> entityManager);
|
||||
entity_template* RegisterEntity(EntityManager& manager, Entity* base, DerivedType entity);
|
||||
void UpdateEntityManager(EntityManager& manager);
|
||||
|
||||
Reference in New Issue
Block a user