#pragma once #include #include #include #include #include #include #define DECLARE_ENTITY() \ Entity* base; \ DECLARE_CLASS() #define DEFINE_ENTITY_VERSIONED(entity, version, serialize_fct) \ constexpr Class entityKind##entity = MakeClass(ConstString(#entity), (uint8)Entity_Type::entity, (version), \ &classKindEntity, sizeof(entity), alignof(entity), (serialize_fct)); \ Class* entity::kind = const_cast(&entityKind##entity); struct EntityManager; using DerivedType = void*; using EntityID = uint64_t; struct Entity final { DECLARE_CLASS() EntityID ID = 0; Class* derived_kind = nullptr; DerivedType derived = nullptr; Vector4 position = {}; }; struct Inert { DECLARE_ENTITY() index_t MeshInstance = indexMax; }; // 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" }; #undef AS_STR #define AS_CLASS(name) name::kind inline Class* kEntity_type_class_ptr[] { ENTITY_TYPE_LIST(AS_CLASS) nullptr }; #undef AS_CLASS #define ENTITY(kind) ToUnderlying(Entity_Type::kind) // clang-format on // Can reinterpret cast to this to have the offset of Base and Kind for any entity struct entity_template { DECLARE_ENTITY(); }; // 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->derived_kind == EntityType::kind; } template requires EntityConcept [[nodiscard]] EntityType* MakeEntity(EntityManager& manager, float x, float y, float z) { EntityType result; Entity base; base.position.x = x; base.position.y = y; base.position.z = z; base.position.w = 1.0f; base.derived_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); } void serialize(Archive& ar, NonNullPtr entity);