]> code.bitgloo.com Git - clyne/entityx.git/commitdiff
Improve entity iteration performance by removing support for custom predicates.
authorAlec Thomas <alec@swapoff.org>
Thu, 9 Oct 2014 23:28:04 +0000 (10:28 +1100)
committerAlec Thomas <alec@swapoff.org>
Thu, 9 Oct 2014 23:28:04 +0000 (10:28 +1100)
entityx/Entity.h
entityx/tags/TagsComponent.h
entityx/tags/TagsComponent_test.cc

index 85c8e796e2af35eb635d7b169b1a669feeb0f007..f3f801223fb82aa9f982088269c7ba74001956ce 100644 (file)
@@ -322,8 +322,6 @@ class EntityManager : entityx::help::NonCopyable {
 
   class View {
    public:
-    typedef std::function<bool (const EntityManager &, const Entity::Id &)> Predicate;
-
     struct BaseUnpacker {
       virtual ~BaseUnpacker() {}
       virtual void unpack(const Entity::Id &id) = 0;
@@ -346,10 +344,10 @@ class EntityManager : entityx::help::NonCopyable {
       friend class View;
 
       Iterator(EntityManager *manager,
-               const std::vector<Predicate> &predicates,
+               const ComponentMask mask,
                const std::vector<std::shared_ptr<BaseUnpacker>> &unpackers,
                uint32_t index)
-          : manager_(manager), predicates_(predicates), unpackers_(unpackers), i_(index), capacity_(manager_->capacity()) {
+          : manager_(manager), mask_(mask), unpackers_(unpackers), i_(index), capacity_(manager_->capacity()) {
         next();
       }
 
@@ -366,32 +364,21 @@ class EntityManager : entityx::help::NonCopyable {
         }
       }
 
-      bool predicate() {
-        Entity::Id id = manager_->create_id(i_);
-        for (auto &p : predicates_) {
-          if (!p(*manager_, id)) {
-            return false;
-          }
-        }
-        return true;
+      inline bool predicate() {
+        return (manager_->entity_component_mask_[i_] & mask_) == mask_;
       }
 
       EntityManager *manager_;
-      std::vector<Predicate> predicates_;
+      ComponentMask mask_;
       std::vector<std::shared_ptr<BaseUnpacker>> unpackers_;
       uint32_t i_;
       size_t capacity_;
     };
 
-    // Create a sub-view with an additional predicate.
-    View(const View &view, Predicate predicate) : manager_(view.manager_), predicates_(view.predicates_) {
-      predicates_.push_back(predicate);
-    }
-
-    Iterator begin() { return Iterator(manager_, predicates_, unpackers_, 0); }
-    Iterator end() { return Iterator(manager_, predicates_, unpackers_, manager_->capacity()); }
-    const Iterator begin() const { return Iterator(manager_, predicates_, unpackers_, 0); }
-    const Iterator end() const { return Iterator(manager_, predicates_, unpackers_, manager_->capacity()); }
+    Iterator begin() { return Iterator(manager_, mask_, unpackers_, 0); }
+    Iterator end() { return Iterator(manager_, mask_, unpackers_, manager_->capacity()); }
+    const Iterator begin() const { return Iterator(manager_, mask_, unpackers_, 0); }
+    const Iterator end() const { return Iterator(manager_, mask_, unpackers_, manager_->capacity()); }
 
     template <typename A>
     View &unpack_to(ComponentHandle<A> &a) {
@@ -421,12 +408,10 @@ class EntityManager : entityx::help::NonCopyable {
       ComponentHandle<C> &c;
     };
 
-    View(EntityManager *manager, Predicate predicate) : manager_(manager) {
-      predicates_.push_back(predicate);
-    }
+    View(EntityManager *manager, ComponentMask mask) : manager_(manager), mask_(mask) {}
 
     EntityManager *manager_;
-    std::vector<Predicate> predicates_;
+    ComponentMask mask_;
     std::vector<std::shared_ptr<BaseUnpacker>> unpackers_;
   };
 
@@ -618,15 +603,13 @@ class EntityManager : entityx::help::NonCopyable {
   template <typename C, typename ... Components>
   View entities_with_components() {
     auto mask = component_mask<C, Components ...>();
-    return View(this, ComponentMaskPredicate(entity_component_mask_, mask));
+    return View(this, mask);
   }
 
   template <typename C>
   View entities_with_components(ComponentHandle<C> &c) {
     auto mask = component_mask<C>();
-    return
-        View(this, ComponentMaskPredicate(entity_component_mask_, mask))
-        .unpack_to(c);
+    return View(this, mask).unpack_to(c);
   }
 
   /**
@@ -644,9 +627,7 @@ class EntityManager : entityx::help::NonCopyable {
   template <typename C, typename ... Components>
   View entities_with_components(ComponentHandle<C> &c, ComponentHandle<Components> & ... args) {
     auto mask = component_mask<C, Components...>();
-    return
-        View(this, ComponentMaskPredicate(entity_component_mask_, mask))
-        .unpack_to(c, args ...);
+    return View(this, mask).unpack_to(c, args ...);
   }
 
   /**
@@ -659,7 +640,9 @@ class EntityManager : entityx::help::NonCopyable {
    * @return An iterator view over all valid entities.
    */
   View entities_for_debugging() {
-    return View(this, ValidEntityPredicate());
+    ComponentMask mask;
+    for (size_t i = 0; i < mask.size(); i++) mask.set(i);
+    return View(this, mask);
   }
 
   template <typename C>
@@ -707,21 +690,6 @@ class EntityManager : entityx::help::NonCopyable {
     }
   };
 
-  /// A predicate that matches valid entities with the given component mask.
-  class ComponentMaskPredicate {
-   public:
-    ComponentMaskPredicate(const std::vector<ComponentMask> &entity_component_masks, ComponentMask mask)
-        : entity_component_masks_(entity_component_masks), mask_(mask) {}
-
-    bool operator()(const EntityManager &entities, const Entity::Id &entity) {
-      return (entity_component_masks_[entity.index()] & mask_) == mask_;
-    }
-
-   private:
-    const std::vector<ComponentMask> &entity_component_masks_;
-    ComponentMask mask_;
-  };
-
   inline void assert_valid(Entity::Id id) const {
     assert(id.index() < entity_component_mask_.size() && "Entity::Id ID outside entity vector range");
     assert(entity_version_[id.index()] == id.version() && "Attempt to access Entity via a stale Entity::Id");
index f47249ff52b8cc999112421a76ea1bd1cb9e0146..6d19734c1567e5bfd0786e9283500e07845b0440 100644 (file)
@@ -24,21 +24,8 @@ namespace tags {
  *
  * ComponentPtr<TagsComponent> tags;
  * for (Entity entity : entity_manager.entities_with_components(tags))
- * for (Entity entity : TagsComponent::view(entity_manager, "tag1")) {
- * }
  */
 class TagsComponent : public Component<TagsComponent> {
-  struct TagsPredicate {
-    explicit TagsPredicate(const std::string &tag) : tag(tag) {}
-
-    bool operator() (const EntityManager &manager, Entity::Id id) {
-      auto tags = manager.component<TagsComponent>(id);
-      return tags && tags->tags.find(tag) != tags->tags.end();
-    }
-
-    std::string tag;
-  };
-
  public:
   /**
    * Construct a new TagsComponent with the given tags.
@@ -50,13 +37,6 @@ class TagsComponent : public Component<TagsComponent> {
     set_tags(tag, tags ...);
   }
 
-  /**
-   * Filter the provided view to only those entities with the given tag.
-   */
-  static EntityManager::View view(const EntityManager::View &view, const std::string &tag) {
-    return EntityManager::View(view, TagsPredicate(tag));
-  }
-
   std::unordered_set<std::string> tags;
 
  private:
index 71a66ede6c9f016672e0d015b9796970e65877ab..c1d575e9ceefd849e414842b07d197707cdb32c7 100644 (file)
@@ -40,19 +40,3 @@ TEST_CASE("TestVariadicConstruction", "TagsComponentTest") {
   expected.insert("indestructible");
   REQUIRE(expected == tags.tags);
 }
-
-TEST_CASE("TestEntitiesWithTag", "TagsComponentTest") {
-  EventManager ev;
-  EntityManager en(ev);
-  Entity a = en.create();
-  a.assign<Position>();
-  for (int i = 0; i < 99; ++i) {
-    auto e = en.create();
-    e.assign<Position>();
-    e.assign<TagsComponent>("positionable");
-  }
-  a.assign<TagsComponent>("player", "indestructible");
-  auto entities = en.entities_with_components<Position>();
-  REQUIRE(100 == size(entities));
-  REQUIRE(1 == size(TagsComponent::view(entities, "player")));
-}