]> git.seodisparate.com - EntityComponentMetaSystem/commitdiff
Add forMatchingSimple, refactorings
authorStephen Seo <seo.disparate@gmail.com>
Wed, 6 Nov 2019 07:33:12 +0000 (16:33 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 6 Nov 2019 07:33:12 +0000 (16:33 +0900)
src/EC/Manager.hpp
src/test/ECTest.cpp

index bca25fad189a9d4ed7e826915a5abd5c460feddd..46e7b72bb13e40446da7bfffefee7de9a60c0a06 100644 (file)
@@ -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
             );
         }
 
-        /*!
-            \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) {
@@ -1687,9 +1741,10 @@ 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 ?
-                        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;
index d15cc7ad9be57575b4075fce79c7d413924a3213..3f1c50311d504fdc52534554dd7839f6576c6adf 100644 (file)
@@ -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;