registry: added discard to free explicitly a pool

This commit is contained in:
Michele Caini
2019-12-21 17:53:38 +01:00
parent 95fd4e4c99
commit d9884917fb
10 changed files with 51 additions and 46 deletions

1
TODO
View File

@@ -25,6 +25,5 @@
- ::group improve, reduce code
* Mission: get rid of named types
- add discard pool functionality (+ test)
- update doc: dispatcher, emitter, registry, meta, across boundaries
- review and suppress warnings, if any

View File

@@ -147,7 +147,7 @@ class basic_registry {
};
struct pool_data {
ENTT_ID_TYPE id;
ENTT_ID_TYPE type_id;
std::unique_ptr<sparse_set<Entity>> pool;
void(* assure)(basic_registry &, const sparse_set<Entity> &);
void(* remove)(sparse_set<Entity> &, basic_registry &, const Entity);
@@ -213,15 +213,15 @@ class basic_registry {
static_assert(std::is_same_v<Component, std::decay_t<Component>>);
static std::size_t index{pools.size()};
if(!(index < pools.size()) || pools[index].id != type_id_v<Component>) {
if(!(index < pools.size()) || pools[index].type_id != type_id_v<Component>) {
index = std::find_if(pools.cbegin(), pools.cend(), [](auto &&cpool) {
return cpool.id == type_id_v<Component>;
return cpool.type_id == type_id_v<Component>;
}) - pools.cbegin();
if(index == pools.size()) {
auto &&pdata = pools.emplace_back();
pdata.id = type_id_v<Component>;
pdata.type_id = type_id_v<Component>;
pdata.pool = std::make_unique<pool_type<Component>>(std::forward<Args>(args)...);
pdata.remove = [](sparse_set<Entity> &cpool, basic_registry &owner, const Entity entt) {
@@ -273,10 +273,21 @@ public:
*/
template<typename Component, typename... Args>
void prepare(Args &&... args) {
ENTT_ASSERT(std::none_of(pools.cbegin(), pools.cend(), [](auto &&pdata) { return pdata.id == type_id_v<Component>; }));
ENTT_ASSERT(std::none_of(pools.cbegin(), pools.cend(), [](auto &&pdata) { return pdata.type_id == type_id_v<Component>; }));
assure<Component>(std::forward<Args>(args)...);
}
/**
* @brief Discards the pools for the given components.
* @tparam Component Types of components for which to discard the pools.
*/
template<typename... Component>
void discard() {
pools.erase(std::remove_if(pools.begin(), pools.end(), [](auto &&pdata) {
return ((pdata.type_id == type_id_v<Component>) || ...);
}), pools.end());
}
/**
* @brief Returns the number of existing components of the given type.
* @tparam Component Type of component of which to return the size.
@@ -1425,7 +1436,7 @@ public:
std::transform(first, last, selected.begin(), [this](const auto ctype) {
const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) {
return pdata.id == ctype;
return pdata.type_id == ctype;
});
return it == pools.cend() ? nullptr : it->pool.get();
@@ -1476,7 +1487,7 @@ public:
if constexpr(sizeof...(Component) == 0) {
for(size_type pos{}; pos < pools.size(); ++pos) {
if(const auto &pdata = pools[pos]; pdata.assure && ((pdata.id != type_id_v<Exclude>) && ...)) {
if(const auto &pdata = pools[pos]; pdata.assure && ((pdata.type_id != type_id_v<Exclude>) && ...)) {
pdata.assure(other, *pdata.pool);
}
}
@@ -1529,7 +1540,7 @@ public:
void stomp(const entity_type dst, const basic_registry &other, const entity_type src, exclude_t<Exclude...> = {}) {
if constexpr(sizeof...(Component) == 0) {
for(size_type pos{}; pos < other.pools.size(); ++pos) {
if(const auto &pdata = other.pools[pos]; pdata.stomp && ((pdata.id != type_id_v<Exclude>) && ...) && pdata.pool->has(src)) {
if(const auto &pdata = other.pools[pos]; pdata.stomp && ((pdata.type_id != type_id_v<Exclude>) && ...) && pdata.pool->has(src)) {
pdata.stomp(*this, dst, *pdata.pool, src);
}
}

View File

@@ -99,8 +99,8 @@ class dispatcher {
public:
/**
* @brief Discards the pool for the given event.
* @tparam Event Type of event for which to discard the pool.
* @brief Discards the pools for the given events.
* @tparam Event Types of events for which to discard the pools.
*/
template<typename... Event>
void discard() {

View File

@@ -187,8 +187,8 @@ public:
emitter & operator=(emitter &&) = default;
/**
* @brief Discards the pool for the given event.
* @tparam Event Type of event for which to discard the pool.
* @brief Discards the pools for the given events.
* @tparam Event Types of events for which to discard the pools.
*/
template<typename... Event>
void discard() {

View File

@@ -2,15 +2,15 @@
#include <entt/entity/registry.hpp>
#include "types.h"
ENTT_API void update_position(int delta, entt::registry &registry) {
registry.view<position, velocity>().each([delta](auto &pos, auto &vel) {
pos.x += delta * vel.dx;
pos.y += delta * vel.dy;
ENTT_API void update_position(entt::registry &registry) {
registry.view<position, velocity>().each([](auto &pos, auto &vel) {
pos.x += 16 * vel.dx;
pos.y += 16 * vel.dy;
});
}
ENTT_API void assign_velocity(int vel, entt::registry &registry) {
ENTT_API void assign_velocity(entt::registry &registry) {
for(auto entity: registry.view<position>()) {
registry.assign<velocity>(entity, vel, vel);
registry.assign<velocity>(entity, 1., 1.);
}
}

View File

@@ -4,26 +4,24 @@
#include <entt/entity/registry.hpp>
#include "types.h"
ENTT_API void update_position(int, entt::registry &);
ENTT_API void assign_velocity(int, entt::registry &);
ENTT_API void update_position(entt::registry &);
ENTT_API void assign_velocity(entt::registry &);
TEST(Lib, Registry) {
entt::registry registry;
for(auto i = 0; i < 3; ++i) {
const auto entity = registry.create();
registry.assign<position>(entity, i, i+1);
registry.assign<position>(entity, i, i);
}
assign_velocity(2, registry);
assign_velocity(registry);
update_position(registry);
ASSERT_EQ(registry.size<position>(), 3u);
ASSERT_EQ(registry.size<velocity>(), 3u);
update_position(1, registry);
ASSERT_EQ(registry.size<position>(), registry.size<velocity>());
registry.view<position>().each([](auto entity, auto &position) {
ASSERT_EQ(position.x, entt::to_integral(entity) + 2);
ASSERT_EQ(position.y, entt::to_integral(entity) + 3);
ASSERT_EQ(position.x, entt::to_integral(entity) + 16);
ASSERT_EQ(position.y, entt::to_integral(entity) + 16);
});
}

View File

@@ -9,8 +9,8 @@ struct ENTT_API position {
};
struct ENTT_API velocity {
int dx;
int dy;
double dx;
double dy;
};
#endif // ENTT_LIB_REGISTRY_TYPES_H

View File

@@ -10,23 +10,19 @@ TEST(Lib, Registry) {
for(auto i = 0; i < 3; ++i) {
const auto entity = registry.create();
registry.assign<position>(entity, i, i+1);
registry.assign<position>(entity, i, i);
}
ASSERT_FALSE(registry.empty<position>());
ASSERT_TRUE(registry.empty<velocity>());
cr_plugin ctx;
ctx.userdata = &registry;
cr_plugin_load(ctx, PLUGIN);
cr_plugin_update(ctx);
ASSERT_FALSE(registry.empty<position>());
ASSERT_FALSE(registry.empty<velocity>());
ASSERT_EQ(registry.size<position>(), registry.size<velocity>());
registry.view<position>().each([](auto entity, auto &position) {
ASSERT_EQ(position.x, entt::to_integral(entity) + 2);
ASSERT_EQ(position.y, entt::to_integral(entity) + 3);
ASSERT_EQ(position.x, entt::to_integral(entity) + 16);
ASSERT_EQ(position.y, entt::to_integral(entity) + 16);
});
cr_plugin_close(ctx);

View File

@@ -7,21 +7,22 @@ CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
case CR_STEP:
[ctx]() {
auto *registry = static_cast<entt::registry *>(ctx->userdata);
registry->reset<velocity>();
for(auto entity: registry->view<position>()) {
registry->assign<velocity>(entity, 1, 1);
registry->assign<velocity>(entity, 1., 1.);
}
registry->view<position, velocity>().each([](auto &pos, auto &vel) {
pos.x += 2 * vel.dx;
pos.y += 2 * vel.dy;
pos.x += 16 * vel.dx;
pos.y += 16 * vel.dy;
});
}();
break;
case CR_CLOSE:
static_cast<entt::registry *>(ctx->userdata)->discard<velocity>();
break;
case CR_LOAD:
case CR_UNLOAD:
case CR_CLOSE:
// nothing to do here, this is only a test.
break;
}

View File

@@ -7,8 +7,8 @@ struct position {
};
struct velocity {
int dx;
int dy;
double dx;
double dy;
};
#endif // ENTT_PLUGIN_REGISTRY_TYPES_H