From f123f075ebebe7b7b5c197c9b0a9970988a8e60c Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sun, 13 Mar 2016 18:07:49 +0900 Subject: [PATCH] Added Meta/Matching, progress on Bitset/Manager --- src/CMakeLists.txt | 6 +- src/EC/Bitset.hpp | 14 ++- src/EC/Manager.hpp | 198 +++++++++++++++++++++++++++++++++++---- src/EC/Meta/Matching.hpp | 54 +++++++++++ src/EC/Meta/Meta.hpp | 1 + src/test/ECTest.cpp | 106 +++++++++++++++++++++ src/test/MetaTest.cpp | 30 ++++++ 7 files changed, 382 insertions(+), 27 deletions(-) create mode 100644 src/EC/Meta/Matching.hpp create mode 100644 src/test/ECTest.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 44f3270..f1fff02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,12 +2,15 @@ cmake_minimum_required(VERSION 3.0) project(EntityComponentSystem) set(EntityComponentSystem_HEADERS - EC/Meta/TypeList.hpp EC/Meta/Combine.hpp EC/Meta/Contains.hpp EC/Meta/ContainsAll.hpp + EC/Meta/ForEach.hpp EC/Meta/IndexOf.hpp + EC/Meta/Matching.hpp EC/Meta/Morph.hpp + EC/Meta/TypeList.hpp + EC/Meta/TypeListGet.hpp EC/Meta/Meta.hpp EC/Bitset.hpp EC/Manager.hpp @@ -53,6 +56,7 @@ find_package(GTest) if(GTEST_FOUND) set(UnitTests_SOURCES test/MetaTest.cpp + test/ECTest.cpp test/Main.cpp) add_executable(UnitTests ${UnitTests_SOURCES}) diff --git a/src/EC/Bitset.hpp b/src/EC/Bitset.hpp index 6e92e32..1288cee 100644 --- a/src/EC/Bitset.hpp +++ b/src/EC/Bitset.hpp @@ -6,6 +6,7 @@ #include "Meta/TypeList.hpp" #include "Meta/Combine.hpp" #include "Meta/IndexOf.hpp" +#include "Meta/ForEach.hpp" namespace EC { @@ -30,17 +31,14 @@ namespace EC template static constexpr Bitset generateBitset() { - //TODO Bitset bitset; -/* - for(unsigned int i = 0; i < Contents::size; ++i) - { - if(EC::Meta::Contains, Combined>::value) + + EC::Meta::forEach([&bitset] (auto t) { + if(EC::Meta::Contains::value) { - bitset[EC::Meta::IndexOf, Combined>::value] = true; + bitset[EC::Meta::IndexOf::value] = true; } - } -*/ + }); return bitset; } diff --git a/src/EC/Manager.hpp b/src/EC/Manager.hpp index 530c6c6..534429e 100644 --- a/src/EC/Manager.hpp +++ b/src/EC/Manager.hpp @@ -2,10 +2,12 @@ #ifndef EC_MANAGER_HPP #define EC_MANAGER_HPP -#define EC_INIT_ENTITIES_SIZE 1024 +#define EC_INIT_ENTITIES_SIZE 256 +#define EC_GROW_SIZE_AMOUNT 256 #include #include +#include #include "Meta/Combine.hpp" #include "Bitset.hpp" @@ -19,29 +21,189 @@ namespace EC using Combined = EC::Meta::Combine; using BitsetType = EC::Bitset; + private: + template + struct Storage + { + using type = std::tuple... >; + }; + using ComponentsStorage = typename EC::Meta::Morph >::type; + // Entity: isAlive, dataIndex, ComponentsTags Info + using EntitiesTupleType = std::tuple; + using EntitiesType = std::vector; + + EntitiesType entities; + ComponentsStorage componentsStorage; + std::size_t currentCapacity = 0; + std::size_t currentSize = 0; + + public: Manager() { - entities.resize(EC_INIT_ENTITIES_SIZE); - - for(auto entity : entities) - { - entity->first = false; - } - } - - template - std::size_t addEntity() - { - //TODO - BitsetType newEntity; - return 0; + resize(EC_INIT_ENTITIES_SIZE); } private: - using ComponentsStorage = EC::Meta::Morph >; - using EntitiesType = std::tuple; + void resize(std::size_t newCapacity) + { + if(currentCapacity >= newCapacity) + { + return; + } - std::vector entities; + EC::Meta::forEach([this, newCapacity] (auto t) { + std::get >(this->componentsStorage).resize(newCapacity); + }); + + entities.resize(newCapacity); + for(std::size_t i = currentCapacity; i < newCapacity; ++i) + { + entities[i] = std::make_tuple(false, i, BitsetType{}); + } + + currentCapacity = newCapacity; + } + + public: + std::size_t addEntity() + { + if(currentSize == currentCapacity) + { + resize(currentCapacity + EC_GROW_SIZE_AMOUNT); + } + + std::get(entities[currentSize]) = true; + + return currentSize++; + } + + void deleteEntity(std::size_t index) + { + std::get(entities.at(index)) = false; + } + + bool hasEntity(std::size_t index) const + { + return index < currentSize; + } + + const EntitiesTupleType& getEntityInfo(std::size_t index) const + { + return entities.at(index); + } + + template + Component& getEntityData(std::size_t index) + { + return std::get >(componentsStorage).at(std::get(entities.at(index))); + } + + void cleanup() + { + std::size_t rhs = currentSize - 1; + std::size_t lhs = 0; + + while(lhs < rhs) + { + if(!std::get(entities[lhs])) + { + // lhs is marked for deletion + // swap lhs entity with rhs entity + std::swap(entities[lhs], entities[rhs]); + + // inc/dec pointers + ++lhs; --rhs; + } + else + { + ++lhs; + } + } + currentSize = rhs + 1; + } + + template + void addComponent(std::size_t entityID, Args&&... args) + { + if(!hasEntity(entityID)) + { + return; + } + + Component component(args...); + + std::get(entities[entityID]).template getComponentBit() = true; + std::get >(componentsStorage)[std::get(entities[entityID])] = component; + } + + template + void removeComponent(std::size_t entityID) + { + if(!hasEntity(entityID)) + { + return; + } + + std::get(entities[entityID]).template getComponentBit() = false; + } + + template + void addTag(std::size_t entityID) + { + if(!hasEntity(entityID)) + { + return; + } + + std::get(entities[entityID]).template getTagBit() = true; + } + + template + void removeTag(std::size_t entityID) + { + if(!hasEntity(entityID)) + { + return; + } + + std::get(entities[entityID]).template getTagBit() = false; + } + + private: + template + struct ForMatchingSignatureHelper + { + template + static void call(std::size_t entityID, CType& ctype, Function&& function) + { + function( + entityID, + ctype.template getEntityData(entityID)... + ); + } + }; + + public: + template + void forMatchingSignature(Function&& function) + { + using SignatureComponents = typename EC::Meta::Matching::type; + using Helper = EC::Meta::Morph >; + + BitsetType signatureBitset = BitsetType::template generateBitset(); + for(std::size_t i = 0; i < currentSize; ++i) + { + if(!std::get(entities[i])) + { + continue; + } + + if((signatureBitset & std::get(entities[i])) == signatureBitset) + { + Helper::call(i, *this, std::forward(function)); + } + } + } }; } diff --git a/src/EC/Meta/Matching.hpp b/src/EC/Meta/Matching.hpp new file mode 100644 index 0000000..e2e5a78 --- /dev/null +++ b/src/EC/Meta/Matching.hpp @@ -0,0 +1,54 @@ + +#ifndef EC_META_MATCHING_HPP +#define EC_META_MATCHING_HPP + +#include "TypeList.hpp" +#include "Contains.hpp" + +namespace EC +{ + namespace Meta + { + template + struct MatchingHelper + { + }; + + template + struct MatchingHelperHelper + { + }; + + template + struct MatchingHelperHelper > + { + using type = TypeList; + }; + + template