Add forMatchingSimple, refactorings
This commit is contained in:
parent
e0da16a63e
commit
a310a8ae38
2 changed files with 144 additions and 23 deletions
|
@ -490,6 +490,23 @@ namespace EC
|
|||
).template getTagBit<Tag>() = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Resets the Manager, removing all entities.
|
||||
|
||||
Some data may persist but will be overwritten when new entities
|
||||
are added. Thus, do not depend on data to persist after a call to
|
||||
reset().
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
clearForMatchingFunctions();
|
||||
|
||||
currentSize = 0;
|
||||
currentCapacity = 0;
|
||||
deletedSet.clear();
|
||||
resize(EC_INIT_ENTITIES_SIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename... Types>
|
||||
struct ForMatchingSignatureHelper
|
||||
|
@ -1634,36 +1651,73 @@ namespace EC
|
|||
);
|
||||
}
|
||||
|
||||
typedef void ForMatchingFn(std::size_t, Manager<ComponentsList, TagsList>*, void*);
|
||||
|
||||
/*!
|
||||
\brief Resets the Manager, removing all entities.
|
||||
|
||||
Some data may persist but will be overwritten when new entities
|
||||
are added. Thus, do not depend on data to persist after a call to
|
||||
reset().
|
||||
* \brief A simple version of forMatchingSignature()
|
||||
*
|
||||
* This function behaves like forMatchingSignature(), but instead of
|
||||
* providing a function with each requested component as a parameter,
|
||||
* the function receives a pointer to the manager itself, with which to
|
||||
* query component/tag data.
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
clearForMatchingFunctions();
|
||||
|
||||
currentSize = 0;
|
||||
currentCapacity = 0;
|
||||
deletedSet.clear();
|
||||
resize(EC_INIT_ENTITIES_SIZE);
|
||||
template <typename Signature>
|
||||
void forMatchingSimple(ForMatchingFn fn, void *userData = nullptr, std::size_t threadCount = 1) {
|
||||
const BitsetType signatureBitset = BitsetType::template generateBitset<Signature>();
|
||||
if(threadCount <= 1) {
|
||||
for(std::size_t i = 0; i < currentSize; ++i) {
|
||||
if(!std::get<bool>(entities[i])) {
|
||||
continue;
|
||||
} else if((signatureBitset & std::get<BitsetType>(entities[i])) == signatureBitset) {
|
||||
fn(i, this, userData);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::vector<std::thread> threads(threadCount);
|
||||
const std::size_t s = currentSize / threadCount;
|
||||
for(std::size_t i = 0; i < threadCount; ++i) {
|
||||
const std::size_t begin = s * i;
|
||||
const std::size_t end =
|
||||
i == threadCount - 1 ?
|
||||
currentSize :
|
||||
s * (i + 1);
|
||||
threads[i] = std::thread(
|
||||
[this] (const std::size_t begin,
|
||||
const std::size_t end,
|
||||
const BitsetType signatureBitset,
|
||||
ForMatchingFn fn,
|
||||
void *userData) {
|
||||
for(std::size_t i = begin; i < end; ++i) {
|
||||
if(!std::get<bool>(entities[i])) {
|
||||
continue;
|
||||
} else if((signatureBitset & std::get<BitsetType>(entities[i])) == signatureBitset) {
|
||||
fn(i, this, userData);
|
||||
}
|
||||
}
|
||||
},
|
||||
begin,
|
||||
end,
|
||||
signatureBitset,
|
||||
fn,
|
||||
userData);
|
||||
}
|
||||
for(std::size_t i = 0; i < threadCount; ++i) {
|
||||
threads[i].join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef void ForMatchingIterableFn(std::size_t, Manager<ComponentsList, TagsList>*, void*);
|
||||
|
||||
/*!
|
||||
* \brief Similar to forMatchingSignature(), but with a collection of Component/Tag indices
|
||||
* \brief Similar to forMatchingSimple(), but with a collection of Component/Tag indices
|
||||
*
|
||||
* This function works like forMatchingSignature(), but instead of
|
||||
* This function works like forMatchingSimple(), but instead of
|
||||
* providing template types that filter out non-matching entities, an
|
||||
* iterable of indices must be provided which correlate to matching
|
||||
* Component/Tag indices. The function given must match the previously
|
||||
* defined typedef of type ForMatchingIterableFn.
|
||||
* defined typedef of type ForMatchingFn.
|
||||
*/
|
||||
template <typename Iterable>
|
||||
void forMatchingIterable(Iterable iterable, ForMatchingIterableFn fn, void* userPtr = nullptr, std::size_t threadCount = 1) {
|
||||
void forMatchingIterable(Iterable iterable, ForMatchingFn fn, void* userPtr = nullptr, std::size_t threadCount = 1) {
|
||||
if(threadCount <= 1) {
|
||||
bool isValid;
|
||||
for(std::size_t i = 0; i < currentSize; ++i) {
|
||||
|
@ -1687,7 +1741,8 @@ namespace EC
|
|||
std::size_t s = currentSize / threadCount;
|
||||
for(std::size_t i = 0; i < threadCount; ++i) {
|
||||
std::size_t begin = s * i;
|
||||
std::size_t end = i == threadCount - 1 ?
|
||||
std::size_t end =
|
||||
i == threadCount - 1 ?
|
||||
currentSize :
|
||||
s * (i + 1);
|
||||
threads[i] = std::thread(
|
||||
|
|
|
@ -1077,6 +1077,72 @@ TEST(EC, FunctionStorageOrder)
|
|||
EXPECT_EQ(6, v.at(5));
|
||||
}
|
||||
|
||||
TEST(EC, forMatchingSimple) {
|
||||
EC::Manager<ListComponentsAll, ListTagsAll> manager;
|
||||
|
||||
auto e0 = manager.addEntity();
|
||||
manager.addComponent<C0>(e0, 0, 1);
|
||||
|
||||
auto e1 = manager.addEntity();
|
||||
manager.addComponent<C0>(e1, 2, 3);
|
||||
manager.addTag<T0>(e1);
|
||||
|
||||
auto e2 = manager.addEntity();
|
||||
manager.addComponent<C0>(e2, 4, 5);
|
||||
manager.addTag<T0>(e2);
|
||||
manager.addTag<T1>(e2);
|
||||
|
||||
// add 10 to C0 components
|
||||
manager.forMatchingSimple<EC::Meta::TypeList<C0>>(
|
||||
[] (std::size_t id, decltype(manager) *manager, void *) {
|
||||
C0 *c0 = manager->getEntityData<C0>(id);
|
||||
c0->x += 10;
|
||||
c0->y += 10;
|
||||
}, nullptr, 3);
|
||||
|
||||
// verify
|
||||
{
|
||||
C0 *c0 = manager.getEntityData<C0>(e0);
|
||||
EXPECT_EQ(c0->x, 10);
|
||||
EXPECT_EQ(c0->y, 11);
|
||||
c0 = manager.getEntityData<C0>(e1);
|
||||
EXPECT_EQ(c0->x, 12);
|
||||
EXPECT_EQ(c0->y, 13);
|
||||
c0 = manager.getEntityData<C0>(e2);
|
||||
EXPECT_EQ(c0->x, 14);
|
||||
EXPECT_EQ(c0->y, 15);
|
||||
}
|
||||
|
||||
auto e3 = manager.addEntity();
|
||||
manager.addComponent<C0>(e3, 6, 7);
|
||||
manager.addTag<T0>(e3);
|
||||
manager.addTag<T1>(e3);
|
||||
|
||||
// add 100 to entities with C0,T1
|
||||
manager.forMatchingSimple<EC::Meta::TypeList<C0, T1>>(
|
||||
[] (std::size_t id, decltype(manager) *manager, void *) {
|
||||
C0 *c0 = manager->getEntityData<C0>(id);
|
||||
c0->x += 100;
|
||||
c0->y += 100;
|
||||
});
|
||||
|
||||
// verify
|
||||
{
|
||||
C0 *c0 = manager.getEntityData<C0>(e0);
|
||||
EXPECT_EQ(c0->x, 10);
|
||||
EXPECT_EQ(c0->y, 11);
|
||||
c0 = manager.getEntityData<C0>(e1);
|
||||
EXPECT_EQ(c0->x, 12);
|
||||
EXPECT_EQ(c0->y, 13);
|
||||
c0 = manager.getEntityData<C0>(e2);
|
||||
EXPECT_EQ(c0->x, 114);
|
||||
EXPECT_EQ(c0->y, 115);
|
||||
c0 = manager.getEntityData<C0>(e3);
|
||||
EXPECT_EQ(c0->x, 106);
|
||||
EXPECT_EQ(c0->y, 107);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(EC, forMatchingIterableFn)
|
||||
{
|
||||
EC::Manager<ListComponentsAll, ListTagsAll> manager;
|
||||
|
|
Loading…
Reference in a new issue