75 lines
2.3 KiB
C++
75 lines
2.3 KiB
C++
#pragma once
|
|
|
|
#include <concepts>
|
|
#include <Core/Common/CoreUtils.h>
|
|
#include <Core/Memory/Allocator.h>
|
|
#include <Core/Memory/MemoryArena.h>
|
|
#include <Engine/Class.h>
|
|
#include <Entity/EntityManager.h>
|
|
#include <type_traits>
|
|
|
|
// Add any new fields into the concept below
|
|
#define DECLARE_ENTITY() \
|
|
Entity* Base; \
|
|
static const Juliet::Class* Kind;
|
|
|
|
// Will register the class globally at launch
|
|
#define DEFINE_ENTITY(entity) \
|
|
constexpr Juliet::Class entityKind##entity(#entity, sizeof(#entity) / sizeof(char)); \
|
|
const Juliet::Class* entity::Kind = &entityKind##entity;
|
|
|
|
namespace Game
|
|
{
|
|
using DerivedType = void*;
|
|
|
|
struct Entity final
|
|
{
|
|
EntityID ID;
|
|
const Juliet::Class* Kind;
|
|
DerivedType Derived;
|
|
float X, Y;
|
|
};
|
|
|
|
template <typename EntityType>
|
|
concept EntityConcept = requires(EntityType entity) {
|
|
requires std::same_as<decltype(entity.Kind), const Juliet::Class*>;
|
|
requires std::same_as<decltype(entity.Base), Entity*>;
|
|
};
|
|
|
|
template <typename EntityType>
|
|
requires EntityConcept<EntityType>
|
|
bool IsA(const Entity* entity)
|
|
{
|
|
return entity->Kind == EntityType::Kind;
|
|
}
|
|
|
|
template <typename EntityType>
|
|
requires EntityConcept<EntityType>
|
|
EntityType* MakeEntity(EntityManager& manager, float x, float y)
|
|
{
|
|
auto* arena = manager.Arena;
|
|
EntityType* result = Juliet::ArenaPushStruct<EntityType>(arena);
|
|
Entity base;
|
|
base.X = x;
|
|
base.Y = y;
|
|
base.Derived = result;
|
|
base.Kind = EntityType::Kind;
|
|
manager.Entities.PushBack(base);
|
|
|
|
result->Base = manager.Entities.Back();
|
|
|
|
RegisterEntity(manager, &base);
|
|
|
|
return result;
|
|
}
|
|
|
|
template <typename EntityType>
|
|
requires EntityConcept<EntityType>
|
|
EntityType* DownCast(Entity* entity)
|
|
{
|
|
Assert(IsA<EntityType>(entity));
|
|
return static_cast<EntityType*>(entity->Derived);
|
|
}
|
|
|
|
} // namespace Game
|