diff --git a/dGame/dEntity/Archetype.h b/dGame/dEntity/Archetype.h index e842171d5..d60c17323 100644 --- a/dGame/dEntity/Archetype.h +++ b/dGame/dEntity/Archetype.h @@ -79,15 +79,15 @@ class Archetype final : public IArchetype { /** * Constructors and assignment operators */ - Archetype(Archetype& other) noexcept : IArchetype{ std::copy(other) } { UpdatePointers(); } // Copy constructor - Archetype(Archetype&& other) noexcept : IArchetype{ std::move(other) } { UpdatePointers(); } // Move constructor + Archetype(Archetype& other) noexcept : IArchetype{ std::copy(other) } { /*UpdatePointers();*/ } // Copy constructor + Archetype(Archetype&& other) noexcept : IArchetype{ std::move(other) } { /*UpdatePointers();*/ } // Move constructor Archetype& operator=(Archetype& other) noexcept { // Copy assignment operator IArchetype::operator=(std::copy(other)); - UpdatePointers(); + /*UpdatePointers();*/ } Archetype& operator=(Archetype&& other) noexcept { // Move assignment operator IArchetype::operator=(std::move(other)); - UpdatePointers(); + /*UpdatePointers();*/ } /** @@ -104,7 +104,7 @@ class Archetype final : public IArchetype { */ template constexpr ContainerType& Container() noexcept { - static_assert(hasComponent, "Archetype does not have container of requested component!"); // Compile-time verification + static_assert(HasComponent(), "Archetype does not have container of requested component!"); // Compile-time verification return std::get>(m_Components); } @@ -136,10 +136,13 @@ class Archetype final : public IArchetype { } /** - * Function-like static bool that "returns" if an archetype contains a specified component + * Static function that returns if an archetype contains a specified component + * @returns Boolean representing component's presence */ template - static constexpr bool hasComponent = std::disjunction_v...>; + static constexpr bool HasComponent() { + return std::disjunction_v...>; + } /** * Contains the number of component types an archetype consists of diff --git a/dGame/dEntity/EntitySystem.h b/dGame/dEntity/EntitySystem.h index ae11022ee..2984bf22c 100644 --- a/dGame/dEntity/EntitySystem.h +++ b/dGame/dEntity/EntitySystem.h @@ -9,17 +9,31 @@ #include #include "Archetype.h" +#include "CharacterComponent.h" // TEMP #include "DestroyableComponent.h" // TEMP #include "SimplePhysicsComponent.h" // TEMP #include "dCommonVars.h" #include "ObjectIDManager.h" -/** - * Archetype visitor struct (for use with std::visit) -*/ -/*struct ArchetypeVisitor { - auto& operator()(auto& archetype) { return archetype->*hasComponent(); } -};*/ +namespace { + /** + * Archetype visitor structs (for use with std::visit) + */ + template + struct ComponentVisitor { + const size_t index; + + explicit ComponentVisitor(const size_t index) noexcept : index{ index } {} + + CType* const operator()(auto&& archetype) { // There might be a way to use this to do compile-time checking... + if constexpr (archetype->template HasComponent()) { + return &archetype->template Container()[index]; + } else { + return nullptr; + } + } + }; +} /** * TODO: Class documentation @@ -32,9 +46,14 @@ class EntitySystem final { using ArchetypeId = uint32_t; using ArchetypeSet = std::unordered_set; using ArchetypeVariantPtr = std::variant< + Archetype*, Archetype*, Archetype*, - Archetype* + + Archetype*, + Archetype*, + + Archetype* >; // TODO: Figure out how to generate this automatically using ComponentTypeId = std::type_index; @@ -79,7 +98,7 @@ class EntitySystem final { /** * Determine if an entity is associated with an Object ID - * + * */ bool EntityExists(const LWOOBJID entityId) noexcept { return m_EntityIndex.count(entityId) != 0; @@ -92,9 +111,11 @@ class EntitySystem final { */ template bool HasComponent(const LWOOBJID entityId) { - IArchetype* const archetype = m_EntityIndex[entityId].archetype; // Gets a pointer to the archetype containing the entity ID - ArchetypeSet& archetypeSet = m_ComponentTypeIndex[std::type_index(typeid(CType))]; // Gets the component container corresponding to the selected component type - return archetypeSet.count(archetype->id) != 0; // Check that the component exists within there + const auto& archetypeRecord = m_EntityIndex[entityId]; + + return std::visit( + [](auto&& archetype) { return archetype->template HasComponent(); }, + archetypeRecord.archetypePtr); // Using visitor pattern } /** @@ -103,12 +124,12 @@ class EntitySystem final { * @returns The pointer if the component exists, or nullptr if it does not */ template - CType* GetComponent(const LWOOBJID entityId) { - if (!HasComponent(entityId)) return nullptr; + CType* const GetComponent(const LWOOBJID entityId) { + const auto& archetypeRecord = m_EntityIndex[entityId]; - auto& archetypeRecord = m_EntityIndex[entityId]; - IArchetype* const archetype = archetypeRecord.archetype; - return &archetype->Container()[archetypeRecord.index]; + return std::visit( + ComponentVisitor{ archetypeRecord.index }, + archetypeRecord.archetypePtr); // Using visitor pattern } protected: @@ -137,9 +158,7 @@ class EntitySystem final { ArchetypeId m_CurrentArchetypeId{ 0 }; struct ArchetypeRecord { - IArchetype* archetype; // Could we potentially make this std::variant in order to deduce the type? - //ArchetypeVariantPtr archetype; - //size_t type = archetype.index(); + ArchetypeVariantPtr archetypePtr; size_t index; }; diff --git a/tests/dGameTests/dEntitiesTests/ArchetypeTests.cpp b/tests/dGameTests/dEntitiesTests/ArchetypeTests.cpp index 733ff280b..b7bef3d63 100644 --- a/tests/dGameTests/dEntitiesTests/ArchetypeTests.cpp +++ b/tests/dGameTests/dEntitiesTests/ArchetypeTests.cpp @@ -93,19 +93,20 @@ TEST_F(ArchetypeTest, ArchetypeDeleteTest) { //Deleting more entries than exist will cause a segfault currently. Wonder if that's actually an issue... } -TEST_F(ArchetypeTest, ReadFromArchetypeTest) { - auto& simplePhysicsContainer = baseArchetype->Container(); - auto& destroyableContainer = baseArchetype->Container(); +/*TEST_F(ArchetypeTest, ReadFromArchetypeTest) { + //auto& simplePhysicsContainer = baseArchetype->Container(); + //auto& destroyableContainer = baseArchetype->Container(); + auto entitySystem = std::make_unique(); std::vector> tempEntity; // Vector of temporary entities (so they die when this test goes out of scope) - LOG("Number of entries per vector: %d", 1000); //simplePhysicsContainer.capacity() + LOG("Number of entries per vector: %d", 1000); srand(time(NULL)); for (auto i = 0; i < 1000; ++i) { tempEntity.emplace_back(std::make_unique(rand() + i, GameDependenciesTest::info)); // Create a new entity const auto tempEntityId = tempEntity[i]->GetObjectID(); - baseArchetype->CreateComponents(DestroyableComponent(tempEntityId), SimplePhysicsComponent(tempEntityId, 2)); + entitySystem->CreateEntity(tempEntityId, DestroyableComponent(tempEntityId), SimplePhysicsComponent(tempEntityId, 2)); } // Benchmarking