#pragma once #include #include #include #include #include #include #include // 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 concept EntityConcept = requires(EntityType entity) { requires std::same_as; requires std::same_as; }; template requires EntityConcept bool IsA(const Entity* entity) { return entity->Kind == EntityType::Kind; } template requires EntityConcept EntityType* MakeEntity(EntityManager& manager, float x, float y) { auto* arena = manager.Arena; EntityType* result = Juliet::ArenaPushStruct(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 requires EntityConcept EntityType* DownCast(Entity* entity) { Assert(IsA(entity)); return static_cast(entity->Derived); } } // namespace Game