Files
Juliet/Game/Entity/Entity.h
2025-02-01 21:03:22 -05:00

71 lines
2.3 KiB
C++

#pragma once
#include <concepts>
#include <Core/Common/CoreUtils.h>
#include <Core/Memory/Allocator.h>
#include <Engine/Class.h>
#include <Entity/EntityManager.h>
#include <type_traits>
// Add any new fields into the concept below
#define DECLARE_ENTITY(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)
{
EntityType* result = static_cast<EntityType*>(Juliet::Calloc(1, sizeof(EntityType)));
Entity* base = result->Base = static_cast<Entity*>(Juliet::Calloc(1, sizeof(Entity)));
base->X = x;
base->Y = y;
base->Derived = result;
base->Kind = EntityType::Kind;
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