aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlec Thomas <alec@swapoff.org>2012-10-24 16:14:48 -0400
committerAlec Thomas <alec@swapoff.org>2012-10-24 16:14:48 -0400
commitf617f3e65b27be7a600e4f28c85bbd88e0d9df6b (patch)
treec03a4becc8c433790d75b93af085862e2e565b09
parentfe7073293163f4b1417a1970164306d2faf97686 (diff)
Fix unpacking bug (segfault from lambda).
-rw-r--r--entityx/Entity.h77
-rw-r--r--entityx/Entity_test.cc1
2 files changed, 40 insertions, 38 deletions
diff --git a/entityx/Entity.h b/entityx/Entity.h
index 356c773..013830e 100644
--- a/entityx/Entity.h
+++ b/entityx/Entity.h
@@ -180,14 +180,10 @@ class EntityManager : boost::noncopyable {
while (i_ < manager_.size() && !predicate()) {
++i_;
}
- if (i_ < manager_.size()) {
- unpack();
- }
- }
-
- void unpack() {
- for (auto unpacker : unpackers_) {
- unpacker(i_);
+ if (i_ < manager_.size() && !unpackers_.empty()) {
+ for (auto unpacker : unpackers_) {
+ unpacker(i_);
+ }
}
}
@@ -218,20 +214,35 @@ class EntityManager : boost::noncopyable {
template <typename A>
View &unpack_to(boost::shared_ptr<A> &a) {
- unpackers_.push_back([&] (Entity id) {
+ unpackers_.push_back(Unpacker<A>(manager_, a));
+ // This resulted in a segfault under clang 4.1 on OSX. No idea why.
+ /*unpackers_.push_back([&a, this](Entity id) {
a = manager_.component<A>(id);
- });
+ });*/
return *this;
}
template <typename A, typename B, typename ... Args>
- View &unpack_to(boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args *& ... args) {
+ View &unpack_to(boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
unpack_to<A>(a);
return unpack_to<B, Args ...>(b, args ...);
}
private:
friend class EntityManager;
+ template <typename T>
+ struct Unpacker {
+ Unpacker(EntityManager &manager, boost::shared_ptr<T> &c) : manager(manager), c(c) {}
+
+ void operator () (Entity id) {
+ c = manager.component<T>(id);
+ }
+
+ private:
+ EntityManager &manager;
+ boost::shared_ptr<T> &c;
+ };
+
View(EntityManager &manager, Predicate predicate) : manager_(manager) {
predicates_.push_back(predicate);
}
@@ -332,43 +343,23 @@ class EntityManager : boost::noncopyable {
}
/**
- * Get all entities with the given component.
- */
- template <typename C>
- View entities_with_components() {
- auto mask = component_mask<C>();
- return View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask));
- }
-
- /**
* Find Entities that have all of the specified Components.
*/
- template <typename C1, typename C2, typename ... Components>
+ template <typename C, typename ... Components>
View entities_with_components() {
- auto mask = component_mask<C1, C2, Components ...>();
+ uint64_t mask = component_mask<C, Components ...>();
return View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask));
}
/**
- * Get all entities with the given component.
- */
- template <typename C>
- View entities_with_components(boost::shared_ptr<C> &c) {
- auto mask = component_mask<C>();
- return
- View(*this, View::ComponentMaskPredicate(entity_component_mask_, mask))
- .unpack_to<C>(c);
- }
-
- /**
* Find Entities that have all of the specified Components.
*/
- template <typename C1, typename C2, typename ... Components>
- View entities_with_components(boost::shared_ptr<C1> &c1, boost::shared_ptr<C2> &c2, Components *& ... args) {
- auto mask = component_mask<C1, C2, Components ...>();
+ template <typename C, typename ... Components>
+ 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))
- .unpack_to<C1, C2, Components...>(c1, c2, args...);
+ .unpack_to(c, args ...);
}
/**
@@ -399,7 +390,7 @@ class EntityManager : boost::noncopyable {
* unpack<Position, Direction>(e, p, d);
*/
template <typename A, typename B, typename ... Args>
- void unpack(Entity id, boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args & ... args) {
+ void unpack(Entity id, boost::shared_ptr<A> &a, boost::shared_ptr<B> &b, Args && ... args) {
unpack<A>(id, a);
unpack<B, Args ...>(id, b, args ...);
}
@@ -415,6 +406,16 @@ class EntityManager : boost::noncopyable {
return component_mask<C1>() | component_mask<C2, Components ...>();
}
+ template <typename C>
+ uint64_t component_mask(const boost::shared_ptr<C> &c) {
+ return uint64_t(1) << C::family();
+ }
+
+ template <typename C1, typename C2, typename ... Components>
+ uint64_t component_mask(const boost::shared_ptr<C1> &c1, const boost::shared_ptr<C2> &c2, Components && ... args) {
+ return component_mask<C1>(c1) | component_mask<C2, Components ...>(c2, args...);
+ }
+
inline void accomodate_entity(Entity entity) {
if (entity_component_mask_.size() <= entity) {
entity_component_mask_.resize(entity + 1);
diff --git a/entityx/Entity_test.cc b/entityx/Entity_test.cc
index aa1b32b..805a3d3 100644
--- a/entityx/Entity_test.cc
+++ b/entityx/Entity_test.cc
@@ -164,6 +164,7 @@ TEST_F(EntityManagerTest, TestGetEntitiesWithComponentAndUnpacking) {
em.assign<Direction>(f, 9.0f, 10.0f)));
em.assign<Position>(g, 5.0f, 6.0f);
int i = 0;
+
shared_ptr<Position> position;
shared_ptr<Direction> direction;
for (auto unused_entity : em.entities_with_components(position, direction)) {