]> code.bitgloo.com Git - clyne/entityx.git/commitdiff
Allow Entity objects to be copied around.
authorAlec Thomas <alec@swapoff.org>
Sat, 9 Mar 2013 17:35:09 +0000 (12:35 -0500)
committerAlec Thomas <alec@swapoff.org>
Sat, 9 Mar 2013 17:47:37 +0000 (12:47 -0500)
Note that this doesn't use shared_ptr, but this is little different
from the previous implementation using a reference.

entityx/Entity.cc
entityx/Entity.h
entityx/Entity_test.cc

index 6c43a063c47d6c74dd568aae9e2f1bc4ceb5da90..41fbb4cedee6961ac3a6e24f7a1afecaf5d5446f 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution.
- * 
+ *
  * Author: Alec Thomas <alec@swapoff.org>
  */
 
@@ -16,7 +16,11 @@ namespace entityx {
 BaseComponent::Family BaseComponent::family_counter_ = 0;
 
 bool Entity::exists() const {
-  return entities_.exists(id_);
+  return entities_ != nullptr && entities_->exists(id_);
+}
+
+void Entity::detach() {
+  entities_ = nullptr;
 }
 
 }
index ae284433d564b98659bc7ec24644af2cc360e8bb..0116a22e3c0c204194d489faf7f48d24c3c5dbc2 100644 (file)
@@ -15,6 +15,7 @@
 #include <algorithm>
 #include <bitset>
 #include <cassert>
+#include <iostream>
 #include <iterator>
 #include <set>
 #include <string>
@@ -38,6 +39,28 @@ class Entity {
  public:
   typedef uint64_t Id;
 
+  Entity(): entities_(nullptr) {}
+
+  /**
+   * Alias for exists().
+   */
+  bool operator ! () const {
+    return exists();
+  }
+
+  bool operator == (const Entity &other) const {
+    return other.entities_ == entities_ && other.id_ == id_;
+  }
+
+  bool operator != (const Entity &other) const {
+    return other.entities_ != entities_ || other.id_ != id_;
+  }
+
+  /**
+   * Detach entity from the EntityManager.
+   */
+  void detach();
+
   Id id() const { return id_; }
 
   operator Id () { return id_; }
@@ -60,13 +83,19 @@ class Entity {
  private:
   friend class EntityManager;
 
-  Entity(EntityManager &entities, Entity::Id id) : entities_(entities), id_(id) {}
+  Entity(EntityManager *entities, Entity::Id id) : entities_(entities), id_(id) {}
 
-  EntityManager &entities_;
+  EntityManager *entities_;
   Entity::Id id_;
 };
 
 
+inline std::ostream &operator << (std::ostream &out, const Entity &entity) {
+  out << "Entity(" << entity.id() << ")";
+  return out;
+}
+
+
 /**
  * Base component class, only used for insertion into collections.
  *
@@ -201,17 +230,19 @@ class EntityManager : boost::noncopyable {
      private:
       friend class View;
 
-      Iterator(EntityManager &manager, const std::vector<Predicate> &predicates,
+      Iterator() : manager_(nullptr) {}
+
+      Iterator(EntityManager *manager, const std::vector<Predicate> &predicates,
                const std::vector<boost::function<void (Entity::Id)>> &unpackers, Entity::Id entity)
           : manager_(manager), predicates_(predicates), unpackers_(unpackers), i_(entity) {
         next();
       }
 
       void next() {
-        while (i_ < manager_.size() && !predicate()) {
+        while (i_ < manager_->size() && !predicate()) {
           ++i_;
         }
-        if (i_ < manager_.size() && !unpackers_.empty()) {
+        if (i_ < manager_->size() && !unpackers_.empty()) {
           for (auto unpacker : unpackers_) {
             unpacker(i_);
           }
@@ -220,14 +251,14 @@ class EntityManager : boost::noncopyable {
 
       bool predicate() {
         for (auto &p : predicates_) {
-          if (!p(manager_, i_)) {
+          if (!p(*manager_, i_)) {
             return false;
           }
         }
         return true;
       }
 
-      EntityManager &manager_;
+      EntityManager *manager_;
       const std::vector<Predicate> predicates_;
       std::vector<boost::function<void (Entity::Id)>> unpackers_;
       Entity::Id i_;
@@ -239,9 +270,9 @@ class EntityManager : boost::noncopyable {
     }
 
     Iterator begin() { return Iterator(manager_, predicates_, unpackers_, 0); }
-    Iterator end() { return Iterator(manager_, predicates_, unpackers_, manager_.size()); }
+    Iterator end() { return Iterator(manager_, predicates_, unpackers_, manager_->size()); }
     const Iterator begin() const { return Iterator(manager_, predicates_, unpackers_, 0); }
-    const Iterator end() const { return Iterator(manager_, predicates_, unpackers_, manager_.size()); }
+    const Iterator end() const { return Iterator(manager_, predicates_, unpackers_, manager_->size()); }
 
     template <typename A>
     View &unpack_to(boost::shared_ptr<A> &a) {
@@ -263,22 +294,22 @@ class EntityManager : boost::noncopyable {
 
     template <typename T>
     struct Unpacker {
-      Unpacker(EntityManager &manager, boost::shared_ptr<T> &c) : manager(manager), c(c) {}
+      Unpacker(EntityManager *manager, boost::shared_ptr<T> &c) : manager_(manager), c(c) {}
 
       void operator () (Entity::Id id) {
-        c = manager.component<T>(id);
+        c = manager_->component<T>(id);
       }
 
      private:
-      EntityManager &manager;
+      EntityManager *manager_;
       boost::shared_ptr<T> &c;
     };
 
-    View(EntityManager &manager, Predicate predicate) : manager_(manager) {
+    View(EntityManager *manager, Predicate predicate) : manager_(manager) {
       predicates_.push_back(predicate);
     }
 
-    EntityManager &manager_;
+    EntityManager *manager_;
     std::vector<Predicate> predicates_;
     std::vector<boost::function<void (Entity::Id)>> unpackers_;
   };
@@ -304,7 +335,7 @@ class EntityManager : boost::noncopyable {
       free_list_.erase(it);
     }
     event_manager_.emit<EntityCreatedEvent>(*this, id);
-    return Entity(*this, id);
+    return Entity(this, id);
   }
 
   /**
@@ -333,7 +364,7 @@ class EntityManager : boost::noncopyable {
   }
 
   Entity get(Entity::Id id) {
-    return Entity(*this, id);
+    return Entity(this, id);
   }
 
   /**
@@ -385,7 +416,7 @@ class EntityManager : boost::noncopyable {
   template <typename C, typename ... Components>
   View entities_with_components() {
     uint64_t mask = component_mask<C, Components ...>();
-    return View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask));
+    return View(this, View::ComponentMaskPredicate(entity_component_mask_, mask));
   }
 
   /**
@@ -395,7 +426,7 @@ class EntityManager : boost::noncopyable {
   View entities_with_components(boost::shared_ptr<C> &c, Components && ... args) {
     uint64_t mask = component_mask(c, args ...);
     return
-        View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask))
+        View(this, View::ComponentMaskPredicate(entity_component_mask_, mask))
         .unpack_to(c, args ...);
   }
 
@@ -484,27 +515,27 @@ class EntityManager : boost::noncopyable {
 
 template <typename C>
 boost::shared_ptr<C> Entity::assign(boost::shared_ptr<C> component) {
-  return entities_.assign<C>(id_, component);
+  return entities_->assign<C>(id_, component);
 }
 
 template <typename C, typename ... Args>
 boost::shared_ptr<C> Entity::assign(Args && ... args) {
-  return entities_.assign<C>(id_, args ...);
+  return entities_->assign<C>(id_, args ...);
 }
 
 template <typename C>
 boost::shared_ptr<C> Entity::component() {
-  return entities_.component<C>(id_);
+  return entities_->component<C>(id_);
 }
 
 template <typename A>
 void Entity::unpack(boost::shared_ptr<A> &a) {
-  entities_.unpack(id_, a);
+  entities_->unpack(id_, a);
 }
 
 template <typename A, typename B, typename ... Args>
 void Entity::unpack(boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
-  entities_.unpack(id_, a, b, args ...);
+  entities_->unpack(id_, a, b, args ...);
 }
 
 }
index d042b4b991e26c01c62a8ca25dcacd467941890b..cc3d11f6b419a96ff8de904480b8bdad00ee9fa1 100644 (file)
@@ -306,3 +306,13 @@ TEST_F(EntityManagerTest, TestComponentAddedEvent) {
   ASSERT_EQ(10, receiver.position_events);
   ASSERT_EQ(10, receiver.direction_events);
 }
+
+TEST_F(EntityManagerTest, TestEntityAssignment) {
+  Entity a, b;
+  a = em.create();
+  ASSERT_NE(a, b);
+  b = a;
+  ASSERT_EQ(a, b);
+  a.detach();
+  ASSERT_NE(a, b);
+}