diff --git a/doc/changelog.md b/doc/changelog.md index ff617de..f6a4c5b 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,6 +1,8 @@ # Change Log -- 0.14.3: `CmptsView`, `SingletonsView` use `Span` +- 0.14.3 + - `CmptsView`, `SingletonsView` use `Span` + - API with `const CmptType* types, size_t num` use `Span types` as instead - 0.14.2 - add `RandomAccessor` for random access other entity's component - `SystemFunc` add the member diff --git a/include/UECS/CmptLocator.h b/include/UECS/CmptLocator.h index 2be7301..88f546a 100644 --- a/include/UECS/CmptLocator.h +++ b/include/UECS/CmptLocator.h @@ -29,7 +29,7 @@ namespace Ubpa::UECS { bool HasWriteCmptType() const noexcept; private: - size_t GenHashCode() const noexcept; + void UpdateHashCode() noexcept; CmptAccessTypeSet cmptTypes; diff --git a/include/UECS/EntityMngr.h b/include/UECS/EntityMngr.h index a25bf77..89689db 100644 --- a/include/UECS/EntityMngr.h +++ b/include/UECS/EntityMngr.h @@ -35,7 +35,7 @@ namespace Ubpa::UECS { std::tuple Create(); // use RTDCmptTraits - Entity Create(const CmptType* types, size_t num); + Entity Create(Span types); Entity Instantiate(Entity); @@ -45,7 +45,7 @@ namespace Ubpa::UECS { std::tuple Attach(Entity); // use RTDCmptTraits - void Attach(Entity, const CmptType* types, size_t num); + void Attach(Entity, Span types); template Cmpt* Emplace(Entity, Args&&...); @@ -53,7 +53,7 @@ namespace Ubpa::UECS { // use Detach(Entity, const CmptType*, size_t) template void Detach(Entity); - void Detach(Entity, const CmptType* types, size_t num); + void Detach(Entity, Span types); // use Have(Entity, CmptType) template @@ -99,17 +99,17 @@ namespace Ubpa::UECS { friend class World; friend class Archetype; - static bool IsSet(const CmptType* types, size_t num) noexcept; + static bool IsSet(Span types) noexcept; template Archetype* GetOrCreateArchetypeOf(); // types not contain Entity - Archetype* GetOrCreateArchetypeOf(const CmptType* types, size_t num); + Archetype* GetOrCreateArchetypeOf(Span types); // return original archetype template Archetype* AttachWithoutInit(Entity); - Archetype* AttachWithoutInit(Entity, const CmptType* types, size_t num); + Archetype* AttachWithoutInit(Entity, Span types); const std::set& QueryArchetypes(const EntityQuery&) const; mutable std::unordered_map> queryCache; diff --git a/include/UECS/EntityQuery.h b/include/UECS/EntityQuery.h index de6d0e1..88f36ed 100644 --- a/include/UECS/EntityQuery.h +++ b/include/UECS/EntityQuery.h @@ -6,14 +6,10 @@ namespace Ubpa::UECS { // ArchetypeFilter + CmptLocator - class EntityQuery { - public: + struct EntityQuery { ArchetypeFilter filter; CmptLocator locator; - EntityQuery(ArchetypeFilter filter = {}, CmptLocator locator = {}) - : filter{ std::move(filter) }, locator{ std::move(locator) } {} - size_t HashCode() const noexcept { return hash_combine(filter.HashCode(), locator.HashCode()); } bool operator==(const EntityQuery& query) const noexcept { diff --git a/include/UECS/SingletonLocator.h b/include/UECS/SingletonLocator.h index 565d86a..29042e6 100644 --- a/include/UECS/SingletonLocator.h +++ b/include/UECS/SingletonLocator.h @@ -2,12 +2,14 @@ #include "CmptType.h" +#include + #include namespace Ubpa::UECS { class SingletonLocator { public: - SingletonLocator(const CmptAccessType* types, size_t num); + SingletonLocator(Span types); SingletonLocator() = default; template diff --git a/include/UECS/detail/Archetype.h b/include/UECS/detail/Archetype.h index d97574f..b2e9f47 100644 --- a/include/UECS/detail/Archetype.h +++ b/include/UECS/detail/Archetype.h @@ -11,9 +11,6 @@ #include #include -#include - -#include namespace Ubpa::UECS { class EntityMngr; @@ -36,15 +33,15 @@ namespace Ubpa::UECS { ~Archetype(); // auto add Entity - static Archetype* New(RTDCmptTraits&, Pool* chunkPool, const CmptType* types, size_t num); + static Archetype* New(RTDCmptTraits&, Pool* chunkPool, Span types); // auto add Entity template static Archetype* Add(const Archetype* from); - static Archetype* Add(RTDCmptTraits&, const Archetype* from, const CmptType* types, size_t num); + static Archetype* Add(RTDCmptTraits&, const Archetype* from, Span types); // auto add Entity - static Archetype* Remove(const Archetype* from, const CmptType* types, size_t num); + static Archetype* Remove(const Archetype* from, Span types); // Entity + Components std::tuple, std::vector>, std::vector> @@ -94,7 +91,7 @@ namespace Ubpa::UECS { size_t ChunkCapacity() const noexcept { return chunkCapacity; } // add Entity - static CmptTypeSet GenCmptTypeSet(const CmptType* types, size_t num); + static CmptTypeSet GenCmptTypeSet(Span types); template static CmptTypeSet GenCmptTypeSet(); @@ -104,7 +101,7 @@ namespace Ubpa::UECS { void SetLayout(); size_t Offsetof(CmptType type) const { return type2offset.at(type); } - static bool NotContainEntity(const CmptType* types, size_t num) noexcept; + static bool NotContainEntity(Span types) noexcept; friend class EntityMngr; diff --git a/include/UECS/detail/Archetype.inl b/include/UECS/detail/Archetype.inl index e8157d7..56ef470 100644 --- a/include/UECS/detail/Archetype.inl +++ b/include/UECS/detail/Archetype.inl @@ -62,9 +62,9 @@ namespace Ubpa::UECS { "... must be different"); constexpr std::array types = { CmptType::Of... }; - return GenCmptTypeSet(types.data(), types.size()); + return GenCmptTypeSet(types); } else - return GenCmptTypeSet(nullptr, 0); + return GenCmptTypeSet({}); } } diff --git a/include/UECS/detail/Chunk.h b/include/UECS/detail/Chunk.h index ed7019b..47c01ae 100644 --- a/include/UECS/detail/Chunk.h +++ b/include/UECS/detail/Chunk.h @@ -2,7 +2,6 @@ #include #include -#include #include #include "../config.h" diff --git a/include/UECS/detail/CmptTypeSet.h b/include/UECS/detail/CmptTypeSet.h index ed7ae76..de8efb2 100644 --- a/include/UECS/detail/CmptTypeSet.h +++ b/include/UECS/detail/CmptTypeSet.h @@ -1,10 +1,8 @@ #pragma once -#include "Util.h" #include "../EntityQuery.h" -#include -#include +#include #include @@ -14,15 +12,15 @@ namespace Ubpa::UECS { size_t HashCode() const noexcept; - void Insert(const CmptType* types, size_t num); - void Erase(const CmptType* types, size_t num) noexcept; + void Insert(Span types); + void Erase(Span types) noexcept; bool Contains(CmptType type) const; - bool ContainsAll(const CmptType* types, size_t num) const; + bool ContainsAll(Span types) const; template bool ContainsAll(const CmptTypeContainer& types) const; - bool ContainsAny(const CmptType* types, size_t num) const; + bool ContainsAny(Span types) const; template bool ContainsAny(const CmptTypeContainer& types) const; diff --git a/include/UECS/detail/CmptTypeSet.inl b/include/UECS/detail/CmptTypeSet.inl index 5e8f91b..f122c3c 100644 --- a/include/UECS/detail/CmptTypeSet.inl +++ b/include/UECS/detail/CmptTypeSet.inl @@ -1,26 +1,23 @@ #pragma once namespace Ubpa::UECS { - inline void CmptTypeSet::Insert(const CmptType* types, size_t num) { - assert(types || num == 0); - for (size_t i = 0; i < num; i++) - data.insert(types[i]); + inline void CmptTypeSet::Insert(Span types) { + for(const auto& type : types) + data.insert(type); } - inline void CmptTypeSet::Erase(const CmptType* types, size_t num) noexcept { - assert(types || num == 0); - for (size_t i = 0; i < num; i++) - data.erase(types[i]); + inline void CmptTypeSet::Erase(Span types) noexcept { + for (const auto& type : types) + data.erase(type); } inline bool CmptTypeSet::Contains(CmptType type) const { return data.find(type) != data.end(); } - inline bool CmptTypeSet::ContainsAll(const CmptType* types, size_t num) const { - assert(types || num == 0); - for (size_t i = 0; i < num; i++) { - if (!Contains(types[i])) + inline bool CmptTypeSet::ContainsAll(Span types) const { + for (const auto& type : types) { + if (Contains(type)) return false; } return true; @@ -35,10 +32,9 @@ namespace Ubpa::UECS { return true; } - inline bool CmptTypeSet::ContainsAny(const CmptType* types, size_t num) const { - assert(types || num == 0); - for (size_t i = 0; i < num; i++) { - if (Contains(types[i])) + inline bool CmptTypeSet::ContainsAny(Span types) const { + for (const auto& type : types) { + if (!Contains(type)) return true; } return false; diff --git a/include/UECS/detail/CmptsLocator.inl b/include/UECS/detail/CmptsLocator.inl index 902c028..0d25c0c 100644 --- a/include/UECS/detail/CmptsLocator.inl +++ b/include/UECS/detail/CmptsLocator.inl @@ -27,6 +27,7 @@ namespace Ubpa::UECS { CmptLocator& CmptLocator::Combine() { CmptLocator funcLocator = Generate(); cmptTypes = SetUnion(cmptTypes, funcLocator.cmptTypes); + UpdateHashCode(); return *this; } } diff --git a/include/UECS/detail/EntityMngr.inl b/include/UECS/detail/EntityMngr.inl index f433da1..728492e 100644 --- a/include/UECS/detail/EntityMngr.inl +++ b/include/UECS/detail/EntityMngr.inl @@ -102,7 +102,7 @@ namespace Ubpa::UECS { template void EntityMngr::Detach(Entity e) { constexpr std::array types{ CmptType::Of... }; - Detach(e, types.data, types.size()); + Detach(e, types); } template diff --git a/include/UECS/detail/SingletonLocator.inl b/include/UECS/detail/SingletonLocator.inl index 5be06dd..76d7bdc 100644 --- a/include/UECS/detail/SingletonLocator.inl +++ b/include/UECS/detail/SingletonLocator.inl @@ -8,10 +8,10 @@ namespace Ubpa::UECS::detail { SingletonLocator GenerateSingletonLocator(TypeList) { if constexpr (sizeof...(Singletons) > 0) { constexpr std::array types{ CmptAccessType::Of... }; - return SingletonLocator{ types.data(), types.size() }; + return SingletonLocator{ types }; } else - return SingletonLocator{}; + return SingletonLocator{{}}; } } diff --git a/src/core/Archetype.cpp b/src/core/Archetype.cpp index 0efa259..54bf961 100644 --- a/src/core/Archetype.cpp +++ b/src/core/Archetype.cpp @@ -82,47 +82,47 @@ void Archetype::SetLayout() { type2offset.emplace(type, layout.offsets[i++]); } -Archetype* Archetype::New(RTDCmptTraits& rtdCmptTraits, Pool* chunkPool, const CmptType* types, size_t num) { - assert(NotContainEntity(types, num)); +Archetype* Archetype::New(RTDCmptTraits& rtdCmptTraits, Pool* chunkPool, Span types) { + assert(NotContainEntity(types)); auto* rst = new Archetype{ chunkPool }; - rst->types.Insert(types, num); + rst->types.Insert(types); rst->types.data.insert(CmptType::Of); rst->cmptTraits.Register(); - for (size_t i = 0; i < num; i++) - rst->cmptTraits.Register(rtdCmptTraits, types[i]); + for(const auto& type : types) + rst->cmptTraits.Register(rtdCmptTraits, type); rst->SetLayout(); return rst; } -Archetype* Archetype::Add(RTDCmptTraits& rtdCmptTraits, const Archetype* from, const CmptType* types, size_t num) { - assert(NotContainEntity(types, num)); - assert(!from->types.ContainsAll(types, num)); +Archetype* Archetype::Add(RTDCmptTraits& rtdCmptTraits, const Archetype* from, Span types) { + assert(NotContainEntity(types)); + assert(!from->types.ContainsAll(types)); auto* rst = new Archetype{ from->chunkPool }; rst->types = from->types; rst->cmptTraits = from->cmptTraits; - rst->types.Insert(types, num); - for (size_t i = 0; i < num; i++) - rst->cmptTraits.Register(rtdCmptTraits, types[i]); + rst->types.Insert(types); + for (const auto& type : types) + rst->cmptTraits.Register(rtdCmptTraits, type); rst->SetLayout(); return rst; } -Archetype* Archetype::Remove(const Archetype* from, const CmptType* types, size_t num) { - assert(NotContainEntity(types, num)); - assert(from->types.ContainsAny(types, num)); +Archetype* Archetype::Remove(const Archetype* from, Span types) { + assert(NotContainEntity(types)); + assert(from->types.ContainsAny(types)); auto* rst = new Archetype{ from->chunkPool }; rst->types = from->types; rst->cmptTraits = from->cmptTraits; - rst->types.Erase(types, num); - for (size_t i = 0; i < num; i++) - rst->cmptTraits.Deregister(types[i]); + rst->types.Erase(types); + for (const auto& type : types) + rst->cmptTraits.Deregister(type); rst->SetLayout(); @@ -309,18 +309,17 @@ size_t Archetype::EntityNumOfChunk(size_t chunkIdx) const noexcept { return chunkCapacity; } -CmptTypeSet Archetype::GenCmptTypeSet(const CmptType* types, size_t num) { - assert(NotContainEntity(types, num)); +CmptTypeSet Archetype::GenCmptTypeSet(Span types) { + assert(NotContainEntity(types)); CmptTypeSet typeset; - typeset.Insert(types, num); + typeset.Insert(types); typeset.data.insert(CmptType::Of); return typeset; } -bool Archetype::NotContainEntity(const CmptType* types, size_t num) noexcept { - assert(types || num == 0); - for (size_t i = 0; i < num; i++) { - if (types[i].Is()) +bool Archetype::NotContainEntity(Span types) noexcept { + for (const auto& type : types) { + if (type.Is()) return false; } return true; diff --git a/src/core/CmptLocator.cpp b/src/core/CmptLocator.cpp index 873ee6a..91362e4 100644 --- a/src/core/CmptLocator.cpp +++ b/src/core/CmptLocator.cpp @@ -9,17 +9,17 @@ CmptLocator::CmptLocator(const CmptAccessType* types, size_t num) { for (size_t i = 0; i < num; i++) cmptTypes.insert(types[i]); - hashCode = GenHashCode(); + UpdateHashCode(); } CmptLocator::CmptLocator() : hashCode{ TypeID } {} -size_t CmptLocator::GenHashCode() const noexcept { +void CmptLocator::UpdateHashCode() noexcept { size_t rst = TypeID; for (const auto& type : cmptTypes) rst = hash_combine(rst, type.HashCode()); - return rst; + hashCode = rst; } bool CmptLocator::HasWriteCmptType() const noexcept { diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index e31f2c4..2640909 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -66,13 +66,13 @@ void EntityMngr::RecycleEntityEntry(Entity e) { entityTableFreeEntry.push_back(e.Idx()); } -Archetype* EntityMngr::GetOrCreateArchetypeOf(const CmptType* types, size_t num) { - auto typeset = Archetype::GenCmptTypeSet(types, num); +Archetype* EntityMngr::GetOrCreateArchetypeOf(Span types) { + auto typeset = Archetype::GenCmptTypeSet(types); auto target = ts2a.find(typeset); if (target != ts2a.end()) return target->second.get(); - auto* archetype = Archetype::New(cmptTraits, sharedChunkPool.get(), types, num); + auto* archetype = Archetype::New(cmptTraits, sharedChunkPool.get(), types); ts2a.emplace(std::move(typeset), std::unique_ptr{ archetype }); for (auto& [query, archetypes] : queryCache) { @@ -83,8 +83,8 @@ Archetype* EntityMngr::GetOrCreateArchetypeOf(const CmptType* types, size_t num) return archetype; } -Entity EntityMngr::Create(const CmptType* types, size_t num) { - Archetype* archetype = GetOrCreateArchetypeOf(types, num); +Entity EntityMngr::Create(Span types) { + Archetype* archetype = GetOrCreateArchetypeOf(types); size_t entityIndex = RequestEntityFreeEntry(); auto& info = entityTable[entityIndex]; Entity e{ entityIndex, info.version }; @@ -93,9 +93,8 @@ Entity EntityMngr::Create(const CmptType* types, size_t num) { return e; } -Archetype* EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t num) { - assert(types != nullptr && num > 0); - assert(IsSet(types, num)); +Archetype* EntityMngr::AttachWithoutInit(Entity e, Span types) { + assert(IsSet(types)); if (!Exist(e)) throw std::invalid_argument("Entity is invalid"); auto& info = entityTable[e.Idx()]; @@ -104,13 +103,13 @@ Archetype* EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t const auto& srcCmptTypeSet = srcArchetype->GetCmptTypeSet(); auto dstCmptTypeSet = srcCmptTypeSet; - dstCmptTypeSet.Insert(types, num); + dstCmptTypeSet.Insert(types); // get dstArchetype Archetype* dstArchetype; auto target = ts2a.find(dstCmptTypeSet); if (target == ts2a.end()) { - dstArchetype = Archetype::Add(cmptTraits, srcArchetype, types, num); + dstArchetype = Archetype::Add(cmptTraits, srcArchetype, types); assert(dstCmptTypeSet == dstArchetype->GetCmptTypeSet()); for (auto& [query, archetypes] : queryCache) { if (dstCmptTypeSet.IsMatch(query)) @@ -145,11 +144,10 @@ Archetype* EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t return srcArchetype; } -void EntityMngr::Attach(Entity e, const CmptType* types, size_t num) { - auto* origArchetype = AttachWithoutInit(e, types, num); +void EntityMngr::Attach(Entity e, Span types) { + auto* origArchetype = AttachWithoutInit(e, types); const auto& info = entityTable[e.Idx()]; - for (size_t i = 0; i < num; i++) { - const auto& type = types[i]; + for (const auto& type : types) { if (origArchetype->GetCmptTypeSet().Contains(type)) continue; @@ -161,9 +159,8 @@ void EntityMngr::Attach(Entity e, const CmptType* types, size_t num) { } } -void EntityMngr::Detach(Entity e, const CmptType* types, size_t num) { - assert(types != nullptr && num > 0); - assert(IsSet(types, num)); +void EntityMngr::Detach(Entity e, Span types) { + assert(IsSet(types)); if (!Exist(e)) throw std::invalid_argument("EntityMngr::Detach: Entity is invalid"); auto& info = entityTable[e.Idx()]; @@ -171,7 +168,7 @@ void EntityMngr::Detach(Entity e, const CmptType* types, size_t num) { const auto& srcCmptTypeSet = srcArchetype->GetCmptTypeSet(); auto dstCmptTypeSet = srcCmptTypeSet; - dstCmptTypeSet.Erase(types, num); + dstCmptTypeSet.Erase(types); // get dstArchetype Archetype* dstArchetype; @@ -179,7 +176,7 @@ void EntityMngr::Detach(Entity e, const CmptType* types, size_t num) { auto target = ts2a.find(dstCmptTypeSet); if (target == ts2a.end()) { isNewArchetype = true; - dstArchetype = Archetype::Remove(srcArchetype, types, num); + dstArchetype = Archetype::Remove(srcArchetype, types); assert(dstCmptTypeSet == dstArchetype->GetCmptTypeSet()); for (auto& [query, archetypes] : queryCache) { if (dstCmptTypeSet.IsMatch(query)) @@ -236,10 +233,8 @@ Entity EntityMngr::Instantiate(Entity srcEntity) { return dstEntity; } -bool EntityMngr::IsSet(const CmptType* types, size_t num) noexcept { - assert(types || num == 0); - - for (size_t i = 0; i < num; i++) { +bool EntityMngr::IsSet(Span types) noexcept { + for (size_t i = 0; i < types.size(); i++) { for (size_t j = 0; j < i; j++) if (types[i] == types[j]) return false; @@ -499,7 +494,7 @@ void EntityMngr::Accept(IListener* listener) const { bool EntityMngr::IsSingleton(CmptType t) const { ArchetypeFilter filter{ {CmptAccessType{t}}, {}, {} }; - EntityQuery query(move(filter)); + EntityQuery query{ move(filter) }; const auto& archetypes = QueryArchetypes(query); if (archetypes.size() != 1) return false; @@ -513,7 +508,7 @@ bool EntityMngr::IsSingleton(CmptType t) const { Entity EntityMngr::GetSingletonEntity(CmptType t) const { assert(IsSingleton(t)); ArchetypeFilter filter{ {CmptAccessType{t}}, {}, {} }; - EntityQuery query(move(filter)); + EntityQuery query{ move(filter) }; const auto& archetypes = QueryArchetypes(query); auto* archetype = *archetypes.begin(); return *archetype->At(0); @@ -521,7 +516,7 @@ Entity EntityMngr::GetSingletonEntity(CmptType t) const { CmptPtr EntityMngr::GetSingleton(CmptType t) const { ArchetypeFilter filter{ {CmptAccessType{t}}, {}, {} }; - EntityQuery query(move(filter)); + EntityQuery query{ move(filter) }; const auto& archetypes = QueryArchetypes(query); size_t num = 0; @@ -544,7 +539,7 @@ std::vector EntityMngr::GetCmptArray(const ArchetypeFilter& filter, Cmp std::vector rst; - const auto& archetypes = QueryArchetypes(filter); + const auto& archetypes = QueryArchetypes(EntityQuery{ filter }); size_t num = 0; for (const auto& archetype : archetypes) @@ -574,7 +569,7 @@ std::vector EntityMngr::GetCmptArray(const ArchetypeFilter& filter, Cmp std::vector EntityMngr::GetEntityArray(const ArchetypeFilter& filter) const { std::vector rst; - const auto& archetypes = QueryArchetypes(filter); + const auto& archetypes = QueryArchetypes(EntityQuery{ filter }); size_t num = 0; for (const auto& archetype : archetypes) diff --git a/src/core/SingletonLocator.cpp b/src/core/SingletonLocator.cpp index 26987e9..100b0d9 100644 --- a/src/core/SingletonLocator.cpp +++ b/src/core/SingletonLocator.cpp @@ -3,11 +3,9 @@ using namespace Ubpa::UECS; using namespace std; -SingletonLocator::SingletonLocator(const CmptAccessType* types, size_t num) { - assert(types || num == 0); - for (size_t i = 0; i < num; i++) { - singletonTypes.insert(types[i]); - } +SingletonLocator::SingletonLocator(Span types) { + for (const auto& type : types) + singletonTypes.insert(type); } bool SingletonLocator::HasWriteSingletonType() const noexcept { diff --git a/src/test/03_query_entity/main.cpp b/src/test/03_query_entity/main.cpp index 53a89a9..91bf9da 100644 --- a/src/test/03_query_entity/main.cpp +++ b/src/test/03_query_entity/main.cpp @@ -30,7 +30,7 @@ struct MySystem { [e, w]() { if (w->entityMngr.Have(e, CmptType::Of)) { cout << "Dettach C" << endl; - w->entityMngr.Detach(e, &CmptType::Of, 1); + w->entityMngr.Detach(e); } } ); diff --git a/src/test/11_runtime_cmpt/main.cpp b/src/test/11_runtime_cmpt/main.cpp index e2c58bc..9029193 100644 --- a/src/test/11_runtime_cmpt/main.cpp +++ b/src/test/11_runtime_cmpt/main.cpp @@ -60,7 +60,7 @@ int main() { .RegisterDestructor(type, [](void*) { cout << "destruct" << endl; }); auto [e] = w.entityMngr.Create(); - w.entityMngr.Attach(e, &type, 1); + w.entityMngr.Attach(e, { &type, 1 }); w.systemMngr.Activate(rtdSystem); w.Update();