From 79a035cf93f52a511327c948f303da6d5c79d0ee Mon Sep 17 00:00:00 2001 From: Ubpa <641614112@qq.com> Date: Sat, 8 Aug 2020 23:17:51 +0800 Subject: [PATCH] basic singleton --- CMakeLists.txt | 2 +- .../{EntityFilter.h => ArchetypeFilter.h} | 18 +- include/UECS/ChunkView.h | 1 + .../UECS/{EntityLocator.h => CmptLocator.h} | 18 +- include/UECS/CmptPtr.h | 32 ++-- include/UECS/CmptTag.h | 161 ++++++++++++++++-- include/UECS/CmptsView.h | 34 +--- include/UECS/EntityMngr.h | 5 + include/UECS/EntityQuery.h | 13 +- include/UECS/Schedule.h | 4 +- include/UECS/SingletonLocator.h | 27 +++ include/UECS/SingletonsView.h | 19 +++ include/UECS/SystemFunc.h | 32 ++-- include/UECS/detail/Archetype.h | 6 +- .../{EntityFilter.inl => ArchetypeFilter.inl} | 18 +- include/UECS/detail/CmptTag.inl | 81 +++++++-- include/UECS/detail/CmptTypeSet.h | 4 +- include/UECS/detail/CmptTypeSet.inl | 10 +- include/UECS/detail/EntityLocator.inl | 27 --- include/UECS/detail/Schedule.inl | 4 +- include/UECS/detail/SingletonLocator.inl | 0 include/UECS/detail/SingletonsView.h | 0 include/UECS/detail/SystemFunc.inl | 158 +++++++++-------- src/core/Archetype.cpp | 17 +- .../{EntityFilter.cpp => ArchetypeFilter.cpp} | 42 ++--- src/core/CmptLocator.cpp | 49 ++++++ src/core/CmptsView.cpp | 15 +- src/core/EntityLocator.cpp | 56 ------ src/core/EntityMngr.cpp | 79 +++++++-- src/core/Schedule.cpp | 36 ++-- src/core/SingletonLocator.cpp | 34 ++++ src/core/SingletonsView.cpp | 13 ++ src/core/SystemFunc.cpp | 16 +- src/core/World.cpp | 16 +- src/test/04_filter/main.cpp | 2 +- src/test/06_none_parallel/main.cpp | 4 +- src/test/11_runtime_cmpt/main.cpp | 4 +- src/test/12_framegraph/main.cpp | 2 +- src/test/15_chunk_job/main.cpp | 2 +- src/test/16_singleton/main.cpp | 21 ++- 40 files changed, 697 insertions(+), 385 deletions(-) rename include/UECS/{EntityFilter.h => ArchetypeFilter.h} (78%) rename include/UECS/{EntityLocator.h => CmptLocator.h} (62%) create mode 100644 include/UECS/SingletonLocator.h create mode 100644 include/UECS/SingletonsView.h rename include/UECS/detail/{EntityFilter.inl => ArchetypeFilter.inl} (75%) delete mode 100644 include/UECS/detail/EntityLocator.inl create mode 100644 include/UECS/detail/SingletonLocator.inl create mode 100644 include/UECS/detail/SingletonsView.h rename src/core/{EntityFilter.cpp => ArchetypeFilter.cpp} (61%) create mode 100644 src/core/CmptLocator.cpp delete mode 100644 src/core/EntityLocator.cpp create mode 100644 src/core/SingletonLocator.cpp create mode 100644 src/core/SingletonsView.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f5fd59..e019db8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -project(UECS VERSION 0.10.8) +project(UECS VERSION 0.11.0) message(STATUS "[Project] ${PROJECT_NAME}") include(cmake/InitUCMake.cmake) diff --git a/include/UECS/EntityFilter.h b/include/UECS/ArchetypeFilter.h similarity index 78% rename from include/UECS/EntityFilter.h rename to include/UECS/ArchetypeFilter.h index ee4c943..6d25f62 100644 --- a/include/UECS/EntityFilter.h +++ b/include/UECS/ArchetypeFilter.h @@ -8,21 +8,21 @@ namespace Ubpa::UECS { // filter Archetype with All, Any and None - class EntityFilter { + class ArchetypeFilter { public: - EntityFilter(); + ArchetypeFilter(); template - EntityFilter(TypeList allList, TypeList anyList, TypeList noneList); + ArchetypeFilter(TypeList allList, TypeList anyList, TypeList noneList); template - static EntityFilter CreateAll() { return { TypeList, TypeList<>{}, TypeList<>{} }; } + static ArchetypeFilter CreateAll() { return { TypeList, TypeList<>{}, TypeList<>{} }; } template - static EntityFilter CreateAny() { return { TypeList<>{}, TypeList, TypeList<>{} }; } + static ArchetypeFilter CreateAny() { return { TypeList<>{}, TypeList, TypeList<>{} }; } template - static EntityFilter CreateNone() { return { TypeList<>{}, TypeList<>{}, TypeList }; } + static ArchetypeFilter CreateNone() { return { TypeList<>{}, TypeList<>{}, TypeList }; } - EntityFilter( + ArchetypeFilter( std::set allCmptTypes, std::set anyCmptTypes = {}, std::set noneCmptTypes = {} @@ -54,7 +54,7 @@ namespace Ubpa::UECS { template void EraseAny(const CmptTypeContainer&); template void EraseNone(const CmptTypeContainer&); - bool operator==(const EntityFilter& filter) const noexcept; + bool operator==(const ArchetypeFilter& filter) const noexcept; private: size_t GenAllHashCode() const noexcept; @@ -74,4 +74,4 @@ namespace Ubpa::UECS { }; } -#include "detail/EntityFilter.inl" +#include "detail/ArchetypeFilter.inl" diff --git a/include/UECS/ChunkView.h b/include/UECS/ChunkView.h index d6c3c13..f76e049 100644 --- a/include/UECS/ChunkView.h +++ b/include/UECS/ChunkView.h @@ -6,6 +6,7 @@ namespace Ubpa::UECS { class Archetype; struct Chunk; + // you shourld get singleton (registered in locator) by world class ChunkView { public: ChunkView(Archetype* archetype, size_t chunkIdx, Chunk* chunk) diff --git a/include/UECS/EntityLocator.h b/include/UECS/CmptLocator.h similarity index 62% rename from include/UECS/EntityLocator.h rename to include/UECS/CmptLocator.h index ece19ee..d973cb6 100644 --- a/include/UECS/EntityLocator.h +++ b/include/UECS/CmptLocator.h @@ -9,17 +9,11 @@ namespace Ubpa::UECS { // locate components in function's argument list for Archetype // TODO: combine with a system function's locator - class EntityLocator { + class CmptLocator { public: - template - EntityLocator(TaggedCmptList); + CmptLocator(const CmptType* types, size_t num); - template - EntityLocator(TypeList, TypeList, TypeList); - - EntityLocator(const CmptType* types, size_t num); - - EntityLocator(); + CmptLocator(); size_t HashCode() const noexcept { return hashCode; } @@ -28,9 +22,7 @@ namespace Ubpa::UECS { const std::set& LatestCmptTypes() const noexcept { return latestCmptTypes; } const std::set& CmptTypes() const noexcept { return cmptTypes; } - AccessMode GetCmptTagMode(CmptType type) const; - - bool operator==(const EntityLocator& locator) const noexcept; + bool operator==(const CmptLocator& rhs) const noexcept; private: size_t GenHashCode() const noexcept; @@ -42,5 +34,3 @@ namespace Ubpa::UECS { size_t hashCode; }; } - -#include "detail/EntityLocator.inl" diff --git a/include/UECS/CmptPtr.h b/include/UECS/CmptPtr.h index 91ca7d9..0b09b2a 100644 --- a/include/UECS/CmptPtr.h +++ b/include/UECS/CmptPtr.h @@ -21,22 +21,22 @@ namespace Ubpa::UECS { template Cmpt* As() const noexcept { return reinterpret_cast(p); } - template - LastFrame AsLastFrame() const noexcept { - assert(type.GetAccessMode() == AccessMode::LAST_FRAME); - return p; - } - - template - Write AsWrite() const noexcept { - assert(type.GetAccessMode() == AccessMode::WRITE); - return p; - } - - template - Latest AsLatest() const noexcept { - assert(type.GetAccessMode() == AccessMode::LATEST); - return p; + template + auto As() const noexcept { + if constexpr (mode == AccessMode::LAST_FRAME) + return LastFrame{p}; + else if constexpr (mode == AccessMode::WRITE) + return Write(p); + else if constexpr (mode == AccessMode::LATEST) + return Latest(p); + else if constexpr (mode == AccessMode::LAST_FRAME_SINGLETON) + return LastFrame>; + else if constexpr (mode == AccessMode::WRITE_SINGLETON) + return Write>; + else if constexpr (mode == AccessMode::LATEST_SINGLETON) + return Latest>; + else + static_assert(false); } private: CmptType type; diff --git a/include/UECS/CmptTag.h b/include/UECS/CmptTag.h index 57fef89..f70ea59 100644 --- a/include/UECS/CmptTag.h +++ b/include/UECS/CmptTag.h @@ -4,12 +4,45 @@ namespace Ubpa::UECS { - // LastFrame -> Write -> Latest + // read/write tag : LastFrame -> Write -> Latest + // singleton tag : Singleton + // ==== + // 1. LastFrame + // 2. Write == Cmpt* + // 3. Latest == const Cmpt* + // 4. LastFrame> + // 5. Write> == Singleton + // 6. Latest> + + enum class AccessMode : size_t { + LAST_FRAME = 0, // 000, LastFrame + WRITE = 1, // 001, Write / Cmpt* + LATEST = 2, // 010, Latest / const Cmpt* + LAST_FRAME_SINGLETON = 4, // 100, LastFrame> + WRITE_SINGLETON = 5, // 101, Write> / Singleton + LATEST_SINGLETON = 6, // 110, Latest> + }; + + constexpr bool AccessMode_IsSingleton(AccessMode mode) noexcept { + return (static_cast(mode) & 4) != 0; + } + + template + class Singleton { + public: + Singleton(Cmpt* cmpt) noexcept : cmpt{ cmpt } {} + Singleton(const Cmpt* cmpt) noexcept : cmpt{ const_cast(cmpt) } {} + + Cmpt* Get() noexcept { return cmpt; } + const Cmpt* Get() const noexcept { return cmpt; } + + operator Cmpt* () noexcept { return cmpt; } + operator const Cmpt* () const noexcept { return cmpt; } - enum class AccessMode { - LAST_FRAME, - WRITE, - LATEST + Cmpt* operator->() noexcept { return cmpt; } + const Cmpt* operator->() const noexcept { return cmpt; } + private: + Cmpt* cmpt; }; template @@ -24,25 +57,86 @@ namespace Ubpa::UECS { }; template - using Write = Cmpt*; + class LastFrame> { + public: + LastFrame(const Cmpt* cmpt) noexcept : cmpt{ cmpt } {} + const Cmpt* Get() const noexcept { return cmpt; } + operator const Cmpt* () const noexcept { return cmpt; } + const Cmpt* operator->() const noexcept { return cmpt; } + private: + const Cmpt* cmpt; + }; + + template + class Write { + public: + Write(Cmpt* cmpt) noexcept : cmpt{ cmpt } {} + Cmpt* Get() const noexcept { return cmpt; } + operator Cmpt* () const noexcept { return cmpt; } + Cmpt* operator->() const noexcept { return cmpt; } + private: + Cmpt* cmpt; + }; template - using Latest = const Cmpt*; + class Write> { + public: + Write(Cmpt* cmpt) noexcept : cmpt{ cmpt } {} + Cmpt* Get() const noexcept { return cmpt; } + operator Cmpt* () const noexcept { return cmpt; } + Cmpt* operator->() const noexcept { return cmpt; } + private: + Cmpt* cmpt; + }; - // + template + class Latest { + public: + Latest(const Cmpt* cmpt) noexcept : cmpt{ cmpt } {} + const Cmpt* Get() const noexcept { return cmpt; } + operator const Cmpt* () const noexcept { return cmpt; } + const Cmpt* operator->() const noexcept { return cmpt; } + private: + const Cmpt* cmpt; + }; + + template + class Latest> { + public: + Latest(const Cmpt* cmpt) noexcept : cmpt{ cmpt } {} + const Cmpt* Get() const noexcept { return cmpt; } + operator const Cmpt* () const noexcept { return cmpt; } + const Cmpt* operator->() const noexcept { return cmpt; } + private: + const Cmpt* cmpt; + }; + + // (without read/write and singleton tag) template struct RemoveTag; template using RemoveTag_t = typename RemoveTag::type; + // / Singleton + template + struct RemoveRWTag; + template + using RemoveRWTag_t = typename RemoveRWTag::type; + + // LastFrame + // Write / Cmpt* + // Latest / const Cmpt* + template + struct RemoveSingletonTag; + template + using RemoveSingletonTag_t = typename RemoveSingletonTag::type; + // * template struct DecayTag; template using DecayTag_t = typename DecayTag::type; - // TODO: use IsInstance to simplify Is - template struct IsLastFrame; template @@ -58,19 +152,54 @@ namespace Ubpa::UECS { template static constexpr bool IsLatest_v = IsLatest::value; + template + struct IsLastFrameSingleton; + template + static constexpr bool IsLastFrameSingleton_v = IsLastFrameSingleton::value; + + template + struct IsWriteSingleton; + template + static constexpr bool IsWriteSingleton_v = IsWriteSingleton::value; + + template + struct IsLatestSingleton; + template + static constexpr bool IsLatestSingleton_v = IsLatestSingleton::value; + + template + struct IsSingleton : IValue + || IsWriteSingleton_v + || IsLatestSingleton_v + > {}; + template + static constexpr bool IsSingleton_v = IsSingleton::value; + + template + struct IsNonSingleton : IValue + || IsWrite_v + || IsLatest_v + > {}; + template + static constexpr bool IsNonSingleton_v = IsNonSingleton::value; + template - struct IsTaggedCmpt : IValue || IsWrite_v || IsLatest_v> {}; + struct IsTaggedCmpt : IValue || IsSingleton_v> {}; template static constexpr bool IsTaggedCmpt_v = IsTaggedCmpt::value; template static constexpr AccessMode AccessModeOf = IsLastFrame_v ? AccessMode::LAST_FRAME : ( - IsWrite_v ? AccessMode::WRITE : ( - IsLatest_v ? AccessMode::LATEST - : AccessMode::WRITE // default - ) - ); + 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, TODO : use static_assert + ))))); } #include "detail/CmptTag.inl" diff --git a/include/UECS/CmptsView.h b/include/UECS/CmptsView.h index c9499f3..45a50c4 100644 --- a/include/UECS/CmptsView.h +++ b/include/UECS/CmptsView.h @@ -1,41 +1,19 @@ #pragma once #include "CmptPtr.h" -#include "CmptType.h" -#include "CmptTag.h" - -#include namespace Ubpa::UECS { - class EntityLocator; - - // use CmptsView::Iterator to read CmptPtr class CmptsView { public: - CmptsView(const EntityLocator* locator, void** cmpts) - : locator{ locator }, cmpts{ cmpts }{} + CmptsView(const CmptPtr* cmpts, size_t num) + : cmpts{ cmpts }, num{ num } {} - // check AccessMode CmptPtr GetCmpt(CmptType) const; - template - LastFrame GetCmptAsLastFrame() const { - return GetCmpt(CmptType::Of>).AsLastFrame(); - } - - template - Write GetCmptAsWrite() const { - return GetCmpt(CmptType::Of>).AsWrite(); - } - - template - Latest GetCmptAsLatest() const { - return GetCmpt(CmptType::Of>).AsLatest(); - } - - void* const* Components() const noexcept { return cmpts; } + const CmptPtr* Components() const noexcept { return cmpts; } + size_t NumberOfComponents() const noexcept { return num; } private: - const EntityLocator* locator; - void* const* cmpts; + const CmptPtr* cmpts; + size_t num; }; } diff --git a/include/UECS/EntityMngr.h b/include/UECS/EntityMngr.h index 4c947cf..41bc8f7 100644 --- a/include/UECS/EntityMngr.h +++ b/include/UECS/EntityMngr.h @@ -62,6 +62,8 @@ namespace Ubpa::UECS { bool IsSingleton(CmptType) const; Entity GetSingletonEntity(CmptType) const; CmptPtr GetSingleton(CmptType) const; + // nullptr if not singleton + CmptPtr GetIfSingleton(CmptType) const; template Cmpt* GetSingleton() const { return GetSingleton(CmptType::Of).As(); } @@ -84,8 +86,11 @@ namespace Ubpa::UECS { void AttachWithoutInit(Entity); void AttachWithoutInit(Entity, const CmptType* types, size_t num); + std::tuple> LocateSingletons(const SingletonLocator& locator) const; + void GenEntityJob(World*, Job*, SystemFunc*) const; void GenChunkJob(World*, Job*, SystemFunc*) const; + void GenJob(World*, Job*, SystemFunc*) const; struct EntityInfo { Archetype* archetype{ nullptr }; diff --git a/include/UECS/EntityQuery.h b/include/UECS/EntityQuery.h index 50090c5..4907bff 100644 --- a/include/UECS/EntityQuery.h +++ b/include/UECS/EntityQuery.h @@ -1,21 +1,22 @@ #pragma once -#include "EntityFilter.h" -#include "EntityLocator.h" +#include "ArchetypeFilter.h" +#include "CmptLocator.h" namespace Ubpa::UECS { - // EntityFilter + EntityLocator + // ArchetypeFilter + CmptLocator class EntityQuery { public: - EntityFilter filter; - EntityLocator locator; + ArchetypeFilter filter; + CmptLocator locator; template EntityQuery(TypeList, TypeList, TypeList, TypeList); - EntityQuery(EntityFilter filter, EntityLocator locator = {}) + EntityQuery(ArchetypeFilter filter, CmptLocator locator = {}) :filter{ std::move(filter) }, locator{ std::move(locator) } {} + // without locator's singletons size_t HashCode() const noexcept { return hash_combine(filter.HashCode(), locator.HashCode()); } bool operator==(const EntityQuery& query) const noexcept { diff --git a/include/UECS/Schedule.h b/include/UECS/Schedule.h index 28a3537..700cbef 100644 --- a/include/UECS/Schedule.h +++ b/include/UECS/Schedule.h @@ -26,11 +26,11 @@ namespace Ubpa::UECS { class Schedule { public: template - const SystemFunc* Register(Func&& func, std::string name, EntityFilter filter = EntityFilter{}); + const SystemFunc* Register(Func&& func, std::string name, ArchetypeFilter filter = ArchetypeFilter{}); // run-time dynamic function template - const SystemFunc* Register(Func&& func, std::string name, EntityLocator locator, EntityFilter filter = EntityFilter{}); + const SystemFunc* Register(Func&& func, std::string name, CmptLocator locator, ArchetypeFilter filter = ArchetypeFilter{}); Schedule& LockFilter(std::string_view sys); diff --git a/include/UECS/SingletonLocator.h b/include/UECS/SingletonLocator.h new file mode 100644 index 0000000..4df7159 --- /dev/null +++ b/include/UECS/SingletonLocator.h @@ -0,0 +1,27 @@ +#pragma once + +#include "CmptTag.h" + +#include "CmptType.h" + +#include + +namespace Ubpa::UECS { + class SingletonLocator { + public: + SingletonLocator(const CmptType* types, size_t num); + + SingletonLocator(); + + const std::set& LastFrameSingletonTypes() const noexcept { return lastFrameSingletonTypes; } + const std::set& WriteSingletonTypes() const noexcept { return writeSingletonTypes; } + const std::set& LatestSingletonTypes() const noexcept { return latestSingletonTypes; } + const std::set& SingletonTypes() const noexcept { return singletonTypes; } + + private: + std::set lastFrameSingletonTypes; + std::set writeSingletonTypes; + std::set latestSingletonTypes; + std::set singletonTypes; + }; +} diff --git a/include/UECS/SingletonsView.h b/include/UECS/SingletonsView.h new file mode 100644 index 0000000..a2bdca6 --- /dev/null +++ b/include/UECS/SingletonsView.h @@ -0,0 +1,19 @@ +#pragma once + +#include "CmptPtr.h" + +namespace Ubpa::UECS { + class SingletonsView { + public: + SingletonsView(const CmptPtr* singletons, size_t num) + : singletons{ singletons }, num{ num } {} + + CmptPtr GetSingleton(CmptType) const; + + const CmptPtr* Singletons() const noexcept { return singletons; } + size_t NumberOfSingletons() const noexcept { return num; } + private: + const CmptPtr* singletons; + size_t num; + }; +} diff --git a/include/UECS/SystemFunc.h b/include/UECS/SystemFunc.h index 78ad05e..bf2e0ee 100644 --- a/include/UECS/SystemFunc.h +++ b/include/UECS/SystemFunc.h @@ -1,8 +1,10 @@ #pragma once #include "EntityQuery.h" +#include "SingletonLocator.h" #include "Entity.h" #include "CmptsView.h" +#include "SingletonsView.h" #include "ChunkView.h" #include @@ -14,14 +16,14 @@ namespace Ubpa::UECS { // name must be unique in global // query.filter can be change dynamically by other with Schedule // [system function kind] (distinguish by argument list) + // common : [World*], [{LastFrame|Write|Latest}Singleton], [SingletonsView] // 1. per entity function - // * [[const] World*] - // * [[const] Entity] + // * [Entity] // * [size_t indexInQuery] - // * [[const] CmptsView] // * : {LastFrame|Write|Latest} - // 2. chunk: [[const] World*], [const] ChunkView - // 3. job: [[const] World*] + // * [CmptsView] + // 2. chunk: ChunkView + // 3. job class SystemFunc { public: enum class Mode { @@ -30,14 +32,11 @@ namespace Ubpa::UECS { Job, }; - EntityQuery query; - - template - SystemFunc(Func&& func, std::string name, EntityFilter filter = EntityFilter{}); + EntityQuery entityQuery; + SingletonLocator singletonLocator; - // run-time dynamic function template - SystemFunc(Func&& func, std::string name, EntityLocator locator, EntityFilter filter = EntityFilter{}); + SystemFunc(Func&& func, std::string name, ArchetypeFilter archetypeFilter); const std::string& Name() const noexcept { return name; } @@ -45,18 +44,15 @@ namespace Ubpa::UECS { size_t HashCode() const noexcept { return hashCode; } - void operator()(World*, Entity e, size_t entityIndexInQuery, CmptsView rtdcmpts); - void operator()(World*, ChunkView chunkView); - void operator()(World*); + void operator()(World*, SingletonsView singletonsView, Entity e, size_t entityIndexInQuery, CmptsView cmptsView); + void operator()(World*, SingletonsView singletonsView, ChunkView chunkView); + void operator()(World*, SingletonsView singletonsView); Mode GetMode() const noexcept { return mode; } bool operator==(const SystemFunc& func) const noexcept { return name == func.name; } private: - template - SystemFunc(Func&& func, std::string name, EntityFilter filter, ArgList); - - std::function func; + std::function func; std::string name; Mode mode; diff --git a/include/UECS/detail/Archetype.h b/include/UECS/detail/Archetype.h index b51d7da..7122bb8 100644 --- a/include/UECS/detail/Archetype.h +++ b/include/UECS/detail/Archetype.h @@ -2,6 +2,7 @@ #include "../Entity.h" #include "../CmptPtr.h" +#include "../CmptLocator.h" #include "RTSCmptTraits.h" #include "CmptTypeSet.h" @@ -40,8 +41,9 @@ namespace Ubpa::UECS { ~Archetype(); // Entity + Components - std::tuple, std::vector>, std::vector> - Locate(const std::set& cmptTypes) const; + // without singleton + std::tuple, std::vector>, std::vector> + Locate(const CmptLocator& locator) const; void* Locate(size_t chunkIdx, CmptType) const; diff --git a/include/UECS/detail/EntityFilter.inl b/include/UECS/detail/ArchetypeFilter.inl similarity index 75% rename from include/UECS/detail/EntityFilter.inl rename to include/UECS/detail/ArchetypeFilter.inl index 5d8e79f..ce50412 100644 --- a/include/UECS/detail/EntityFilter.inl +++ b/include/UECS/detail/ArchetypeFilter.inl @@ -4,7 +4,7 @@ namespace Ubpa::UECS { template - EntityFilter::EntityFilter(TypeList, TypeList, TypeList) + ArchetypeFilter::ArchetypeFilter(TypeList, TypeList, TypeList) : allCmptTypes{ CmptType::Of... }, anyCmptTypes{ CmptType::Of... }, noneCmptTypes{ CmptType::Of... }, @@ -18,7 +18,7 @@ namespace Ubpa::UECS { } template - void EntityFilter::InsertAll(const CmptTypeContainer& c) { + void ArchetypeFilter::InsertAll(const CmptTypeContainer& c) { if (c.empty()) return; for (const auto& type : c) @@ -28,7 +28,7 @@ namespace Ubpa::UECS { } template - void EntityFilter::InsertAny(const CmptTypeContainer& c) { + void ArchetypeFilter::InsertAny(const CmptTypeContainer& c) { if (c.empty()) return; for (const auto& type : c) @@ -38,7 +38,7 @@ namespace Ubpa::UECS { } template - void EntityFilter::InsertNone(const CmptTypeContainer& c) { + void ArchetypeFilter::InsertNone(const CmptTypeContainer& c) { if (c.empty()) return; for (const auto& type : c) @@ -48,7 +48,7 @@ namespace Ubpa::UECS { } template - void EntityFilter::EraseAll(const CmptTypeContainer& c) { + void ArchetypeFilter::EraseAll(const CmptTypeContainer& c) { if (c.empty()) return; for (const auto& type : c) @@ -58,7 +58,7 @@ namespace Ubpa::UECS { } template - void EntityFilter::EraseAny(const CmptTypeContainer& c) { + void ArchetypeFilter::EraseAny(const CmptTypeContainer& c) { if (c.empty()) return; for (const auto& type : c) @@ -68,7 +68,7 @@ namespace Ubpa::UECS { } template - void EntityFilter::EraseNone(const CmptTypeContainer& c) { + void ArchetypeFilter::EraseNone(const CmptTypeContainer& c) { if (c.empty()) return; for (const auto& type : c) @@ -82,8 +82,8 @@ namespace std { template struct hash; template<> - struct hash { - size_t operator()(const Ubpa::UECS::EntityFilter& filter) const noexcept { + struct hash { + size_t operator()(const Ubpa::UECS::ArchetypeFilter& filter) const noexcept { return filter.HashCode(); } }; diff --git a/include/UECS/detail/CmptTag.inl b/include/UECS/detail/CmptTag.inl index f718564..879c637 100644 --- a/include/UECS/detail/CmptTag.inl +++ b/include/UECS/detail/CmptTag.inl @@ -4,33 +4,90 @@ namespace Ubpa::UECS { class Entity; - class EntityLocator; + class CmptLocator; class World; } namespace Ubpa::UECS { template struct RemoveTag : IType {}; // default - template struct RemoveTag : IType {}; - template struct RemoveTag : IType {}; + template struct RemoveTag> : IType {}; + template struct RemoveTag> : IType {}; + template struct RemoveTag> : IType {}; + + template struct RemoveTag>> : IType {}; + template struct RemoveTag>> : IType {}; + template struct RemoveTag>> : IType {}; + + template struct RemoveTag : IType {}; + template struct RemoveTag : IType {}; + template struct RemoveTag> : IType {}; + template struct RemoveTag> : IType {}; + + // ==== + + template struct RemoveRWTag : IType {}; // default + + template struct RemoveRWTag> : IType {}; + template struct RemoveRWTag> : IType {}; + template struct RemoveRWTag> : IType {}; + + template struct RemoveRWTag : IType {}; + template struct RemoveRWTag : IType {}; + template struct RemoveRWTag> : IType> {}; + + // ==== + + template struct RemoveSingletonTag : IType {}; // default + + template struct RemoveSingletonTag>> : IType> {}; + template struct RemoveSingletonTag>> : IType> {}; + template struct RemoveSingletonTag>> : IType> {}; + + template struct RemoveSingletonTag> : IType {}; + template struct RemoveSingletonTag> : IType {}; + + // ==== template struct DecayTag : IType {}; - template struct DecayTag : IType {}; + template struct DecayTag> : IType {}; - template struct DecayTag : IType {}; + template struct DecayTag> : IType {}; + template struct DecayTag> : IType {}; + + template struct DecayTag>> : IType {}; + template struct DecayTag>> : IType {}; + template struct DecayTag>> : IType {}; - template struct IsLastFrame : std::false_type {}; + template struct DecayTag : IType {}; + template struct DecayTag> : IType {}; + template struct DecayTag> : IType {}; + + // ==== + + template struct IsLastFrame : std::false_type {}; template struct IsLastFrame> : std::true_type {}; + template struct IsLastFrame>> : std::false_type {}; - template struct IsWrite : std::false_type {}; - template struct IsWrite : std::false_type {}; + template struct IsWrite : std::false_type {}; + template struct IsWrite> : std::true_type {}; + template struct IsWrite>> : std::false_type {}; template struct IsWrite : std::true_type {}; + template struct IsWrite : std::false_type {}; template<> struct IsWrite : std::false_type {}; - template struct IsLatest : std::false_type {}; + template struct IsLatest : std::false_type {}; + template struct IsLatest> : std::true_type {}; + template struct IsLatest>> : std::false_type {}; template struct IsLatest : std::true_type {}; - template<> struct IsLatest : std::false_type {}; - template struct IsTimePoint : - IValue || IsLastFrame_v || IsLatest_v> {}; + template struct IsLastFrameSingleton : std::false_type {}; + template struct IsLastFrameSingleton>> : std::true_type {}; + + template struct IsWriteSingleton : std::false_type {}; + template struct IsWriteSingleton>> : std::true_type {}; + template struct IsWriteSingleton> : std::true_type {}; + + template struct IsLatestSingleton : std::false_type {}; + template struct IsLatestSingleton>> : std::true_type {}; } diff --git a/include/UECS/detail/CmptTypeSet.h b/include/UECS/detail/CmptTypeSet.h index d82f2f5..8215cdc 100644 --- a/include/UECS/detail/CmptTypeSet.h +++ b/include/UECS/detail/CmptTypeSet.h @@ -42,9 +42,9 @@ namespace Ubpa::UECS { template bool NotContain(const CmptTypeContainer& types) const; - bool IsMatch(const EntityFilter& filter) const; + bool IsMatch(const ArchetypeFilter& filter) const; - bool IsMatch(const EntityLocator& locator) const; + bool IsMatch(const CmptLocator& locator) const; bool IsMatch(const EntityQuery& query) const; diff --git a/include/UECS/detail/CmptTypeSet.inl b/include/UECS/detail/CmptTypeSet.inl index eee9c6d..61addeb 100644 --- a/include/UECS/detail/CmptTypeSet.inl +++ b/include/UECS/detail/CmptTypeSet.inl @@ -66,14 +66,18 @@ namespace Ubpa::UECS { return true; } - inline bool CmptTypeSet::IsMatch(const EntityFilter& filter) const { + inline bool CmptTypeSet::IsMatch(const ArchetypeFilter& filter) const { return Contains(filter.AllCmptTypes()) && ContainsAny(filter.AnyCmptTypes()) && NotContain(filter.NoneCmptTypes()); } - inline bool CmptTypeSet::IsMatch(const EntityLocator& locator) const { - return Contains(locator.CmptTypes()); + inline bool CmptTypeSet::IsMatch(const CmptLocator& locator) const { + for (const auto& t : locator.CmptTypes()) { + if (!Contains(t)) + return false; + } + return true; } inline bool CmptTypeSet::IsMatch(const EntityQuery& query) const { diff --git a/include/UECS/detail/EntityLocator.inl b/include/UECS/detail/EntityLocator.inl deleted file mode 100644 index 3cd6adf..0000000 --- a/include/UECS/detail/EntityLocator.inl +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "CmptTag.inl" - -#include - -#include - -namespace Ubpa::UECS { - template - EntityLocator::EntityLocator(TaggedCmptList) - : EntityLocator{ Filter_t{}, - Filter_t{}, - Filter_t{} } - { - } - - template - EntityLocator::EntityLocator(TypeList, TypeList, TypeList) - : lastFrameCmptTypes{ CmptType::Of>... }, - writeCmptTypes{ CmptType::Of>... }, - latestCmptTypes{ CmptType::Of>... }, - cmptTypes{ CmptType::Of>..., CmptType::Of>...,CmptType::Of>... }, - hashCode{ GenHashCode() } - { - } -} diff --git a/include/UECS/detail/Schedule.inl b/include/UECS/detail/Schedule.inl index 2258a30..724f9fc 100644 --- a/include/UECS/detail/Schedule.inl +++ b/include/UECS/detail/Schedule.inl @@ -2,12 +2,12 @@ namespace Ubpa::UECS { template - const SystemFunc* Schedule::Register(Func&& func, std::string name, EntityFilter filter) { + const SystemFunc* Schedule::Register(Func&& func, std::string name, ArchetypeFilter filter) { return Request(std::forward(func), std::move(name), std::move(filter)); } template - const SystemFunc* Schedule::Register(Func&& func, std::string name, EntityLocator locator, EntityFilter filter) { + const SystemFunc* Schedule::Register(Func&& func, std::string name, CmptLocator locator, ArchetypeFilter filter) { return Request(std::forward(func), std::move(name), std::move(locator), std::move(filter)); } diff --git a/include/UECS/detail/SingletonLocator.inl b/include/UECS/detail/SingletonLocator.inl new file mode 100644 index 0000000..e69de29 diff --git a/include/UECS/detail/SingletonsView.h b/include/UECS/detail/SingletonsView.h new file mode 100644 index 0000000..e69de29 diff --git a/include/UECS/detail/SystemFunc.inl b/include/UECS/detail/SystemFunc.inl index 630a9fa..f10feec 100644 --- a/include/UECS/detail/SystemFunc.inl +++ b/include/UECS/detail/SystemFunc.inl @@ -2,96 +2,72 @@ #include <_deps/nameof.hpp> -namespace Ubpa::UECS::detail::System_ { +#include + +namespace Ubpa::UECS::detail { template auto Pack(Func&& func) noexcept; + template + constexpr CmptLocator GenCmptLocator() noexcept; + template + constexpr SingletonLocator GenSingletonLocator() noexcept; } namespace Ubpa::UECS { template - SystemFunc::SystemFunc(Func&& func, std::string name, EntityLocator locator, EntityFilter filter) - : mode{ Mode::Entity }, - func{ detail::System_::Pack(std::forward(func)) }, - name{ std::move(name) }, - hashCode{ HashCode(this->name) }, - query{ std::move(filter), std::move(locator) } - { - using ArgList = FuncTraits_ArgList; - using DecayedArgList = Transform_t; - - static_assert(Contain_v, - "(Mode::Entity) 's argument list must contain [const] CmptsView"); - - static_assert(!Contain_v, - "(Mode::Entity) 's argument list must not contain [const] ChunkView"); - } - - template - SystemFunc::SystemFunc(Func&& func, std::string name, EntityFilter filter) - : SystemFunc(std::forward(func), std::move(name), std::move(filter), FuncTraits_ArgList{}) - { - } - - - template - SystemFunc::SystemFunc(Func&& func, std::string name, EntityFilter filter, ArgList) + SystemFunc::SystemFunc(Func&& func, std::string name, ArchetypeFilter archetypeFilter) : - func{ detail::System_::Pack(std::forward(func)) }, + func{ detail::Pack(std::forward(func)) }, + entityQuery{ std::move(archetypeFilter), detail::GenCmptLocator() }, + singletonLocator{ detail::GenSingletonLocator() }, name{ std::move(name) }, - hashCode{ HashCode(this->name) }, - query{ std::move(filter), EntityLocator{Filter_t{}} } + hashCode{ HashCode(this->name) } { - using DecayedArgList = Transform_t; + using ArgList = FuncTraits_ArgList>; + static_assert(!Contain_v && !Contain_v); - static_assert(!Contain_v, - "'s argument list contains CmptsView, so you should use the constructor of the run-time dynamic version"); - - if constexpr ( - IsEmpty_v - || Length_v == 1 && Contain_v - ) { - // [[const] World*] - mode = Mode::Job; - } - else if constexpr ( - Contain_v - && ( - Length_v == 1 - || Length_v == 2 && Contain_v - ) - ) { - // [[const] World*] - // [const] ChunkView - mode = Mode::Chunk; + if constexpr (Length_v> > 0) { + static_assert(!Contain_v); + mode = Mode::Entity; } else { - // default - static_assert(!Contain_v, - "(Mode::Entity) 's argument list must not contain ChunkView"); - mode = Mode::Entity; + static_assert(!Contain_v && !Contain_v); + if constexpr (Contain_v) + mode = Mode::Chunk; + else + mode = Mode::Job; } } } -namespace Ubpa::UECS::detail::System_ { - template +namespace Ubpa::UECS::detail { + template struct Packer; - template - struct Packer, TypeList> { - using CmptList = TypeList; // sorted + template + struct Packer, TypeList, TypeList> { + using SortedSingletonList = TypeList; // sorted + using SortedNonSingletonList = TypeList; // sorted template static auto run(Func&& func) noexcept { - return [func = std::forward(func)](World* w, Entity e, size_t entityIndexInQuery, CmptsView rtdcmpts, ChunkView chunkView) { - auto unsorted_arg_tuple = std::make_tuple( + return [func = std::forward(func)]( + World* w, + SingletonsView singletonsView, + Entity e, + size_t entityIndexInQuery, + CmptsView cmptsView, + ChunkView chunkView) + { + auto args = std::tuple{ w, + reinterpret_cast(singletonsView.Singletons()[Find_v].Ptr())..., e, entityIndexInQuery, - rtdcmpts, + cmptsView, chunkView, - reinterpret_cast(rtdcmpts.Components()[Find_v])... - ); - func(std::get(unsorted_arg_tuple)...); + reinterpret_cast(cmptsView.Components()[Find_v].Ptr())... + }; + func(std::get(args)...); }; } }; @@ -105,9 +81,53 @@ namespace Ubpa::UECS::detail::System_ { using TaggedCmptList = Filter_t; - using CmptList = Transform_t; - using SortedCmptList = QuickSort_t; + using TaggedSingletonList = Filter_t; + using TaggedNonSingletonList = Filter_t; + + using SingletonList = Transform_t; + using NonSingletonList = Transform_t; + + using SortedSingletonList = QuickSort_t; + using SortedNonSingletonList = QuickSort_t; + + return Packer::run(std::forward(func)); + } + + // ==================== + + template + constexpr CmptLocator GenCmptLocator(TypeList) noexcept { + if constexpr (sizeof...(Cmpts) > 0) { + constexpr std::array types{ CmptType::Of... }; + return CmptLocator{ types.data(), types.size() }; + } + else + return CmptLocator{}; + } + + template + constexpr CmptLocator GenCmptLocator() noexcept { + using ArgList = FuncTraits_ArgList>; + using CmptList = Filter_t; + return GenCmptLocator(CmptList{}); + } + + // ==================== - return Packer::run(std::forward(func)); + template + constexpr SingletonLocator GenSingletonLocator(TypeList) noexcept { + if constexpr (sizeof...(Singletons) > 0) { + constexpr std::array types{ CmptType::Of... }; + return SingletonLocator{ types.data(), types.size() }; + } + else + return SingletonLocator{}; + } + + template + constexpr SingletonLocator GenSingletonLocator() noexcept { + using ArgList = FuncTraits_ArgList>; + using SingletonList = Filter_t; + return GenSingletonLocator(SingletonList{}); } } diff --git a/src/core/Archetype.cpp b/src/core/Archetype.cpp index 95cc4a6..a637195 100644 --- a/src/core/Archetype.cpp +++ b/src/core/Archetype.cpp @@ -158,24 +158,25 @@ size_t Archetype::Instantiate(Entity e, size_t srcIdx) { return dstIdx; } -tuple, vector>, vector> Archetype::Locate(const set& cmptTypes) const { - assert(types.Contains(cmptTypes)); - vector> chunkCmpts(chunks.size()); +tuple, vector>, vector> Archetype::Locate(const CmptLocator& locator) const { + assert(types.IsMatch(locator)); + + vector> chunkCmpts(chunks.size()); vector chunkEntity; for (size_t i = 0; i < chunks.size(); i++) { auto data = chunks[i]->Data(); - for (const auto& type : cmptTypes) - chunkCmpts[i].push_back(data + Offsetof(type)); + chunkCmpts[i].reserve(locator.CmptTypes().size()); + for (const auto& type : locator.CmptTypes()) + chunkCmpts[i].emplace_back(type, data + Offsetof(type)); chunkEntity.push_back(reinterpret_cast(data + Offsetof(CmptType::Of))); } vector sizes; - - for (const auto& type : cmptTypes) + sizes.reserve(locator.CmptTypes().size()); + for (const auto& type : locator.CmptTypes()) sizes.push_back(cmptTraits.Sizeof(type)); - return { chunkEntity, chunkCmpts, sizes }; } diff --git a/src/core/EntityFilter.cpp b/src/core/ArchetypeFilter.cpp similarity index 61% rename from src/core/EntityFilter.cpp rename to src/core/ArchetypeFilter.cpp index 101f075..a7b6d12 100644 --- a/src/core/EntityFilter.cpp +++ b/src/core/ArchetypeFilter.cpp @@ -1,17 +1,17 @@ -#include +#include using namespace Ubpa::UECS; -EntityFilter::EntityFilter() +ArchetypeFilter::ArchetypeFilter() : - allHashCode{ TypeID }, - anyHashCode{ TypeID }, - noneHashCode{ TypeID }, - combinedHashCode{ hash_combine(std::array{TypeID, TypeID, TypeID}) } + allHashCode{ TypeID }, + anyHashCode{ TypeID }, + noneHashCode{ TypeID }, + combinedHashCode{ hash_combine(std::array{TypeID, TypeID, TypeID}) } { } -EntityFilter::EntityFilter( +ArchetypeFilter::ArchetypeFilter( std::set allCmptTypes, std::set anyCmptTypes, std::set noneCmptTypes) @@ -26,7 +26,7 @@ EntityFilter::EntityFilter( { } -void EntityFilter::InsertAll(const CmptType* types, size_t num) { +void ArchetypeFilter::InsertAll(const CmptType* types, size_t num) { assert(types != nullptr); for (size_t i = 0; i < num; i++) allCmptTypes.insert(types[i]); @@ -34,7 +34,7 @@ void EntityFilter::InsertAll(const CmptType* types, size_t num) { combinedHashCode = GenCombinedHashCode(); } -void EntityFilter::InsertAny(const CmptType* types, size_t num) { +void ArchetypeFilter::InsertAny(const CmptType* types, size_t num) { assert(types != nullptr); for (size_t i = 0; i < num; i++) anyCmptTypes.insert(types[i]); @@ -42,7 +42,7 @@ void EntityFilter::InsertAny(const CmptType* types, size_t num) { combinedHashCode = GenCombinedHashCode(); } -void EntityFilter::InsertNone(const CmptType* types, size_t num) { +void ArchetypeFilter::InsertNone(const CmptType* types, size_t num) { assert(types != nullptr); for (size_t i = 0; i < num; i++) noneCmptTypes.insert(types[i]); @@ -50,7 +50,7 @@ void EntityFilter::InsertNone(const CmptType* types, size_t num) { combinedHashCode = GenCombinedHashCode(); } -void EntityFilter::EraseAll(const CmptType* types, size_t num) { +void ArchetypeFilter::EraseAll(const CmptType* types, size_t num) { assert(types != nullptr); for (size_t i = 0; i < num; i++) allCmptTypes.erase(types[i]); @@ -58,14 +58,14 @@ void EntityFilter::EraseAll(const CmptType* types, size_t num) { combinedHashCode = GenCombinedHashCode(); } -void EntityFilter::EraseAny(const CmptType* types, size_t num) { +void ArchetypeFilter::EraseAny(const CmptType* types, size_t num) { assert(types != nullptr); for (size_t i = 0; i < num; i++) anyHashCode = GenAnyHashCode(); combinedHashCode = GenCombinedHashCode(); } -void EntityFilter::EraseNone(const CmptType* types, size_t num) { +void ArchetypeFilter::EraseNone(const CmptType* types, size_t num) { assert(types != nullptr); for (size_t i = 0; i < num; i++) noneCmptTypes.erase(types[i]); @@ -73,35 +73,35 @@ void EntityFilter::EraseNone(const CmptType* types, size_t num) { combinedHashCode = GenCombinedHashCode(); } -size_t EntityFilter::GenAllHashCode() const noexcept { - size_t rst = TypeID; +size_t ArchetypeFilter::GenAllHashCode() const noexcept { + size_t rst = TypeID; for (auto type : allCmptTypes) { rst = hash_combine(rst, type.HashCode()); } return rst; } -size_t EntityFilter::GenAnyHashCode() const noexcept { - size_t rst = TypeID; +size_t ArchetypeFilter::GenAnyHashCode() const noexcept { + size_t rst = TypeID; for (auto type : anyCmptTypes) { rst = hash_combine(rst, type.HashCode()); } return rst; } -size_t EntityFilter::GenNoneHashCode() const noexcept { - size_t rst = TypeID; +size_t ArchetypeFilter::GenNoneHashCode() const noexcept { + size_t rst = TypeID; for (auto type : noneCmptTypes) { rst = hash_combine(rst, type.HashCode()); } return rst; } -size_t EntityFilter::GenCombinedHashCode() const noexcept { +size_t ArchetypeFilter::GenCombinedHashCode() const noexcept { return hash_combine(std::array{allHashCode, anyHashCode, noneHashCode}); } -bool EntityFilter::operator==(const EntityFilter& filter) const noexcept { +bool ArchetypeFilter::operator==(const ArchetypeFilter& filter) const noexcept { return allCmptTypes == filter.allCmptTypes && anyCmptTypes == filter.anyCmptTypes && noneCmptTypes == filter.noneCmptTypes; diff --git a/src/core/CmptLocator.cpp b/src/core/CmptLocator.cpp new file mode 100644 index 0000000..807cb35 --- /dev/null +++ b/src/core/CmptLocator.cpp @@ -0,0 +1,49 @@ +#include + +#include + +#include + +using namespace Ubpa::UECS; +using namespace std; + +CmptLocator::CmptLocator(const CmptType* types, size_t num) { + assert(types != nullptr && num > 0); + for (size_t i = 0; i < num; i++) { + switch (types[i].GetAccessMode()) + { + case Ubpa::UECS::AccessMode::LAST_FRAME: + lastFrameCmptTypes.insert(types[i]); + break; + case Ubpa::UECS::AccessMode::WRITE: + writeCmptTypes.insert(types[i]); + break; + case Ubpa::UECS::AccessMode::LATEST: + latestCmptTypes.insert(types[i]); + break; + default: + assert(false); + break; + } + } + cmptTypes = SetUnion(lastFrameCmptTypes, writeCmptTypes); + cmptTypes = SetUnion(cmptTypes, latestCmptTypes); + + hashCode = GenHashCode(); +} + +CmptLocator::CmptLocator() + : hashCode{ TypeID } {} + +size_t CmptLocator::GenHashCode() const noexcept { + size_t rst = TypeID; + for (auto type : cmptTypes) + rst = hash_combine(rst, type.HashCode()); + return rst; +} + +bool CmptLocator::operator==(const CmptLocator& rhs) const noexcept { + return lastFrameCmptTypes == rhs.lastFrameCmptTypes + && writeCmptTypes == rhs.writeCmptTypes + && latestCmptTypes == rhs.latestCmptTypes; +} diff --git a/src/core/CmptsView.cpp b/src/core/CmptsView.cpp index c8a46f3..13d247e 100644 --- a/src/core/CmptsView.cpp +++ b/src/core/CmptsView.cpp @@ -1,18 +1,13 @@ #include -#include - using namespace Ubpa::UECS; -using namespace std; CmptPtr CmptsView::GetCmpt(CmptType t) const { - size_t i = 0; - for (auto iter = locator->CmptTypes().begin(); iter != locator->CmptTypes().end(); ++iter, ++i) { - if (*iter == t) { - assert(iter->GetAccessMode() == t.GetAccessMode()); - return CmptPtr(*iter, *(cmpts + i)); + for (size_t i = 0; i < num; i++) { + if (cmpts[i].Type() == t) { + assert(cmpts[i].Type().GetAccessMode() == t.GetAccessMode()); + return cmpts[i]; } } - assert(false); - return CmptPtr(t, nullptr); + return { CmptType::Invalid(), nullptr }; } diff --git a/src/core/EntityLocator.cpp b/src/core/EntityLocator.cpp deleted file mode 100644 index 25e3a16..0000000 --- a/src/core/EntityLocator.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include - -#include - -using namespace Ubpa::UECS; -using namespace std; - -EntityLocator::EntityLocator(const CmptType* types, size_t num) { - assert(types != nullptr && num > 0); - for (size_t i = 0; i < num; i++) { - switch (types[i].GetAccessMode()) - { - case Ubpa::UECS::AccessMode::LAST_FRAME: - lastFrameCmptTypes.insert(types[i]); - break; - case Ubpa::UECS::AccessMode::WRITE: - writeCmptTypes.insert(types[i]); - break; - case Ubpa::UECS::AccessMode::LATEST: - latestCmptTypes.insert(types[i]); - break; - default: - assert(false); - break; - } - } - cmptTypes = SetUnion(lastFrameCmptTypes, writeCmptTypes); - cmptTypes = SetUnion(cmptTypes, latestCmptTypes); - hashCode = GenHashCode(); -} - -EntityLocator::EntityLocator() - : hashCode{ TypeID } {} - -size_t EntityLocator::GenHashCode() const noexcept { - size_t rst = TypeID; - for (auto type : cmptTypes) - rst = hash_combine(rst, type.HashCode()); - return rst; -} - -bool EntityLocator::operator==(const EntityLocator& locator) const noexcept { - return lastFrameCmptTypes == locator.lastFrameCmptTypes - && writeCmptTypes == locator.writeCmptTypes - && latestCmptTypes == latestCmptTypes; -} - -AccessMode EntityLocator::GetCmptTagMode(CmptType type) const { - assert(cmptTypes.find(type) != cmptTypes.end()); - if (lastFrameCmptTypes.find(type) != lastFrameCmptTypes.end()) - return AccessMode::LAST_FRAME; - else if (writeCmptTypes.find(type) != writeCmptTypes.end()) - return AccessMode::WRITE; - else // lastestCmptTypes.find(type) != lastestCmptTypes.end()) - return AccessMode::LATEST; -} diff --git a/src/core/EntityMngr.cpp b/src/core/EntityMngr.cpp index 6d24660..3027c78 100644 --- a/src/core/EntityMngr.cpp +++ b/src/core/EntityMngr.cpp @@ -258,25 +258,48 @@ void EntityMngr::Destroy(Entity e) { RecycleEntityEntry(e); } +tuple> EntityMngr::LocateSingletons(const SingletonLocator& locator) const { + size_t numSingletons = 0; + vector rst; + rst.reserve(locator.SingletonTypes().size()); + for (const auto& t : locator.SingletonTypes()) { + auto ptr = GetIfSingleton(t); + if (ptr.Ptr() == nullptr) + return { false, {} }; + rst.push_back(ptr); + } + return { true, rst }; +} + void EntityMngr::GenEntityJob(World* w, Job* job, SystemFunc* sys) const { assert(sys->GetMode() == SystemFunc::Mode::Entity); + auto [success, singletons] = LocateSingletons(sys->singletonLocator); + if (!success) + return; + size_t indexOffsetInQuery = 0; - for (Archetype* archetype : QueryArchetypes(sys->query)) { - auto [chunkEntity, chunkCmpts, sizes] = archetype->Locate(sys->query.locator.CmptTypes()); + for (Archetype* archetype : QueryArchetypes(sys->entityQuery)) { + auto [chunkEntity, chunkCmpts, sizes] = archetype->Locate(sys->entityQuery.locator); size_t num = archetype->EntityNum(); size_t chunkNum = archetype->ChunkNum(); size_t chunkCapacity = archetype->ChunkCapacity(); for (size_t i = 0; i < chunkNum; i++) { - job->emplace([=, sizes = sizes, entities = chunkEntity[i], cmpts = move(chunkCmpts[i])]() mutable { + job->emplace([=, sizes = sizes, entities = chunkEntity[i], cmpts = move(chunkCmpts[i]), singletons = singletons]() mutable { size_t idxOffsetInChunk = i * chunkCapacity; size_t indexOffsetInQueryChunk = indexOffsetInQuery + idxOffsetInChunk; size_t J = min(chunkCapacity, num - idxOffsetInChunk); for (size_t j = 0; j < J; j++) { - (*sys)(w, entities[j], indexOffsetInQueryChunk + j, { &sys->query.locator, cmpts.data() }); + (*sys)( + w, + SingletonsView{ singletons.data(), singletons.size() }, + entities[j], + indexOffsetInQueryChunk + j, + CmptsView{ cmpts.data(), cmpts.size() } + ); for (size_t k = 0; k < cmpts.size(); k++) reinterpret_cast(cmpts[k]) += sizes[k]; } @@ -290,17 +313,40 @@ void EntityMngr::GenEntityJob(World* w, Job* job, SystemFunc* sys) const { void EntityMngr::GenChunkJob(World* w, Job* job, SystemFunc* sys) const { assert(sys->GetMode() == SystemFunc::Mode::Chunk); - for (Archetype* archetype : QueryArchetypes(sys->query)) { + auto [success, singletons] = LocateSingletons(sys->singletonLocator); + if (!success) + return; + + for (Archetype* archetype : QueryArchetypes(sys->entityQuery)) { size_t chunkNum = archetype->ChunkNum(); for (size_t i = 0; i < chunkNum; i++) { - job->emplace([=]() { - (*sys)(w, ChunkView{ archetype, i, archetype->GetChunk(i) }); + job->emplace([=, singletons = singletons]() { + (*sys)( + w, + SingletonsView{ singletons.data(), singletons.size() }, + ChunkView{ archetype, i, archetype->GetChunk(i) } + ); }); } } } +void EntityMngr::GenJob(World* w, Job* job, SystemFunc* sys) const { + assert(sys->GetMode() == SystemFunc::Mode::Job); + + auto [success, singletons] = LocateSingletons(sys->singletonLocator); + if (!success) + return; + + job->emplace([=, singletons = std::move(singletons)]() { + (*sys)( + w, + SingletonsView{ singletons.data(), singletons.size() } + ); + }); +} + void EntityMngr::Accept(IListener* listener) const { listener->EnterEntityMngr(this); for (const auto& [h, a] : h2a) { @@ -318,7 +364,7 @@ void EntityMngr::Accept(IListener* listener) const { } bool EntityMngr::IsSingleton(CmptType t) const { - EntityFilter filter{ {t}, {}, {} }; + ArchetypeFilter filter{ {t}, {}, {} }; EntityQuery query(move(filter)); const auto& archetypes = QueryArchetypes(query); if (archetypes.size() != 1) @@ -332,7 +378,7 @@ bool EntityMngr::IsSingleton(CmptType t) const { Entity EntityMngr::GetSingletonEntity(CmptType t) const { assert(IsSingleton(t)); - EntityFilter filter{ {t}, {}, {} }; + ArchetypeFilter filter{ {t}, {}, {} }; EntityQuery query(move(filter)); const auto& archetypes = QueryArchetypes(query); auto archetype = *archetypes.begin(); @@ -341,9 +387,22 @@ Entity EntityMngr::GetSingletonEntity(CmptType t) const { CmptPtr EntityMngr::GetSingleton(CmptType t) const { assert(IsSingleton(t)); - EntityFilter filter{ {t}, {}, {} }; + ArchetypeFilter filter{ {t}, {}, {} }; + EntityQuery query(move(filter)); + const auto& archetypes = QueryArchetypes(query); + auto archetype = *archetypes.begin(); + return { t, archetype->At(t, 0) }; +} + +CmptPtr EntityMngr::GetIfSingleton(CmptType t) const { + ArchetypeFilter filter{ {t}, {}, {} }; EntityQuery query(move(filter)); const auto& archetypes = QueryArchetypes(query); + if (archetypes.size() != 1) + return { CmptType::Invalid(), nullptr }; auto archetype = *archetypes.begin(); + if (archetype->EntityNum() != 1) + return { CmptType::Invalid(), nullptr }; + return { t, archetype->At(t, 0) }; } diff --git a/src/core/Schedule.cpp b/src/core/Schedule.cpp index 2c3fc1b..87e060b 100644 --- a/src/core/Schedule.cpp +++ b/src/core/Schedule.cpp @@ -13,9 +13,9 @@ namespace Ubpa::UECS::detail::Schedule_ { NoneGroup(SystemFunc* func) : sysFuncs{ func } { - needTypes = SetUnion(func->query.filter.AllCmptTypes(), func->query.filter.AnyCmptTypes()); - needTypes = SetUnion(needTypes, func->query.locator.CmptTypes()); - noneTypes = func->query.filter.NoneCmptTypes(); + needTypes = SetUnion(func->entityQuery.filter.AllCmptTypes(), func->entityQuery.filter.AnyCmptTypes()); + needTypes = SetUnion(needTypes, func->entityQuery.locator.CmptTypes()); + noneTypes = func->entityQuery.filter.NoneCmptTypes(); } static bool Parallelable(const NoneGroup& x, const NoneGroup& y) { @@ -213,16 +213,24 @@ void Schedule::Clear() { unordered_map Schedule::GenCmptSysFuncsMap() const { unordered_map rst; for (const auto& [hashcode, sysFunc] : sysFuncs) { - const auto& locator = sysFunc->query.locator; - for (const auto& type : locator.LastFrameCmptTypes()) + const auto& cmptsLocator = sysFunc->entityQuery.locator; + for (const auto& type : cmptsLocator.LastFrameCmptTypes()) rst[type].lastFrameSysFuncs.push_back(sysFunc); - for (const auto& type : locator.WriteCmptTypes()) + for (const auto& type : cmptsLocator.WriteCmptTypes()) rst[type].writeSysFuncs.push_back(sysFunc); - for (const auto& type : locator.LatestCmptTypes()) + for (const auto& type : cmptsLocator.LatestCmptTypes()) + rst[type].latestSysFuncs.push_back(sysFunc); + + const auto& singletonsLocator = sysFunc->singletonLocator; + for (const auto& type : singletonsLocator.LastFrameSingletonTypes()) + rst[type].lastFrameSysFuncs.push_back(sysFunc); + for (const auto& type : singletonsLocator.WriteSingletonTypes()) + rst[type].writeSysFuncs.push_back(sysFunc); + for (const auto& type : singletonsLocator.LatestSingletonTypes()) rst[type].latestSysFuncs.push_back(sysFunc); if (sysFunc->GetMode() == SystemFunc::Mode::Chunk) { - const auto& filter = sysFunc->query.filter; + const auto& filter = sysFunc->entityQuery.filter; for (const auto& type : filter.AllCmptTypes()) { auto& cmptSysFuncs = rst[type]; switch (type.GetAccessMode()) @@ -277,12 +285,12 @@ SysFuncGraph Schedule::GenSysFuncGraph() const { auto func = target->second; - func->query.filter.InsertAll(change.insertAlls); - func->query.filter.InsertAny(change.insertAnys); - func->query.filter.InsertNone(change.insertNones); - func->query.filter.EraseAll(change.eraseAlls); - func->query.filter.EraseAny(change.eraseAnys); - func->query.filter.EraseNone(change.eraseNones); + func->entityQuery.filter.InsertAll(change.insertAlls); + func->entityQuery.filter.InsertAny(change.insertAnys); + func->entityQuery.filter.InsertNone(change.insertNones); + func->entityQuery.filter.EraseAll(change.eraseAlls); + func->entityQuery.filter.EraseAny(change.eraseAnys); + func->entityQuery.filter.EraseNone(change.eraseNones); } auto cmptSysFuncsMap = GenCmptSysFuncsMap(); diff --git a/src/core/SingletonLocator.cpp b/src/core/SingletonLocator.cpp new file mode 100644 index 0000000..51f7c93 --- /dev/null +++ b/src/core/SingletonLocator.cpp @@ -0,0 +1,34 @@ +#include + +#include + +#include + +using namespace Ubpa::UECS; +using namespace std; + +SingletonLocator::SingletonLocator(const CmptType* types, size_t num) { + assert(types != nullptr && num > 0); + for (size_t i = 0; i < num; i++) { + switch (types[i].GetAccessMode()) + { + case Ubpa::UECS::AccessMode::LAST_FRAME_SINGLETON: + lastFrameSingletonTypes.insert(types[i]); + break; + case Ubpa::UECS::AccessMode::WRITE_SINGLETON: + writeSingletonTypes.insert(types[i]); + break; + case Ubpa::UECS::AccessMode::LATEST_SINGLETON: + latestSingletonTypes.insert(types[i]); + break; + default: + assert(false); + break; + } + } + + singletonTypes = SetUnion(lastFrameSingletonTypes, writeSingletonTypes); + singletonTypes = SetUnion(singletonTypes, latestSingletonTypes); +} + +SingletonLocator::SingletonLocator() {} diff --git a/src/core/SingletonsView.cpp b/src/core/SingletonsView.cpp new file mode 100644 index 0000000..c745c32 --- /dev/null +++ b/src/core/SingletonsView.cpp @@ -0,0 +1,13 @@ +#include + +using namespace Ubpa::UECS; + +CmptPtr SingletonsView::GetSingleton(CmptType t) const { + for (size_t i = 0; i < num; i++) { + if (singletons[i].Type() == t) { + assert(singletons[i].Type().GetAccessMode() == t.GetAccessMode()); + return singletons[i]; + } + } + return { CmptType::Invalid(), nullptr }; +} diff --git a/src/core/SystemFunc.cpp b/src/core/SystemFunc.cpp index 68d3611..1d29d6b 100644 --- a/src/core/SystemFunc.cpp +++ b/src/core/SystemFunc.cpp @@ -2,36 +2,38 @@ using namespace Ubpa::UECS; -void SystemFunc::operator()(World* w, Entity e, size_t entityIndexInQuery, CmptsView rtdcmpts) { +void SystemFunc::operator()(World* w, SingletonsView singletonsView, Entity e, size_t entityIndexInQuery, CmptsView cmptsView) { assert(mode == Mode::Entity); return func( w, + singletonsView, e, entityIndexInQuery, - rtdcmpts, + cmptsView, ChunkView{ nullptr, size_t_invalid, nullptr } ); } -void SystemFunc::operator()(World* w, ChunkView chunkView) { +void SystemFunc::operator()(World* w, SingletonsView singletonsView, ChunkView chunkView) { assert(mode == Mode::Chunk); return func( w, + singletonsView, Entity::Invalid(), size_t_invalid, - CmptsView{ nullptr, nullptr }, + CmptsView{ nullptr, 0 }, chunkView ); } -void SystemFunc::operator()(World* w) { +void SystemFunc::operator()(World* w, SingletonsView singletonsView) { assert(mode == Mode::Job); return func( w, + singletonsView, Entity::Invalid(), size_t_invalid, - CmptsView{ nullptr, nullptr }, + CmptsView{ nullptr, 0 }, ChunkView{ nullptr, size_t_invalid, nullptr } ); } - diff --git a/src/core/World.cpp b/src/core/World.cpp index 48aea0a..eddaeee 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -34,9 +34,7 @@ void World::Update() { entityMngr.GenChunkJob(this, job, func); break; case Ubpa::UECS::SystemFunc::Mode::Job: - job->emplace([this, func = func]() { - (*func)(this); - }); + entityMngr.GenJob(this, job, func); break; default: break; @@ -122,13 +120,13 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const { }; for (const auto& [hash, sysFunc] : schedule.sysFuncs) { - for (auto cmptType : sysFunc->query.locator.CmptTypes()) + for (auto cmptType : sysFunc->entityQuery.locator.CmptTypes()) cmptTypes.insert(cmptType); - for (auto cmptType : sysFunc->query.filter.AllCmptTypes()) + for (auto cmptType : sysFunc->entityQuery.filter.AllCmptTypes()) cmptTypes.insert(cmptType); - for (auto cmptType : sysFunc->query.filter.AnyCmptTypes()) + for (auto cmptType : sysFunc->entityQuery.filter.AnyCmptTypes()) cmptTypes.insert(cmptType); - for (auto cmptType : sysFunc->query.filter.NoneCmptTypes()) + for (auto cmptType : sysFunc->entityQuery.filter.NoneCmptTypes()) cmptTypes.insert(cmptType); } @@ -144,7 +142,7 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const { subgraph_sys.AddNode(sysIdx); - const auto& locator = sysFunc->query.locator; + const auto& locator = sysFunc->entityQuery.locator; for (const auto& cmptType : locator.LastFrameCmptTypes()) { auto edgeIdx = registry.RegisterEdge(cmptType2idx[cmptType], sysIdx); subgraph_lastframe.AddEdge(edgeIdx); @@ -158,7 +156,7 @@ UGraphviz::Graph World::GenUpdateFrameGraph() const { subgraph_latest.AddEdge(edgeIdx); } - const auto& filter = sysFunc->query.filter; + const auto& filter = sysFunc->entityQuery.filter; if (sysFunc->GetMode() == SystemFunc::Mode::Chunk) { // filter's and components are treat as r/w for (const auto& cmptType : filter.AllCmptTypes()) { diff --git a/src/test/04_filter/main.cpp b/src/test/04_filter/main.cpp index 2440050..cf6f1a6 100644 --- a/src/test/04_filter/main.cpp +++ b/src/test/04_filter/main.cpp @@ -17,7 +17,7 @@ class MySystem : public System { using System::System; virtual void OnUpdate(Schedule& schedule) override { - EntityFilter filter( + ArchetypeFilter filter( TypeList{}, // all TypeList{}, // any TypeList{} // none diff --git a/src/test/06_none_parallel/main.cpp b/src/test/06_none_parallel/main.cpp index b4b4aa2..d7db21c 100644 --- a/src/test/06_none_parallel/main.cpp +++ b/src/test/06_none_parallel/main.cpp @@ -14,12 +14,12 @@ class MySystem : public System { using System::System; virtual void OnUpdate(Schedule& schedule) override { - EntityFilter filter_w0( + ArchetypeFilter filter_w0( TypeList<>{}, // all TypeList<>{}, // any TypeList{} // none ); - EntityFilter filter_w1( + ArchetypeFilter filter_w1( TypeList{}, // all TypeList<>{}, // any TypeList<>{} // none diff --git a/src/test/11_runtime_cmpt/main.cpp b/src/test/11_runtime_cmpt/main.cpp index a421b09..f2ab6eb 100644 --- a/src/test/11_runtime_cmpt/main.cpp +++ b/src/test/11_runtime_cmpt/main.cpp @@ -17,10 +17,10 @@ class RTDSystem: public System{ CmptType{ "LuaCmpt", AccessMode::LATEST } }; - EntityLocator locator_write( + CmptLocator locator_write( cmpts_write.data(), cmpts_write.size() ); - EntityLocator locator_read( + CmptLocator locator_read( cmpts_read.data(), cmpts_read.size() ); diff --git a/src/test/12_framegraph/main.cpp b/src/test/12_framegraph/main.cpp index ae5f02c..2d46f2f 100644 --- a/src/test/12_framegraph/main.cpp +++ b/src/test/12_framegraph/main.cpp @@ -19,7 +19,7 @@ class MySystem : public System { using System::System; virtual void OnUpdate(Schedule& schedule) override { - EntityFilter filter( + ArchetypeFilter filter( TypeList{}, // all TypeList{}, // any TypeList{} // none diff --git a/src/test/15_chunk_job/main.cpp b/src/test/15_chunk_job/main.cpp index 12863cd..670c05f 100644 --- a/src/test/15_chunk_job/main.cpp +++ b/src/test/15_chunk_job/main.cpp @@ -17,7 +17,7 @@ class SAB_System : public System { using System::System; virtual void OnUpdate(Schedule& schedule) override { - EntityFilter filter{ + ArchetypeFilter filter{ TypeList{}, // all TypeList, Latest>{}, // any TypeList<>{} // none diff --git a/src/test/16_singleton/main.cpp b/src/test/16_singleton/main.cpp index b5be27f..d3bda26 100644 --- a/src/test/16_singleton/main.cpp +++ b/src/test/16_singleton/main.cpp @@ -5,7 +5,7 @@ using namespace Ubpa::UECS; struct Timer { - float dt; + float dt{ 0.f }; }; struct Position { float val{ 1.f }; }; @@ -16,22 +16,29 @@ class MoverSystem : public System { using System::System; virtual void OnUpdate(Schedule& schedule) override { - float dt = GetWorld()->entityMngr.GetSingleton()->dt; - schedule.Register([dt](const Velocity* v, Position* p) { - p->val += dt * v->val; + schedule.Register([](Singleton timer) { + timer->dt = 0.03f; + }, "Timer"); + schedule.Register([](const Velocity* v, Position* p, Latest> timer) { + p->val += timer->dt * v->val; }, "Mover"); - schedule.Register([dt](const Position* p) { + schedule.Register([](const Position* p) { std::cout << p->val << std::endl; }, "Print"); } }; int main() { + constexpr auto mode = AccessModeOf>; + RTDCmptTraits::Instance().Register + (); + World w; w.systemMngr.Register(); w.entityMngr.Create(); - auto [e_singleton, timer] = w.entityMngr.Create(); - timer->dt = 0.03f; + w.entityMngr.Create(); w.Update(); + std::cout << w.DumpUpdateJobGraph() << std::endl; + std::cout << w.GenUpdateFrameGraph().Dump() << std::endl; }