aboutsummaryrefslogtreecommitdiffstats
path: root/entityx/Entity.h
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2017-01-10 21:26:13 -0500
committerClyne Sullivan <tullivan99@gmail.com>2017-01-10 21:26:13 -0500
commitf800dbc034e7a70a613bab8cd9d147be4f6e88b6 (patch)
treec8714ddc8f6712f07d921c08fd92ae8ef228494b /entityx/Entity.h
parentc6651145a4a6e6611b585c1a87c127f38751db4b (diff)
windows build
Diffstat (limited to 'entityx/Entity.h')
-rw-r--r--entityx/Entity.h1104
1 files changed, 1104 insertions, 0 deletions
diff --git a/entityx/Entity.h b/entityx/Entity.h
new file mode 100644
index 0000000..3217ae5
--- /dev/null
+++ b/entityx/Entity.h
@@ -0,0 +1,1104 @@
+/*
+ * Copyright (C) 2012 Alec Thomas <alec@swapoff.org>
+ * All rights reserved.
+ *
+ * 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>
+ */
+
+#pragma once
+
+
+#include <cstdint>
+#include <tuple>
+#include <new>
+#include <cstdlib>
+#include <algorithm>
+#include <bitset>
+#include <cassert>
+#include <iostream>
+#include <iterator>
+#include <list>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+#include <type_traits>
+ #include <functional>
+
+#include "entityx/help/Pool.h"
+#include "entityx/config.h"
+#include "entityx/Event.h"
+#include "entityx/help/NonCopyable.h"
+
+namespace entityx {
+
+typedef std::uint32_t uint32_t;
+typedef std::uint64_t uint64_t;
+
+class EntityManager;
+
+
+template <typename C, typename EM = EntityManager>
+class ComponentHandle;
+
+
+
+/** A convenience handle around an Entity::Id.
+ *
+ * If an entity is destroyed, any copies will be invalidated. Use valid() to
+ * check for validity before using.
+ *
+ * Create entities with `EntityManager`:
+ *
+ * Entity entity = entity_manager->create();
+ */
+class Entity {
+public:
+ struct Id {
+ Id() : id_(0) {}
+ explicit Id(uint64_t id) : id_(id) {}
+ Id(uint32_t index, uint32_t version) : id_(uint64_t(index) | uint64_t(version) << 32UL) {}
+
+ uint64_t id() const { return id_; }
+
+ bool operator == (const Id &other) const { return id_ == other.id_; }
+ bool operator != (const Id &other) const { return id_ != other.id_; }
+ bool operator < (const Id &other) const { return id_ < other.id_; }
+
+ uint32_t index() const { return id_ & 0xffffffffUL; }
+ uint32_t version() const { return id_ >> 32; }
+
+ private:
+ friend class EntityManager;
+
+ uint64_t id_;
+ };
+
+
+ /**
+ * Id of an invalid Entity.
+ */
+ static const Id INVALID;
+
+ Entity() = default;
+ Entity(EntityManager *manager, Entity::Id id) : manager_(manager), id_(id) {}
+ Entity(const Entity &other) = default;
+ Entity &operator = (const Entity &other) = default;
+
+ /**
+ * Check if Entity handle is invalid.
+ */
+ operator bool() const {
+ return valid();
+ }
+
+ bool operator == (const Entity &other) const {
+ return other.manager_ == manager_ && other.id_ == id_;
+ }
+
+ bool operator != (const Entity &other) const {
+ return !(other == *this);
+ }
+
+ bool operator < (const Entity &other) const {
+ return other.id_ < id_;
+ }
+
+ /**
+ * Is this Entity handle valid?
+ *
+ * In older versions of EntityX, there were no guarantees around entity
+ * validity if a previously allocated entity slot was reassigned. That is no
+ * longer the case: if a slot is reassigned, old Entity::Id's will be
+ * invalid.
+ */
+ bool valid() const;
+
+ /**
+ * Invalidate Entity handle, disassociating it from an EntityManager and invalidating its ID.
+ *
+ * Note that this does *not* affect the underlying entity and its
+ * components. Use destroy() to destroy the associated Entity and components.
+ */
+ void invalidate();
+
+ Id id() const { return id_; }
+
+ template <typename C, typename ... Args>
+ ComponentHandle<C> assign(Args && ... args);
+
+ template <typename C>
+ ComponentHandle<C> assign_from_copy(const C &component);
+
+ template <typename C, typename ... Args>
+ ComponentHandle<C> replace(Args && ... args);
+
+ template <typename C>
+ void remove();
+
+ template <typename C, typename = typename std::enable_if<!std::is_const<C>::value>::type>
+ ComponentHandle<C> component();
+
+ template <typename C, typename = typename std::enable_if<std::is_const<C>::value>::type>
+ const ComponentHandle<C, const EntityManager> component() const;
+
+ template <typename ... Components>
+ std::tuple<ComponentHandle<Components>...> components();
+
+ template <typename ... Components>
+ std::tuple<ComponentHandle<const Components, const EntityManager>...> components() const;
+
+ template <typename C>
+ bool has_component() const;
+
+ template <typename A, typename ... Args>
+ void unpack(ComponentHandle<A> &a, ComponentHandle<Args> & ... args);
+
+ /**
+ * Destroy and invalidate this Entity.
+ */
+ void destroy();
+
+ std::bitset<entityx::MAX_COMPONENTS> component_mask() const;
+
+ private:
+ EntityManager *manager_ = nullptr;
+ Entity::Id id_ = INVALID;
+};
+
+
+/**
+ * A ComponentHandle<C> is a wrapper around an instance of a component.
+ *
+ * It provides safe access to components. The handle will be invalidated under
+ * the following conditions:
+ *
+ * - If a component is removed from its host entity.
+ * - If its host entity is destroyed.
+ */
+template <typename C, typename EM>
+class ComponentHandle {
+public:
+ typedef C ComponentType;
+
+ ComponentHandle() : manager_(nullptr) {}
+
+ bool valid() const;
+ operator bool() const;
+
+ C *operator -> ();
+ const C *operator -> () const;
+
+ C &operator * ();
+ const C &operator * () const;
+
+ C *get();
+ const C *get() const;
+
+ /**
+ * Remove the component from its entity and destroy it.
+ */
+ void remove();
+
+ /**
+ * Returns the Entity associated with the component
+ */
+ Entity entity();
+
+ bool operator == (const ComponentHandle<C> &other) const {
+ return manager_ == other.manager_ && id_ == other.id_;
+ }
+
+ bool operator != (const ComponentHandle<C> &other) const {
+ return !(*this == other);
+ }
+
+private:
+ friend class EntityManager;
+
+ ComponentHandle(EM *manager, Entity::Id id) :
+ manager_(manager), id_(id) {}
+
+ EM *manager_;
+ Entity::Id id_;
+};
+
+
+/**
+ * Base component class, only used for insertion into collections.
+ *
+ * Family is used for registration.
+ */
+struct BaseComponent {
+ public:
+ typedef size_t Family;
+
+ // NOTE: Component memory is *always* managed by the EntityManager.
+ // Use Entity::destroy() instead.
+ void operator delete(void *p) { (void)p; fail(); }
+ void operator delete[](void *p) { (void)p; fail(); }
+
+
+ protected:
+ static void fail() {
+#if defined(_HAS_EXCEPTIONS) || defined(__EXCEPTIONS)
+ throw std::bad_alloc();
+#else
+ std::abort();
+#endif
+ }
+
+ static Family family_counter_;
+};
+
+
+/**
+ * Component implementations should inherit from this.
+ *
+ * Components MUST provide a no-argument constructor.
+ * Components SHOULD provide convenience constructors for initializing on assignment to an Entity::Id.
+ *
+ * This is a struct to imply that components should be data-only.
+ *
+ * Usage:
+ *
+ * struct Position : public Component<Position> {
+ * Position(float x = 0.0f, float y = 0.0f) : x(x), y(y) {}
+ *
+ * float x, y;
+ * };
+ *
+ * family() is used for registration.
+ */
+template <typename Derived>
+struct Component : public BaseComponent {
+ public:
+ typedef ComponentHandle<Derived> Handle;
+ typedef ComponentHandle<const Derived, const EntityManager> ConstHandle;
+
+private:
+ friend class EntityManager;
+ /// Used internally for registration.
+ static Family family();
+};
+
+
+/**
+ * Emitted when an entity is added to the system.
+ */
+struct EntityCreatedEvent : public Event<EntityCreatedEvent> {
+ explicit EntityCreatedEvent(Entity entity) : entity(entity) {}
+ virtual ~EntityCreatedEvent();
+
+ Entity entity;
+};
+
+
+/**
+ * Called just prior to an entity being destroyed.
+ */
+struct EntityDestroyedEvent : public Event<EntityDestroyedEvent> {
+ explicit EntityDestroyedEvent(Entity entity) : entity(entity) {}
+ virtual ~EntityDestroyedEvent();
+
+ Entity entity;
+};
+
+
+/**
+ * Emitted when any component is added to an entity.
+ */
+template <typename C>
+struct ComponentAddedEvent : public Event<ComponentAddedEvent<C>> {
+ ComponentAddedEvent(Entity entity, ComponentHandle<C> component) :
+ entity(entity), component(component) {}
+
+ Entity entity;
+ ComponentHandle<C> component;
+};
+
+/**
+ * Emitted when any component is removed from an entity.
+ */
+template <typename C>
+struct ComponentRemovedEvent : public Event<ComponentRemovedEvent<C>> {
+ ComponentRemovedEvent(Entity entity, ComponentHandle<C> component) :
+ entity(entity), component(component) {}
+
+ Entity entity;
+ ComponentHandle<C> component;
+};
+
+/**
+ * Helper class to perform component operations in a typed manner.
+ */
+class BaseComponentHelper {
+public:
+ virtual ~BaseComponentHelper() {}
+ virtual void remove_component(Entity e) = 0;
+ virtual void copy_component_to(Entity source, Entity target) = 0;
+};
+
+template <typename C>
+class ComponentHelper : public BaseComponentHelper {
+public:
+ void remove_component(Entity e) override {
+ e.remove<C>();
+ }
+ void copy_component_to(Entity source, Entity target) override {
+ target.assign_from_copy<C>(*(source.component<C>().get()));
+ }
+};
+
+/**
+ * Manages Entity::Id creation and component assignment.
+ */
+class EntityManager : entityx::help::NonCopyable {
+ public:
+ typedef std::bitset<entityx::MAX_COMPONENTS> ComponentMask;
+
+ explicit EntityManager(EventManager &event_manager);
+ virtual ~EntityManager();
+
+ /// An iterator over a view of the entities in an EntityManager.
+ /// If All is true it will iterate over all valid entities and will ignore the entity mask.
+ template <class Delegate, bool All = false>
+ class ViewIterator : public std::iterator<std::input_iterator_tag, Entity::Id> {
+ public:
+ Delegate &operator ++() {
+ ++i_;
+ next();
+ return *static_cast<Delegate*>(this);
+ }
+ bool operator == (const Delegate& rhs) const { return i_ == rhs.i_; }
+ bool operator != (const Delegate& rhs) const { return i_ != rhs.i_; }
+ Entity operator * () { return Entity(manager_, manager_->create_id(i_)); }
+ const Entity operator * () const { return Entity(manager_, manager_->create_id(i_)); }
+
+ protected:
+ ViewIterator(EntityManager *manager, uint32_t index)
+ : manager_(manager), i_(index), capacity_(manager_->capacity()), free_cursor_(~0UL) {
+ if (All) {
+ std::sort(manager_->free_list_.begin(), manager_->free_list_.end());
+ free_cursor_ = 0;
+ }
+ }
+ ViewIterator(EntityManager *manager, const ComponentMask mask, uint32_t index)
+ : manager_(manager), mask_(mask), i_(index), capacity_(manager_->capacity()), free_cursor_(~0UL) {
+ if (All) {
+ std::sort(manager_->free_list_.begin(), manager_->free_list_.end());
+ free_cursor_ = 0;
+ }
+ }
+
+ void next() {
+ while (i_ < capacity_ && !predicate()) {
+ ++i_;
+ }
+
+ if (i_ < capacity_) {
+ Entity entity = manager_->get(manager_->create_id(i_));
+ static_cast<Delegate*>(this)->next_entity(entity);
+ }
+ }
+
+ inline bool predicate() {
+ return (All && valid_entity()) || (manager_->entity_component_mask_[i_] & mask_) == mask_;
+ }
+
+ inline bool valid_entity() {
+ const std::vector<uint32_t> &free_list = manager_->free_list_;
+ if (free_cursor_ < free_list.size() && free_list[free_cursor_] == i_) {
+ ++free_cursor_;
+ return false;
+ }
+ return true;
+ }
+
+ EntityManager *manager_;
+ ComponentMask mask_;
+ uint32_t i_;
+ size_t capacity_;
+ size_t free_cursor_;
+ };
+
+ template <bool All>
+ class BaseView {
+ public:
+ class Iterator : public ViewIterator<Iterator, All> {
+ public:
+ Iterator(EntityManager *manager,
+ const ComponentMask mask,
+ uint32_t index) : ViewIterator<Iterator, All>(manager, mask, index) {
+ ViewIterator<Iterator, All>::next();
+ }
+
+ void next_entity(Entity &entity) { (void)entity; }
+ };
+
+ Iterator begin() { return Iterator(manager_, mask_, 0); }
+ Iterator end() { return Iterator(manager_, mask_, uint32_t(manager_->capacity())); }
+ const Iterator begin() const { return Iterator(manager_, mask_, 0); }
+ const Iterator end() const { return Iterator(manager_, mask_, manager_->capacity()); }
+
+ private:
+ friend class EntityManager;
+
+ explicit BaseView(EntityManager *manager) : manager_(manager) { mask_.set(); }
+ BaseView(EntityManager *manager, ComponentMask mask) :
+ manager_(manager), mask_(mask) {}
+
+ EntityManager *manager_;
+ ComponentMask mask_;
+ };
+
+ template <bool All, typename ... Components>
+ class TypedView: public BaseView<All> {
+ public:
+ template <typename T> struct identity { typedef T type; };
+
+ void each(typename identity<std::function<void(Entity entity, Components&...)>>::type f) {
+ for (auto it : *this)
+ f(it, *(it.template component<Components>().get())...);
+ }
+
+ private:
+ friend class EntityManager;
+
+ explicit TypedView(EntityManager *manager) : BaseView<All>(manager) {}
+ TypedView(EntityManager *manager, ComponentMask mask) : BaseView<All>(manager, mask) {}
+ };
+
+ template <typename ... Components> using View = TypedView<false, Components...>;
+ typedef BaseView<true> DebugView;
+
+ template <typename ... Components>
+ class UnpackingView {
+ public:
+ struct Unpacker {
+ explicit Unpacker(ComponentHandle<Components> & ... handles) :
+ handles(std::tuple<ComponentHandle<Components> & ...>(handles...)) {}
+
+ void unpack(entityx::Entity &entity) const {
+ unpack_<0, Components...>(entity);
+ }
+
+
+ private:
+ template <int N, typename C>
+ void unpack_(entityx::Entity &entity) const {
+ std::get<N>(handles) = entity.component<C>();
+ }
+
+ template <int N, typename C0, typename C1, typename ... Cn>
+ void unpack_(entityx::Entity &entity) const {
+ std::get<N>(handles) = entity.component<C0>();
+ unpack_<N + 1, C1, Cn...>(entity);
+ }
+
+ std::tuple<ComponentHandle<Components> & ...> handles;
+ };
+
+
+ class Iterator : public ViewIterator<Iterator> {
+ public:
+ Iterator(EntityManager *manager,
+ const ComponentMask mask,
+ uint32_t index,
+ const Unpacker &unpacker) : ViewIterator<Iterator>(manager, mask, index), unpacker_(unpacker) {
+ ViewIterator<Iterator>::next();
+ }
+
+ void next_entity(Entity &entity) {
+ unpacker_.unpack(entity);
+ }
+
+ private:
+ const Unpacker &unpacker_;
+ };
+
+
+ Iterator begin() { return Iterator(manager_, mask_, 0, unpacker_); }
+ Iterator end() { return Iterator(manager_, mask_, static_cast<uint32_t>(manager_->capacity()), unpacker_); }
+ const Iterator begin() const { return Iterator(manager_, mask_, 0, unpacker_); }
+ const Iterator end() const { return Iterator(manager_, mask_, static_cast<uint32_t>(manager_->capacity()), unpacker_); }
+
+
+ private:
+ friend class EntityManager;
+
+ UnpackingView(EntityManager *manager, ComponentMask mask, ComponentHandle<Components> & ... handles) :
+ manager_(manager), mask_(mask), unpacker_(handles...) {}
+
+ EntityManager *manager_;
+ ComponentMask mask_;
+ Unpacker unpacker_;
+ };
+
+ /**
+ * Number of managed entities.
+ */
+ size_t size() const { return entity_component_mask_.size() - free_list_.size(); }
+
+ /**
+ * Current entity capacity.
+ */
+ size_t capacity() const { return entity_component_mask_.size(); }
+
+ /**
+ * Return true if the given entity ID is still valid.
+ */
+ bool valid(Entity::Id id) const {
+ return id.index() < entity_version_.size() && entity_version_[id.index()] == id.version();
+ }
+
+ /**
+ * Create a new Entity::Id.
+ *
+ * Emits EntityCreatedEvent.
+ */
+ Entity create() {
+ uint32_t index, version;
+ if (free_list_.empty()) {
+ index = index_counter_++;
+ accomodate_entity(index);
+ version = entity_version_[index] = 1;
+ } else {
+ index = free_list_.back();
+ free_list_.pop_back();
+ version = entity_version_[index];
+ }
+ Entity entity(this, Entity::Id(index, version));
+ event_manager_.emit<EntityCreatedEvent>(entity);
+ return entity;
+ }
+
+ /**
+ * Create a new Entity by copying another. Copy-constructs each component.
+ *
+ * Emits EntityCreatedEvent.
+ */
+ Entity create_from_copy(Entity original) {
+ assert(original.valid());
+ auto clone = create();
+ auto mask = original.component_mask();
+ for (size_t i = 0; i < component_helpers_.size(); i++) {
+ BaseComponentHelper *helper = component_helpers_[i];
+ if (helper && mask.test(i))
+ helper->copy_component_to(original, clone);
+ }
+ return clone;
+ }
+
+
+ /**
+ * Destroy an existing Entity::Id and its associated Components.
+ *
+ * Emits EntityDestroyedEvent.
+ */
+ void destroy(Entity::Id entity) {
+ assert_valid(entity);
+ uint32_t index = entity.index();
+ auto mask = entity_component_mask_[index];
+ for (size_t i = 0; i < component_helpers_.size(); i++) {
+ BaseComponentHelper *helper = component_helpers_[i];
+ if (helper && mask.test(i))
+ helper->remove_component(Entity(this, entity));
+ }
+ event_manager_.emit<EntityDestroyedEvent>(Entity(this, entity));
+ entity_component_mask_[index].reset();
+ entity_version_[index]++;
+ free_list_.push_back(index);
+ }
+
+ Entity get(Entity::Id id) {
+ assert_valid(id);
+ return Entity(this, id);
+ }
+
+ /**
+ * Create an Entity::Id for a slot.
+ *
+ * NOTE: Does *not* check for validity, but the Entity::Id constructor will
+ * fail if the ID is invalid.
+ */
+ Entity::Id create_id(uint32_t index) const {
+ return Entity::Id(index, entity_version_[index]);
+ }
+
+ /**
+ * Assign a Component to an Entity::Id, passing through Component constructor arguments.
+ *
+ * Position &position = em.assign<Position>(e, x, y);
+ *
+ * @returns Smart pointer to newly created component.
+ */
+ template <typename C, typename ... Args>
+ ComponentHandle<C> assign(Entity::Id id, Args && ... args) {
+ assert_valid(id);
+ const BaseComponent::Family family = component_family<C>();
+ assert(!entity_component_mask_[id.index()].test(family));
+
+ // Placement new into the component pool.
+ Pool<C> *pool = accomodate_component<C>();
+ ::new(pool->get(id.index())) C(std::forward<Args>(args) ...);
+
+ // Set the bit for this component.
+ entity_component_mask_[id.index()].set(family);
+
+ // Create and return handle.
+ ComponentHandle<C> component(this, id);
+ event_manager_.emit<ComponentAddedEvent<C>>(Entity(this, id), component);
+ return component;
+ }
+
+ /**
+ * Remove a Component from an Entity::Id
+ *
+ * Emits a ComponentRemovedEvent<C> event.
+ */
+ template <typename C>
+ void remove(Entity::Id id) {
+ assert_valid(id);
+ const BaseComponent::Family family = component_family<C>();
+ const uint32_t index = id.index();
+
+ // Find the pool for this component family.
+ BasePool *pool = component_pools_[family];
+ ComponentHandle<C> component(this, id);
+ event_manager_.emit<ComponentRemovedEvent<C>>(Entity(this, id), component);
+
+ // Remove component bit.
+ entity_component_mask_[id.index()].reset(family);
+
+ // Call destructor.
+ pool->destroy(index);
+ }
+
+ /**
+ * Check if an Entity has a component.
+ */
+ template <typename C>
+ bool has_component(Entity::Id id) const {
+ assert_valid(id);
+ size_t family = component_family<C>();
+ // We don't bother checking the component mask, as we return a nullptr anyway.
+ if (family >= component_pools_.size())
+ return false;
+ BasePool *pool = component_pools_[family];
+ if (!pool || !entity_component_mask_[id.index()][family])
+ return false;
+ return true;
+ }
+
+ /**
+ * Retrieve a Component assigned to an Entity::Id.
+ *
+ * @returns Pointer to an instance of C, or nullptr if the Entity::Id does not have that Component.
+ */
+ template <typename C, typename = typename std::enable_if<!std::is_const<C>::value>::type>
+ ComponentHandle<C> component(Entity::Id id) {
+ assert_valid(id);
+ size_t family = component_family<C>();
+ // We don't bother checking the component mask, as we return a nullptr anyway.
+ if (family >= component_pools_.size())
+ return ComponentHandle<C>();
+ BasePool *pool = component_pools_[family];
+ if (!pool || !entity_component_mask_[id.index()][family])
+ return ComponentHandle<C>();
+ return ComponentHandle<C>(this, id);
+ }
+
+ /**
+ * Retrieve a Component assigned to an Entity::Id.
+ *
+ * @returns Component instance, or nullptr if the Entity::Id does not have that Component.
+ */
+ template <typename C, typename = typename std::enable_if<std::is_const<C>::value>::type>
+ const ComponentHandle<C, const EntityManager> component(Entity::Id id) const {
+ assert_valid(id);
+ size_t family = component_family<C>();
+ // We don't bother checking the component mask, as we return a nullptr anyway.
+ if (family >= component_pools_.size())
+ return ComponentHandle<C, const EntityManager>();
+ BasePool *pool = component_pools_[family];
+ if (!pool || !entity_component_mask_[id.index()][family])
+ return ComponentHandle<C, const EntityManager>();
+ return ComponentHandle<C, const EntityManager>(this, id);
+ }
+
+ template <typename ... Components>
+ std::tuple<ComponentHandle<Components>...> components(Entity::Id id) {
+ return std::make_tuple(component<Components>(id)...);
+ }
+
+ template <typename ... Components>
+ std::tuple<ComponentHandle<const Components, const EntityManager>...> components(Entity::Id id) const {
+ return std::make_tuple(component<const Components>(id)...);
+ }
+
+ /**
+ * Find Entities that have all of the specified Components.
+ *
+ * @code
+ * for (Entity entity : entity_manager.entities_with_components<Position, Direction>()) {
+ * ComponentHandle<Position> position = entity.component<Position>();
+ * ComponentHandle<Direction> direction = entity.component<Direction>();
+ *
+ * ...
+ * }
+ * @endcode
+ */
+ template <typename ... Components>
+ View<Components...> entities_with_components() {
+ auto mask = component_mask<Components ...>();
+ return View<Components...>(this, mask);
+ }
+
+ template <typename T> struct identity { typedef T type; };
+
+ template <typename ... Components>
+ void each(typename identity<std::function<void(Entity entity, Components&...)>>::type f) {
+ return entities_with_components<Components...>().each(f);
+ }
+
+ /**
+ * Find Entities that have all of the specified Components and assign them
+ * to the given parameters.
+ *
+ * @code
+ * ComponentHandle<Position> position;
+ * ComponentHandle<Direction> direction;
+ * for (Entity entity : entity_manager.entities_with_components(position, direction)) {
+ * // Use position and component here.
+ * }
+ * @endcode
+ */
+ template <typename ... Components>
+ UnpackingView<Components...> entities_with_components(ComponentHandle<Components> & ... components) {
+ auto mask = component_mask<Components...>();
+ return UnpackingView<Components...>(this, mask, components...);
+ }
+
+ /**
+ * Iterate over all *valid* entities (ie. not in the free list). Not fast,
+ * so should only be used for debugging.
+ *
+ * @code
+ * for (Entity entity : entity_manager.entities_for_debugging()) {}
+ *
+ * @return An iterator view over all valid entities.
+ */
+ DebugView entities_for_debugging() {
+ return DebugView(this);
+ }
+
+ template <typename C>
+ void unpack(Entity::Id id, ComponentHandle<C> &a) {
+ assert_valid(id);
+ a = component<C>(id);
+ }
+
+ /**
+ * Unpack components directly into pointers.
+ *
+ * Components missing from the entity will be set to nullptr.
+ *
+ * Useful for fast bulk iterations.
+ *
+ * ComponentHandle<Position> p;
+ * ComponentHandle<Direction> d;
+ * unpack<Position, Direction>(e, p, d);
+ */
+ template <typename A, typename ... Args>
+ void unpack(Entity::Id id, ComponentHandle<A> &a, ComponentHandle<Args> & ... args) {
+ assert_valid(id);
+ a = component<A>(id);
+ unpack<Args ...>(id, args ...);
+ }
+
+ /**
+ * Destroy all entities and reset the EntityManager.
+ */
+ void reset();
+
+ // Retrieve the component family for a type.
+ template <typename C>
+ static BaseComponent::Family component_family() {
+ return Component<typename std::remove_const<C>::type>::family();
+ }
+
+ private:
+ friend class Entity;
+ template <typename C, typename EM>
+ friend class ComponentHandle;
+
+
+ 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");
+ }
+
+ template <typename C>
+ C *get_component_ptr(Entity::Id id) {
+ assert(valid(id));
+ BasePool *pool = component_pools_[component_family<C>()];
+ assert(pool);
+ return static_cast<C*>(pool->get(id.index()));
+ }
+
+ template <typename C>
+ const C *get_component_ptr(Entity::Id id) const {
+ assert_valid(id);
+ BasePool *pool = component_pools_[component_family<C>()];
+ assert(pool);
+ return static_cast<const C*>(pool->get(id.index()));
+ }
+
+ ComponentMask component_mask(Entity::Id id) {
+ assert_valid(id);
+ return entity_component_mask_.at(id.index());
+ }
+
+ template <typename C>
+ ComponentMask component_mask() {
+ ComponentMask mask;
+ mask.set(component_family<C>());
+ return mask;
+ }
+
+ template <typename C1, typename C2, typename ... Components>
+ ComponentMask component_mask() {
+ return component_mask<C1>() | component_mask<C2, Components ...>();
+ }
+
+ template <typename C>
+ ComponentMask component_mask(const ComponentHandle<C> &c) {
+ return component_mask<C>();
+ }
+
+ template <typename C1, typename ... Components>
+ ComponentMask component_mask(const ComponentHandle<C1> &c1, const ComponentHandle<Components> &... args) {
+ return component_mask<C1, Components ...>();
+ }
+
+ inline void accomodate_entity(uint32_t index) {
+ if (entity_component_mask_.size() <= index) {
+ entity_component_mask_.resize(index + 1);
+ entity_version_.resize(index + 1);
+ for (BasePool *pool : component_pools_)
+ if (pool) pool->expand(index + 1);
+ }
+ }
+
+ template <typename C>
+ Pool<C> *accomodate_component() {
+ BaseComponent::Family family = component_family<C>();
+ if (component_pools_.size() <= family) {
+ component_pools_.resize(family + 1, nullptr);
+ }
+ if (!component_pools_[family]) {
+ Pool<C> *pool = new Pool<C>();
+ pool->expand(index_counter_);
+ component_pools_[family] = pool;
+ }
+ if (component_helpers_.size() <= family) {
+ component_helpers_.resize(family + 1, nullptr);
+ }
+ if (!component_helpers_[family]) {
+ ComponentHelper<C> *helper = new ComponentHelper<C>();
+ component_helpers_[family] = helper;
+ }
+ return static_cast<Pool<C>*>(component_pools_[family]);
+ }
+
+
+ uint32_t index_counter_ = 0;
+
+ EventManager &event_manager_;
+ // Each element in component_pools_ corresponds to a Pool for a Component.
+ // The index into the vector is the Component::family().
+ std::vector<BasePool*> component_pools_;
+ // Each element in component_helpers_ corresponds to a ComponentHelper for a Component type.
+ // The index into the vector is the Component::family().
+ std::vector<BaseComponentHelper*> component_helpers_;
+ // Bitmask of components associated with each entity. Index into the vector is the Entity::Id.
+ std::vector<ComponentMask> entity_component_mask_;
+ // Vector of entity version numbers. Incremented each time an entity is destroyed
+ std::vector<uint32_t> entity_version_;
+ // List of available entity slots.
+ std::vector<uint32_t> free_list_;
+};
+
+
+template <typename C>
+BaseComponent::Family Component<C>::family() {
+ static Family family = family_counter_++;
+ assert(family < entityx::MAX_COMPONENTS);
+ return family;
+}
+
+
+template <typename C, typename ... Args>
+ComponentHandle<C> Entity::assign(Args && ... args) {
+ assert(valid());
+ return manager_->assign<C>(id_, std::forward<Args>(args) ...);
+}
+
+template <typename C>
+ComponentHandle<C> Entity::assign_from_copy(const C &component) {
+ assert(valid());
+ return manager_->assign<C>(id_, std::forward<const C &>(component));
+}
+
+template <typename C, typename ... Args>
+ComponentHandle<C> Entity::replace(Args && ... args) {
+ assert(valid());
+ auto handle = component<C>();
+ if (handle) {
+ *(handle.get()) = C(std::forward<Args>(args) ...);
+ } else {
+ handle = manager_->assign<C>(id_, std::forward<Args>(args) ...);
+ }
+ return handle;
+}
+
+template <typename C>
+void Entity::remove() {
+ assert(valid() && has_component<C>());
+ manager_->remove<C>(id_);
+}
+
+template <typename C, typename>
+ComponentHandle<C> Entity::component() {
+ assert(valid());
+ return manager_->component<C>(id_);
+}
+
+ template <typename C, typename>
+const ComponentHandle<C, const EntityManager> Entity::component() const {
+ assert(valid());
+ return const_cast<const EntityManager*>(manager_)->component<const C>(id_);
+}
+
+template <typename ... Components>
+std::tuple<ComponentHandle<Components>...> Entity::components() {
+ assert(valid());
+ return manager_->components<Components...>(id_);
+}
+
+template <typename ... Components>
+std::tuple<ComponentHandle<const Components, const EntityManager>...> Entity::components() const {
+ assert(valid());
+ return const_cast<const EntityManager*>(manager_)->components<const Components...>(id_);
+}
+
+
+template <typename C>
+bool Entity::has_component() const {
+ assert(valid());
+ return manager_->has_component<C>(id_);
+}
+
+template <typename A, typename ... Args>
+void Entity::unpack(ComponentHandle<A> &a, ComponentHandle<Args> & ... args) {
+ assert(valid());
+ manager_->unpack(id_, a, args ...);
+}
+
+inline bool Entity::valid() const {
+ return manager_ && manager_->valid(id_);
+}
+
+inline std::ostream &operator << (std::ostream &out, const Entity::Id &id) {
+ out << "Entity::Id(" << id.index() << "." << id.version() << ")";
+ return out;
+}
+
+
+inline std::ostream &operator << (std::ostream &out, const Entity &entity) {
+ out << "Entity(" << entity.id() << ")";
+ return out;
+}
+
+
+template <typename C, typename EM>
+inline ComponentHandle<C, EM>::operator bool() const {
+ return valid();
+}
+
+template <typename C, typename EM>
+inline bool ComponentHandle<C, EM>::valid() const {
+ return manager_ && manager_->valid(id_) && manager_->template has_component<C>(id_);
+}
+
+template <typename C, typename EM>
+inline C *ComponentHandle<C, EM>::operator -> () {
+ assert(valid());
+ return manager_->template get_component_ptr<C>(id_);
+}
+
+template <typename C, typename EM>
+inline const C *ComponentHandle<C, EM>::operator -> () const {
+ assert(valid());
+ return manager_->template get_component_ptr<C>(id_);
+}
+
+template <typename C, typename EM>
+inline C &ComponentHandle<C, EM>::operator * () {
+ assert(valid());
+ return *manager_->template get_component_ptr<C>(id_);
+}
+
+template <typename C, typename EM>
+inline const C &ComponentHandle<C, EM>::operator * () const {
+ assert(valid());
+ return *manager_->template get_component_ptr<C>(id_);
+}
+
+template <typename C, typename EM>
+inline C *ComponentHandle<C, EM>::get() {
+ assert(valid());
+ return manager_->template get_component_ptr<C>(id_);
+}
+
+template <typename C, typename EM>
+inline const C *ComponentHandle<C, EM>::get() const {
+ assert(valid());
+ return manager_->template get_component_ptr<C>(id_);
+}
+
+template <typename C, typename EM>
+inline void ComponentHandle<C, EM>::remove() {
+ assert(valid());
+ manager_->template remove<C>(id_);
+}
+
+template <typename C, typename EM>
+inline Entity ComponentHandle<C, EM>::entity() {
+ assert(valid());
+ return manager_->get(id_);
+}
+
+
+} // namespace entityx
+
+
+namespace std {
+template <> struct hash<entityx::Entity> {
+ std::size_t operator () (const entityx::Entity &entity) const {
+ return static_cast<std::size_t>(entity.id().index() ^ entity.id().version());
+ }
+};
+
+template <> struct hash<const entityx::Entity> {
+ std::size_t operator () (const entityx::Entity &entity) const {
+ return static_cast<std::size_t>(entity.id().index() ^ entity.id().version());
+ }
+};
+}
+