#pragma once #include #include #include #include #include #define DECLARE_ENTITY() \ Entity* Base; \ static const Class* Kind; // Will register the class globally at launch #define DEFINE_ENTITY(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 = 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 concept EntityConcept = requires(EntityType entity) { { EntityType::Kind } -> std::convertible_to; requires std::same_as; }; template requires EntityConcept [[nodiscard]] bool IsA(const Entity* entity) { Assert(entity != nullptr); return entity->Kind == EntityType::Kind; } template requires EntityConcept [[nodiscard]] EntityType* MakeEntity(EntityManager& manager, float x, float y, float z) { EntityType result; Entity base; base.X = x; base.Y = y; base.Z = z; base.Kind = EntityType::Kind; return (EntityType*)RegisterEntity(manager, &base, &result); } template requires EntityConcept [[nodiscard]] EntityType* DownCast(Entity* entity) { Assert(entity != nullptr); Assert(IsA(entity)); return static_cast(entity->Derived); }