#pragma once #include #include #include #include #include struct Entity final { DECLARE_CLASS() EntityID ID = 0; const Class* derived_kind = nullptr; DerivedType derived = nullptr; Vector4 position = {}; bool is_dirty = false; }; // Can reinterpret cast to this to have the offset of Base and Kind for any entity struct EntityTemplate { 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) { Entity* base_ptr = allocate_entity(manager, EntityType::kind); Assert(base_ptr); base_ptr->ID = EntityManager::ID++; base_ptr->position.x = x; base_ptr->position.y = y; base_ptr->position.z = z; base_ptr->position.w = 1.0f; return (EntityType*)base_ptr->derived; } 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); [[nodiscard]] const Class* find_class_by_name(String name); [[nodiscard]] const Class* resolve_entity_class(uint8 kind, uint32 crc);