diff --git a/src/EC/Manager.hpp b/src/EC/Manager.hpp index bd15b08..c8b8a71 100644 --- a/src/EC/Manager.hpp +++ b/src/EC/Manager.hpp @@ -491,10 +491,12 @@ namespace EC static void call( const std::size_t& entityID, CType& ctype, - Function&& function) + Function&& function, + void* context = nullptr) { function( entityID, + context, ctype.template getEntityData(entityID)... ); } @@ -503,10 +505,12 @@ namespace EC static void callPtr( const std::size_t& entityID, CType& ctype, - Function* function) + Function* function, + void* context = nullptr) { (*function)( entityID, + context, ctype.template getEntityData(entityID)... ); } @@ -515,24 +519,28 @@ namespace EC void callInstance( const std::size_t& entityID, CType& ctype, - Function&& function) const + Function&& function, + void* context = nullptr) const { ForMatchingSignatureHelper::call( entityID, ctype, - std::forward(function)); + std::forward(function), + context); } template void callInstancePtr( const std::size_t& entityID, CType& ctype, - Function* function) const + Function* function, + void* context = nullptr) const { ForMatchingSignatureHelper::callPtr( entityID, ctype, - function); + function, + context); } }; @@ -542,24 +550,33 @@ namespace EC Signature. The function object given to this function must accept std::size_t - as its first parameter and Component pointers 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. + as its first parameter, void* as its second parameter, and Component + pointers 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. - The second parameter is default 1 (not multi-threaded). If the - second parameter threadCount is set to a value greater than 1, then - threadCount threads will be used. - Note that multi-threading is based on splitting the task of calling - the function across sections of entities. Thus if there are only - a small amount of entities in the manager, then using multiple - threads may not have as great of a speed-up. + The second parameter is default nullptr and will be passed to the + function call as the second parameter as a means of providing + context (useful when the function is not a lambda function). The + third parameter is default 1 (not multi-threaded). If the third + parameter threadCount is set to a value greater than 1, then + threadCount threads will be used. Note that multi-threading is + based on splitting the task of calling the function across sections + of entities. Thus if there are only a small amount of entities in + the manager, then using multiple threads may not have as great of a + speed-up. Example: \code{.cpp} - manager.forMatchingSignature>([] ( - std::size_t ID, C0* component0, C1* component1) { + Context c; // some class/struct with data + manager.forMatchingSignature>([] + (std::size_t ID, + void* context, + C0* component0, C1* component1) + { // Lambda function contents here }, + &c, // "Context" object passed to the function 4 // four threads ); \endcode @@ -568,6 +585,7 @@ namespace EC */ template void forMatchingSignature(Function&& function, + void* context = nullptr, std::size_t threadCount = 1) { using SignatureComponents = @@ -592,7 +610,7 @@ namespace EC == signatureBitset) { Helper::call(i, *this, - std::forward(function)); + std::forward(function), context); } } } @@ -612,7 +630,8 @@ namespace EC { end = s * (i + 1); } - threads[i] = std::thread([this, &function, &signatureBitset] + threads[i] = std::thread( + [this, &function, &signatureBitset, &context] (std::size_t begin, std::size_t end) { for(std::size_t i = begin; i < end; ++i) @@ -627,7 +646,7 @@ namespace EC == signatureBitset) { Helper::call(i, *this, - std::forward(function)); + std::forward(function), context); } } }, @@ -646,26 +665,35 @@ namespace EC Signature. The function pointer given to this function must accept std::size_t - as its first parameter and Component pointers 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. + as its first parameter, void* as its second parameter, and + Component pointers 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. - The second parameter is default 1 (not multi-threaded). If the - second parameter threadCount is set to a value greater than 1, then - threadCount threads will be used. - Note that multi-threading is based on splitting the task of calling - the function across sections of entities. Thus if there are only - a small amount of entities in the manager, then using multiple - threads may not have as great of a speed-up. + The second parameter is default nullptr and will be passed to the + function call as the second parameter as a means of providing + context (useful when the function is not a lambda function). The + third parameter is default 1 (not multi-threaded). If the third + parameter threadCount is set to a value greater than 1, then + threadCount threads will be used. Note that multi-threading is based + on splitting the task of calling the function across sections of + entities. Thus if there are only a small amount of entities in the + manager, then using multiple threads may not have as great of a + speed-up. Example: \code{.cpp} - auto function = [] (std::size_t ID, C0* component0, - C1* component1) { + Context c; // some class/struct with data + auto function = [] + (std::size_t ID, + void* context, + C0* component0, C1* component1) + { // Lambda function contents here }; manager.forMatchingSignaturePtr>( &function, // ptr + &c, // "Context" object passed to the function 4 // four threads ); \endcode @@ -674,6 +702,7 @@ namespace EC */ template void forMatchingSignaturePtr(Function* function, + void* context = nullptr, std::size_t threadCount = 1) { using SignatureComponents = @@ -697,7 +726,7 @@ namespace EC if((signatureBitset & std::get(entities[i])) == signatureBitset) { - Helper::callPtr(i, *this, function); + Helper::callPtr(i, *this, function, context); } } } @@ -717,7 +746,8 @@ namespace EC { end = s * (i + 1); } - threads[i] = std::thread([this, &function, &signatureBitset] + threads[i] = std::thread( + [this, &function, &signatureBitset, &context] (std::size_t begin, std::size_t end) { for(std::size_t i = begin; i < end; ++i) @@ -731,7 +761,7 @@ namespace EC & std::get(entities[i])) == signatureBitset) { - Helper::callPtr(i, *this, function); + Helper::callPtr(i, *this, function, context); } } }, @@ -750,9 +780,11 @@ namespace EC private: std::unordered_map)> > > + std::vector, + void*)> > > forMatchingFunctions; std::size_t functionIndex = 0; @@ -775,10 +807,16 @@ namespace EC std::size_t). Calling clearForMatchingFunctions() will reset this counter to zero. + Note that the context pointer provided here (default nullptr) will + be provided to the stored function when called. + Example: \code{.cpp} - manager.addForMatchingFunction>([] ( - std::size_t ID, C0* component0, C1* component1) { + manager.addForMatchingFunction>([] + (std::size_t ID, + void* context, + C0* component0, C1* component1) + { // Lambda function contents here }); @@ -795,7 +833,9 @@ namespace EC or calling with callForMatchingFunction(). */ template - std::size_t addForMatchingFunction(Function&& function) + std::size_t addForMatchingFunction( + Function&& function, + void* context = nullptr) { while(forMatchingFunctions.find(functionIndex) != forMatchingFunctions.end()) @@ -818,9 +858,11 @@ namespace EC functionIndex, std::make_tuple( signatureBitset, + context, [function, helper, this] - (std::size_t threadCount, - std::vector matching) + (std::size_t threadCount, + std::vector matching, + void* context) { if(threadCount <= 1) { @@ -828,7 +870,8 @@ namespace EC { if(isAlive(eid)) { - helper.callInstancePtr(eid, *this, &function); + helper.callInstancePtr( + eid, *this, &function, context); } } } @@ -849,14 +892,15 @@ namespace EC end = s * (i + 1); } threads[i] = std::thread( - [this, &function, &helper] + [this, &function, &helper, &context] (std::size_t begin, std::size_t end) { for(std::size_t i = begin; i < end; ++i) { if(isAlive(i)) { - helper.callInstancePtr(i, *this, &function); + helper.callInstancePtr( + i, *this, &function, context); } } }, @@ -950,8 +994,8 @@ namespace EC /*! \brief Call all stored functions. - A second parameter can be optionally used to specify the number - of threads to use when calling the functions. Otherwise, this + The first (and only) parameter can be optionally used to specify the + number of threads to use when calling the functions. Otherwise, this function is by default not multi-threaded. Note that multi-threading is based on splitting the task of calling the functions across sections of entities. Thus if there are only @@ -960,8 +1004,10 @@ namespace EC Example: \code{.cpp} - manager.addForMatchingFunction>([] ( - std::size_t ID, C0* component0, C1* component1) { + manager.addForMatchingFunction>([] + (std::size_t ID, + void* context, + C0* component0, C1* component1) { // Lambda function contents here }); @@ -993,7 +1039,8 @@ namespace EC iter != forMatchingFunctions.end(); ++iter) { - std::get<1>(iter->second)(threadCount, matching[i++]); + std::get<2>(iter->second)( + threadCount, matching[i++], std::get<1>(iter->second)); } } @@ -1012,7 +1059,7 @@ namespace EC \code{.cpp} std::size_t id = manager.addForMatchingFunction>( - [] (std::size_t ID, C0* c0, C1* c1) { + [] (std::size_t ID, void* context, C0* c0, C1* c1) { // Lambda function contents here }); @@ -1036,7 +1083,8 @@ namespace EC std::vector > matching = getMatchingEntities(std::vector{ &std::get(iter->second)}, threadCount); - std::get<1>(iter->second)(threadCount, matching[0]); + std::get<2>(iter->second)( + threadCount, matching[0], std::get<1>(iter->second)); return true; } @@ -1047,8 +1095,11 @@ namespace EC Example: \code{.cpp} - manager.addForMatchingFunction>([] ( - std::size_t ID, C0* component0, C1* component1) { + manager.addForMatchingFunction>([] + (std::size_t ID, + void* context, + C0* component0, C1* component1) + { // Lambda function contents here }); @@ -1170,6 +1221,22 @@ namespace EC return forMatchingFunctions.erase(index) == 1; } + /*! + \brief Sets the context pointer of a stored function + + \return True if id is valid and context was updated + */ + bool changeForMatchingFunctionContext(std::size_t id, void* context) + { + auto f = forMatchingFunctions.find(id); + if(f != forMatchingFunctions.end()) + { + std::get<1>(f->second) = context; + return true; + } + return false; + } + /*! \brief Call multiple functions with mulitple signatures on all living entities. @@ -1191,6 +1258,9 @@ namespace EC See the Unit Test of this function in src/test/ECTest.cpp for usage examples. + The second parameter (default nullptr) will be provided to every + function call as a void* (context). + This function was created for the use case where there are many entities in the system which can cause multiple calls to forMatchingSignature to be slow due to the overhead of iterating @@ -1209,7 +1279,9 @@ namespace EC */ template void forMatchingSignatures( - FTuple fTuple, const std::size_t threadCount = 1) + FTuple fTuple, + void* context = nullptr, + const std::size_t threadCount = 1) { std::vector > multiMatchingEntities( SigList::size); @@ -1294,7 +1366,7 @@ namespace EC EC::Meta::forEachDoubleTuple( EC::Meta::Morph >{}, fTuple, - [this, &multiMatchingEntities, &threadCount] + [this, &multiMatchingEntities, &threadCount, &context] (auto sig, auto func, auto index) { using SignatureComponents = @@ -1310,7 +1382,7 @@ namespace EC { if(isAlive(id)) { - Helper::call(id, *this, func); + Helper::call(id, *this, func, context); } } } @@ -1332,7 +1404,8 @@ namespace EC end = s * (i + 1); } threads[i] = std::thread( - [this, &multiMatchingEntities, &index, &func] + [this, &multiMatchingEntities, &index, &func, + &context] (std::size_t begin, std::size_t end) { for(std::size_t j = begin; j < end; @@ -1343,7 +1416,8 @@ namespace EC Helper::call( multiMatchingEntities[index][j], *this, - func); + func, + context); } } }, begin, end); @@ -1381,6 +1455,9 @@ namespace EC See the Unit Test of this function in src/test/ECTest.cpp for usage examples. + The second parameter (default nullptr) will be provided to every + function call as a void* (context). + This function was created for the use case where there are many entities in the system which can cause multiple calls to forMatchingSignature to be slow due to the overhead of iterating @@ -1399,6 +1476,7 @@ namespace EC */ template void forMatchingSignaturesPtr(FTuple fTuple, + void* context = nullptr, std::size_t threadCount = 1) { std::vector > multiMatchingEntities( @@ -1484,7 +1562,7 @@ namespace EC EC::Meta::forEachDoubleTuple( EC::Meta::Morph >{}, fTuple, - [this, &multiMatchingEntities, &threadCount] + [this, &multiMatchingEntities, &threadCount, &context] (auto sig, auto func, auto index) { using SignatureComponents = @@ -1500,7 +1578,7 @@ namespace EC { if(isAlive(id)) { - Helper::callPtr(id, *this, func); + Helper::callPtr(id, *this, func, context); } } } @@ -1522,7 +1600,8 @@ namespace EC end = s * (i + 1); } threads[i] = std::thread( - [this, &multiMatchingEntities, &index, &func] + [this, &multiMatchingEntities, &index, &func, + &context] (std::size_t begin, std::size_t end) { for(std::size_t j = begin; j < end; @@ -1533,7 +1612,8 @@ namespace EC Helper::callPtr( multiMatchingEntities[index][j], *this, - func); + func, + context); } } }, begin, end); diff --git a/src/test/ECTest.cpp b/src/test/ECTest.cpp index 3167a52..1e76c51 100644 --- a/src/test/ECTest.cpp +++ b/src/test/ECTest.cpp @@ -58,6 +58,38 @@ struct Derived : public Base typedef std::unique_ptr TestPtr; +struct Context +{ + int a, b; +}; + +void assignContextToC0(std::size_t /* id */, void* context, C0* c) +{ + Context* contextPtr = (Context*) context; + c->x = contextPtr->a; + c->y = contextPtr->b; +} + +void assignC0ToContext(std::size_t /* id */, void* context, C0* c) +{ + Context* contextPtr = (Context*) context; + contextPtr->a = c->x; + contextPtr->b = c->y; +} + +void setC0ToOneAndTwo(std::size_t /* id */, void* /* context */, C0* c) +{ + c->x = 1; + c->y = 2; +} + +void setContextToThreeAndFour(std::size_t /* id */, void* context, C0* /* c */) +{ + Context* contextPtr = (Context*) context; + contextPtr->a = 3; + contextPtr->b = 4; +} + TEST(EC, Bitset) { { @@ -101,12 +133,16 @@ TEST(EC, Manager) vel->vy = 1; } - auto posUpdate = [] (std::size_t id, C0* pos, C1* vel) { + auto posUpdate = [] + (std::size_t /* id */, void* /* context */, C0* pos, C1* vel) + { pos->x += vel->vx; pos->y += vel->vy; }; - auto updateTag = [] (std::size_t id, C0* pos, C1* vel) { + auto updateTag = [] + (std::size_t /* id */, void* /* context */, C0* pos, C1* vel) + { pos->x = pos->y = vel->vx = vel->vy = 0; }; @@ -139,7 +175,7 @@ TEST(EC, Manager) std::size_t count = 0; - auto updateTagOnly = [&count] (std::size_t id) { + auto updateTagOnly = [&count] (std::size_t /* id */, void* /* context */) { std::cout << "UpdateTagOnly was run." << std::endl; ++count; }; @@ -167,7 +203,7 @@ TEST(EC, MoveComponentWithUniquePtr) int x = 0; int y = 0; manager.forMatchingSignature >([&x, &y] - (std::size_t eID, C0Ptr* ptr) { + (std::size_t /* id */, void* /* context */, C0Ptr* ptr) { x = (*ptr)->x; y = (*ptr)->y; }); @@ -186,7 +222,9 @@ TEST(EC, MoveComponentWithUniquePtr) int result = 0; - auto getResultFunction = [&result] (std::size_t eID, TestPtr* ptr) { + auto getResultFunction = [&result] + (std::size_t /* id */, void* /* context */, TestPtr* ptr) + { result = (*ptr)->getInt(); }; @@ -246,31 +284,31 @@ TEST(EC, FunctionStorage) manager.addComponent(eid); auto f0index = manager.addForMatchingFunction>( - [] (std::size_t eid, C0* c0) { + [] (std::size_t /* id */, void* /* context */, C0* c0) { ++c0->x; ++c0->y; }); auto f1index = manager.addForMatchingFunction>( - [] (std::size_t eid, C0* c0, C1* c1) { + [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) { c1->vx = c0->x + 10; c1->vy = c1->vy + c1->vx + c0->y + 10; }); auto f2index = manager.addForMatchingFunction>( - [] (std::size_t eid, C0* c0) { + [] (std::size_t /* id */, void* /* context */, C0* c0) { c0->x = c0->y = 9999; }); auto f3index = manager.addForMatchingFunction>( - [] (std::size_t eid, C1* c1) { + [] (std::size_t /* id */, void* /* context */, C1* c1) { c1->vx = c1->vy = 10000; }); EXPECT_EQ(2, manager.removeSomeMatchingFunctions({f2index, f3index})); auto f4index = manager.addForMatchingFunction>( - [] (std::size_t eid, C0* c0) { + [] (std::size_t /* id */, void* /* context */, C0* c0) { c0->x = 999; c0->y = 888; }); @@ -281,7 +319,7 @@ TEST(EC, FunctionStorage) } auto f5index = manager.addForMatchingFunction>( - [] (std::size_t eid, C0* c0) { + [] (std::size_t /* id */, void* /* context */, C0* c0) { c0->x = 777; c0->y = 666; }); @@ -418,10 +456,11 @@ TEST(EC, MultiThreaded) } manager.forMatchingSignature >( - [] (const std::size_t& eid, C0* c) { + [] (const std::size_t& /* id */, void* /* context */, C0* c) { c->x = 1; c->y = 2; }, + nullptr, 2 ); @@ -443,10 +482,11 @@ TEST(EC, MultiThreaded) } manager.forMatchingSignature >( - [] (const std::size_t& eid, C0* c) { + [] (const std::size_t& /* id */, void* /* context */, C0* c) { c->x = 3; c->y = 4; }, + nullptr, 8 ); @@ -467,7 +507,7 @@ TEST(EC, MultiThreaded) } auto f0 = manager.addForMatchingFunction >( - [] (const std::size_t& eid, C0* c) { + [] (const std::size_t& /* id */, void* /* context */, C0* c) { c->x = 1; c->y = 2; } @@ -482,7 +522,7 @@ TEST(EC, MultiThreaded) } auto f1 = manager.addForMatchingFunction >( - [] (const std::size_t& eid, C0* c) { + [] (const std::size_t& /* id */, void* /* context */, C0* c) { c->x = 3; c->y = 4; } @@ -559,13 +599,13 @@ TEST(EC, ForMatchingSignatures) TypeList, TypeList > >( std::make_tuple( - [] (std::size_t eid, C0* c) { + [] (std::size_t /* id */, void* /* context */, C0* c) { EXPECT_EQ(c->x, 0); EXPECT_EQ(c->y, 0); c->x = 1; c->y = 1; }, - [] (std::size_t eid, C0* c0, C1* c1) { + [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) { EXPECT_EQ(c0->x, 1); EXPECT_EQ(c0->y, 1); EXPECT_EQ(c1->vx, 0); @@ -612,7 +652,8 @@ TEST(EC, ForMatchingSignatures) > ( std::make_tuple( - [&first, &last, &cx, &cy, &cxM, &cyM] (std::size_t eid, C0* c) { + [&first, &last, &cx, &cy, &cxM, &cyM] + (std::size_t eid, void* /* context */, C0* c) { if(eid != first && eid != last) { { @@ -641,7 +682,7 @@ TEST(EC, ForMatchingSignatures) } }, [&c0x, &c0y, &c1vx, &c1vy, &c0xM, &c0yM, &c1vxM, &c1vyM] - (std::size_t eid, C0* c0, C1* c1) { + (std::size_t eid, void* /* context */, C0* c0, C1* c1) { { std::lock_guard guard(c0xM); c0x.insert(std::make_pair(eid, c0->x)); @@ -665,6 +706,7 @@ TEST(EC, ForMatchingSignatures) c0->x = 1; c0->y = 2; }), + nullptr, 3 ); @@ -729,13 +771,13 @@ TEST(EC, ForMatchingSignatures) TypeList, TypeList > >( std::make_tuple( - [] (std::size_t eid, C0* c0, C1* c1) { + [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) { c0->x = 9999; c0->y = 9999; c1->vx = 9999; c1->vy = 9999; }, - [] (std::size_t eid, C0* c0, C1* c1) { + [] (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) { c0->x = 10000; c0->y = 10000; c1->vx = 10000; @@ -785,14 +827,15 @@ TEST(EC, forMatchingPtrs) } } - const auto func0 = [] (std::size_t eid, C0* c0, C1* c1) + const auto func0 = [] + (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) { c0->x = 1; c0->y = 2; c1->vx = 3; c1->vy = 4; }; - const auto func1 = [] (std::size_t eid, C0* c0) + const auto func1 = [] (std::size_t /* id */, void* /* context */, C0* c0) { c0->x = 11; c0->y = 12; @@ -864,13 +907,17 @@ TEST(EC, forMatchingPtrs) } // test duplicate signatures - const auto setTo9999 = [] (std::size_t eid, C0* c0, C1* c1) { + const auto setTo9999 = [] + (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) + { c0->x = 9999; c0->y = 9999; c1->vx = 9999; c1->vy = 9999; }; - const auto setTo10000 = [] (std::size_t eid, C0* c0, C1* c1) { + const auto setTo10000 = [] + (std::size_t /* id */, void* /* context */, C0* c0, C1* c1) + { c0->x = 10000; c0->y = 10000; c1->vx = 10000; @@ -895,3 +942,88 @@ TEST(EC, forMatchingPtrs) }; } +TEST(EC, context) +{ + EC::Manager manager; + auto e0 = manager.addEntity(); + auto e1 = manager.addEntity(); + + manager.addComponent(e0, 1, 2); + manager.addComponent(e1, 3, 4); + + Context c; + c.a = 2000; + c.b = 5432; + + EXPECT_EQ(1, manager.getEntityData(e0)->x); + EXPECT_EQ(2, manager.getEntityData(e0)->y); + EXPECT_EQ(3, manager.getEntityData(e1)->x); + EXPECT_EQ(4, manager.getEntityData(e1)->y); + + manager.forMatchingSignature>(assignContextToC0, &c); + + EXPECT_EQ(2000, manager.getEntityData(e0)->x); + EXPECT_EQ(5432, manager.getEntityData(e0)->y); + EXPECT_EQ(2000, manager.getEntityData(e1)->x); + EXPECT_EQ(5432, manager.getEntityData(e1)->y); + + c.a = 1111; + c.b = 2222; + + using C0TL = EC::Meta::TypeList; + manager.forMatchingSignatures>( + std::make_tuple( + setC0ToOneAndTwo, assignContextToC0, setContextToThreeAndFour), + &c); + EXPECT_EQ(1111, manager.getEntityData(e0)->x); + EXPECT_EQ(2222, manager.getEntityData(e0)->y); + EXPECT_EQ(1111, manager.getEntityData(e1)->x); + EXPECT_EQ(2222, manager.getEntityData(e1)->y); + + EXPECT_EQ(3, c.a); + EXPECT_EQ(4, c.b); + + manager.forMatchingSignaturesPtr>( + std::make_tuple( + &setC0ToOneAndTwo, &assignC0ToContext), + &c); + + EXPECT_EQ(1, c.a); + EXPECT_EQ(2, c.b); + + EXPECT_EQ(1, manager.getEntityData(e0)->x); + EXPECT_EQ(2, manager.getEntityData(e0)->y); + EXPECT_EQ(1, manager.getEntityData(e1)->x); + EXPECT_EQ(2, manager.getEntityData(e1)->y); + + c.a = 1980; + c.b = 1990; + + auto fid = manager.addForMatchingFunction(assignContextToC0, &c); + + manager.callForMatchingFunction(fid); + EXPECT_EQ(1980, manager.getEntityData(e0)->x); + EXPECT_EQ(1990, manager.getEntityData(e0)->y); + EXPECT_EQ(1980, manager.getEntityData(e1)->x); + EXPECT_EQ(1990, manager.getEntityData(e1)->y); + + c.a = 2000; + c.b = 2010; + + manager.callForMatchingFunctions(); + EXPECT_EQ(2000, manager.getEntityData(e0)->x); + EXPECT_EQ(2010, manager.getEntityData(e0)->y); + EXPECT_EQ(2000, manager.getEntityData(e1)->x); + EXPECT_EQ(2010, manager.getEntityData(e1)->y); + + Context altC; + altC.a = 999; + altC.b = 1999; + + manager.changeForMatchingFunctionContext(fid, &altC); + manager.callForMatchingFunctions(); + EXPECT_EQ(999, manager.getEntityData(e0)->x); + EXPECT_EQ(1999, manager.getEntityData(e0)->y); + EXPECT_EQ(999, manager.getEntityData(e1)->x); + EXPECT_EQ(1999, manager.getEntityData(e1)->y); +}