diff --git a/include/UECS/Entity.hpp b/include/UECS/Entity.hpp index c0fce1e..006b483 100644 --- a/include/UECS/Entity.hpp +++ b/include/UECS/Entity.hpp @@ -2,25 +2,18 @@ #include "details/Util.hpp" +#include +#include + namespace Ubpa::UECS { // index + version - class Entity { - public: - constexpr Entity(std::size_t idx, std::size_t version) noexcept : idx(idx), version(version) {} - constexpr Entity() noexcept : Entity{ Invalid() } {} - constexpr std::size_t Idx() const noexcept { return idx; } - constexpr std::size_t Version() const noexcept { return version; } - static constexpr Entity Invalid() noexcept { return { static_cast(-1),static_cast(-1) }; } - constexpr bool Valid() const noexcept { return idx != static_cast(-1); } - constexpr bool operator==(const Entity& rhs) const noexcept { - return idx == rhs.idx && version == rhs.version; - } - constexpr bool operator<(const Entity& rhs) const noexcept { - return idx < rhs.idx || (idx == rhs.idx && version < rhs.version); - } - private: - friend class EntityMngr; - std::size_t idx; + struct Entity { + std::size_t index; std::size_t version; + + static constexpr Entity Invalid() noexcept { return { .index = static_cast(-1), .version = static_cast(-1) }; } + constexpr bool Valid() const noexcept { return index != static_cast(-1); } + constexpr auto operator<=>(const Entity&) const = default; }; + static_assert(std::is_trivial_v); } diff --git a/include/UECS/EntityQuery.hpp b/include/UECS/EntityQuery.hpp index ace470b..2a0ce98 100644 --- a/include/UECS/EntityQuery.hpp +++ b/include/UECS/EntityQuery.hpp @@ -13,10 +13,15 @@ namespace Ubpa::UECS { std::size_t GetValue() const noexcept { return hash_combine(filter.GetValue(), locator.GetValue()); } bool IsMatch(const small_flat_set& types) const noexcept{ - return std::find_if_not(filter.all.begin(), filter.all.end(), [&](const auto& type) { return types.contains(type); }) == filter.all.end() + return std::find_if_not(filter.all.begin(), filter.all.end(), + [&](const auto& type) { return types.contains(type); }) == filter.all.end() && (filter.any.empty() - || std::find_if(filter.any.begin(), filter.any.end(), [&](const auto& type) { return types.contains(type); }) != filter.any.end()) - && std::find_if(filter.none.begin(), filter.none.end(), [&](const auto& type) { return types.contains(type); }) == filter.none.end(); + || std::find_if(filter.any.begin(), filter.any.end(), + [&](const auto& type) { return types.contains(type); }) != filter.any.end()) + && std::find_if(filter.none.begin(), filter.none.end(), + [&](const auto& type) { return types.contains(type); }) == filter.none.end() + && std::find_if_not(locator.AccessTypeIDs().begin(), locator.AccessTypeIDs().end(), + [&](const auto& type) { return types.contains(type); }) == locator.AccessTypeIDs().end(); } friend bool operator==(const EntityQuery& lhs, const EntityQuery& rhs) noexcept { diff --git a/include/UECS/IListener.hpp b/include/UECS/IListener.hpp index e1c5ad7..ab668e7 100644 --- a/include/UECS/IListener.hpp +++ b/include/UECS/IListener.hpp @@ -3,7 +3,7 @@ namespace Ubpa::UECS { class World; class EntityMngr; - class Entity; + struct Entity; class CmptPtr; class IListener { diff --git a/include/UECS/details/CmptTag.inl b/include/UECS/details/CmptTag.inl index 3192aa2..a5229f4 100644 --- a/include/UECS/details/CmptTag.inl +++ b/include/UECS/details/CmptTag.inl @@ -3,7 +3,7 @@ #include namespace Ubpa::UECS { - class Entity; + struct Entity; class CmptLocator; class World; } diff --git a/src/core/Archetype.cpp b/src/core/Archetype.cpp index 3db0b4f..65d1ddb 100644 --- a/src/core/Archetype.cpp +++ b/src/core/Archetype.cpp @@ -32,10 +32,10 @@ Archetype::Archetype(std::pmr::memory_resource* rsrc, const Archetype& src) cmptTraits = src.cmptTraits; entityNum = src.entityNum; chunkCapacity = src.chunkCapacity; + offsets = src.offsets; chunks.resize(src.chunks.size(), nullptr); - if (cmptTraits.IsTrivial()) { // [0, src.chunks.size() - 1) for (std::size_t i = 0; i < src.chunks.size() - 1; i++) { @@ -133,7 +133,7 @@ Archetype* Archetype::New(RTDCmptTraits& rtdCmptTraits, std::pmr::memory_resourc Archetype* Archetype::Add(RTDCmptTraits& rtdCmptTraits, const Archetype* from, std::span types) { assert(std::find(types.begin(), types.end(), TypeID_of) == types.end()); - assert(std::find_if_not(types.begin(), types.end(), [&](const auto& type) { return from->cmptTraits.GetTypes().contains(type); }) == types.end()); + assert(std::find_if_not(types.begin(), types.end(), [&](const auto& type) { return from->cmptTraits.GetTypes().contains(type); }) != types.end()); auto* rst = new Archetype{ from->chunkAllocator.resource() }; @@ -306,7 +306,7 @@ std::size_t Archetype::Erase(std::size_t idx) { byte* src = srcBuffer + offset + srcIdxInChunk * size; if (cmptTraits.GetTypes().data()[i].Is()) - movedIdx = reinterpret_cast(src)->Idx(); + movedIdx = reinterpret_cast(src)->index; trait.MoveAssign(dst, src); trait.Destruct(src); diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index 3dbde4e..339d138 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -59,18 +59,18 @@ void EntityMngr::Clear() { bool EntityMngr::Have(Entity e, TypeID type) const { assert(!type.Is()); if (!Exist(e)) throw std::invalid_argument("EntityMngr::Have: Entity is invalid"); - return entityTable[e.Idx()].archetype->GetCmptTraits().GetTypes().contains(type); + return entityTable[e.index].archetype->GetCmptTraits().GetTypes().contains(type); } CmptPtr EntityMngr::Get(Entity e, TypeID type) const { assert(!type.Is()); if (!Exist(e)) throw std::invalid_argument("EntityMngr::Get: Entity is invalid"); - const auto& info = entityTable[e.Idx()]; + const auto& info = entityTable[e.index]; return { type, info.archetype->At(type, info.idxInArchetype) }; } bool EntityMngr::Exist(Entity e) const noexcept { - return e.Idx() < entityTable.size() && e.Version() == entityTable[e.Idx()].version; + return e.index < entityTable.size() && e.version == entityTable[e.index].version; } std::size_t EntityMngr::RequestEntityFreeEntry() { @@ -88,12 +88,12 @@ std::size_t EntityMngr::RequestEntityFreeEntry() { void EntityMngr::RecycleEntityEntry(Entity e) { assert(Exist(e)); - auto& info = entityTable[e.Idx()]; + auto& info = entityTable[e.index]; info.archetype = nullptr; info.idxInArchetype = static_cast(-1); info.version++; - entityTableFreeEntry.push_back(e.Idx()); + entityTableFreeEntry.push_back(e.index); } Archetype* EntityMngr::GetOrCreateArchetypeOf(std::span types) { @@ -127,7 +127,7 @@ void EntityMngr::Attach(Entity e, std::span types) { assert(IsSet(types)); if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); - auto& info = entityTable[e.Idx()]; + auto& info = entityTable[e.index]; Archetype* srcArchetype = info.archetype; std::size_t srcIdxInArchetype = info.idxInArchetype; @@ -187,7 +187,7 @@ void EntityMngr::Detach(Entity e, std::span types) { assert(IsSet(types)); if (!Exist(e)) throw std::invalid_argument("EntityMngr::Detach: Entity is invalid"); - auto& info = entityTable[e.Idx()]; + auto& info = entityTable[e.index]; Archetype* srcArchetype = info.archetype; const auto& srcTypeIDSet = srcArchetype->GetCmptTraits().GetTypes(); @@ -241,7 +241,7 @@ void EntityMngr::Detach(Entity e, std::span types) { vector EntityMngr::Components(Entity e) const { if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); - const auto& info = entityTable[e.Idx()]; + const auto& info = entityTable[e.index]; return info.archetype->Components(info.idxInArchetype); } @@ -249,7 +249,7 @@ Entity EntityMngr::Instantiate(Entity srcEntity) { if (!Exist(srcEntity)) throw std::invalid_argument("Entity is invalid"); std::size_t dstEntityIndex = RequestEntityFreeEntry(); - const auto& srcInfo = entityTable[srcEntity.Idx()]; + const auto& srcInfo = entityTable[srcEntity.index]; auto& dstInfo = entityTable[dstEntityIndex]; Entity dstEntity{ dstEntityIndex, dstInfo.version }; std::size_t dstIndexInArchetype = srcInfo.archetype->Instantiate(dstEntity, srcInfo.idxInArchetype); @@ -293,7 +293,7 @@ std::size_t EntityMngr::EntityNum(const EntityQuery& query) const { void EntityMngr::Destroy(Entity e) { if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); - auto info = entityTable[e.Idx()]; + auto info = entityTable[e.index]; auto* archetype = info.archetype; auto idxInArchetype = info.idxInArchetype; diff --git a/src/test/01_tag/main.cpp b/src/test/01_tag/main.cpp index aaa9eb2..a3a706d 100644 --- a/src/test/01_tag/main.cpp +++ b/src/test/01_tag/main.cpp @@ -21,10 +21,10 @@ struct DataSystem { int main() { World w; - w.entityMngr.cmptTraits.Register(); + w.entityMngr.cmptTraits.Register(); w.systemMngr.RegisterAndActivate(); - w.entityMngr.Create(Ubpa::TypeIDs_of); + w.entityMngr.Create(Ubpa::TypeIDs_of); w.Update(); diff --git a/src/test/10_instantiate/main.cpp b/src/test/10_instantiate/main.cpp index 050484e..086910f 100644 --- a/src/test/10_instantiate/main.cpp +++ b/src/test/10_instantiate/main.cpp @@ -10,7 +10,7 @@ struct A { float val; }; struct MySystem { static void OnUpdate(Schedule& schedule) { schedule.RegisterEntityJob([](Entity e, const A* a) { - cout << e.Idx() << ": " << a->val << endl; + cout << e.index << ": " << a->val << endl; }, "MySystem", false); } }; diff --git a/src/test/17_serial/main.cpp b/src/test/17_serial/main.cpp index 7db194d..9f0caa7 100644 --- a/src/test/17_serial/main.cpp +++ b/src/test/17_serial/main.cpp @@ -42,7 +42,7 @@ int main() { w.entityMngr.Create(); w.RunEntityJob([](Entity e) { - std::cout << e.Idx() << std::endl; + std::cout << e.index << std::endl; }, false); std::cout << w.DumpUpdateJobGraph() << std::endl;