aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlec Thomas <alec@swapoff.org>2014-03-02 15:59:44 +1100
committerAlec Thomas <alec@swapoff.org>2014-03-02 16:22:06 +1100
commitf21209417a2c4b3c874d8f58b653489c5cb2494f (patch)
tree643f480e759adedd402a0fa6ad97c2fd798e7179
parent644d0560c925fa9068b6d03b199c63387ceb9352 (diff)
Removed Manager. Add EntityX class. Largely eradicate use of shared_ptr.
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md55
-rw-r--r--entityx/Benchmarks_test.cc22
-rw-r--r--entityx/Entity.cc8
-rw-r--r--entityx/Entity.h136
-rw-r--r--entityx/Entity_test.cc98
-rw-r--r--entityx/Event.h15
-rw-r--r--entityx/Event_test.cc30
-rw-r--r--entityx/Manager.cc41
-rw-r--r--entityx/Manager.h83
-rw-r--r--entityx/System.cc4
-rw-r--r--entityx/System.h52
-rw-r--r--entityx/System_test.cc46
-rw-r--r--entityx/config.h.in44
-rw-r--r--entityx/deps/Dependencies.cc11
-rw-r--r--entityx/deps/Dependencies.h6
-rw-r--r--entityx/deps/Dependencies_test.cc31
-rw-r--r--entityx/entityx.h1
-rw-r--r--entityx/tags/TagsComponent.cc11
-rw-r--r--entityx/tags/TagsComponent.h13
-rw-r--r--entityx/tags/TagsComponent_test.cc10
21 files changed, 274 insertions, 445 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f996eb9..1b6efb6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -122,7 +122,7 @@ endif()
# Things to install
set(install_libs entityx)
-set(sources entityx/tags/TagsComponent.cc entityx/deps/Dependencies.cc entityx/System.cc entityx/Event.cc entityx/Entity.cc entityx/Manager.cc entityx/help/Timer.cc)
+set(sources entityx/System.cc entityx/Event.cc entityx/Entity.cc entityx/help/Timer.cc)
add_library(entityx STATIC ${sources})
if (ENTITYX_BUILD_SHARED)
diff --git a/README.md b/README.md
index ee1fe5e..3bb4547 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,7 @@ You can also contact me directly via [email](mailto:alec@swapoff.org) or [Twitte
## Recent Notable Changes
+- 2014-03-02 - (1.0.0alpha1) Switch to using cache friendly component storage (big breaking change). Also largely eradicated use of `std::shared_ptr`.
- 2014-02-13 - Visual C++ support thanks to [Jarrett Chisholm](https://github.com/jarrettchisholm)!
- 2013-10-29 - Boost has been removed as a primary dependency for builds not using python.
- 2013-08-21 - Remove dependency on `boost::signal` and switch to embedded [Simple::Signal](http://timj.testbit.eu/2013/cpp11-signal-system-performance/).
@@ -58,10 +59,11 @@ An `entityx::Entity` is a convenience class wrapping an opaque `uint64_t` value
Creating an entity is as simple as:
```c++
-entityx::ptr<entityx::EventManager> events(new entityx::EventManager());
-entityx::ptr<entityx::EntityManager> entities(new entityx::EntityManager(event));
+#include <entityx/entityx.h>
-entityx::Entity entity = entities->create();
+EntityX entityx;
+
+entityx::Entity entity = entityx.entities.create();
```
And destroying an entity is done with:
@@ -75,13 +77,13 @@ entity.destroy();
- Each `entityx::Entity` is a convenience class wrapping an `entityx::Entity::Id`.
- An `entityx::Entity` handle can be invalidated with `invalidate()`. This does not affect the underlying entity.
- When an entity is destroyed the manager adds its ID to a free list and invalidates the `entityx::Entity` handle.
-- When an entity is created IDs are recycled from the free list before allocating new ones.
+- When an entity is created IDs are recycled from the free list first, before allocating new ones.
- An `entityx::Entity` ID contains an index and a version. When an entity is destroyed, the version associated with the index is incremented, invalidating all previous entities referencing the previous ID.
-- EntityX uses a reference counting smart pointer`entityx::ptr<T>` to manage object lifetimes. As a general rule, passing a pointer to any EntityX method will convert to a smart pointer and take ownership. To maintain your own reference to the pointer you will need to wrap it in `entityx::ptr<T>`.
+- To improve cache coherence, components are constructed in contiguous memory ranges by using `entityx::EntityManager::assign<C>(id, ...)`. A light weight smart pointer (`ComponentPtr<C>`) is used to access the component.
### Components (entity data)
-The general idea with the EntityX interpretation of ECS is to have as little functionality in components as possible. All logic should be contained in Systems.
+The general idea with the EntityX interpretation of ECS is to have as little logic in components as possible. All logic should be contained in Systems.
To that end Components are typically [POD types](http://en.wikipedia.org/wiki/Plain_Old_Data_Structures) consisting of self-contained sets of related data. Implementations are [curiously recurring template pattern](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) (CRTP) subclasses of `entityx::Component<T>`.
@@ -112,21 +114,14 @@ To associate a component with a previously created entity call ``entityx::Entity
entity.assign<Position>(1.0f, 2.0f);
```
-You can also assign existing instances of components:
-
-```c++
-entityx::ptr<Position> position(new Position(1.0f, 2.0f));
-entity.assign(position);
-```
-
#### Querying entities and their components
To query all entities with a set of components assigned, use ``entityx::EntityManager::entities_with_components()``. This method will return only those entities that have *all* of the specified components associated with them, assigning each component pointer to the corresponding component instance:
```c++
-for (auto entity : entities->entities_with_components<Position, Direction>()) {
- entityx::ptr<Position> position = entity.component<Position>();
- entityx::ptr<Direction> direction = entity.component<Direction>();
+for (Entity entity : entities.entities_with_components<Position, Direction>()) {
+ ComponentPtr<Position> position = entity.component<Position>();
+ ComponentPtr<Direction> direction = entity.component<Direction>();
// Do things with entity, position and direction.
}
@@ -135,7 +130,7 @@ for (auto entity : entities->entities_with_components<Position, Direction>()) {
To retrieve a component associated with an entity use ``entityx::Entity::component<C>()``:
```c++
-entityx::ptr<Position> position = entity.component<Position>();
+ComponentPtr<Position> position = entity.component<Position>();
if (position) {
// Do stuff with position
}
@@ -166,10 +161,10 @@ A basic movement system might be implemented with something like the following:
```c++
struct MovementSystem : public System<MovementSystem> {
- void update(entityx::ptr<entityx::EntityManager> es, entityx::ptr<entityx::EventManager> events, double dt) override {
- for (auto entity : es->entities_with_components<Position, Direction>()) {
- entityx::ptr<Position> position = entity.component<Position>();
- entityx::ptr<Direction> direction = entity.component<Direction>();
+ void update(entityx::EntityManager &es, entityx::EventManager &events, double dt) override {
+ for (Entity entity : es.entities_with_components<Position, Direction>()) {
+ ComponentPtr<Position> position = entity.component<Position>();
+ ComponentPtr<Direction> direction = entity.component<Direction>();
position->x += direction->x * dt;
position->y += direction->y * dt;
@@ -204,10 +199,10 @@ Next we implement our collision system, which emits ``Collision`` objects via an
```c++
class CollisionSystem : public System<CollisionSystem> {
public:
- void update(entityx::ptr<entityx::EntityManager> es, entityx::ptr<entityx::EventManager> events, double dt) override {
- entityx::ptr<Position> left_position, right_position;
- for (auto left_entity : es->entities_with_components<Position>(left_position)) {
- for (auto right_entity : es->entities_with_components<Position>(right_position)) {
+ void update(entityx::EntityManager &es, entityx::EventManager &events, double dt) override {
+ ComponentPtr<Position> left_position, right_position;
+ for (Entity left_entity : es.entities_with_components<Position>(left_position)) {
+ for (auto right_entity : es.entities_with_components<Position>(right_position)) {
if (collide(left_position, right_position)) {
events->emit<Collision>(left_entity, right_entity);
}
@@ -223,11 +218,11 @@ Objects interested in receiving collision information can subscribe to ``Collisi
```c++
struct DebugSystem : public System<DebugSystem>, Receiver<DebugSystem> {
- void configure(entityx::ptr<entityx::EventManager> event_manager) {
- event_manager->subscribe<Collision>(*this);
+ void configure(entityx::EventManager &event_manager) {
+ event_manager.subscribe<Collision>(*this);
}
- void update(ptr<entityx::EntityManager> entities, ptr<entityx::EventManager> events, double dt) {}
+ void update(entityx::EntityManager &entities, entityx::EventManager &events, double dt) {}
void receive(const Collision &collision) {
LOG(DEBUG) << "entities collided: " << collision.left << " and " << collision.right << endl;
@@ -245,10 +240,10 @@ Several events are emitted by EntityX itself:
- `entityx::Entity entity` - entityx::Entity about to be destroyed.
- `ComponentAddedEvent<T>` - emitted when a new component is added to an entity.
- `entityx::Entity entity` - entityx::Entity that component was added to.
- - `entityx::ptr<T> component` - The component added.
+ - `ComponentPtr<T> component` - The component added.
- `ComponentRemovedEvent<T>` - emitted when a component is removed from an entity.
- `entityx::Entity entity` - entityx::Entity that component was removed from.
- - `entityx::ptr<T> component` - The component removed.
+ - `ComponentPtr<T> component` - The component removed.
#### Implementation notes
diff --git a/entityx/Benchmarks_test.cc b/entityx/Benchmarks_test.cc
index 2790ae0..084b7bd 100644
--- a/entityx/Benchmarks_test.cc
+++ b/entityx/Benchmarks_test.cc
@@ -19,10 +19,10 @@ private:
class BenchmarksTest : public ::testing::Test {
protected:
- BenchmarksTest() : ev(EventManager::make()), em(EntityManager::make(ev)) {}
+ BenchmarksTest() : em(ev) {}
- ptr<EventManager> ev;
- ptr<EntityManager> em;
+ EventManager ev;
+ EntityManager em;
};
@@ -33,7 +33,7 @@ TEST_F(BenchmarksTest, TestCreateEntities) {
cout << "creating " << count << " entities" << endl;
for (uint64_t i = 0; i < count; i++) {
- em->create();
+ em.create();
}
}
@@ -42,7 +42,7 @@ TEST_F(BenchmarksTest, TestDestroyEntities) {
uint64_t count = 10000000L;
vector<Entity> entities;
for (uint64_t i = 0; i < count; i++) {
- entities.push_back(em->create());
+ entities.push_back(em.create());
}
AutoTimer t;
@@ -60,7 +60,7 @@ struct Listener : public Receiver<Listener> {
TEST_F(BenchmarksTest, TestCreateEntitiesWithListener) {
Listener listen;
- ev->subscribe<EntityCreatedEvent>(listen);
+ ev.subscribe<EntityCreatedEvent>(listen);
uint64_t count = 10000000L;
@@ -69,18 +69,18 @@ TEST_F(BenchmarksTest, TestCreateEntitiesWithListener) {
vector<Entity> entities;
for (uint64_t i = 0; i < count; i++) {
- entities.push_back(em->create());
+ entities.push_back(em.create());
}
}
TEST_F(BenchmarksTest, TestDestroyEntitiesWithListener) {
Listener listen;
- ev->subscribe<EntityDestroyedEvent>(listen);
+ ev.subscribe<EntityDestroyedEvent>(listen);
uint64_t count = 10000000L;
vector<Entity> entities;
for (uint64_t i = 0; i < count; i++) {
- entities.push_back(em->create());
+ entities.push_back(em.create());
}
AutoTimer t;
@@ -98,7 +98,7 @@ TEST_F(BenchmarksTest, TestEntityIteration) {
uint64_t count = 10000000L;
vector<Entity> entities;
for (uint64_t i = 0; i < count; i++) {
- auto e = em->create();
+ auto e = em.create();
e.assign<Position>();
entities.push_back(e);
}
@@ -108,7 +108,7 @@ TEST_F(BenchmarksTest, TestEntityIteration) {
for (int i = 0; i < 10; ++i) {
ComponentPtr<Position> position;
- for (auto e : em->entities_with_components<Position>(position)) {
+ for (auto e : em.entities_with_components<Position>(position)) {
}
}
}
diff --git a/entityx/Entity.cc b/entityx/Entity.cc
index f23e974..ffdfbee 100644
--- a/entityx/Entity.cc
+++ b/entityx/Entity.cc
@@ -18,20 +18,20 @@ BaseComponent::Family BaseComponent::family_counter_ = 0;
void Entity::invalidate() {
id_ = INVALID;
- manager_.reset();
+ manager_ = nullptr;
}
void Entity::destroy() {
assert(valid());
- manager_.lock()->destroy(id_);
+ manager_->destroy(id_);
invalidate();
}
std::bitset<entityx::MAX_COMPONENTS> Entity::component_mask() const {
- return manager_.lock()->component_mask(id_);
+ return manager_->component_mask(id_);
}
-EntityManager::EntityManager(ptr<EventManager> event_manager) : event_manager_(event_manager) {
+EntityManager::EntityManager(EventManager &event_manager) : event_manager_(event_manager) {
}
EntityManager::~EntityManager() {
diff --git a/entityx/Entity.h b/entityx/Entity.h
index 141f2e6..18f04b8 100644
--- a/entityx/Entity.h
+++ b/entityx/Entity.h
@@ -19,6 +19,7 @@
#include <iostream>
#include <iterator>
#include <list>
+#include <memory>
#include <set>
#include <string>
#include <utility>
@@ -76,7 +77,7 @@ public:
static const Id INVALID;
Entity() {}
- Entity(const ptr<EntityManager> &manager, Entity::Id id) : manager_(manager), id_(id) {}
+ Entity(EntityManager *manager, Entity::Id id) : manager_(manager), id_(id) {}
Entity(const Entity &other) : manager_(other.manager_), id_(other.id_) {}
Entity &operator = (const Entity &other) {
@@ -142,7 +143,7 @@ public:
std::bitset<entityx::MAX_COMPONENTS> component_mask() const;
private:
- weak_ptr<EntityManager> manager_;
+ EntityManager *manager_ = nullptr;
Entity::Id id_ = INVALID;
};
@@ -221,6 +222,8 @@ private:
friend class EntityManager;
ComponentPtr(Entity::Id id, EntityManager *manager) : id_(id), manager_(manager) {}
+ ComponentPtr(Entity::Id id, const EntityManager *manager) :
+ id_(id), manager_(const_cast<EntityManager*>(manager)) {}
T *get_component_ptr();
const T *get_component_ptr() const;
@@ -351,36 +354,16 @@ public:
/**
* Manages Entity::Id creation and component assignment.
*/
-class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this<EntityManager> {
+class EntityManager : entityx::help::NonCopyable {
public:
typedef std::bitset<entityx::MAX_COMPONENTS> ComponentMask;
- explicit EntityManager(ptr<EventManager> event_manager);
+ explicit EntityManager(EventManager &event_manager);
virtual ~EntityManager();
- static ptr<EntityManager> make(ptr<EventManager> event_manager) {
- return ptr<EntityManager>(new EntityManager(event_manager));
- }
-
class View {
public:
- typedef std::function<bool (const ptr<EntityManager> &, const Entity::Id &)> Predicate;
-
- /// 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 ptr<EntityManager> &entities, const Entity::Id &entity) {
- return entities->entity_version_[entity.index()] == entity.version()
- && (entity_component_masks_[entity.index()] & mask_) == mask_;
- }
-
- private:
- const std::vector<ComponentMask> &entity_component_masks_;
- ComponentMask mask_;
- };
+ typedef std::function<bool (const EntityManager &, const Entity::Id &)> Predicate;
struct BaseUnpacker {
virtual ~BaseUnpacker() {}
@@ -403,9 +386,9 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
private:
friend class View;
- Iterator(ptr<EntityManager> manager,
+ Iterator(EntityManager *manager,
const std::vector<Predicate> &predicates,
- const std::vector<ptr<BaseUnpacker>> &unpackers,
+ const std::vector<std::shared_ptr<BaseUnpacker>> &unpackers,
uint32_t index)
: manager_(manager), predicates_(predicates), unpackers_(unpackers), i_(index), capacity_(manager_->capacity()) {
next();
@@ -427,16 +410,16 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
bool predicate() {
Entity::Id id = manager_->create_id(i_);
for (auto &p : predicates_) {
- if (!p(manager_, id)) {
+ if (!p(*manager_, id)) {
return false;
}
}
return true;
}
- ptr<EntityManager> manager_;
+ EntityManager *manager_;
std::vector<Predicate> predicates_;
- std::vector<ptr<BaseUnpacker>> unpackers_;
+ std::vector<std::shared_ptr<BaseUnpacker>> unpackers_;
uint32_t i_;
size_t capacity_;
};
@@ -453,7 +436,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
template <typename A>
View &unpack_to(ComponentPtr<A> &a) {
- unpackers_.push_back(ptr<Unpacker<A>>(new Unpacker<A>(manager_, a)));
+ unpackers_.push_back(std::shared_ptr<Unpacker<A>>(new Unpacker<A>(manager_, a)));
return *this;
}
@@ -468,24 +451,24 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
template <typename T>
struct Unpacker : BaseUnpacker {
- Unpacker(ptr<EntityManager> manager, ComponentPtr<T> &c) : manager_(manager), c(c) {}
+ Unpacker(EntityManager *manager, ComponentPtr<T> &c) : manager_(manager), c(c) {}
void unpack(const Entity::Id &id) {
c = manager_->component<T>(id);
}
private:
- ptr<EntityManager> manager_;
+ EntityManager *manager_;
ComponentPtr<T> &c;
};
- View(ptr<EntityManager> manager, Predicate predicate) : manager_(manager) {
+ View(EntityManager *manager, Predicate predicate) : manager_(manager) {
predicates_.push_back(predicate);
}
- ptr<EntityManager> manager_;
+ EntityManager *manager_;
std::vector<Predicate> predicates_;
- std::vector<ptr<BaseUnpacker>> unpackers_;
+ std::vector<std::shared_ptr<BaseUnpacker>> unpackers_;
};
/**
@@ -521,8 +504,8 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
free_list_.pop_front();
version = entity_version_[index];
}
- Entity entity(shared_from_this(), Entity::Id(index, version));
- event_manager_->emit<EntityCreatedEvent>(entity);
+ Entity entity(this, Entity::Id(index, version));
+ event_manager_.emit<EntityCreatedEvent>(entity);
return entity;
}
@@ -534,7 +517,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
void destroy(Entity::Id entity) {
assert_valid(entity);
int index = entity.index();
- event_manager_->emit<EntityDestroyedEvent>(Entity(shared_from_this(), entity));
+ event_manager_.emit<EntityDestroyedEvent>(Entity(this, entity));
for (BaseComponentAllocator *allocator : component_allocators_) {
if (allocator) allocator->destroy(index);
}
@@ -545,7 +528,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
Entity get(Entity::Id id) {
assert_valid(id);
- return Entity(shared_from_this(), id);
+ return Entity(this, id);
}
/**
@@ -573,7 +556,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
new(allocator->get(id.index())) C(std::forward<Args>(args) ...);
entity_component_mask_[id.index()] |= uint64_t(1) << family;
ComponentPtr<C> component(id, this);
- event_manager_->emit<ComponentAddedEvent<C>>(Entity(shared_from_this(), id), component);
+ event_manager_.emit<ComponentAddedEvent<C>>(Entity(this, id), component);
return ComponentPtr<C>(id, this);
}
@@ -591,14 +574,14 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
assert(allocator);
entity_component_mask_[id.index()] &= ~(uint64_t(1) << family);
ComponentPtr<C> component(id, this);
- event_manager_->emit<ComponentRemovedEvent<C>>(Entity(shared_from_this(), id), component);
+ event_manager_.emit<ComponentRemovedEvent<C>>(Entity(this, id), component);
allocator->destroy(index);
}
/**
* Retrieve a Component assigned to an Entity::Id.
*
- * @returns Component instance, or empty ptr<> if the Entity::Id does not have that Component.
+ * @returns Component instance, or empty ComponentPtr<> if the Entity::Id does not have that Component.
*/
template <typename C>
ComponentPtr<C> component(Entity::Id id) {
@@ -614,23 +597,58 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
}
/**
+ * Retrieve a Component assigned to an Entity::Id.
+ *
+ * @returns Component instance, or empty ComponentPtr<> if the Entity::Id does not have that Component.
+ */
+ template <typename C>
+ ComponentPtr<const C> component(Entity::Id id) const {
+ assert_valid(id);
+ size_t family = C::family();
+ // We don't bother checking the component mask, as we return a nullptr anyway.
+ if (family >= component_allocators_.size())
+ return ComponentPtr<const C>();
+ BaseComponentAllocator *allocator = component_allocators_[family];
+ if (!allocator || !entity_component_mask_[id.index()][family])
+ return ComponentPtr<const C>();
+ return ComponentPtr<const C>(id, this);
+ }
+
+ /**
* Find Entities that have all of the specified Components.
+ *
+ * @code
+ * for (Entity entity : entity_manager.entities_with_components<Position, Direction>()) {
+ * ComponentPtr<Position> position = entity.component<Position>();
+ * ComponentPtr<Direction> direction = entity.component<Direction>();
+ *
+ * ...
+ * }
+ * @endcode
*/
template <typename C, typename ... Components>
View entities_with_components() {
auto mask = component_mask<C, Components ...>();
- return View(shared_from_this(), View::ComponentMaskPredicate(entity_component_mask_, mask));
+ return View(this, ComponentMaskPredicate(entity_component_mask_, mask));
}
/**
* Find Entities that have all of the specified Components and assign them
* to the given parameters.
+ *
+ * @code
+ * ComponentPtr<Position> position;
+ * ComponentPtr<Direction> direction;
+ * for (Entity entity : entity_manager.entities_with_components(position, direction)) {
+ * // Use position and component here.
+ * }
+ * @endcode
*/
template <typename C, typename ... Components>
View entities_with_components(ComponentPtr<C> &c, ComponentPtr<Components> & ... args) {
auto mask = component_mask(c, args ...);
return
- View(shared_from_this(), View::ComponentMaskPredicate(entity_component_mask_, mask))
+ View(this, ComponentMaskPredicate(entity_component_mask_, mask))
.unpack_to(c, args ...);
}
@@ -668,6 +686,22 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
friend class ComponentPtr;
friend class Entity;
+ /// 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 entities.entity_version_[entity.index()] == entity.version()
+ && (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");
@@ -741,7 +775,7 @@ class EntityManager : entityx::help::NonCopyable, public enable_shared_from_this
uint32_t index_counter_ = 0;
- ptr<EventManager> event_manager_;
+ EventManager &event_manager_;
// Each element in component_allocators_ corresponds to a Component::family().
std::vector<BaseComponentAllocator*> component_allocators_;
// Bitmask of components associated with each entity. Index into the vector is the Entity::Id.
@@ -764,29 +798,29 @@ BaseComponent::Family Component<C>::family() {
template <typename C, typename ... Args>
ComponentPtr<C> Entity::assign(Args && ... args) {
assert(valid());
- return manager_.lock()->assign<C>(id_, std::forward<Args>(args) ...);
+ return manager_->assign<C>(id_, std::forward<Args>(args) ...);
}
template <typename C>
void Entity::remove() {
assert(valid() && component<C>());
- manager_.lock()->remove<C>(id_);
+ manager_->remove<C>(id_);
}
template <typename C>
ComponentPtr<C> Entity::component() {
assert(valid());
- return manager_.lock()->component<C>(id_);
+ return manager_->component<C>(id_);
}
template <typename A, typename ... Args>
void Entity::unpack(ComponentPtr<A> &a, ComponentPtr<Args> & ... args) {
assert(valid());
- manager_.lock()->unpack(id_, a, args ...);
+ manager_->unpack(id_, a, args ...);
}
inline bool Entity::valid() const {
- return !manager_.expired() && manager_.lock()->valid(id_);
+ return manager_ && manager_->valid(id_);
}
diff --git a/entityx/Entity_test.cc b/entityx/Entity_test.cc
index 553a159..2caf8f4 100644
--- a/entityx/Entity_test.cc
+++ b/entityx/Entity_test.cc
@@ -77,10 +77,10 @@ ostream &operator << (ostream &out, const Tag &tag) {
class EntityManagerTest : public ::testing::Test {
protected:
- EntityManagerTest() : ev(EventManager::make()), em(EntityManager::make(ev)) {}
+ EntityManagerTest() : em(ev) {}
- ptr<EventManager> ev;
- ptr<EntityManager> em;
+ EventManager ev;
+ EntityManager em;
virtual void SetUp() {
}
@@ -88,29 +88,29 @@ class EntityManagerTest : public ::testing::Test {
TEST_F(EntityManagerTest, TestCreateEntity) {
- ASSERT_EQ(em->size(), 0UL);
+ ASSERT_EQ(em.size(), 0UL);
Entity e2;
ASSERT_FALSE(e2.valid());
- Entity e = em->create();
+ Entity e = em.create();
ASSERT_TRUE(e.valid());
- ASSERT_EQ(em->size(), 1UL);
+ ASSERT_EQ(em.size(), 1UL);
e2 = e;
ASSERT_TRUE(e2.valid());
}
TEST_F(EntityManagerTest, TestEntityAsBoolean) {
- ASSERT_EQ(em->size(), 0UL);
- Entity e = em->create();
+ ASSERT_EQ(em.size(), 0UL);
+ Entity e = em.create();
ASSERT_TRUE(e.valid());
- ASSERT_EQ(em->size(), 1UL);
+ ASSERT_EQ(em.size(), 1UL);
ASSERT_FALSE(!e);
e.destroy();
- ASSERT_EQ(em->size(), 0UL);
+ ASSERT_EQ(em.size(), 0UL);
ASSERT_TRUE(!e);
@@ -119,7 +119,7 @@ TEST_F(EntityManagerTest, TestEntityAsBoolean) {
}
TEST_F(EntityManagerTest, TestEntityReuse) {
- Entity e1 = em->create();
+ Entity e1 = em.create();
Entity e2 = e1;
auto id = e1.id();
ASSERT_TRUE(e1.valid());
@@ -127,7 +127,7 @@ TEST_F(EntityManagerTest, TestEntityReuse) {
e1.destroy();
ASSERT_TRUE(!e1.valid());
ASSERT_TRUE(!e2.valid());
- Entity e3 = em->create();
+ Entity e3 = em.create();
// It is assumed that the allocation will reuse the same entity id, though
// the version will change.
auto new_id = e3.id();
@@ -136,7 +136,7 @@ TEST_F(EntityManagerTest, TestEntityReuse) {
}
TEST_F(EntityManagerTest, TestComponentConstruction) {
- auto e = em->create();
+ auto e = em.create();
auto p = e.assign<Position>(1, 2);
auto cp = e.component<Position>();
ASSERT_EQ(p, cp);
@@ -145,8 +145,8 @@ TEST_F(EntityManagerTest, TestComponentConstruction) {
}
TEST_F(EntityManagerTest, TestDestroyEntity) {
- Entity e = em->create();
- Entity f = em->create();
+ Entity e = em.create();
+ Entity f = em.create();
e.assign<Position>();
f.assign<Position>();
e.assign<Direction>();
@@ -168,37 +168,37 @@ TEST_F(EntityManagerTest, TestDestroyEntity) {
}
TEST_F(EntityManagerTest, TestGetEntitiesWithComponent) {
- Entity e = em->create();
- Entity f = em->create();
- Entity g = em->create();
+ Entity e = em.create();
+ Entity f = em.create();
+ Entity g = em.create();
e.assign<Position>();
e.assign<Direction>();
f.assign<Position>();
g.assign<Position>();
- ASSERT_EQ(3, size(em->entities_with_components<Position>()));
- ASSERT_EQ(1, size(em->entities_with_components<Direction>()));
+ ASSERT_EQ(3, size(em.entities_with_components<Position>()));
+ ASSERT_EQ(1, size(em.entities_with_components<Direction>()));
}
TEST_F(EntityManagerTest, TestGetEntitiesWithIntersectionOfComponents) {
vector<Entity> entities;
for (int i = 0; i < 150; ++i) {
- Entity e = em->create();
+ Entity e = em.create();
entities.push_back(e);
if (i % 2 == 0)
e.assign<Position>();
if (i % 3 == 0)
e.assign<Direction>();
}
- ASSERT_EQ(50, size(em->entities_with_components<Direction>()));
- ASSERT_EQ(75, size(em->entities_with_components<Position>()));
- ASSERT_EQ(25, size(em->entities_with_components<Direction, Position>()));
+ ASSERT_EQ(50, size(em.entities_with_components<Direction>()));
+ ASSERT_EQ(75, size(em.entities_with_components<Position>()));
+ ASSERT_EQ(25, size(em.entities_with_components<Direction, Position>()));
}
TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
vector<Entity::Id> entities;
- Entity e = em->create();
- Entity f = em->create();
- Entity g = em->create();
+ Entity e = em.create();
+ Entity f = em.create();
+ Entity g = em.create();
std::vector<std::pair<ComponentPtr<Position>, ComponentPtr<Direction>>> position_directions;
position_directions.push_back(std::make_pair(
e.assign<Position>(1.0f, 2.0f),
@@ -212,10 +212,10 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
ComponentPtr<Position> position;
- ASSERT_EQ(3, size(em->entities_with_components(position)));
+ ASSERT_EQ(3, size(em.entities_with_components(position)));
ComponentPtr<Direction> direction;
- for (auto unused_entity : em->entities_with_components(position, direction)) {
+ for (auto unused_entity : em.entities_with_components(position, direction)) {
(void)unused_entity;
ASSERT_TRUE(static_cast<bool>(position));
ASSERT_TRUE(static_cast<bool>(direction));
@@ -227,7 +227,7 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
ASSERT_EQ(2, i);
ComponentPtr<Tag> tag;
i = 0;
- for (auto unused_entity : em->entities_with_components(position, direction, tag)) {
+ for (auto unused_entity : em.entities_with_components(position, direction, tag)) {
(void)unused_entity;
ASSERT_TRUE(static_cast<bool>(position));
ASSERT_TRUE(static_cast<bool>(direction));
@@ -242,7 +242,7 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
}
TEST_F(EntityManagerTest, TestUnpack) {
- Entity e = em->create();
+ Entity e = em.create();
auto p = e.assign<Position>(1.0, 2.0);
auto d = e.assign<Direction>(3.0, 4.0);
auto t = e.assign<Tag>("tag");
@@ -264,14 +264,14 @@ TEST_F(EntityManagerTest, TestUnpack) {
// gcc 4.7.2 does not allow this struct to be declared locally inside the TEST_F.
// TEST_F(EntityManagerTest, TestUnpackNullMissing) {
-// Entity e = em->create();
+// Entity e = em.create();
// auto p = e.assign<Position>();
-// ptr<Position> up(reinterpret_cast<Position*>(0Xdeadbeef), NullDeleter());
-// ptr<Direction> ud(reinterpret_cast<Direction*>(0Xdeadbeef), NullDeleter());
+// std::shared_ptr<Position> up(reinterpret_cast<Position*>(0Xdeadbeef), NullDeleter());
+// std::shared_ptr<Direction> ud(reinterpret_cast<Direction*>(0Xdeadbeef), NullDeleter());
// e.unpack<Position, Direction>(up, ud);
// ASSERT_EQ(p, up);
-// ASSERT_EQ(ptr<Direction>(), ud);
+// ASSERT_EQ(std::shared_ptr<Direction>(), ud);
// }
TEST_F(EntityManagerTest, TestComponentIdsDiffer) {
@@ -288,11 +288,11 @@ TEST_F(EntityManagerTest, TestEntityCreatedEvent) {
};
EntityCreatedEventReceiver receiver;
- ev->subscribe<EntityCreatedEvent>(receiver);
+ ev.subscribe<EntityCreatedEvent>(receiver);
ASSERT_EQ(0UL, receiver.created.size());
for (int i = 0; i < 10; ++i) {
- em->create();
+ em.create();
}
ASSERT_EQ(10UL, receiver.created.size());
}
@@ -307,12 +307,12 @@ TEST_F(EntityManagerTest, TestEntityDestroyedEvent) {
};
EntityDestroyedEventReceiver receiver;
- ev->subscribe<EntityDestroyedEvent>(receiver);
+ ev.subscribe<EntityDestroyedEvent>(receiver);
ASSERT_EQ(0UL, receiver.destroyed.size());
vector<Entity> entities;
for (int i = 0; i < 10; ++i) {
- entities.push_back(em->create());
+ entities.push_back(em.create());
}
ASSERT_EQ(0UL, receiver.destroyed.size());
for (auto e : entities) {
@@ -344,8 +344,8 @@ TEST_F(EntityManagerTest, TestComponentAddedEvent) {
};
ComponentAddedEventReceiver receiver;
- ev->subscribe<ComponentAddedEvent<Position>>(receiver);
- ev->subscribe<ComponentAddedEvent<Direction>>(receiver);
+ ev.subscribe<ComponentAddedEvent<Position>>(receiver);
+ ev.subscribe<ComponentAddedEvent<Direction>>(receiver);
ASSERT_NE(ComponentAddedEvent<Position>::family(),
ComponentAddedEvent<Direction>::family());
@@ -353,7 +353,7 @@ TEST_F(EntityManagerTest, TestComponentAddedEvent) {
ASSERT_EQ(0, receiver.position_events);
ASSERT_EQ(0, receiver.direction_events);
for (int i = 0; i < 10; ++i) {
- Entity e = em->create();
+ Entity e = em.create();
e.assign<Position>(static_cast<float>(i), static_cast<float>(i));
e.assign<Direction>(static_cast<float>(-i), static_cast<float>(-i));
}
@@ -371,10 +371,10 @@ TEST_F(EntityManagerTest, TestComponentRemovedEvent) {
};
ComponentRemovedReceiver receiver;
- ev->subscribe<ComponentRemovedEvent<Direction>>(receiver);
+ ev.subscribe<ComponentRemovedEvent<Direction>>(receiver);
ASSERT_FALSE(receiver.removed);
- Entity e = em->create();
+ Entity e = em.create();
auto p = e.assign<Direction>(1.0, 2.0);
e.remove<Direction>();
ASSERT_EQ(receiver.removed, p);
@@ -383,7 +383,7 @@ TEST_F(EntityManagerTest, TestComponentRemovedEvent) {
TEST_F(EntityManagerTest, TestEntityAssignment) {
Entity a, b;
- a = em->create();
+ a = em.create();
ASSERT_NE(a, b);
b = a;
ASSERT_EQ(a, b);
@@ -392,8 +392,8 @@ TEST_F(EntityManagerTest, TestEntityAssignment) {
}
TEST_F(EntityManagerTest, TestEntityDestroyAll) {
- Entity a = em->create(), b = em->create();
- em->reset();
+ Entity a = em.create(), b = em.create();
+ em.reset();
ASSERT_FALSE(a.valid());
ASSERT_FALSE(b.valid());
}
@@ -403,12 +403,12 @@ TEST_F(EntityManagerTest, TestEntityDestroyHole) {
std::vector<Entity> entities;
auto count = [this]() -> int {
- auto e = em->entities_with_components<Position>();
+ auto e = em.entities_with_components<Position>();
return std::count_if(e.begin(), e.end(), [] (const Entity &) { return true; });
};
for (int i = 0; i < 5000; i++) {
- auto e = em->create();
+ auto e = em.create();
e.assign<Position>();
entities.push_back(e);
}
diff --git a/entityx/Event.h b/entityx/Event.h
index 8c8a8dc..a4b3e5d 100644
--- a/entityx/Event.h
+++ b/entityx/Event.h
@@ -10,10 +10,11 @@
#pragma once
+#include <unordered_map>
#include <stdint.h>
#include <list>
+#include <memory>
#include <utility>
-#include <unordered_map>
#include "entityx/config.h"
#include "entityx/3rdparty/simplesignal.h"
#include "entityx/help/NonCopyable.h"
@@ -37,8 +38,8 @@ class BaseEvent {
typedef Simple::Signal<void (const BaseEvent*)> EventSignal;
-typedef ptr<EventSignal> EventSignalPtr;
-typedef weak_ptr<EventSignal> EventSignalWeakPtr;
+typedef std::shared_ptr<EventSignal> EventSignalPtr;
+typedef std::weak_ptr<EventSignal> EventSignalWeakPtr;
/**
@@ -107,10 +108,6 @@ class EventManager : entityx::help::NonCopyable {
EventManager();
virtual ~EventManager();
- static ptr<EventManager> make() {
- return ptr<EventManager>(new EventManager());
- }
-
/**
* Subscribe an object to receive events of type E.
*
@@ -142,7 +139,7 @@ class EventManager : entityx::help::NonCopyable {
* Emit an already constructed event.
*/
template <typename E>
- void emit(ptr<E> event) {
+ void emit(std::unique_ptr<E> event) {
auto sig = signal_for(E::family());
sig->emit(static_cast<BaseEvent*>(event.get()));
}
@@ -154,7 +151,7 @@ class EventManager : entityx::help::NonCopyable {
*
* eg.
*
- * ptr<EventManager> em = new EventManager();
+ * std::shared_ptr<EventManager> em = new EventManager();
* em->emit<Explosion>(10);
*
*/
diff --git a/entityx/Event_test.cc b/entityx/Event_test.cc
index 7986526..362d361 100644
--- a/entityx/Event_test.cc
+++ b/entityx/Event_test.cc
@@ -33,49 +33,49 @@ struct ExplosionSystem : public Receiver<ExplosionSystem> {
};
TEST(EventManagerTest, TestEmitReceive) {
- auto em = EventManager::make();
+ EventManager em;
ExplosionSystem explosion_system;
- em->subscribe<Explosion>(explosion_system);
+ em.subscribe<Explosion>(explosion_system);
ASSERT_EQ(0, explosion_system.damage_received);
- em->emit<Explosion>(10);
+ em.emit<Explosion>(10);
ASSERT_EQ(10, explosion_system.damage_received);
}
TEST(EventManagerTest, TestUntypedEmitReceive) {
- auto em = EventManager::make();
+ EventManager em;
ExplosionSystem explosion_system;
- em->subscribe<Explosion>(explosion_system);
+ em.subscribe<Explosion>(explosion_system);
ASSERT_EQ(0, explosion_system.damage_received);
Explosion explosion(10);
- em->emit(explosion);
+ em.emit(explosion);
ASSERT_EQ(10, explosion_system.damage_received);
}
TEST(EventManagerTest, TestReceiverExpired) {
- auto em = EventManager::make();
+ EventManager em;
{
ExplosionSystem explosion_system;
- em->subscribe<Explosion>(explosion_system);
- em->emit<Explosion>(10);
+ em.subscribe<Explosion>(explosion_system);
+ em.emit<Explosion>(10);
ASSERT_EQ(10, explosion_system.damage_received);
ASSERT_EQ(1, explosion_system.connected_signals());
- ASSERT_EQ(1, em->connected_receivers());
+ ASSERT_EQ(1, em.connected_receivers());
}
- ASSERT_EQ(0, em->connected_receivers());
+ ASSERT_EQ(0, em.connected_receivers());
}
TEST(EventManagerTest, TestSenderExpired) {
ExplosionSystem explosion_system;
{
- auto em = EventManager::make();
- em->subscribe<Explosion>(explosion_system);
- em->emit<Explosion>(10);
+ EventManager em;
+ em.subscribe<Explosion>(explosion_system);
+ em.emit<Explosion>(10);
ASSERT_EQ(10, explosion_system.damage_received);
ASSERT_EQ(1, explosion_system.connected_signals());
- ASSERT_EQ(1, em->connected_receivers());
+ ASSERT_EQ(1, em.connected_receivers());
}
ASSERT_EQ(0, explosion_system.connected_signals());
}
diff --git a/entityx/Manager.cc b/entityx/Manager.cc
deleted file mode 100644
index a86ee56..0000000
--- a/entityx/Manager.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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>
- */
-
-#include "Manager.h"
-
-namespace entityx {
-
-void Manager::start() {
- configure();
- system_manager->configure();
- initialize();
-}
-
-void Manager::run() {
- running_ = true;
- double dt;
- timer_.restart();
- while (running_) {
- dt = timer_.elapsed();
- timer_.restart();
- update(dt);
- }
-}
-
-void Manager::step(double dt) {
- update(dt);
-}
-
-
-void Manager::stop() {
- running_ = false;
-}
-
-} // namespace entityx
diff --git a/entityx/Manager.h b/entityx/Manager.h
deleted file mode 100644
index 2da482e..0000000
--- a/entityx/Manager.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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 "entityx/Entity.h"
-#include "entityx/Event.h"
-#include "entityx/System.h"
-#include "entityx/help/Timer.h"
-
-namespace entityx {
-
-class Manager {
- public:
- virtual ~Manager() {}
-
- /**
- * Call start() to initialize the Manager.
- */
- void start();
-
-
- /**
- * Run the main loop. To explicitly manage your own main loop use step(dt);
- */
- void run();
-
- /**
- * Step the system by dt.
- * @param dt Delta time since last frame.
- */
- void step(double dt);
-
- /**
- * Stop the manager.
- */
- void stop();
-
- protected:
- Manager() :
- event_manager(EventManager::make()),
- entity_manager(EntityManager::make(event_manager)),
- system_manager(SystemManager::make(entity_manager, event_manager)) {}
-
- /**
- * Configure the world.
- *
- * This is called once on Manager initialization. It is typically used to add Systems to the world, load permanent
- * resources, global configuration, etc.
- */
- virtual void configure() = 0;
-
- /**
- * Initialize the entities and events in the world.
- *
- * Typically used to create initial entities, setup event handlers, and so on.
- */
- virtual void initialize() = 0;
-
- /**
- * Update the world.
- *
- * Typically this is where you would call update() on all Systems in the world.
- */
- virtual void update(double dt) = 0;
-
- ptr<EventManager> event_manager;
- ptr<EntityManager> entity_manager;
- ptr<SystemManager> system_manager;
-
- private:
- help::Timer timer_;
- bool running_ = false;
-};
-
-} // namespace entityx
diff --git a/entityx/System.cc b/entityx/System.cc
index 44995bc..dc83cac 100644
--- a/entityx/System.cc
+++ b/entityx/System.cc
@@ -15,10 +15,10 @@ namespace entityx {
BaseSystem::Family BaseSystem::family_counter_;
void SystemManager::configure() {
- for (auto pair : systems_) {
+ for (auto &pair : systems_) {
pair.second->configure(event_manager_);
}
initialized_ = true;
}
-}
+} // namespace entityx
diff --git a/entityx/System.h b/entityx/System.h
index 9c0b2ec..d94c91a 100644
--- a/entityx/System.h
+++ b/entityx/System.h
@@ -11,9 +11,9 @@
#pragma once
+#include <stdint.h>
#include <unordered_map>
#include <utility>
-#include <stdint.h>
#include <cassert>
#include "entityx/config.h"
#include "entityx/Entity.h"
@@ -23,6 +23,10 @@
namespace entityx {
+
+class SystemManager;
+
+
/**
* Base System class. Generally should not be directly used, instead see System<Derived>.
*/
@@ -37,14 +41,14 @@ class BaseSystem : entityx::help::NonCopyable {
*
* Typically used to set up event handlers.
*/
- virtual void configure(ptr<EventManager> events) {}
+ virtual void configure(EventManager &events) {}
/**
* Apply System behavior.
*
* Called every game step.
*/
- virtual void update(ptr<EntityManager> entities, ptr<EventManager> events, double dt) = 0;
+ virtual void update(EntityManager &entities, EventManager &events, double dt) = 0;
static Family family_counter_;
@@ -56,7 +60,7 @@ class BaseSystem : entityx::help::NonCopyable {
* Use this class when implementing Systems.
*
* struct MovementSystem : public System<MovementSystem> {
- * void update(ptr<EntityManager> entities, EventManager &events, double dt) {
+ * void update(EntityManager &entities, EventManager &events, double dt) {
* // Do stuff to/with entities...
* }
* }
@@ -66,6 +70,9 @@ class System : public BaseSystem {
public:
virtual ~System() {}
+private:
+ friend class SystemManager;
+
static Family family() {
static Family family = family_counter_++;
return family;
@@ -73,29 +80,24 @@ class System : public BaseSystem {
};
-class SystemManager : entityx::help::NonCopyable, public enable_shared_from_this<SystemManager> {
+class SystemManager : entityx::help::NonCopyable {
public:
- SystemManager(ptr<EntityManager> entity_manager,
- ptr<EventManager> event_manager) :
+ SystemManager(EntityManager &entity_manager,
+ EventManager &event_manager) :
entity_manager_(entity_manager),
event_manager_(event_manager) {}
- static ptr<SystemManager> make(ptr<EntityManager> entity_manager,
- ptr<EventManager> event_manager) {
- return ptr<SystemManager>(new SystemManager(entity_manager, event_manager));
- }
-
/**
* Add a System to the SystemManager.
*
* Must be called before Systems can be used.
*
* eg.
- * ptr<MovementSystem> movement = entityx::make_shared<MovementSystem>();
+ * std::shared_ptr<MovementSystem> movement = entityx::make_shared<MovementSystem>();
* system.add(movement);
*/
template <typename S>
- void add(ptr<S> system) {
+ void add(std::shared_ptr<S> system) {
systems_.insert(std::make_pair(S::family(), system));
}
@@ -108,8 +110,8 @@ class SystemManager : entityx::help::NonCopyable, public enable_shared_from_this
* auto movement = system.add<MovementSystem>();
*/
template <typename S, typename ... Args>
- ptr<S> add(Args && ... args) {
- ptr<S> s(new S(std::forward<Args>(args) ...));
+ std::shared_ptr<S> add(Args && ... args) {
+ std::shared_ptr<S> s(new S(std::forward<Args>(args) ...));
add(s);
return s;
}
@@ -117,17 +119,17 @@ class SystemManager : entityx::help::NonCopyable, public enable_shared_from_this
/**
* Retrieve the registered System instance, if any.
*
- * ptr<CollisionSystem> collisions = systems.system<CollisionSystem>();
+ * std::shared_ptr<CollisionSystem> collisions = systems.system<CollisionSystem>();
*
- * @return System instance or empty shared_ptr<S>.
+ * @return System instance or empty shared_std::shared_ptr<S>.
*/
template <typename S>
- ptr<S> system() {
+ std::shared_ptr<S> system() {
auto it = systems_.find(S::family());
assert(it != systems_.end());
return it == systems_.end()
- ? ptr<S>()
- : ptr<S>(static_pointer_cast<S>(it->second));
+ ? std::shared_ptr<S>()
+ : std::shared_ptr<S>(std::static_pointer_cast<S>(it->second));
}
/**
@@ -136,7 +138,7 @@ class SystemManager : entityx::help::NonCopyable, public enable_shared_from_this
template <typename S>
void update(double dt) {
assert(initialized_ && "SystemManager::configure() not called");
- ptr<S> s = system<S>();
+ std::shared_ptr<S> s = system<S>();
s->update(entity_manager_, event_manager_, dt);
}
@@ -149,9 +151,9 @@ class SystemManager : entityx::help::NonCopyable, public enable_shared_from_this
private:
bool initialized_ = false;
- ptr<EntityManager> entity_manager_;
- ptr<EventManager> event_manager_;
- std::unordered_map<BaseSystem::Family, ptr<BaseSystem>> systems_;
+ EntityManager &entity_manager_;
+ EventManager &event_manager_;
+ std::unordered_map<BaseSystem::Family, std::shared_ptr<BaseSystem>> systems_;
};
} // namespace entityx
diff --git a/entityx/System_test.cc b/entityx/System_test.cc
index e0d5b6a..16f7372 100644
--- a/entityx/System_test.cc
+++ b/entityx/System_test.cc
@@ -8,11 +8,11 @@
* Author: Alec Thomas <alec@swapoff.org>
*/
+#include <gtest/gtest.h>
#include <string>
#include <vector>
-#include <gtest/gtest.h>
-#include "entityx/Manager.h"
#include "entityx/System.h"
+#include "entityx/quick.h"
// using namespace std;
@@ -36,8 +36,8 @@ class MovementSystem : public System<MovementSystem> {
public:
explicit MovementSystem(string label = "") : label(label) {}
- void update(ptr<EntityManager> es, ptr<EventManager> events, double) override {
- EntityManager::View entities = es->entities_with_components<Position, Direction>();
+ void update(EntityManager &es, EventManager &events, double) override {
+ EntityManager::View entities = es.entities_with_components<Position, Direction>();
ComponentPtr<Position> position;
ComponentPtr<Direction> direction;
for (auto entity : entities) {
@@ -51,59 +51,49 @@ class MovementSystem : public System<MovementSystem> {
};
-class TestManager : public entityx::Manager {
+class TestContainer : public EntityX {
public:
- std::vector<Entity> entities;
-
- ptr<SystemManager> sm() { return system_manager; }
- ptr<EntityManager> em() { return entity_manager; }
-
- protected:
- void configure() override {
- }
+ std::vector<Entity> created_entities;
- void initialize() override {
+ void initialize() {
for (int i = 0; i < 150; ++i) {
- Entity e = entity_manager->create();
- entities.push_back(e);
+ Entity e = entities.create();
+ created_entities.push_back(e);
if (i % 2 == 0)
e.assign<Position>(1, 2);
if (i % 3 == 0)
e.assign<Direction>(1, 1);
}
}
-
- void update(double dt) override {
- }
};
class SystemManagerTest : public ::testing::Test {
protected:
- TestManager manager;
+ TestContainer manager;
virtual void SetUp() override {
- manager.start();
+ manager.initialize();
}
};
TEST_F(SystemManagerTest, TestConstructSystemWithArgs) {
- manager.sm()->add<MovementSystem>("movement");
- manager.sm()->configure();
+ manager.systems.add<MovementSystem>("movement");
+ manager.systems.configure();
- ASSERT_EQ("movement", manager.sm()->system<MovementSystem>()->label);
+ ASSERT_EQ("movement", manager.systems.system<MovementSystem>()->label);
}
TEST_F(SystemManagerTest, TestApplySystem) {
- manager.sm()->add<MovementSystem>();
- manager.sm()->configure();
+ manager.systems.add<MovementSystem>();
+ manager.systems.configure();
- manager.sm()->update<MovementSystem>(0.0);
+ manager.systems.update<MovementSystem>(0.0);
ComponentPtr<Position> position;
ComponentPtr<Direction> direction;
- for (auto entity : manager.entities) {
+ for (auto entity : manager.created_entities) {
entity.unpack<Position, Direction>(position, direction);
if (position && direction) {
ASSERT_FLOAT_EQ(2.0, position->x);
diff --git a/entityx/config.h.in b/entityx/config.h.in
index 940d4d1..575b34f 100644
--- a/entityx/config.h.in
+++ b/entityx/config.h.in
@@ -1,55 +1,11 @@
#pragma once
#cmakedefine ENTITYX_MAX_COMPONENTS @ENTITYX_MAX_COMPONENTS@
-#cmakedefine ENTITYX_HAVE_BOOST_PYTHON 1
-#cmakedefine ENTITYX_INSTALLED_PYTHON_PACKAGE_DIR "@ENTITYX_INSTALLED_PYTHON_PACKAGE_DIR@"
-#cmakedefine ENTITYX_NEED_GET_POINTER_SHARED_PTR_SPECIALIZATION "@ENTITYX_NEED_GET_POINTER_SHARED_PTR_SPECIALIZATION@"
#include <stdint.h>
-#include "entityx/config.h"
namespace entityx {
static const uint64_t MAX_COMPONENTS = ENTITYX_MAX_COMPONENTS;
} // namespace entityx
-
-
-// Which shared_ptr implementation should we use?
-#include <memory>
-// for std::forward()
-#include <utility>
-
-namespace entityx {
-
-template <typename T>
-using ptr = std::shared_ptr<T>;
-template <typename T>
-using weak_ptr = std::weak_ptr<T>;
-template <typename T, typename U>
-ptr<U> static_pointer_cast(const ptr<T> &ptr) {
- return std::static_pointer_cast<U>(ptr);
-}
-template <typename T>
-using enable_shared_from_this = std::enable_shared_from_this<T>;
-
-} // namespace entityx
-
-namespace entityx {
-
-template <typename T, typename... Args>
-ptr<T> make_ptr(Args&&... args) {
- return ptr<T>(::new T(std::forward<Args>(args)...));
-}
-
-template <typename T>
-bool operator == (const weak_ptr<T> &a, const weak_ptr<T> &b) {
- return a.lock() == b.lock();
-}
-
-template <typename T>
-int use_count(const ptr<T> &ptr) {
- return ptr.use_count();
-}
-
-} // namespace entityx
diff --git a/entityx/deps/Dependencies.cc b/entityx/deps/Dependencies.cc
deleted file mode 100644
index 9271a2f..0000000
--- a/entityx/deps/Dependencies.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (C) 2013 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>
- */
-
-#include "entityx/deps/Dependencies.h"
diff --git a/entityx/deps/Dependencies.h b/entityx/deps/Dependencies.h
index 69e68bb..83ab4a5 100644
--- a/entityx/deps/Dependencies.h
+++ b/entityx/deps/Dependencies.h
@@ -31,11 +31,11 @@ public:
assign<Deps...>(event.entity);
}
- virtual void configure(ptr<EventManager> events) override {
- events->subscribe<ComponentAddedEvent<C>>(*this);
+ virtual void configure(EventManager &events) override {
+ events.subscribe<ComponentAddedEvent<C>>(*this);
}
- virtual void update(ptr<EntityManager> entities, ptr<EventManager> events, double dt) override {}
+ virtual void update(EntityManager &entities, EventManager &events, double dt) override {}
private:
template <typename D>
diff --git a/entityx/deps/Dependencies_test.cc b/entityx/deps/Dependencies_test.cc
index 8a2f17c..72d4ae8 100644
--- a/entityx/deps/Dependencies_test.cc
+++ b/entityx/deps/Dependencies_test.cc
@@ -10,6 +10,7 @@
#include <gtest/gtest.h>
#include "entityx/deps/Dependencies.h"
+#include "entityx/quick.h"
namespace ex = entityx;
@@ -25,25 +26,15 @@ struct B : public ex::Component<B> {
struct C : public ex::Component<C> {};
-class DepsTest : public ::testing::Test {
- protected:
- DepsTest() : events(ex::EventManager::make()),
- entities(ex::EntityManager::make(events)),
- systems(ex::SystemManager::make(entities, events)) {}
-
- ex::ptr<ex::EventManager> events;
- ex::ptr<ex::EntityManager> entities;
- ex::ptr<ex::SystemManager> systems;
-
- virtual void SetUp() {}
+class DepsTest : public ::testing::Test, public ex::EntityX {
};
TEST_F(DepsTest, TestSingleDependency) {
- systems->add<deps::Dependency<A, B>>();
- systems->configure();
+ systems.add<deps::Dependency<A, B>>();
+ systems.configure();
- ex::Entity e = entities->create();
+ ex::Entity e = entities.create();
ASSERT_FALSE(static_cast<bool>(e.component<A>()));
ASSERT_FALSE(static_cast<bool>(e.component<B>()));
e.assign<A>();
@@ -52,10 +43,10 @@ TEST_F(DepsTest, TestSingleDependency) {
}
TEST_F(DepsTest, TestMultipleDependencies) {
- systems->add<deps::Dependency<A, B, C>>();
- systems->configure();
+ systems.add<deps::Dependency<A, B, C>>();
+ systems.configure();
- ex::Entity e = entities->create();
+ ex::Entity e = entities.create();
ASSERT_FALSE(static_cast<bool>(e.component<A>()));
ASSERT_FALSE(static_cast<bool>(e.component<B>()));
ASSERT_FALSE(static_cast<bool>(e.component<C>()));
@@ -66,10 +57,10 @@ TEST_F(DepsTest, TestMultipleDependencies) {
}
TEST_F(DepsTest, TestDependencyDoesNotRecreateComponent) {
- systems->add<deps::Dependency<A, B>>();
- systems->configure();
+ systems.add<deps::Dependency<A, B>>();
+ systems.configure();
- ex::Entity e = entities->create();
+ ex::Entity e = entities.create();
e.assign<B>(true);
ASSERT_TRUE(e.component<B>()->b);
e.assign<A>();
diff --git a/entityx/entityx.h b/entityx/entityx.h
index eb83073..72cfa24 100644
--- a/entityx/entityx.h
+++ b/entityx/entityx.h
@@ -5,3 +5,4 @@
#include "entityx/Entity.h"
#include "entityx/System.h"
#include "entityx/Manager.h"
+#include "entityx/quick.h"
diff --git a/entityx/tags/TagsComponent.cc b/entityx/tags/TagsComponent.cc
deleted file mode 100644
index 509debf..0000000
--- a/entityx/tags/TagsComponent.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * 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>
- */
-
-#include "entityx/tags/TagsComponent.h"
diff --git a/entityx/tags/TagsComponent.h b/entityx/tags/TagsComponent.h
index 6fcb937..f47249f 100644
--- a/entityx/tags/TagsComponent.h
+++ b/entityx/tags/TagsComponent.h
@@ -10,8 +10,8 @@
#pragma once
-#include <string>
#include <unordered_set>
+#include <string>
#include "entityx/Entity.h"
namespace entityx {
@@ -19,13 +19,20 @@ namespace tags {
/**
* Allow entities to be tagged with strings.
+ *
+ * entity.assign<TagsComponent>("tag1", "tag2");
+ *
+ * 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() (ptr<EntityManager> manager, Entity::Id id) {
- auto tags = manager->component<TagsComponent>(id);
+ bool operator() (const EntityManager &manager, Entity::Id id) {
+ auto tags = manager.component<TagsComponent>(id);
return tags && tags->tags.find(tag) != tags->tags.end();
}
diff --git a/entityx/tags/TagsComponent_test.cc b/entityx/tags/TagsComponent_test.cc
index 34651b3..4674c5a 100644
--- a/entityx/tags/TagsComponent_test.cc
+++ b/entityx/tags/TagsComponent_test.cc
@@ -8,6 +8,7 @@
* Author: Alec Thomas <alec@swapoff.org>
*/
+#include <string>
#include <gtest/gtest.h>
#include "entityx/tags/TagsComponent.h"
@@ -39,16 +40,17 @@ TEST(TagsComponentTest, TestVariadicConstruction) {
}
TEST(TagsComponentTest, TestEntitiesWithTag) {
- auto en = EntityManager::make(EventManager::make());
- Entity a = en->create();
+ EventManager ev;
+ EntityManager en(ev);
+ Entity a = en.create();
a.assign<Position>();
for (int i = 0; i < 99; ++i) {
- auto e = en->create();
+ auto e = en.create();
e.assign<Position>();
e.assign<TagsComponent>("positionable");
}
a.assign<TagsComponent>("player", "indestructible");
- auto entities = en->entities_with_components<Position>();
+ auto entities = en.entities_with_components<Position>();
ASSERT_EQ(100, size(entities));
ASSERT_EQ(1, size(TagsComponent::view(entities, "player")));
}