diff --git a/CMakeLists.txt b/CMakeLists.txt index c47c1f4..253bfc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -project(UECS VERSION 0.11.7) +project(UECS VERSION 0.12.0) message(STATUS "[Project] ${PROJECT_NAME}") include(cmake/InitUCMake.cmake) diff --git a/include/UECS/ArchetypeFilter.h b/include/UECS/ArchetypeFilter.h index 1521717..0e04bee 100644 --- a/include/UECS/ArchetypeFilter.h +++ b/include/UECS/ArchetypeFilter.h @@ -7,10 +7,10 @@ #include namespace Ubpa::UECS { - // filter Archetype with All, Any and None + // filter Archetype with all, any and none struct ArchetypeFilter { - std::set all; - std::set any; + std::set all; + std::set any; std::set none; size_t HashCode() const noexcept; diff --git a/include/UECS/CmptLocator.h b/include/UECS/CmptLocator.h index 3374795..f938525 100644 --- a/include/UECS/CmptLocator.h +++ b/include/UECS/CmptLocator.h @@ -11,7 +11,7 @@ namespace Ubpa::UECS { // immutable class CmptLocator { public: - CmptLocator(const CmptType* types, size_t num); + CmptLocator(const CmptAccessType* types, size_t num); CmptLocator(); @@ -23,13 +23,13 @@ namespace Ubpa::UECS { size_t HashCode() const noexcept { return hashCode; } - const std::set& CmptTypes() const noexcept { return cmptTypes; } + const std::set& CmptAccessTypes() const noexcept { return cmptTypes; } bool operator==(const CmptLocator& rhs) const; private: size_t GenHashCode() const noexcept; - std::set cmptTypes; + std::set cmptTypes; size_t hashCode; }; diff --git a/include/UECS/CmptPtr.h b/include/UECS/CmptPtr.h index 7005a88..6572068 100644 --- a/include/UECS/CmptPtr.h +++ b/include/UECS/CmptPtr.h @@ -8,25 +8,45 @@ namespace Ubpa::UECS { // CmptType + void* class CmptPtr { public: - CmptPtr(CmptType type, void* p) noexcept : type{ type }, p{ p }{} + constexpr CmptPtr(CmptType type, void* p) noexcept : type{ type }, p{ p }{} template - CmptPtr(Cmpt* p) noexcept : type{ CmptType::Of }, p{ p }{} + constexpr CmptPtr(Cmpt* p) noexcept : type{ CmptType::Of }, p{ p }{} - // unchecked - void* const& Ptr() const noexcept { return p; } + constexpr void* Ptr() const noexcept { return p; } - CmptType Type() const noexcept { return type; } + constexpr CmptType Type() const noexcept { return type; } - bool Valid() const noexcept { return p != nullptr; } + static constexpr CmptPtr Invalid() { return { CmptType::Invalid(), nullptr }; }; + constexpr bool Valid() const noexcept { return p != nullptr && type.Valid(); } - // unchecked template - Cmpt* As() const noexcept { return reinterpret_cast(p); } + constexpr Cmpt* As() const noexcept { return reinterpret_cast(p); } + private: + CmptType type; + void* p; + }; + + // CmptAccessType + void* + class CmptAccessPtr { + public: + constexpr CmptAccessPtr(CmptType type, void* p, AccessMode mode) noexcept : accessType{ type, mode }, p{ p } {} + constexpr CmptAccessPtr(CmptAccessType accessType, void* p) noexcept : accessType{ accessType }, p{ p } {} + constexpr CmptAccessPtr(CmptPtr p, AccessMode mode) noexcept : accessType{ p.Type(), mode }, p{ p.Ptr() } {} + template + constexpr CmptAccessPtr(TaggedCmpt p) noexcept : accessType{ CmptAccessType::Of }, p{ CastToVoidPointer(p) } {} + explicit constexpr CmptAccessPtr(CmptPtr p) noexcept : CmptAccessPtr{ p, AccessMode::LATEST } {} + + constexpr void* Ptr() const noexcept { return p; } + + constexpr CmptAccessType AccessType() const noexcept { return accessType; } + + static constexpr CmptAccessPtr Invalid() { return { CmptAccessType::Invalid(), nullptr }; }; + constexpr bool Valid() const noexcept { return p != nullptr && accessType.Valid(); } // check: type's access mode must be equal to template - auto As() const noexcept { - assert(type.GetAccessMode() == mode); + constexpr auto As() const noexcept { + assert(accessType.GetAccessMode() == mode); if constexpr (mode == AccessMode::LAST_FRAME) return LastFrame{p}; else if constexpr (mode == AccessMode::WRITE) @@ -43,7 +63,8 @@ namespace Ubpa::UECS { static_assert(false); } private: - CmptType type; + friend class EntityMngr; + CmptAccessType accessType; void* p; }; } diff --git a/include/UECS/CmptTag.h b/include/UECS/CmptTag.h index 6990e1b..6a51ec1 100644 --- a/include/UECS/CmptTag.h +++ b/include/UECS/CmptTag.h @@ -111,6 +111,11 @@ namespace Ubpa::UECS { const Cmpt* cmpt; }; + template + void* CastToVoidPointer(TaggedCmpt p) { + return const_cast(reinterpret_cast(p)); + } + // (without read/write and singleton tag) template struct RemoveTag; @@ -190,16 +195,19 @@ namespace Ubpa::UECS { template static constexpr bool IsTaggedCmpt_v = IsTaggedCmpt::value; - template - static constexpr AccessMode AccessModeOf = + template + static constexpr AccessMode AccessModeOf_default = IsLastFrame_v ? AccessMode::LAST_FRAME : ( IsWrite_v ? AccessMode::WRITE : ( IsLatest_v ? AccessMode::LATEST : ( IsLastFrameSingleton_v ? AccessMode::LAST_FRAME_SINGLETON : ( IsWriteSingleton_v ? AccessMode::WRITE_SINGLETON : ( IsLatestSingleton_v ? AccessMode::LATEST_SINGLETON : - AccessMode::WRITE // default + defaultMode ))))); + + template + static constexpr AccessMode AccessModeOf = AccessModeOf_default; } #include "detail/CmptTag.inl" diff --git a/include/UECS/CmptType.h b/include/UECS/CmptType.h index e5921f0..c83f3bd 100644 --- a/include/UECS/CmptType.h +++ b/include/UECS/CmptType.h @@ -2,6 +2,8 @@ #include "CmptTag.h" +#include "detail/Util.h" + #include namespace Ubpa::UECS { @@ -9,29 +11,63 @@ namespace Ubpa::UECS { // use a hashcode to distinguish different type class CmptType { public: - explicit constexpr CmptType(size_t id, AccessMode mode = AccessMode::WRITE) noexcept - : hashcode{ id }, mode{ mode } {} - explicit constexpr CmptType(std::string_view type_name, AccessMode mode = AccessMode::WRITE) noexcept - : hashcode{ RuntimeTypeID(type_name) }, mode{ mode } {} + explicit constexpr CmptType(size_t id) noexcept : hashcode{ id } {} + explicit constexpr CmptType(std::string_view type_name) noexcept : hashcode{ RuntimeTypeID(type_name) } {} - template // non-tagged component's access mode is AccessMode::WRITE - static constexpr CmptType Of = CmptType{ TypeID>, AccessModeOf }; + template, int> = 0> + static constexpr CmptType Of = CmptType{ TypeID }; constexpr size_t HashCode() const noexcept { return hashcode; } - constexpr AccessMode GetAccessMode() const noexcept { return mode; } - - static constexpr CmptType Invalid() noexcept { return CmptType{ static_cast(-1) }; } + static constexpr CmptType Invalid() noexcept { return CmptType{ size_t_invalid }; } + constexpr bool Valid() const noexcept { return hashcode == size_t_invalid; } - template // non-tagged + template, int> = 0> constexpr bool Is() const noexcept { return hashcode == TypeID; } - // only compare hash - constexpr bool operator<(const CmptType& rhs) const noexcept { return hashcode < rhs.hashcode; } + constexpr bool operator< (const CmptType& rhs) const noexcept { return hashcode < rhs.hashcode; } + constexpr bool operator<=(const CmptType& rhs) const noexcept { return hashcode <= rhs.hashcode; } + constexpr bool operator> (const CmptType& rhs) const noexcept { return hashcode > rhs.hashcode; } + constexpr bool operator>=(const CmptType& rhs) const noexcept { return hashcode >= rhs.hashcode; } constexpr bool operator==(const CmptType& rhs) const noexcept { return hashcode == rhs.hashcode; } constexpr bool operator!=(const CmptType& rhs) const noexcept { return hashcode != rhs.hashcode; } private: size_t hashcode; + }; + + // CmptType with AccessMode + class CmptAccessType { + public: + constexpr CmptAccessType(size_t id, AccessMode mode) noexcept + : type{ id }, mode{ mode } {} + constexpr CmptAccessType(std::string_view type_name, AccessMode mode) noexcept + : type{ RuntimeTypeID(type_name) }, mode{ mode } {} + constexpr CmptAccessType(CmptType type, AccessMode mode) noexcept + : type{ type }, mode{ mode } {} + explicit constexpr CmptAccessType(CmptType type) noexcept : CmptAccessType{ type, AccessMode::LATEST } {} + + template + static constexpr CmptAccessType Of = CmptAccessType{ CmptType::Of>, AccessModeOf_default }; + + // same with CmptType's HashCode + constexpr size_t HashCode() const noexcept { return type.HashCode(); } + constexpr CmptType GetCmptType() const noexcept { return type; } + constexpr AccessMode GetAccessMode() const noexcept { return mode; } + + constexpr operator CmptType()const noexcept { return type; } + + static constexpr CmptAccessType Invalid() noexcept { return CmptAccessType{ size_t_invalid, AccessMode::LATEST }; } + constexpr bool Valid() const noexcept { return type.Valid(); } + + // same with CmptType's operator< + constexpr bool operator< (const CmptAccessType& rhs) const noexcept { return type < rhs.type; } + constexpr bool operator<=(const CmptAccessType& rhs) const noexcept { return type <= rhs.type; } + constexpr bool operator> (const CmptAccessType& rhs) const noexcept { return type > rhs.type; } + constexpr bool operator>=(const CmptAccessType& rhs) const noexcept { return type >= rhs.type; } + constexpr bool operator==(const CmptAccessType& rhs) const noexcept { return type == rhs.type; } + constexpr bool operator!=(const CmptAccessType& rhs) const noexcept { return type != rhs.type; } + private: + CmptType type; AccessMode mode; }; } diff --git a/include/UECS/CmptsView.h b/include/UECS/CmptsView.h index 0f8d4ef..12fb1db 100644 --- a/include/UECS/CmptsView.h +++ b/include/UECS/CmptsView.h @@ -5,15 +5,15 @@ namespace Ubpa::UECS { class CmptsView { public: - CmptsView(const CmptPtr* cmpts, size_t num) noexcept + CmptsView(const CmptAccessPtr* cmpts, size_t num) noexcept : cmpts{ cmpts }, num{ num } {} - CmptPtr GetCmpt(CmptType) const noexcept; + CmptAccessPtr GetCmpt(CmptAccessType) const noexcept; - const CmptPtr* Components() const noexcept { return cmpts; } + const CmptAccessPtr* Components() const noexcept { return cmpts; } size_t NumberOfComponents() const noexcept { return num; } private: - const CmptPtr* cmpts; + const CmptAccessPtr* cmpts; size_t num; }; } diff --git a/include/UECS/Entity.h b/include/UECS/Entity.h index 6ed3e44..f5b8f20 100644 --- a/include/UECS/Entity.h +++ b/include/UECS/Entity.h @@ -15,6 +15,7 @@ namespace Ubpa::UECS { return idx < rhs.idx || (idx == rhs.idx && version < rhs.version); } static constexpr Entity Invalid() noexcept { return { size_t_invalid,size_t_invalid }; } + constexpr bool IsValid() const noexcept { return idx == size_t_invalid; } private: friend class EntityMngr; friend class Archetype; diff --git a/include/UECS/EntityMngr.h b/include/UECS/EntityMngr.h index b0d78ca..58af4d9 100644 --- a/include/UECS/EntityMngr.h +++ b/include/UECS/EntityMngr.h @@ -44,8 +44,7 @@ namespace Ubpa::UECS { // use RTDCmptTraits void Attach(Entity, const CmptType* types, size_t num); - // if not exist cmpt, attach with ... - // else return it directly + // assert(Have(e, CmptType::Of)) template Cmpt* Emplace(Entity, Args&&...); @@ -53,10 +52,10 @@ namespace Ubpa::UECS { bool Have(Entity, CmptType) const; - // nullptr if not singleton + // nullptr if not containts template Cmpt* Get(Entity) const; - // nullptr if not singleton + // nullptr if not containts CmptType CmptPtr Get(Entity, CmptType) const; std::vector Components(Entity) const; @@ -67,7 +66,7 @@ namespace Ubpa::UECS { size_t EntityNum(const EntityQuery&) const; - std::tuple> LocateSingletons(const SingletonLocator&) const; + std::tuple> LocateSingletons(const SingletonLocator&) const; bool IsSingleton(CmptType) const; Entity GetSingletonEntity(CmptType) const; diff --git a/include/UECS/EntityQuery.h b/include/UECS/EntityQuery.h index fe9b326..5659d4e 100644 --- a/include/UECS/EntityQuery.h +++ b/include/UECS/EntityQuery.h @@ -11,9 +11,6 @@ namespace Ubpa::UECS { ArchetypeFilter filter; CmptLocator locator; - template - EntityQuery(TypeList, TypeList, TypeList, TypeList); - EntityQuery(ArchetypeFilter filter = {}, CmptLocator locator = {}) :filter{ std::move(filter) }, locator{ std::move(locator) } {} diff --git a/include/UECS/Schedule.h b/include/UECS/Schedule.h index 4d069bf..2f3c876 100644 --- a/include/UECS/Schedule.h +++ b/include/UECS/Schedule.h @@ -70,11 +70,7 @@ namespace Ubpa::UECS { Schedule& LockFilter(std::string_view sys); - Schedule& InsertAll(std::string_view sys, CmptType); - Schedule& InsertAny(std::string_view sys, CmptType); Schedule& InsertNone(std::string_view sys, CmptType); - Schedule& EraseAll(std::string_view sys, CmptType); - Schedule& EraseAny(std::string_view sys, CmptType); Schedule& EraseNone(std::string_view sys, CmptType); private: @@ -101,11 +97,7 @@ namespace Ubpa::UECS { std::unordered_map sysFuncOrder; struct FilterChange { - std::set insertAlls; - std::set insertAnys; std::set insertNones; - std::set eraseAlls; - std::set eraseAnys; std::set eraseNones; }; std::unordered_map sysFilterChange; diff --git a/include/UECS/SingletonLocator.h b/include/UECS/SingletonLocator.h index 166a738..5c665b4 100644 --- a/include/UECS/SingletonLocator.h +++ b/include/UECS/SingletonLocator.h @@ -9,7 +9,7 @@ namespace Ubpa::UECS { class SingletonLocator { public: - SingletonLocator(const CmptType* types, size_t num); + SingletonLocator(const CmptAccessType* types, size_t num); SingletonLocator() = default; template @@ -18,12 +18,12 @@ namespace Ubpa::UECS { template SingletonLocator& Combine(); - const std::set& SingletonTypes() const noexcept { return singletonTypes; } + const std::set& SingletonTypes() const noexcept { return singletonTypes; } bool HasWriteSingletonType() const noexcept; private: - std::set singletonTypes; + std::set singletonTypes; }; } diff --git a/include/UECS/SingletonsView.h b/include/UECS/SingletonsView.h index a2bdca6..470b106 100644 --- a/include/UECS/SingletonsView.h +++ b/include/UECS/SingletonsView.h @@ -5,15 +5,15 @@ namespace Ubpa::UECS { class SingletonsView { public: - SingletonsView(const CmptPtr* singletons, size_t num) + SingletonsView(const CmptAccessPtr* singletons, size_t num) : singletons{ singletons }, num{ num } {} - CmptPtr GetSingleton(CmptType) const; + CmptAccessPtr GetSingleton(CmptAccessType) const; - const CmptPtr* Singletons() const noexcept { return singletons; } + const CmptAccessPtr* Singletons() const noexcept { return singletons; } size_t NumberOfSingletons() const noexcept { return num; } private: - const CmptPtr* singletons; + const CmptAccessPtr* singletons; size_t num; }; } diff --git a/include/UECS/detail/Archetype.h b/include/UECS/detail/Archetype.h index db1cd0d..b8fe4f2 100644 --- a/include/UECS/detail/Archetype.h +++ b/include/UECS/detail/Archetype.h @@ -39,7 +39,7 @@ namespace Ubpa::UECS { static Archetype* Remove(const Archetype* from, const CmptType* types, size_t num); // Entity + Components - std::tuple, std::vector>, std::vector> + std::tuple, std::vector>, std::vector> Locate(const CmptLocator& locator) const; // nullptr if not contains diff --git a/include/UECS/detail/Archetype.inl b/include/UECS/detail/Archetype.inl index b39deb5..c231a2d 100644 --- a/include/UECS/detail/Archetype.inl +++ b/include/UECS/detail/Archetype.inl @@ -21,7 +21,7 @@ namespace Ubpa::UECS { static_assert(sizeof...(Cmpts) > 0); static_assert(IsSet_v>, "... must be different"); - assert(!from->types.Contains(std::array{ CmptType::Of... })); + assert(!(from->types.Contains(CmptType::Of) &&...)); Archetype* rst = new Archetype{ from->entityMngr }; diff --git a/include/UECS/detail/CmptType.inl b/include/UECS/detail/CmptType.inl index 89d542b..c8ff82e 100644 --- a/include/UECS/detail/CmptType.inl +++ b/include/UECS/detail/CmptType.inl @@ -10,4 +10,11 @@ namespace std { return t.HashCode(); } }; + + template<> + struct hash { + constexpr size_t operator()(const Ubpa::UECS::CmptAccessType& t) const noexcept { + return t.HashCode(); + } + }; } diff --git a/include/UECS/detail/CmptTypeSet.h b/include/UECS/detail/CmptTypeSet.h index fb14b46..20825a7 100644 --- a/include/UECS/detail/CmptTypeSet.h +++ b/include/UECS/detail/CmptTypeSet.h @@ -17,10 +17,10 @@ namespace Ubpa::UECS { void Insert(const CmptType* types, size_t num); void Erase(const CmptType* types, size_t num); bool Contains(CmptType type) const; - bool Contains(const CmptType* types, size_t num) const; + bool ContainsAll(const CmptType* types, size_t num) const; template - bool Contains(const CmptTypeContainer& types) const; + bool ContainsAll(const CmptTypeContainer& types) const; bool ContainsAny(const CmptType* types, size_t num) const; template diff --git a/include/UECS/detail/CmptTypeSet.inl b/include/UECS/detail/CmptTypeSet.inl index 9b3df59..80c518c 100644 --- a/include/UECS/detail/CmptTypeSet.inl +++ b/include/UECS/detail/CmptTypeSet.inl @@ -17,7 +17,7 @@ namespace Ubpa::UECS { return data.find(type) != data.end(); } - inline bool CmptTypeSet::Contains(const CmptType* types, size_t num) const { + 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])) @@ -27,7 +27,7 @@ namespace Ubpa::UECS { } template - bool CmptTypeSet::Contains(const CmptTypeContainer& types) const { + bool CmptTypeSet::ContainsAll(const CmptTypeContainer& types) const { for (const auto& type : types) { if (!Contains(type)) return false; @@ -67,13 +67,13 @@ namespace Ubpa::UECS { } inline bool CmptTypeSet::IsMatch(const ArchetypeFilter& filter) const { - return Contains(filter.all) + return ContainsAll(filter.all) && ContainsAny(filter.any) && NotContain(filter.none); } inline bool CmptTypeSet::IsMatch(const CmptLocator& locator) const { - for (const auto& t : locator.CmptTypes()) { + for (const auto& t : locator.CmptAccessTypes()) { if (!Contains(t)) return false; } diff --git a/include/UECS/detail/CmptsLocator.inl b/include/UECS/detail/CmptsLocator.inl index 1e42178..902c028 100644 --- a/include/UECS/detail/CmptsLocator.inl +++ b/include/UECS/detail/CmptsLocator.inl @@ -7,7 +7,7 @@ namespace Ubpa::UECS::detail { template CmptLocator GenerateCmptLocator(TypeList) { if constexpr (sizeof...(Cmpts) > 0) { - constexpr std::array types{ CmptType::Of... }; + constexpr std::array types{ CmptAccessType::Of... }; return CmptLocator{ types.data(), types.size() }; } else diff --git a/include/UECS/detail/EntityMngr.inl b/include/UECS/detail/EntityMngr.inl index d836b44..dbed852 100644 --- a/include/UECS/detail/EntityMngr.inl +++ b/include/UECS/detail/EntityMngr.inl @@ -105,12 +105,9 @@ namespace Ubpa::UECS { || is_list_initializable_v, " isn't constructible/list_initializable with Args..."); - if (!Have(e, CmptType::Of)) { - AttachWithoutInit(e); - return new(Get(e))Cmpt{ std::forward(args)... }; - } - else - return Get(e); + assert(!Have(e, CmptType::Of)); + AttachWithoutInit(e); + return new(Get(e))Cmpt{ std::forward(args)... }; } inline bool EntityMngr::Have(Entity e, CmptType type) const { diff --git a/include/UECS/detail/EntityQuery.inl b/include/UECS/detail/EntityQuery.inl index b78aa0d..97d64f7 100644 --- a/include/UECS/detail/EntityQuery.inl +++ b/include/UECS/detail/EntityQuery.inl @@ -1,14 +1,5 @@ #pragma once -namespace Ubpa::UECS { - template - EntityQuery::EntityQuery(TypeList, TypeList, TypeList, TypeList) - : filter{ TypeList{}, TypeList{}, TypeList{} }, - locator{ TypeList{} } - { - } -} - namespace std { template struct hash; diff --git a/include/UECS/detail/RTDCmptTraits.inl b/include/UECS/detail/RTDCmptTraits.inl index f993bcc..5a2dde6 100644 --- a/include/UECS/detail/RTDCmptTraits.inl +++ b/include/UECS/detail/RTDCmptTraits.inl @@ -108,6 +108,7 @@ namespace Ubpa::UECS { template void RTDCmptTraits::RegisterOne() { + static_assert(!IsTaggedCmpt_v, " should not be tagged"); static_assert(std::is_default_constructible_v, " must be default-constructible"); static_assert(std::is_copy_constructible_v, " must be copy-constructible"); static_assert(std::is_move_constructible_v, " must be move-constructible"); diff --git a/include/UECS/detail/RTSCmptTraits.inl b/include/UECS/detail/RTSCmptTraits.inl index ab3cec8..e974d94 100644 --- a/include/UECS/detail/RTSCmptTraits.inl +++ b/include/UECS/detail/RTSCmptTraits.inl @@ -48,6 +48,7 @@ namespace Ubpa::UECS { template void RTSCmptTraits::Register() { + static_assert(!IsTaggedCmpt_v, " should not be tagged"); static_assert(std::is_copy_constructible_v, " must be copy-constructible"); static_assert(std::is_move_constructible_v, " must be move-constructible"); static_assert(std::is_move_assignable_v, " must be move-assignable"); diff --git a/include/UECS/detail/SingletonLocator.inl b/include/UECS/detail/SingletonLocator.inl index 129426d..5be06dd 100644 --- a/include/UECS/detail/SingletonLocator.inl +++ b/include/UECS/detail/SingletonLocator.inl @@ -7,7 +7,7 @@ namespace Ubpa::UECS::detail { template SingletonLocator GenerateSingletonLocator(TypeList) { if constexpr (sizeof...(Singletons) > 0) { - constexpr std::array types{ CmptType::Of... }; + constexpr std::array types{ CmptAccessType::Of... }; return SingletonLocator{ types.data(), types.size() }; } else diff --git a/src/core/Archetype.cpp b/src/core/Archetype.cpp index d9c2960..370a8db 100644 --- a/src/core/Archetype.cpp +++ b/src/core/Archetype.cpp @@ -65,7 +65,7 @@ Archetype* Archetype::New(EntityMngr* entityMngr, const CmptType* types, size_t Archetype* Archetype::Add(const Archetype* from, const CmptType* types, size_t num) { assert(NotContainEntity(types, num)); - assert(!from->types.Contains(types, num)); + assert(!from->types.ContainsAll(types, num)); Archetype* rst = new Archetype{ from->entityMngr }; @@ -175,27 +175,27 @@ size_t Archetype::Instantiate(Entity e, size_t srcIdx) { return dstIdx; } -tuple, vector>, vector> Archetype::Locate(const CmptLocator& locator) const { +tuple, vector>, vector> Archetype::Locate(const CmptLocator& locator) const { assert(types.IsMatch(locator)); const size_t numChunk = chunks.size(); - const size_t numType = locator.CmptTypes().size(); + const size_t numType = locator.CmptAccessTypes().size(); const size_t offsetEntity = Offsetof(CmptType::Of); - vector> chunkCmpts(numChunk); + vector> chunkCmpts(numChunk); vector chunkEntity(numChunk); for (size_t i = 0; i < numChunk; i++) { byte* data = chunks[i]->Data(); chunkCmpts[i].reserve(numType); - for (const auto& type : locator.CmptTypes()) + for (const auto& type : locator.CmptAccessTypes()) chunkCmpts[i].emplace_back(type, data + Offsetof(type)); chunkEntity[i] = reinterpret_cast(data + offsetEntity); } vector sizes; sizes.reserve(numType); - for (const auto& type : locator.CmptTypes()) + for (const auto& type : locator.CmptAccessTypes()) sizes.push_back(cmptTraits.Sizeof(type)); return { chunkEntity, chunkCmpts, sizes }; diff --git a/src/core/CmptLocator.cpp b/src/core/CmptLocator.cpp index d7bc99a..f9eedd1 100644 --- a/src/core/CmptLocator.cpp +++ b/src/core/CmptLocator.cpp @@ -7,8 +7,8 @@ using namespace Ubpa::UECS; using namespace std; -CmptLocator::CmptLocator(const CmptType* types, size_t num) { - assert(types != nullptr && num > 0); +CmptLocator::CmptLocator(const CmptAccessType* types, size_t num) { + assert(types || num == 0); for (size_t i = 0; i < num; i++) cmptTypes.insert(types[i]); diff --git a/src/core/CmptsView.cpp b/src/core/CmptsView.cpp index 1ca0485..f88623c 100644 --- a/src/core/CmptsView.cpp +++ b/src/core/CmptsView.cpp @@ -2,12 +2,11 @@ using namespace Ubpa::UECS; -CmptPtr CmptsView::GetCmpt(CmptType t) const noexcept { +CmptAccessPtr CmptsView::GetCmpt(CmptAccessType t) const noexcept { for (size_t i = 0; i < num; i++) { - if (cmpts[i].Type() == t) { - assert(cmpts[i].Type().GetAccessMode() == t.GetAccessMode()); + if (cmpts[i].AccessType() == t) { return cmpts[i]; } } - return { CmptType::Invalid(), nullptr }; + return CmptAccessPtr::Invalid(); } diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index 79034c5..183a6a3 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -247,15 +247,15 @@ void EntityMngr::Destroy(Entity e) { RecycleEntityEntry(e); } -tuple> EntityMngr::LocateSingletons(const SingletonLocator& locator) const { +tuple> EntityMngr::LocateSingletons(const SingletonLocator& locator) const { size_t numSingletons = 0; - vector rst; + vector rst; rst.reserve(locator.SingletonTypes().size()); for (const auto& t : locator.SingletonTypes()) { auto ptr = GetSingleton(t); if (ptr.Ptr() == nullptr) return { false, {} }; - rst.push_back(ptr); + rst.emplace_back(ptr, t.GetAccessMode()); } return { true, rst }; } @@ -290,7 +290,7 @@ void EntityMngr::GenEntityJob(World* w, Job* job, SystemFunc* sys) const { CmptsView{ cmpts.data(), cmpts.size() } ); for (size_t k = 0; k < cmpts.size(); k++) - reinterpret_cast(const_cast(cmpts[k].Ptr())) += sizes[k]; + reinterpret_cast(cmpts[k].p) += sizes[k]; } }); } @@ -353,7 +353,7 @@ void EntityMngr::Accept(IListener* listener) const { } bool EntityMngr::IsSingleton(CmptType t) const { - ArchetypeFilter filter{ {t}, {}, {} }; + ArchetypeFilter filter{ {CmptAccessType{t}}, {}, {} }; EntityQuery query(move(filter)); const auto& archetypes = QueryArchetypes(query); if (archetypes.size() != 1) @@ -367,7 +367,7 @@ bool EntityMngr::IsSingleton(CmptType t) const { Entity EntityMngr::GetSingletonEntity(CmptType t) const { assert(IsSingleton(t)); - ArchetypeFilter filter{ {t}, {}, {} }; + ArchetypeFilter filter{ {CmptAccessType{t}}, {}, {} }; EntityQuery query(move(filter)); const auto& archetypes = QueryArchetypes(query); auto archetype = *archetypes.begin(); @@ -375,7 +375,7 @@ Entity EntityMngr::GetSingletonEntity(CmptType t) const { } CmptPtr EntityMngr::GetSingleton(CmptType t) const { - ArchetypeFilter filter{ {t}, {}, {} }; + ArchetypeFilter filter{ {CmptAccessType{t}}, {}, {} }; EntityQuery query(move(filter)); const auto& archetypes = QueryArchetypes(query); if (archetypes.size() != 1) @@ -388,7 +388,7 @@ CmptPtr EntityMngr::GetSingleton(CmptType t) const { } std::vector EntityMngr::GetCmptArray(const ArchetypeFilter& filter, CmptType type) const { - assert(filter.all.find(type) != filter.all.end()); + assert(filter.all.find(CmptAccessType{ type }) != filter.all.end()); std::vector rst; diff --git a/src/core/Schedule.cpp b/src/core/Schedule.cpp index e2713c3..3a2f786 100644 --- a/src/core/Schedule.cpp +++ b/src/core/Schedule.cpp @@ -14,13 +14,38 @@ namespace Ubpa::UECS::detail { : sysFuncs{ func } { needTypes = SetUnion(func->entityQuery.filter.all, func->entityQuery.filter.any); - needTypes = SetUnion(needTypes, func->entityQuery.locator.CmptTypes()); + needTypes = SetUnion(needTypes, func->entityQuery.locator.CmptAccessTypes()); noneTypes = func->entityQuery.filter.none; } static bool Parallelable(const NoneGroup& x, const NoneGroup& y) { - return !SetIntersection(x.needTypes, y.noneTypes).empty() - || !SetIntersection(y.needTypes, x.noneTypes).empty(); + /*return !SetIntersection(x.needTypes, y.noneTypes).empty() + || !SetIntersection(y.needTypes, x.noneTypes).empty();*/ + { + auto x_iter = x.needTypes.begin(); + auto y_iter = y.noneTypes.begin(); + while (x_iter != x.needTypes.end() && y_iter != y.noneTypes.end()) { + if (x_iter->GetCmptType() < *y_iter) + ++x_iter; + else if (x_iter->GetCmptType() > * y_iter) + ++y_iter; + else // == + return true; + } + } + { + auto x_iter = x.noneTypes.begin(); + auto y_iter = y.needTypes.begin(); + while (x_iter != x.noneTypes.end() && y_iter != y.needTypes.end()) { + if (*x_iter < y_iter->GetCmptType()) + ++x_iter; + else if (*x_iter > y_iter->GetCmptType()) + ++y_iter; + else // == + return true; + } + } + return false; } NoneGroup& operator+=(const NoneGroup& y) { @@ -30,7 +55,7 @@ namespace Ubpa::UECS::detail { return *this; } - set needTypes; + set needTypes; set noneTypes; set sysFuncs; }; @@ -153,22 +178,6 @@ Schedule& Schedule::Order(string_view x, string_view y) { return *this; } -Schedule& Schedule::InsertAll(string_view sys, CmptType type) { - size_t hashcode = SystemFunc::HashCode(sys); - auto& change = sysFilterChange[hashcode]; - change.eraseAlls.erase(type); - change.insertAlls.insert(type); - return *this; -} - -Schedule& Schedule::InsertAny(string_view sys, CmptType type) { - size_t hashcode = SystemFunc::HashCode(sys); - auto& change = sysFilterChange[hashcode]; - change.eraseAnys.erase(type); - change.insertAnys.insert(type); - return *this; -} - Schedule& Schedule::InsertNone(string_view sys, CmptType type) { size_t hashcode = SystemFunc::HashCode(sys); auto& change = sysFilterChange[hashcode]; @@ -177,22 +186,6 @@ Schedule& Schedule::InsertNone(string_view sys, CmptType type) { return *this; } -Schedule& Schedule::EraseAll(string_view sys, CmptType type) { - size_t hashcode = SystemFunc::HashCode(sys); - auto& change = sysFilterChange[hashcode]; - change.eraseAlls.insert(type); - change.insertAlls.erase(type); - return *this; -} - -Schedule& Schedule::EraseAny(string_view sys, CmptType type) { - size_t hashcode = SystemFunc::HashCode(sys); - auto& change = sysFilterChange[hashcode]; - change.eraseAnys.insert(type); - change.insertAnys.erase(type); - return *this; -} - Schedule& Schedule::EraseNone(string_view sys, CmptType type) { size_t hashcode = SystemFunc::HashCode(sys); auto& change = sysFilterChange[hashcode]; @@ -213,7 +206,7 @@ void Schedule::Clear() { unordered_map Schedule::GenCmptSysFuncsMap() const { unordered_map rst; for (const auto& [hashcode, sysFunc] : sysFuncs) { - for (const auto& type : sysFunc->entityQuery.locator.CmptTypes()) { + for (const auto& type : sysFunc->entityQuery.locator.CmptAccessTypes()) { switch (type.GetAccessMode()) { case Ubpa::UECS::AccessMode::LAST_FRAME: @@ -304,16 +297,8 @@ SysFuncGraph Schedule::GenSysFuncGraph() const { auto func = target->second; - for (const auto& type : change.insertAlls) - func->entityQuery.filter.all.insert(type); - for (const auto& type : change.insertAnys) - func->entityQuery.filter.any.insert(type); for (const auto& type : change.insertNones) func->entityQuery.filter.none.insert(type); - for (const auto& type : change.eraseAlls) - func->entityQuery.filter.all.erase(type); - for (const auto& type : change.eraseAnys) - func->entityQuery.filter.any.erase(type); for (const auto& type : change.eraseNones) func->entityQuery.filter.none.erase(type); } diff --git a/src/core/SingletonLocator.cpp b/src/core/SingletonLocator.cpp index 2385ae3..8203f9a 100644 --- a/src/core/SingletonLocator.cpp +++ b/src/core/SingletonLocator.cpp @@ -7,7 +7,7 @@ using namespace Ubpa::UECS; using namespace std; -SingletonLocator::SingletonLocator(const CmptType* types, size_t num) { +SingletonLocator::SingletonLocator(const CmptAccessType* types, size_t num) { assert(types || num == 0); for (size_t i = 0; i < num; i++) singletonTypes.insert(types[i]); diff --git a/src/core/SingletonsView.cpp b/src/core/SingletonsView.cpp index c745c32..84f2b09 100644 --- a/src/core/SingletonsView.cpp +++ b/src/core/SingletonsView.cpp @@ -2,12 +2,10 @@ using namespace Ubpa::UECS; -CmptPtr SingletonsView::GetSingleton(CmptType t) const { +CmptAccessPtr SingletonsView::GetSingleton(CmptAccessType t) const { for (size_t i = 0; i < num; i++) { - if (singletons[i].Type() == t) { - assert(singletons[i].Type().GetAccessMode() == t.GetAccessMode()); + if (singletons[i].AccessType() == t) return singletons[i]; - } } - return { CmptType::Invalid(), nullptr }; + return CmptAccessPtr::Invalid(); } diff --git a/src/core/World.cpp b/src/core/World.cpp index 52b01d9..360da62 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -115,7 +115,7 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const { .RegisterGraphEdgeAttr("color", "#C785C8") .RegisterGraphEdgeAttr("arrowhead", "odot"); - unordered_set cmptTypes; + unordered_set cmptTypes; unordered_map cmptType2idx; unordered_map sysFuncHashcode2idx; @@ -125,14 +125,14 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const { }; for (const auto& [hash, sysFunc] : schedule.sysFuncs) { - for (auto cmptType : sysFunc->entityQuery.locator.CmptTypes()) + for (auto cmptType : sysFunc->entityQuery.locator.CmptAccessTypes()) cmptTypes.insert(cmptType); for (auto cmptType : sysFunc->entityQuery.filter.all) cmptTypes.insert(cmptType); for (auto cmptType : sysFunc->entityQuery.filter.any) cmptTypes.insert(cmptType); for (auto cmptType : sysFunc->entityQuery.filter.none) - cmptTypes.insert(cmptType); + cmptTypes.insert(CmptAccessType{ cmptType }); for (auto singleton : sysFunc->singletonLocator.SingletonTypes()) cmptTypes.insert(singleton); } @@ -152,7 +152,7 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const { subgraph_sys.AddNode(sysIdx); - for (const auto& cmptType : sysFunc->entityQuery.locator.CmptTypes()) { + for (const auto& cmptType : sysFunc->entityQuery.locator.CmptAccessTypes()) { size_t edgeIdx; switch (cmptType.GetAccessMode()) { diff --git a/src/test/04_filter/main.cpp b/src/test/04_filter/main.cpp index 4e72eb5..a4f6d8d 100644 --- a/src/test/04_filter/main.cpp +++ b/src/test/04_filter/main.cpp @@ -18,8 +18,8 @@ class MySystem : public System { virtual void OnUpdate(Schedule& schedule) override { ArchetypeFilter filter; - filter.all = { CmptType::Of }; - filter.any = { CmptType::Of, CmptType::Of }; + filter.all = { CmptAccessType::Of }; + filter.any = { CmptAccessType::Of, CmptAccessType::Of }; filter.none = { CmptType::Of }; schedule.RegisterEntityJob( diff --git a/src/test/06_none_parallel/main.cpp b/src/test/06_none_parallel/main.cpp index d718e9e..f88192c 100644 --- a/src/test/06_none_parallel/main.cpp +++ b/src/test/06_none_parallel/main.cpp @@ -16,7 +16,7 @@ class MySystem : public System { virtual void OnUpdate(Schedule& schedule) override { ArchetypeFilter filter_w0, filter_w1; filter_w0.none = { CmptType::Of }; - filter_w1.all = { CmptType::Of }; + filter_w1.all = { CmptAccessType::Of }; schedule.RegisterEntityJob([](B*) {}, "need B, none A", filter_w0); schedule.RegisterEntityJob([](B*) {}, "need A, B", filter_w1);; } diff --git a/src/test/11_runtime_cmpt/main.cpp b/src/test/11_runtime_cmpt/main.cpp index 62de438..d935d9a 100644 --- a/src/test/11_runtime_cmpt/main.cpp +++ b/src/test/11_runtime_cmpt/main.cpp @@ -10,11 +10,11 @@ class RTDSystem: public System{ using System::System; virtual void OnUpdate(Schedule& schedule) override { - std::array cmpts_write = { - CmptType{ "LuaCmpt", AccessMode::WRITE } + std::array cmpts_write = { + CmptAccessType{ "LuaCmpt", AccessMode::WRITE } }; - std::array cmpts_read = { - CmptType{ "LuaCmpt", AccessMode::LATEST } + std::array cmpts_read = { + CmptAccessType{ "LuaCmpt", AccessMode::LATEST } }; CmptLocator locator_write( @@ -26,13 +26,13 @@ class RTDSystem: public System{ schedule.RegisterEntityJob( [](CmptsView cmpts) { - auto luaCmpt = cmpts.GetCmpt(CmptType{ "LuaCmpt", AccessMode::WRITE }); + auto luaCmpt = cmpts.GetCmpt(CmptAccessType{ "LuaCmpt", AccessMode::WRITE }); double& val = *reinterpret_cast(luaCmpt.Ptr()); val = 520.; }, "write", ArchetypeFilter{}, locator_write); schedule.RegisterEntityJob( [](CmptsView cmpts) { - auto luaCmpt = cmpts.GetCmpt(CmptType{ "LuaCmpt", AccessMode::LATEST }); + auto luaCmpt = cmpts.GetCmpt(CmptAccessType{ "LuaCmpt", AccessMode::LATEST }); const double& val = *reinterpret_cast(luaCmpt.Ptr()); cout << "value : " << val << endl; }, "read", ArchetypeFilter{}, locator_read); diff --git a/src/test/12_framegraph/main.cpp b/src/test/12_framegraph/main.cpp index 3d1f5a4..31263ef 100644 --- a/src/test/12_framegraph/main.cpp +++ b/src/test/12_framegraph/main.cpp @@ -20,8 +20,8 @@ class MySystem : public System { virtual void OnUpdate(Schedule& schedule) override { ArchetypeFilter filter; - filter.all = { CmptType::Of }; - filter.any = { CmptType::Of, CmptType::Of }; + filter.all = { CmptAccessType::Of }; + filter.any = { CmptAccessType::Of, CmptAccessType::Of }; filter.none = { CmptType::Of }; schedule .RegisterEntityJob( diff --git a/src/test/15_chunk_job/main.cpp b/src/test/15_chunk_job/main.cpp index 326d18b..af971fc 100644 --- a/src/test/15_chunk_job/main.cpp +++ b/src/test/15_chunk_job/main.cpp @@ -18,8 +18,8 @@ class SAB_System : public System { virtual void OnUpdate(Schedule& schedule) override { ArchetypeFilter filter; - filter.all = { CmptType::Of> }; - filter.any = { CmptType::Of>,CmptType::Of> }; + filter.all = { CmptAccessType::Of> }; + filter.any = { CmptAccessType::Of>, CmptAccessType::Of> }; schedule.RegisterChunkJob([](ChunkView chunk) { auto arrayS = chunk.GetCmptArray();