Changed clearSomeMatchingFunctions, line lengths

clearSomeMatchingFunctions removed for
keepSomeMatchingFunctions and removeSomeMatchingFunctions to
avoid confusion.

Lines now respect 80 column limit.
This commit is contained in:
Stephen Seo 2017-07-13 16:13:37 +09:00
parent 49ae172c3a
commit 1f052154ad
2 changed files with 262 additions and 172 deletions

View file

@ -15,8 +15,10 @@
#include <utility> #include <utility>
#include <functional> #include <functional>
#include <map> #include <map>
#include <unordered_map>
#include <set> #include <set>
#include <unordered_set> #include <unordered_set>
#include <algorithm>
#include "Meta/Combine.hpp" #include "Meta/Combine.hpp"
#include "Meta/Matching.hpp" #include "Meta/Matching.hpp"
@ -49,7 +51,8 @@ namespace EC
{ {
using type = std::tuple<std::vector<Types>... >; using type = std::tuple<std::vector<Types>... >;
}; };
using ComponentsStorage = typename EC::Meta::Morph<ComponentsList, Storage<> >::type; using ComponentsStorage =
typename EC::Meta::Morph<ComponentsList, Storage<> >::type;
// Entity: isAlive, dataIndex, ComponentsTags Info // Entity: isAlive, dataIndex, ComponentsTags Info
using EntitiesTupleType = std::tuple<bool, std::size_t, BitsetType>; using EntitiesTupleType = std::tuple<bool, std::size_t, BitsetType>;
using EntitiesType = std::vector<EntitiesTupleType>; using EntitiesType = std::vector<EntitiesTupleType>;
@ -80,7 +83,8 @@ namespace EC
} }
EC::Meta::forEach<ComponentsList>([this, newCapacity] (auto t) { EC::Meta::forEach<ComponentsList>([this, newCapacity] (auto t) {
std::get<std::vector<decltype(t)> >(this->componentsStorage).resize(newCapacity); std::get<std::vector<decltype(t)> >(
this->componentsStorage).resize(newCapacity);
}); });
entities.resize(newCapacity); entities.resize(newCapacity);
@ -98,7 +102,8 @@ namespace EC
WARNING: The ID of an entity may change after calls to cleanup(). WARNING: The ID of an entity may change after calls to cleanup().
Usage of entity IDs should be safe during initialization. Usage of entity IDs should be safe during initialization.
Otherwise, only use the ID given during usage of forMatchingSignature(). Otherwise, only use the ID given during usage of
forMatchingSignature().
*/ */
std::size_t addEntity() std::size_t addEntity()
{ {
@ -116,8 +121,8 @@ namespace EC
\brief Marks an entity for deletion. \brief Marks an entity for deletion.
A deleted Entity is not actually deleted until cleanup() is called. A deleted Entity is not actually deleted until cleanup() is called.
While an Entity is "deleted" but still in the system, calls to forMatchingSignature() While an Entity is "deleted" but still in the system, calls to
will ignore the Entity. forMatchingSignature() will ignore the Entity.
*/ */
void deleteEntity(const std::size_t& index) void deleteEntity(const std::size_t& index)
{ {
@ -128,8 +133,8 @@ namespace EC
/*! /*!
\brief Checks if the Entity with the given ID is in the system. \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 Note that deleted Entities that haven't yet been cleaned up
considered still in the system. (via cleanup()) are considered still in the system.
*/ */
bool hasEntity(const std::size_t& index) const bool hasEntity(const std::size_t& index) const
{ {
@ -140,8 +145,8 @@ namespace EC
/*! /*!
\brief Checks if the Entity is not marked as deleted. \brief Checks if the Entity is not marked as deleted.
Note that invalid Entities (Entities where calls to hasEntity() returns false) Note that invalid Entities (Entities where calls to hasEntity()
will return false. returns false) will return false.
*/ */
bool isAlive(const std::size_t& index) const bool isAlive(const std::size_t& index) const
{ {
@ -151,7 +156,9 @@ namespace EC
/*! /*!
\brief Returns a const reference to an Entity's info. \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. 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 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 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. \n The bitset shows what Components and Tags belong to the Entity.
@ -162,12 +169,14 @@ namespace EC
} }
/*! /*!
\brief Returns a reference to a component belonging to the given Entity. \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 This function will return a reference to a Component regardless of
not the Entity actually owns the reference. If the Entity doesn't own the Component, whether or not the Entity actually owns the reference. If the Entity
changes to the Component will not affect any Entity. It is recommended to use doesn't own the Component, changes to the Component will not affect
hasComponent() to determine if the Entity actually owns that Component. any Entity. It is recommended to use hasComponent() to determine if
the Entity actually owns that Component.
*/ */
template <typename Component> template <typename Component>
Component& getEntityData(const std::size_t& index) Component& getEntityData(const std::size_t& index)
@ -176,14 +185,16 @@ namespace EC
} }
/*! /*!
\brief Returns a reference to a component belonging to the given Entity. \brief Returns a reference to a component belonging to the given
Entity.
Note that this function is the same as getEntityData(). Note that this function is the same as getEntityData().
This function will return a reference to a Component regardless of whether or This function will return a reference to a Component regardless of
not the Entity actually owns the reference. If the Entity doesn't own the Component, whether or not the Entity actually owns the reference. If the Entity
changes to the Component will not affect any Entity. It is recommended to use doesn't own the Component, changes to the Component will not affect
hasComponent() to determine if the Entity actually owns that Component. any Entity. It is recommended to use hasComponent() to determine if
the Entity actually owns that Component.
*/ */
template <typename Component> template <typename Component>
Component& getEntityComponent(const std::size_t& index) Component& getEntityComponent(const std::size_t& index)
@ -192,7 +203,8 @@ namespace EC
} }
/*! /*!
\brief Checks whether or not the given Entity has the given Component. \brief Checks whether or not the given Entity has the given
Component.
Example: Example:
\code{.cpp} \code{.cpp}
@ -202,7 +214,8 @@ namespace EC
template <typename Component> template <typename Component>
bool hasComponent(const std::size_t& index) const bool hasComponent(const std::size_t& index) const
{ {
return std::get<BitsetType>(entities.at(index)).template getComponentBit<Component>(); return std::get<BitsetType>(
entities.at(index)).template getComponentBit<Component>();
} }
/*! /*!
@ -216,14 +229,17 @@ namespace EC
template <typename Tag> template <typename Tag>
bool hasTag(const std::size_t& index) const bool hasTag(const std::size_t& index) const
{ {
return std::get<BitsetType>(entities.at(index)).template getTagBit<Tag>(); return std::get<BitsetType>(
entities.at(index)).template getTagBit<Tag>();
} }
/*! /*!
\brief Does garbage collection on Entities. \brief Does garbage collection on Entities.
Does housekeeping on the vector containing Entities that will result in Does housekeeping on the vector containing Entities that will
entity IDs changing if some Entities were marked for deletion. result in entity IDs changing if some Entities were marked for
deletion.
<b>This function should be called periodically to correctly handle deletion of entities.</b> <b>This function should be called periodically to correctly handle deletion of entities.</b>
*/ */
void cleanup() void cleanup()
@ -275,11 +291,12 @@ namespace EC
/*! /*!
\brief Adds a component to the given Entity. \brief Adds a component to the given Entity.
Additional parameters given to this function will construct the Component with those Additional parameters given to this function will construct the
parameters. Component with those parameters.
Note that if the Entity already has the same component, then it will be overwritten Note that if the Entity already has the same component, then it
by the newly created Component with the given arguments. will be overwritten by the newly created Component with the given
arguments.
Example: Example:
\code{.cpp} \code{.cpp}
@ -307,14 +324,20 @@ namespace EC
Component component(std::forward<Args>(args)...); Component component(std::forward<Args>(args)...);
std::get<BitsetType>(entities[entityID]).template getComponentBit<Component>() = true; std::get<BitsetType>(
std::get<std::vector<Component> >(componentsStorage)[std::get<std::size_t>(entities[entityID])] = std::move(component); entities[entityID]
).template getComponentBit<Component>() = true;
std::get<std::vector<Component> >(
componentsStorage
)[std::get<std::size_t>(entities[entityID])] = std::move(component);
} }
/*! /*!
\brief Removes the given Component from the given Entity. \brief Removes the given Component from the given Entity.
If the Entity does not have the Component given, nothing will change. If the Entity does not have the Component given, nothing will
change.
Example: Example:
\code{.cpp} \code{.cpp}
@ -329,7 +352,9 @@ namespace EC
return; return;
} }
std::get<BitsetType>(entities[entityID]).template getComponentBit<Component>() = false; std::get<BitsetType>(
entities[entityID]
).template getComponentBit<Component>() = false;
} }
/*! /*!
@ -348,7 +373,9 @@ namespace EC
return; return;
} }
std::get<BitsetType>(entities[entityID]).template getTagBit<Tag>() = true; std::get<BitsetType>(
entities[entityID]
).template getTagBit<Tag>() = true;
} }
/*! /*!
@ -369,7 +396,9 @@ namespace EC
return; return;
} }
std::get<BitsetType>(entities[entityID]).template getTagBit<Tag>() = false; std::get<BitsetType>(
entities[entityID]
).template getTagBit<Tag>() = false;
} }
private: private:
@ -377,7 +406,10 @@ namespace EC
struct ForMatchingSignatureHelper struct ForMatchingSignatureHelper
{ {
template <typename CType, typename Function> template <typename CType, typename Function>
static void call(const std::size_t& entityID, CType& ctype, Function&& function) static void call(
const std::size_t& entityID,
CType& ctype,
Function&& function)
{ {
function( function(
entityID, entityID,
@ -386,35 +418,50 @@ namespace EC
} }
template <typename CType, typename Function> template <typename CType, typename Function>
void callInstance(const std::size_t& entityID, CType& ctype, Function&& function) const void callInstance(
const std::size_t& entityID,
CType& ctype,
Function&& function) const
{ {
ForMatchingSignatureHelper<Types...>::call(entityID, ctype, std::forward<Function>(function)); ForMatchingSignatureHelper<Types...>::call(
entityID,
ctype,
std::forward<Function>(function));
} }
}; };
public: public:
/*! /*!
\brief Calls the given function on all Entities matching the given Signature. \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 The function object given to this function must accept std::size_t
parameter and Component references for the rest of the parameters. Tags specified in the as its first parameter and Component references for the rest of the
Signature are only used as filters and will not be given as a parameter to the function. parameters. Tags specified in the Signature are only used as
filters and will not be given as a parameter to the function.
Example: Example:
\code{.cpp} \code{.cpp}
manager.forMatchingSignature<TypeList<C0, C1, T0>>([] (std::size_t ID, C0& component0, C1& component1) { manager.forMatchingSignature<TypeList<C0, C1, T0>>([] (
std::size_t ID, C0& component0, C1& component1) {
// Lambda function contents here // Lambda function contents here
}); });
\endcode \endcode
Note, the ID given to the function is not permanent. An entity's ID may change when cleanup() is called. Note, the ID given to the function is not permanent. An entity's ID
may change when cleanup() is called.
*/ */
template <typename Signature, typename Function> template <typename Signature, typename Function>
void forMatchingSignature(Function&& function) void forMatchingSignature(Function&& function)
{ {
using SignatureComponents = typename EC::Meta::Matching<Signature, ComponentsList>::type; using SignatureComponents =
using Helper = EC::Meta::Morph<SignatureComponents, ForMatchingSignatureHelper<> >; typename EC::Meta::Matching<Signature, ComponentsList>::type;
using Helper =
EC::Meta::Morph<
SignatureComponents,
ForMatchingSignatureHelper<> >;
BitsetType signatureBitset = BitsetType::template generateBitset<Signature>(); BitsetType signatureBitset =
BitsetType::template generateBitset<Signature>();
for(std::size_t i = 0; i < currentSize; ++i) for(std::size_t i = 0; i < currentSize; ++i)
{ {
if(!std::get<bool>(entities[i])) if(!std::get<bool>(entities[i]))
@ -422,7 +469,8 @@ namespace EC
continue; continue;
} }
if((signatureBitset & std::get<BitsetType>(entities[i])) == signatureBitset) if((signatureBitset & std::get<BitsetType>(entities[i]))
== signatureBitset)
{ {
Helper::call(i, *this, std::forward<Function>(function)); Helper::call(i, *this, std::forward<Function>(function));
} }
@ -430,8 +478,8 @@ namespace EC
} }
private: private:
std::map<unsigned long long, std::function<void()> > forMatchingFunctions; std::unordered_map<std::size_t, std::function<void()> > forMatchingFunctions;
unsigned long long functionIndex = 0; std::size_t functionIndex = 0;
public: public:
/*! /*!
@ -440,49 +488,70 @@ namespace EC
As an alternative to calling functions directly with As an alternative to calling functions directly with
forMatchingSignature(), functions can be stored in the manager to forMatchingSignature(), functions can be stored in the manager to
be called later with callForMatchingFunctions() and be called later with callForMatchingFunctions() and
callForMatchingFunction, and removed with clearForMatchingFunctions() callForMatchingFunction, and removed with
and removeForMatchingFunction(). clearForMatchingFunctions() and removeForMatchingFunction().
The syntax for the Function is the same as with forMatchingSignature(). The syntax for the Function is the same as with
forMatchingSignature().
Note that functions will be called in the same order they are inserted. Note that functions will be called in the same order they are
inserted if called by callForMatchingFunctions() unless the
Old functions may be overwritten if there are more functions than internal functionIndex counter has wrapped around (is a
sizeof(unsigned long long) as they are stored in a map with std::size_t). Calling clearForMatchingFunctions() will reset this
unsigned long long as the key (index). counter to zero.
Example: Example:
\code{.cpp} \code{.cpp}
manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (std::size_t ID, C0& component0, C1& component1) { manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (
std::size_t ID, C0& component0, C1& component1) {
// Lambda function contents here // Lambda function contents here
}); });
manager.callForMatchingFunctions(); // call all stored functions // call all stored functions
manager.callForMatchingFunctions();
manager.clearForMatchingFunctions(); // remove all stored functions // remove all stored functions
manager.clearForMatchingFunctions();
\endcode \endcode
\return The index of the function, used for deletion with \return The index of the function, used for deletion with
deleteForMatchingFunction() or filtering with deleteForMatchingFunction() or filtering with
clearSomeMatchingFunctions(). keepSomeMatchingFunctions() or removeSomeMatchingFunctions(),
or calling with callForMatchingFunction().
*/ */
template <typename Signature, typename Function> template <typename Signature, typename Function>
unsigned long long addForMatchingFunction(Function&& function) std::size_t addForMatchingFunction(Function&& function)
{ {
using SignatureComponents = typename EC::Meta::Matching<Signature, ComponentsList>::type; while(forMatchingFunctions.find(functionIndex)
using Helper = EC::Meta::Morph<SignatureComponents, ForMatchingSignatureHelper<> >; != forMatchingFunctions.end())
{
++functionIndex;
}
using SignatureComponents =
typename EC::Meta::Matching<Signature, ComponentsList>::type;
using Helper =
EC::Meta::Morph<
SignatureComponents,
ForMatchingSignatureHelper<> >;
Helper helper; Helper helper;
BitsetType signatureBitset = BitsetType::template generateBitset<Signature>(); BitsetType signatureBitset =
BitsetType::template generateBitset<Signature>();
forMatchingFunctions.emplace(std::make_pair(functionIndex, [function, signatureBitset, helper, this] () { forMatchingFunctions.emplace(std::make_pair(
functionIndex,
[function, signatureBitset, helper, this] ()
{
for(std::size_t i = 0; i < this->currentSize; ++i) for(std::size_t i = 0; i < this->currentSize; ++i)
{ {
if(!std::get<bool>(this->entities[i])) if(!std::get<bool>(this->entities[i]))
{ {
continue; continue;
} }
if((signatureBitset & std::get<BitsetType>(this->entities[i])) == signatureBitset) if((signatureBitset
& std::get<BitsetType>(this->entities[i]))
== signatureBitset)
{ {
helper.callInstance(i, *this, function); helper.callInstance(i, *this, function);
} }
@ -497,18 +566,23 @@ namespace EC
Example: Example:
\code{.cpp} \code{.cpp}
manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (std::size_t ID, C0& component0, C1& component1) { manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (
std::size_t ID, C0& component0, C1& component1) {
// Lambda function contents here // Lambda function contents here
}); });
manager.callForMatchingFunctions(); // call all stored functions // call all stored functions
manager.callForMatchingFunctions();
manager.clearForMatchingFunctions(); // remove all stored functions // remove all stored functions
manager.clearForMatchingFunctions();
\endcode \endcode
*/ */
void callForMatchingFunctions() void callForMatchingFunctions()
{ {
for(auto functionIter = forMatchingFunctions.begin(); functionIter != forMatchingFunctions.end(); ++functionIter) for(auto functionIter = forMatchingFunctions.begin();
functionIter != forMatchingFunctions.end();
++functionIter)
{ {
functionIter->second(); functionIter->second();
} }
@ -519,17 +593,19 @@ namespace EC
Example: Example:
\code{.cpp} \code{.cpp}
unsigned long long id = manager.addForMatchingFunction<TypeList<C0, C1, T0>>( std::size_t id =
manager.addForMatchingFunction<TypeList<C0, C1, T0>>(
[] (std::size_t ID, C0& c0, C1& c1) { [] (std::size_t ID, C0& c0, C1& c1) {
// Lambda function contents here // Lambda function contents here
}); });
manager.callForMatchingFunction(id); // call the previously added function // call the previously added function
manager.callForMatchingFunction(id);
\endcode \endcode
\return False if a function with the given id does not exist. \return False if a function with the given id does not exist.
*/ */
bool callForMatchingFunction(unsigned long long id) bool callForMatchingFunction(std::size_t id)
{ {
auto iter = forMatchingFunctions.find(id); auto iter = forMatchingFunctions.find(id);
if(iter == forMatchingFunctions.end()) if(iter == forMatchingFunctions.end())
@ -547,13 +623,16 @@ namespace EC
Example: Example:
\code{.cpp} \code{.cpp}
manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (std::size_t ID, C0& component0, C1& component1) { manager.addForMatchingFunction<TypeList<C0, C1, T0>>([] (
std::size_t ID, C0& component0, C1& component1) {
// Lambda function contents here // Lambda function contents here
}); });
manager.callForMatchingFunctions(); // call all stored functions // call all stored functions
manager.callForMatchingFunctions();
manager.clearForMatchingFunctions(); // remove all stored functions // remove all stored functions
manager.clearForMatchingFunctions();
\endcode \endcode
*/ */
void clearForMatchingFunctions() void clearForMatchingFunctions()
@ -562,107 +641,90 @@ namespace EC
functionIndex = 0; functionIndex = 0;
} }
/*!
\brief Removes all functions that do not have the index specified
in argument "list".
Note this function is slower than the variant that uses a set
argument as all items in the List are traversed during
traversal through all entities to check if they are in the list.
Thus the complexity of this function is n^2.
*/
template <typename List>
void clearSomeMatchingFunctions(List list)
{
bool willErase;
for(auto functionIter = forMatchingFunctions.begin();
functionIter != forMatchingFunctions.end();
++functionIter)
{
willErase = true;
for(auto listIter = list.begin();
listIter != list.end();
++listIter)
{
if(functionIter->first == *listIter)
{
willErase = false;
break;
}
}
if(willErase)
{
functionIter = --(forMatchingFunctions.erase(functionIter));
}
}
}
/*!
\brief Removes all functions that do not have the index specified
in argument "list".
Note this function is slower than the variant that uses a set
argument as all items in the List are traversed during
traversal through all entities to check if they are in the list.
Thus the complexity of this function is n^2.
*/
void clearSomeMatchingFunctions(std::initializer_list<unsigned long long> list)
{
clearSomeMatchingFunctions<decltype(list)>(list);
}
/*! /*!
\brief Removes a function that has the given id. \brief Removes a function that has the given id.
\return True if a function was erased. \return True if a function was erased.
*/ */
bool removeForMatchingFunction(unsigned long long id) bool removeForMatchingFunction(std::size_t id)
{ {
return forMatchingFunctions.erase(id) == 1; return forMatchingFunctions.erase(id) == 1;
} }
private:
template <typename Set>
void clearSomeMatchingFunctionsWithSet(Set set)
{
for(auto functionIter = forMatchingFunctions.begin();
functionIter != forMatchingFunctions.end();
++functionIter)
{
if(set.find(functionIter->first) == set.end())
{
functionIter = --(forMatchingFunctions.erase(functionIter));
}
}
}
public:
/*! /*!
\brief Removes all functions that do not have the index specified \brief Removes all functions that do not have the index specified
in argument "set". in argument "list".
Note this function is faster than the variant that uses a list The given List must be iterable.
argument as the set's implementation as a tree allows for This is the only requirement, so a set could also be given.
log(n) time checking of an index to the set. Thus the complexity
of this function is n*log(n). \return The number of functions deleted.
*/ */
void clearSomeMatchingFunctions(std::set<unsigned long long> set) template <typename List>
std::size_t keepSomeMatchingFunctions(List list)
{ {
clearSomeMatchingFunctionsWithSet<decltype(set)>(set); std::size_t deletedCount = 0;
for(std::size_t i = 0; i < functionIndex; ++i)
{
if(forMatchingFunctions.find(i) != forMatchingFunctions.end()
&& std::find(list.begin(), list.end(), i) == list.end())
{
deletedCount += forMatchingFunctions.erase(i);
}
}
return deletedCount;
} }
/*! /*!
\brief Removes all functions that do not have the index specified \brief Removes all functions that do not have the index specified
in argument "set". in argument "list".
Note this function is faster than the variant that uses a list This function allows for passing an initializer list.
argument as the unordered_set's implementation as a hash table
allows for constant time checking of an index to the set. Thus the \return The number of functions deleted.
complexity of this function is n.
*/ */
void clearSomeMatchingFunctions(std::unordered_set<unsigned long long> set) std::size_t keepSomeMatchingFunctions(
std::initializer_list<std::size_t> list)
{ {
clearSomeMatchingFunctionsWithSet<decltype(set)>(set); return keepSomeMatchingFunctions<decltype(list)>(list);
}
/*!
\brief Removes all functions that do have the index specified
in argument "list".
The given List must be iterable.
This is the only requirement, so a set could also be given.
\return The number of functions deleted.
*/
template <typename List>
std::size_t removeSomeMatchingFunctions(List list)
{
std::size_t deletedCount = 0;
for(auto listIter = list.begin();
listIter != list.end();
++listIter)
{
deletedCount += forMatchingFunctions.erase(*listIter);
}
return deletedCount;
}
/*!
\brief Removes all functions that do have the index specified
in argument "list".
This function allows for passing an initializer list.
\return The number of functions deleted.
*/
std::size_t removeSomeMatchingFunctions(
std::initializer_list<std::size_t> list)
{
return removeSomeMatchingFunctions<decltype(list)>(list);
} }
/*! /*!
@ -670,10 +732,12 @@ namespace EC
The index of a function is returned from addForMatchingFunction() The index of a function is returned from addForMatchingFunction()
so there is no other way to get the index of a function. so there is no other way to get the index of a function.
\return True if function existed and has been deleted.
*/ */
void deleteForMatchingFunction(unsigned long long index) bool deleteForMatchingFunction(std::size_t index)
{ {
forMatchingFunctions.erase(index); return forMatchingFunctions.erase(index) == 1;
} }
/*! /*!

View file

@ -261,16 +261,42 @@ TEST(EC, FunctionStorage)
c1.vy = c1.vy + c1.vx + c0.y + 10; c1.vy = c1.vy + c1.vx + c0.y + 10;
}); });
manager.addForMatchingFunction<EC::Meta::TypeList<>>( auto f2index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
[] (std::size_t eid) { [] (std::size_t eid, C0& c0) {
//derp 0 c0.x = c0.y = 9999;
}); });
auto lastIndex = manager.addForMatchingFunction<EC::Meta::TypeList<>>( auto f3index = manager.addForMatchingFunction<EC::Meta::TypeList<C1>>(
[] (std::size_t eid) { [] (std::size_t eid, C1& c1) {
//derp 1 c1.vx = c1.vy = 10000;
}); });
EXPECT_EQ(2, manager.removeSomeMatchingFunctions({f2index, f3index}));
auto f4index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
[] (std::size_t eid, C0& c0) {
c0.x = 999;
c0.y = 888;
});
{
auto set = std::set<std::size_t>({f4index});
EXPECT_EQ(1, manager.removeSomeMatchingFunctions(set));
}
auto f5index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
[] (std::size_t eid, C0& c0) {
c0.x = 777;
c0.y = 666;
});
auto lastIndex = f5index;
{
auto set = std::unordered_set<std::size_t>({f5index});
EXPECT_EQ(1, manager.removeSomeMatchingFunctions(set));
}
manager.callForMatchingFunctions(); manager.callForMatchingFunctions();
{ {
@ -303,19 +329,19 @@ TEST(EC, FunctionStorage)
EXPECT_EQ(23, c1.vy); EXPECT_EQ(23, c1.vy);
} }
manager.clearSomeMatchingFunctions({f1index}); EXPECT_EQ(1, manager.keepSomeMatchingFunctions({f1index}));
{ {
std::vector<unsigned long long> indices{f1index}; std::vector<std::size_t> indices{f1index};
manager.clearSomeMatchingFunctions(indices); EXPECT_EQ(0, manager.keepSomeMatchingFunctions(indices));
} }
{ {
std::set<unsigned long long> indices{f1index}; std::set<std::size_t> indices{f1index};
manager.clearSomeMatchingFunctions(indices); EXPECT_EQ(0, manager.keepSomeMatchingFunctions(indices));
} }
{ {
std::unordered_set<unsigned long long> indices{f1index}; std::unordered_set<std::size_t> indices{f1index};
manager.clearSomeMatchingFunctions(indices); EXPECT_EQ(0, manager.keepSomeMatchingFunctions(indices));
} }
manager.callForMatchingFunctions(); manager.callForMatchingFunctions();