API change: context/userdata provided to functions
All functions called by EC/Manager now accept an additional parameter as a void* to support user-provided data (or context) for functions (useful when the function is not a lambda function and doesn't have any other data stored with it).
This commit is contained in:
parent
2411125003
commit
6bf239a43b
2 changed files with 300 additions and 88 deletions
|
@ -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<Types>(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<Types>(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<Types...>::call(
|
||||
entityID,
|
||||
ctype,
|
||||
std::forward<Function>(function));
|
||||
std::forward<Function>(function),
|
||||
context);
|
||||
}
|
||||
|
||||
template <typename CType, typename Function>
|
||||
void callInstancePtr(
|
||||
const std::size_t& entityID,
|
||||
CType& ctype,
|
||||
Function* function) const
|
||||
Function* function,
|
||||
void* context = nullptr) const
|
||||
{
|
||||
ForMatchingSignatureHelper<Types...>::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<TypeList<C0, C1, T0>>([] (
|
||||
std::size_t ID, C0* component0, C1* component1) {
|
||||
Context c; // some class/struct with data
|
||||
manager.forMatchingSignature<TypeList<C0, C1, T0>>([]
|
||||
(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 <typename Signature, typename Function>
|
||||
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>(function));
|
||||
std::forward<Function>(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>(function));
|
||||
std::forward<Function>(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<TypeList<C0, C1, T0>>(
|
||||
&function, // ptr
|
||||
&c, // "Context" object passed to the function
|
||||
4 // four threads
|
||||
);
|
||||
\endcode
|
||||
|
@ -674,6 +702,7 @@ namespace EC
|
|||
*/
|
||||
template <typename Signature, typename Function>
|
||||
void forMatchingSignaturePtr(Function* function,
|
||||
void* context = nullptr,
|
||||
std::size_t threadCount = 1)
|
||||
{
|
||||
using SignatureComponents =
|
||||
|
@ -697,7 +726,7 @@ namespace EC
|
|||
if((signatureBitset & std::get<BitsetType>(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<BitsetType>(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::size_t, std::tuple<
|
||||
BitsetType,
|
||||
void*,
|
||||
std::function<void(
|
||||
std::size_t,
|
||||
std::vector<std::size_t>)> > >
|
||||
std::vector<std::size_t>,
|
||||
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<TypeList<C0, C1, T0>>([] (
|
||||
std::size_t ID, C0* component0, C1* component1) {
|
||||
manager.addForMatchingFunction<TypeList<C0, C1, T0>>([]
|
||||
(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 <typename Signature, typename Function>
|
||||
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<std::size_t> matching)
|
||||
std::vector<std::size_t> 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<TypeList<C0, C1, T0>>([] (
|
||||
std::size_t ID, C0* component0, C1* component1) {
|
||||
manager.addForMatchingFunction<TypeList<C0, C1, T0>>([]
|
||||
(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<TypeList<C0, C1, T0>>(
|
||||
[] (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<std::vector<std::size_t> > matching =
|
||||
getMatchingEntities(std::vector<BitsetType*>{
|
||||
&std::get<BitsetType>(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<TypeList<C0, C1, T0>>([] (
|
||||
std::size_t ID, C0* component0, C1* component1) {
|
||||
manager.addForMatchingFunction<TypeList<C0, C1, T0>>([]
|
||||
(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 <typename SigList, typename FTuple>
|
||||
void forMatchingSignatures(
|
||||
FTuple fTuple, const std::size_t threadCount = 1)
|
||||
FTuple fTuple,
|
||||
void* context = nullptr,
|
||||
const std::size_t threadCount = 1)
|
||||
{
|
||||
std::vector<std::vector<std::size_t> > multiMatchingEntities(
|
||||
SigList::size);
|
||||
|
@ -1294,7 +1366,7 @@ namespace EC
|
|||
EC::Meta::forEachDoubleTuple(
|
||||
EC::Meta::Morph<SigList, std::tuple<> >{},
|
||||
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 <typename SigList, typename FTuple>
|
||||
void forMatchingSignaturesPtr(FTuple fTuple,
|
||||
void* context = nullptr,
|
||||
std::size_t threadCount = 1)
|
||||
{
|
||||
std::vector<std::vector<std::size_t> > multiMatchingEntities(
|
||||
|
@ -1484,7 +1562,7 @@ namespace EC
|
|||
EC::Meta::forEachDoubleTuple(
|
||||
EC::Meta::Morph<SigList, std::tuple<> >{},
|
||||
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);
|
||||
|
|
|
@ -58,6 +58,38 @@ struct Derived : public Base
|
|||
|
||||
typedef std::unique_ptr<Base> 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<EC::Meta::TypeList<C0Ptr> >([&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<C3>(eid);
|
||||
|
||||
auto f0index = manager.addForMatchingFunction<EC::Meta::TypeList<C0>>(
|
||||
[] (std::size_t eid, C0* c0) {
|
||||
[] (std::size_t /* id */, void* /* context */, C0* c0) {
|
||||
++c0->x;
|
||||
++c0->y;
|
||||
});
|
||||
|
||||
auto f1index = manager.addForMatchingFunction<EC::Meta::TypeList<C0, C1>>(
|
||||
[] (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<EC::Meta::TypeList<C0>>(
|
||||
[] (std::size_t eid, C0* c0) {
|
||||
[] (std::size_t /* id */, void* /* context */, C0* c0) {
|
||||
c0->x = c0->y = 9999;
|
||||
});
|
||||
|
||||
auto f3index = manager.addForMatchingFunction<EC::Meta::TypeList<C1>>(
|
||||
[] (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<EC::Meta::TypeList<C0>>(
|
||||
[] (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<EC::Meta::TypeList<C0>>(
|
||||
[] (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<EC::Meta::TypeList<C0> >(
|
||||
[] (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<EC::Meta::TypeList<C0> >(
|
||||
[] (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<EC::Meta::TypeList<C0> >(
|
||||
[] (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<EC::Meta::TypeList<C0> >(
|
||||
[] (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<C0>, TypeList<C0, C1> >
|
||||
>(
|
||||
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<std::mutex> 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<C0, C1>,
|
||||
TypeList<C0, C1> > >(
|
||||
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<ListComponentsAll, ListTagsAll> manager;
|
||||
auto e0 = manager.addEntity();
|
||||
auto e1 = manager.addEntity();
|
||||
|
||||
manager.addComponent<C0>(e0, 1, 2);
|
||||
manager.addComponent<C0>(e1, 3, 4);
|
||||
|
||||
Context c;
|
||||
c.a = 2000;
|
||||
c.b = 5432;
|
||||
|
||||
EXPECT_EQ(1, manager.getEntityData<C0>(e0)->x);
|
||||
EXPECT_EQ(2, manager.getEntityData<C0>(e0)->y);
|
||||
EXPECT_EQ(3, manager.getEntityData<C0>(e1)->x);
|
||||
EXPECT_EQ(4, manager.getEntityData<C0>(e1)->y);
|
||||
|
||||
manager.forMatchingSignature<EC::Meta::TypeList<C0>>(assignContextToC0, &c);
|
||||
|
||||
EXPECT_EQ(2000, manager.getEntityData<C0>(e0)->x);
|
||||
EXPECT_EQ(5432, manager.getEntityData<C0>(e0)->y);
|
||||
EXPECT_EQ(2000, manager.getEntityData<C0>(e1)->x);
|
||||
EXPECT_EQ(5432, manager.getEntityData<C0>(e1)->y);
|
||||
|
||||
c.a = 1111;
|
||||
c.b = 2222;
|
||||
|
||||
using C0TL = EC::Meta::TypeList<C0>;
|
||||
manager.forMatchingSignatures<EC::Meta::TypeList<C0TL, C0TL, C0TL>>(
|
||||
std::make_tuple(
|
||||
setC0ToOneAndTwo, assignContextToC0, setContextToThreeAndFour),
|
||||
&c);
|
||||
EXPECT_EQ(1111, manager.getEntityData<C0>(e0)->x);
|
||||
EXPECT_EQ(2222, manager.getEntityData<C0>(e0)->y);
|
||||
EXPECT_EQ(1111, manager.getEntityData<C0>(e1)->x);
|
||||
EXPECT_EQ(2222, manager.getEntityData<C0>(e1)->y);
|
||||
|
||||
EXPECT_EQ(3, c.a);
|
||||
EXPECT_EQ(4, c.b);
|
||||
|
||||
manager.forMatchingSignaturesPtr<EC::Meta::TypeList<C0TL, C0TL>>(
|
||||
std::make_tuple(
|
||||
&setC0ToOneAndTwo, &assignC0ToContext),
|
||||
&c);
|
||||
|
||||
EXPECT_EQ(1, c.a);
|
||||
EXPECT_EQ(2, c.b);
|
||||
|
||||
EXPECT_EQ(1, manager.getEntityData<C0>(e0)->x);
|
||||
EXPECT_EQ(2, manager.getEntityData<C0>(e0)->y);
|
||||
EXPECT_EQ(1, manager.getEntityData<C0>(e1)->x);
|
||||
EXPECT_EQ(2, manager.getEntityData<C0>(e1)->y);
|
||||
|
||||
c.a = 1980;
|
||||
c.b = 1990;
|
||||
|
||||
auto fid = manager.addForMatchingFunction<C0TL>(assignContextToC0, &c);
|
||||
|
||||
manager.callForMatchingFunction(fid);
|
||||
EXPECT_EQ(1980, manager.getEntityData<C0>(e0)->x);
|
||||
EXPECT_EQ(1990, manager.getEntityData<C0>(e0)->y);
|
||||
EXPECT_EQ(1980, manager.getEntityData<C0>(e1)->x);
|
||||
EXPECT_EQ(1990, manager.getEntityData<C0>(e1)->y);
|
||||
|
||||
c.a = 2000;
|
||||
c.b = 2010;
|
||||
|
||||
manager.callForMatchingFunctions();
|
||||
EXPECT_EQ(2000, manager.getEntityData<C0>(e0)->x);
|
||||
EXPECT_EQ(2010, manager.getEntityData<C0>(e0)->y);
|
||||
EXPECT_EQ(2000, manager.getEntityData<C0>(e1)->x);
|
||||
EXPECT_EQ(2010, manager.getEntityData<C0>(e1)->y);
|
||||
|
||||
Context altC;
|
||||
altC.a = 999;
|
||||
altC.b = 1999;
|
||||
|
||||
manager.changeForMatchingFunctionContext(fid, &altC);
|
||||
manager.callForMatchingFunctions();
|
||||
EXPECT_EQ(999, manager.getEntityData<C0>(e0)->x);
|
||||
EXPECT_EQ(1999, manager.getEntityData<C0>(e0)->y);
|
||||
EXPECT_EQ(999, manager.getEntityData<C0>(e1)->x);
|
||||
EXPECT_EQ(1999, manager.getEntityData<C0>(e1)->y);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue