From 2e115cd7a2e0a33e0d6f632453553a2a514da81d Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 20 Sep 2016 20:31:56 +0900 Subject: [PATCH] Fixed docs, ids changed to const references --- src/EC/Manager.hpp | 411 +++++++++++++++++++++++++------------------- src/test/ECTest.cpp | 18 +- 2 files changed, 248 insertions(+), 181 deletions(-) diff --git a/src/EC/Manager.hpp b/src/EC/Manager.hpp index 2338c8d..40c60cd 100644 --- a/src/EC/Manager.hpp +++ b/src/EC/Manager.hpp @@ -21,6 +21,18 @@ namespace EC { + /*! + \brief Manages an EntityComponent system. + + EC::Manager must be created with a list of all used Components and all used tags. + + Note that all components must have a default constructor. + + Example: + \code{.cpp} + EC::Manager, TypeList> manager; + \endcode + */ template struct Manager { @@ -45,6 +57,12 @@ namespace EC std::size_t currentSize = 0; public: + /*! + \brief Initializes the manager with a default capacity. + + The default capacity is set with macro EC_INIT_ENTITIES_SIZE, + and will grow by amounts of EC_GROW_SIZE_AMOUNT when needed. + */ Manager() { resize(EC_INIT_ENTITIES_SIZE); @@ -72,6 +90,13 @@ namespace EC } public: + /*! + \brief Adds an entity to the system, returning the ID of the entity. + + WARNING: The ID of an entity may change after calls to cleanup(). + Usage of entity IDs should be safe during initialization. + Otherwise, only use the ID given during usage of forMatchingSignature(). + */ std::size_t addEntity() { if(currentSize == currentCapacity) @@ -84,44 +109,120 @@ namespace EC return currentSize++; } - void deleteEntity(std::size_t index) + /*! + \brief Marks an entity for deletion. + + A deleted Entity is not actually deleted until cleanup() is called. + While an Entity is "deleted" but still in the system, calls to forMatchingSignature() + will ignore the Entity. + */ + void deleteEntity(const std::size_t& index) { std::get(entities.at(index)) = false; } - bool hasEntity(std::size_t index) const + + /*! + \brief Checks if the Entity with the given ID is in the system. + + Note that deleted Entities that haven't yet been cleaned up (via cleanup()) are + considered still in the system. + */ + bool hasEntity(const std::size_t& index) const { return index < currentSize; } - bool isAlive(std::size_t index) const + + /*! + \brief Checks if the Entity is not marked as deleted. + + Note that invalid Entities (Entities where calls to hasEntity() returns false) + will return false. + */ + bool isAlive(const std::size_t& index) const { return hasEntity(index) && std::get(entities.at(index)); } - const EntitiesTupleType& getEntityInfo(std::size_t index) const + /*! + \brief Returns a const reference to an Entity's info. + + An Entity's info is a std::tuple with a bool, std::size_t, and a bitset. + \n The bool determines if the Entity is alive. + \n The std::size_t is the ID to this Entity's data in the system. + \n The bitset shows what Components and Tags belong to the Entity. + */ + const EntitiesTupleType& getEntityInfo(const std::size_t& index) const { return entities.at(index); } + /*! + \brief Returns a reference to a component belonging to the given Entity. + + This function will return a reference to a Component regardless of whether or + not the Entity actually owns the reference. If the Entity doesn't own the Component, + changes to the Component will not affect any Entity. It is recommended to use + hasComponent() to determine if the Entity actually owns that Component. + */ template - Component& getEntityData(std::size_t index) + Component& getEntityData(const std::size_t& index) { return std::get >(componentsStorage).at(std::get(entities.at(index))); } + /*! + \brief Returns a reference to a component belonging to the given Entity. + + Note that this function is the same as getEntityData(). + + This function will return a reference to a Component regardless of whether or + not the Entity actually owns the reference. If the Entity doesn't own the Component, + changes to the Component will not affect any Entity. It is recommended to use + hasComponent() to determine if the Entity actually owns that Component. + */ template - bool hasComponent(std::size_t index) const + Component& getEntityComponent(const std::size_t& index) + { + return getEntityData(index); + } + + /*! + \brief Checks whether or not the given Entity has the given Component. + + Example: + \code{.cpp} + manager.hasComponent(entityID); + \endcode + */ + template + bool hasComponent(const std::size_t& index) const { return std::get(entities.at(index)).template getComponentBit(); } + /*! + \brief Checks whether or not the given Entity has the given Tag. + + Example: + \code{.cpp} + manager.hasTag(entityID); + \endcode + */ template - bool hasTag(std::size_t index) const + bool hasTag(const std::size_t& index) const { return std::get(entities.at(index)).template getTagBit(); } + /*! + \brief Does garbage collection on Entities. + + Does housekeeping on the vector containing Entities that will result in + entity IDs changing if some Entities were marked for deletion. + This function should be called periodically to correctly handle deletion of entities. + */ void cleanup() { if(currentSize == 0) @@ -168,8 +269,33 @@ namespace EC currentSize = rhs + 1; } + /*! + \brief Adds a component to the given Entity. + + Additional parameters given to this function will construct the Component with those + parameters. + + Note that if the Entity already has the same component, then it will be overwritten + by the newly created Component with the given arguments. + + Example: + \code{.cpp} + struct C0 + { + // constructor is compatible as a default constructor + C0(int a = 0, char b = 'b') : + a(a), b(b) + {} + + int a; + char b; + } + + manager.addComponent(entityID, 10, 'd'); + \endcode + */ template - void addComponent(std::size_t entityID, Args&&... args) + void addComponent(const std::size_t& entityID, Args&&... args) { if(!hasEntity(entityID) || !isAlive(entityID)) { @@ -182,8 +308,18 @@ namespace EC std::get >(componentsStorage)[std::get(entities[entityID])] = std::move(component); } + /*! + \brief Removes the given Component from the given Entity. + + If the Entity does not have the Component given, nothing will change. + + Example: + \code{.cpp} + manager.removeComponent(entityID); + \endcode + */ template - void removeComponent(std::size_t entityID) + void removeComponent(const std::size_t& entityID) { if(!hasEntity(entityID) || !isAlive(entityID)) { @@ -193,8 +329,16 @@ namespace EC std::get(entities[entityID]).template getComponentBit() = false; } + /*! + \brief Adds the given Tag to the given Entity. + + Example: + \code{.cpp} + manager.addTag(entityID); + \endcode + */ template - void addTag(std::size_t entityID) + void addTag(const std::size_t& entityID) { if(!hasEntity(entityID) || !isAlive(entityID)) { @@ -204,8 +348,18 @@ namespace EC std::get(entities[entityID]).template getTagBit() = true; } + /*! + \brief Removes the given Tag from the given Entity. + + If the Entity does not have the Tag given, nothing will change. + + Example: + \code{.cpp} + manager.removeTag(entityID); + \endcode + */ template - void removeTag(std::size_t entityID) + void removeTag(const std::size_t& entityID) { if(!hasEntity(entityID) || !isAlive(entityID)) { @@ -220,7 +374,7 @@ namespace EC struct ForMatchingSignatureHelper { template - static void call(std::size_t entityID, CType& ctype, Function&& function) + static void call(const std::size_t& entityID, CType& ctype, Function&& function) { function( entityID, @@ -229,13 +383,28 @@ namespace EC } template - void callInstance(std::size_t entityID, CType& ctype, Function&& function) const + void callInstance(const std::size_t& entityID, CType& ctype, Function&& function) const { ForMatchingSignatureHelper::call(entityID, ctype, std::forward(function)); } }; public: + /*! + \brief Calls the given function on all Entities matching the given Signature. + + The function object given to this function must accept std::size_t as its first + parameter and Component references for the rest of the parameters. Tags specified in the + Signature are only used as filters and will not be given as a parameter to the function. + + Example: + \code{.cpp} + manager.forMatchingSignature>([] (std::size_t ID, C0& component0, C1& component1) { + // Lambda function contents here + }); + \endcode + Note, the ID given to the function is not permanent. An entity's ID may change when cleanup() is called. + */ template void forMatchingSignature(Function&& function) { @@ -261,6 +430,27 @@ namespace EC std::vector > forMatchingFunctions; public: + /*! + \brief Stores a function in the manager to be called later. + + As an alternative to calling functions directly with + forMatchingSignature(), functions can be stored in the manager to + be called later with callForMatchingFunctions() and removed with + clearForMatchingFunctions(). + + The syntax for the Function is the same as with forMatchingSignature(). + + Example: + \code{.cpp} + manager.addForMatchingFunction>([] (std::size_t ID, C0& component0, C1& component1) { + // Lambda function contents here + }); + + manager.callForMatchingFunctions(); // call all stored functions + + manager.clearForMatchingFunctions(); // remove all stored functions + \endcode + */ template void addForMatchingFunction(Function&& function) { @@ -285,6 +475,20 @@ namespace EC }); } + /*! + \brief Call all stored functions. + + Example: + \code{.cpp} + manager.addForMatchingFunction>([] (std::size_t ID, C0& component0, C1& component1) { + // Lambda function contents here + }); + + manager.callForMatchingFunctions(); // call all stored functions + + manager.clearForMatchingFunctions(); // remove all stored functions + \endcode + */ void callForMatchingFunctions() { for(auto functionIter = forMatchingFunctions.begin(); functionIter != forMatchingFunctions.end(); ++functionIter) @@ -293,6 +497,20 @@ namespace EC } } + /*! + \brief Remove all stored functions. + + Example: + \code{.cpp} + manager.addForMatchingFunction>([] (std::size_t ID, C0& component0, C1& component1) { + // Lambda function contents here + }); + + manager.callForMatchingFunctions(); // call all stored functions + + manager.clearForMatchingFunctions(); // remove all stored functions + \endcode + */ void clearForMatchingFunctions() { forMatchingFunctions.clear(); @@ -303,170 +521,3 @@ namespace EC #endif -/*! \class EC::Manager - \brief Manages an EntityComponent system. - - EC::Manager must be created with a list of all used Components and all used tags. - - Note that all components must have a default constructor. - - Example: - \code{.cpp} - EC::Manager, TypeList> manager; - \endcode -*/ - -/*! \fn EC::Manager::Manager() - \brief Initializes the manager with a default capacity. - - The default capacity is set with macro EC_INIT_ENTITIES_SIZE, - and will grow by amounts of EC_GROW_SIZE_AMOUNT when needed. -*/ - -/*! \fn std::size_t EC::Manager::addEntity() - \brief Adds an entity to the system, returning the ID of the entity. - - WARNING: The ID of an entity may change after calls to cleanup(). - Usage of entity IDs should be safe during initialization. - Otherwise, only use the ID given during usage of forMatchingSignature(). -*/ - -/*! \fn void EC::Manager::deleteEntity(std::size_t index) - \brief Marks an entity for deletion. - - A deleted Entity is not actually deleted until cleanup() is called. - While an Entity is "deleted" but still in the system, calls to forMatchingSignature() - will ignore the Entity. -*/ - -/*! \fn bool EC::Manager::hasEntity(std::size_t index) const - \brief Checks if the Entity with the given ID is in the system. - - Note that deleted Entities that haven't yet been cleaned up (via cleanup()) are - considered still in the system. -*/ - -/*! \fn bool EC::Manager::isAlive(std::size_t index) const - \brief Checks if the Entity is not marked as deleted. - - Note that invalid Entities (Entities where calls to hasEntity() returns false) - will return false. -*/ - -/*! \fn const EntitiesTupleType& EC::Manager::getEntityInfo(std::size_t index) const - \brief Returns a const reference to an Entity's info. - - An Entity's info is a std::tuple with a bool, std::size_t, and a bitset. - \n The bool determines if the Entity is alive. - \n The std::size_t is the ID to this Entity's data in the system. - \n The bitset shows what Components and Tags belong to the Entity. -*/ - -/*! \fn Component& EC::Manager::getEntityData(std::size_t index) - \brief Returns a reference to a component belonging to the given Entity. - - This function will return a reference to a Component regardless of whether or - not the Entity actually owns the reference. If the Entity doesn't own the Component, - changes to the Component will not affect any Entity. It is recommended to use - hasComponent() to determine if the Entity actually owns that Component. -*/ - -/*! \fn bool EC::Manager::hasComponent(std::size_t index) const - \brief Checks whether or not the given Entity has the given Component. - - Example: - \code{.cpp} - manager.hasComponent(entityID); - \endcode -*/ - -/*! \fn bool EC::Manager::hasTag(std::size_t index) const - \brief Checks whether or not the given Entity has the given Tag. - - Example: - \code{.cpp} - manager.hasTag(entityID); - \endcode -*/ - -/*! \fn void EC::Manager::cleanup() - \brief Does garbage collection on Entities. - - Does housekeeping on the vector containing Entities that will result in - entity IDs changing if some Entities were marked for deletion. - This function should be called periodically to correctly handle deletion of entities. -*/ - -/*! \fn void EC::Manager::addComponent(std::size_t entityID, Args&&... args) - \brief Adds a component to the given Entity. - - Additional parameters given to this function will construct the Component with those - parameters. - - Note that if the Entity already has the same component, then it will be overwritten - by the newly created Component with the given arguments. - - Example: - \code{.cpp} - struct C0 - { - // constructor is compatible as a default constructor - C0(int a = 0, char b = 'b') : - a(a), b(b) - {} - - int a; - char b; - } - - manager.addComponent(entityID, 10, 'd'); - \endcode -*/ - -/*! \fn void EC::Manager::removeComponent(std::size_t entityID) - \brief Removes the given Component from the given Entity. - - If the Entity does not have the Component given, nothing will change. - - Example: - \code{.cpp} - manager.removeComponent(entityID); - \endcode -*/ - -/*! \fn void EC::Manager::addTag(std::size_t entityID) - \brief Adds the given Tag to the given Entity. - - Example: - \code{.cpp} - manager.addTag(entityID); - \endcode -*/ - -/*! \fn void EC::Manager::removeTag(std::size_t entityID) - \brief Removes the given Tag from the given Entity. - - If the Entity does not have the Tag given, nothing will change. - - Example: - \code{.cpp} - manager.removeTag(entityID); - \endcode -*/ - -/*! \fn void EC::Manager::forMatchingSignature(Function&& function) - \brief Calls the given function on all Entities matching the given Signature. - - The function object given to this function must accept std::size_t as its first - parameter and Component references for the rest of the parameters. Tags specified in the - Signature are only used as filters and will not be given as a parameter to the function. - - Example: - \code{.cpp} - manager.forMatchingSignature>([] (std::size_t ID, C0& component0, C1& component1) { - // Lambda function contents here. - }); - \endcode - Note, the ID given to the function is not permanent. An entity's ID may change when cleanup() is called. -*/ - diff --git a/src/test/ECTest.cpp b/src/test/ECTest.cpp index e93d929..0e5e4eb 100644 --- a/src/test/ECTest.cpp +++ b/src/test/ECTest.cpp @@ -247,12 +247,18 @@ TEST(EC, FunctionStorage) EC::Manager manager; auto eid = manager.addEntity(); manager.addComponent(eid); + manager.addComponent(eid); - manager.addForMatchingFunction >( [] (std::size_t eid, C0& c0) { + manager.addForMatchingFunction>( [] (std::size_t eid, C0& c0) { c0.x = 1; c0.y = 2; }); + manager.addForMatchingFunction>( [] (std::size_t eid, C0& c0, C1& c1) { + c1.vx = c0.x + 10; + c1.vy = c1.vx + c0.y + 10; + }); + manager.callForMatchingFunctions(); { @@ -260,6 +266,11 @@ TEST(EC, FunctionStorage) EXPECT_EQ(c0.x, 1); EXPECT_EQ(c0.y, 2); + + auto c1 = manager.getEntityData(eid); + + EXPECT_EQ(c1.vx, 11); + EXPECT_EQ(c1.vy, 23); } manager.clearForMatchingFunctions(); @@ -271,6 +282,11 @@ TEST(EC, FunctionStorage) EXPECT_EQ(c0.x, 1); EXPECT_EQ(c0.y, 2); + + auto c1 = manager.getEntityData(eid); + + EXPECT_EQ(c1.vx, 11); + EXPECT_EQ(c1.vy, 23); } }