).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
);
}
- /*!
- \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();
+ typedef void ForMatchingFn(std::size_t, Manager<ComponentsList, TagsList>*, void*);
- currentSize = 0;
- currentCapacity = 0;
- deletedSet.clear();
- resize(EC_INIT_ENTITIES_SIZE);
+ /*!
+ * \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.
+ */
+ 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) {
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 ?
- currentSize :
- s * (i + 1);
+ std::size_t end =
+ i == threadCount - 1 ?
+ currentSize :
+ s * (i + 1);
threads[i] = std::thread(
[this, &fn, &iterable, userPtr] (std::size_t begin, std::size_t end) {
bool isValid;
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;