added Registry::data/::raw

This commit is contained in:
Michele Caini
2018-04-20 16:23:39 +02:00
parent fda44063ce
commit cf5074bdc5
3 changed files with 96 additions and 27 deletions

View File

@@ -72,9 +72,15 @@ class Registry {
};
template<typename Component>
const SparseSet<Entity, Component> & pool() const ENTT_NOEXCEPT {
bool managed() const ENTT_NOEXCEPT {
const auto ctype = component_family::type<Component>();
return ctype < pools.size() && std::get<0>(pools[ctype]);
}
template<typename Component>
const SparseSet<Entity, Component> & pool() const ENTT_NOEXCEPT {
assert(managed<Component>());
const auto ctype = component_family::type<Component>();
assert(ctype < pools.size() && std::get<0>(pools[ctype]));
return static_cast<SparseSet<Entity, Component> &>(*std::get<0>(pools[ctype]));
}
@@ -175,8 +181,7 @@ public:
*/
template<typename Component>
size_type size() const ENTT_NOEXCEPT {
const auto ctype = component_family::type<Component>();
return ((ctype < pools.size()) && std::get<0>(pools[ctype])) ? std::get<0>(pools[ctype])->size() : size_type{};
return managed<Component>() ? pool<Component>().size() : size_type{};
}
/**
@@ -230,8 +235,7 @@ public:
*/
template<typename Component>
bool empty() const ENTT_NOEXCEPT {
const auto ctype = component_family::type<Component>();
return (!(ctype < pools.size()) || !std::get<0>(pools[ctype]) || std::get<0>(pools[ctype])->empty());
return !managed<Component>() || pool<Component>().empty();
}
/**
@@ -242,6 +246,63 @@ public:
return entities.size() == available;
}
/**
* @brief Direct access to the list of components of a given pool.
*
* The returned pointer is such that range
* `[raw<Component>(), raw<Component>() + size<Component>()]` is always a
* valid range, even if the container is empty.
*
* @note
* There are no guarantees on the order of the components. Use a view if you
* want to iterate entities and components in the expected order.
*
* @tparam Component Type of component in which one is interested.
* @return A pointer to the array of components of the given type.
*/
template<typename Component>
const Component * raw() const ENTT_NOEXCEPT {
return managed<Component>() ? pool<Component>().raw() : nullptr;
}
/**
* @brief Direct access to the list of components of a given pool.
*
* The returned pointer is such that range
* `[raw<Component>(), raw<Component>() + size<Component>()]` is always a
* valid range, even if the container is empty.
*
* @note
* There are no guarantees on the order of the components. Use a view if you
* want to iterate entities and components in the expected order.
*
* @tparam Component Type of component in which one is interested.
* @return A pointer to the array of components of the given type.
*/
template<typename Component>
Component * raw() ENTT_NOEXCEPT {
return const_cast<Component *>(const_cast<const Registry *>(this)->raw<Component>());
}
/**
* @brief Direct access to the list of entities of a given pool.
*
* The returned pointer is such that range
* `[data<Component>(), data<Component>() + size<Component>()]` is always a
* valid range, even if the container is empty.
*
* @note
* There are no guarantees on the order of the entities. Use a view if you
* want to iterate entities and components in the expected order.
*
* @tparam Component Type of component in which one is interested.
* @return A pointer to the array of entities.
*/
template<typename Component>
const entity_type * data() const ENTT_NOEXCEPT {
return managed<Component>() ? pool<Component>().data() : nullptr;
}
/**
* @brief Checks if an entity identifier refers to a valid entity.
* @param entity An entity identifier, either valid or not.
@@ -480,8 +541,8 @@ public:
template<typename Component>
void remove(entity_type entity) {
assert(valid(entity));
assert(managed<Component>());
const auto ctype = component_family::type<Component>();
assert(ctype < pools.size() && std::get<0>(pools[ctype]));
std::get<2>(pools[ctype]).publish(*this, entity);
pool<Component>().destroy(entity);
}
@@ -522,9 +583,8 @@ public:
assert(valid(entity));
using accumulator_type = bool[];
bool all = true;
auto test = [entity, this](auto ctype) { return (ctype < pools.size()) && std::get<0>(pools[ctype]) && std::get<0>(pools[ctype])->has(entity); };
accumulator_type accumulator = { all, (all = all && test(component_family::type<Component>()))... };
(void)test, (void)accumulator;
accumulator_type accumulator = { all, (all = all && managed<Component>() && pool<Component>().has(entity))... };
(void)accumulator;
return all;
}
@@ -580,9 +640,8 @@ public:
template<typename Component>
const Component & get(entity_type entity) const ENTT_NOEXCEPT {
assert(valid(entity));
const auto ctype = component_family::type<Component>();
assert((ctype < pools.size()) && std::get<0>(pools[ctype]));
return static_cast<SparseSet<Entity, Component> &>(*std::get<0>(pools[ctype])).get(entity);
assert(managed<Component>());
return pool<Component>().get(entity);
}
/**
@@ -1315,7 +1374,6 @@ public:
*/
Snapshot<Entity> snapshot() const {
using follow_fn_type = entity_type(*)(const Registry &, entity_type);
using raw_fn_type = const entity_type *(*)(const Registry &, component_type);
const entity_type seed = available ? (next | (entities[next] & ~traits_type::entity_mask)) : next;
follow_fn_type follow = [](const Registry &registry, entity_type entity) -> entity_type {
@@ -1325,12 +1383,7 @@ public:
return (next | (entities[next] & ~traits_type::entity_mask));
};
raw_fn_type raw = [](const Registry &registry, component_type component) -> const entity_type * {
const auto &pools = registry.pools;
return (component < pools.size() && std::get<0>(pools[component])) ? std::get<0>(pools[component])->data() : nullptr;
};
return { *this, seed, available, follow, raw };
return { *this, seed, available, follow };
}
/**

View File

@@ -40,21 +40,18 @@ class Snapshot final {
friend class Registry<Entity>;
using follow_fn_type = Entity(*)(const Registry<Entity> &, Entity);
using raw_fn_type = const Entity *(*)(const Registry<Entity> &, typename Registry<Entity>::component_type);
Snapshot(const Registry<Entity> &registry, Entity seed, std::size_t size, follow_fn_type follow, raw_fn_type raw) ENTT_NOEXCEPT
Snapshot(const Registry<Entity> &registry, Entity seed, std::size_t size, follow_fn_type follow) ENTT_NOEXCEPT
: registry{registry},
seed{seed},
size{size},
follow{follow},
raw{raw}
follow{follow}
{}
template<typename Component, typename Archive>
void get(Archive &archive, const Registry<Entity> &registry) {
const auto component = registry.template type<Component>();
const auto sz = registry.template size<Component>();
const auto *entities = raw(registry, component);
const auto *entities = registry.template data<Component>();
archive(static_cast<Entity>(sz));
@@ -176,7 +173,6 @@ private:
const Entity seed;
const std::size_t size;
follow_fn_type follow;
raw_fn_type raw;
};

View File

@@ -195,6 +195,26 @@ TEST(DefaultRegistry, Functionalities) {
ASSERT_TRUE(registry.empty<int>());
}
TEST(DefaultRegistry, RawData) {
entt::DefaultRegistry registry;
const entt::DefaultRegistry &cregistry = registry;
const auto entity = registry.create();
ASSERT_EQ(registry.raw<int>(), nullptr);
ASSERT_EQ(cregistry.raw<int>(), nullptr);
ASSERT_EQ(cregistry.data<int>(), nullptr);
registry.assign<int>(entity, 42);
ASSERT_NE(registry.raw<int>(), nullptr);
ASSERT_NE(cregistry.raw<int>(), nullptr);
ASSERT_NE(cregistry.data<int>(), nullptr);
ASSERT_EQ(*registry.raw<int>(), 42);
ASSERT_EQ(*cregistry.raw<int>(), 42);
ASSERT_EQ(*cregistry.data<int>(), entity);
}
TEST(DefaultRegistry, CreateDestroyCornerCase) {
entt::DefaultRegistry registry;