registry: make entity storage storage as any other
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
</Intrinsic>
|
||||
<DisplayString>{{ pools={ pools.size() } }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[entities]">*entities</Item>
|
||||
<Item Name="[entities]">shortcut,na</Item>
|
||||
<Synthetic Name="[pools]">
|
||||
<DisplayString>{ pools.size() }</DisplayString>
|
||||
<Expand>
|
||||
|
||||
@@ -338,8 +338,6 @@ class basic_registry {
|
||||
}
|
||||
|
||||
void rebind() {
|
||||
entities->bind(forward_as_any(*this));
|
||||
|
||||
for(auto &&curr: pools) {
|
||||
curr.second->bind(forward_as_any(*this));
|
||||
}
|
||||
@@ -347,11 +345,11 @@ class basic_registry {
|
||||
|
||||
public:
|
||||
/*! @brief Entity traits. */
|
||||
using traits_type = entt_traits<Entity>;
|
||||
using traits_type = typename basic_common_type::traits_type;
|
||||
/*! @brief Allocator type. */
|
||||
using allocator_type = Allocator;
|
||||
/*! @brief Underlying entity identifier. */
|
||||
using entity_type = Entity;
|
||||
using entity_type = typename traits_type::value_type;
|
||||
/*! @brief Underlying version type. */
|
||||
using version_type = typename traits_type::version_type;
|
||||
/*! @brief Unsigned integer type. */
|
||||
@@ -380,7 +378,7 @@ public:
|
||||
basic_registry(const size_type count, const allocator_type &allocator = allocator_type{})
|
||||
: vars{allocator},
|
||||
pools{allocator},
|
||||
entities{std::allocate_shared<storage_for_type<entity_type>>(allocator, allocator)},
|
||||
shortcut{&assure<entity_type>()},
|
||||
groups{allocator} {
|
||||
pools.reserve(count);
|
||||
rebind();
|
||||
@@ -393,7 +391,7 @@ public:
|
||||
basic_registry(basic_registry &&other) noexcept
|
||||
: vars{std::move(other.vars)},
|
||||
pools{std::move(other.pools)},
|
||||
entities{std::move(other.entities)},
|
||||
shortcut{std::move(other.shortcut)},
|
||||
groups{std::move(other.groups)} {
|
||||
rebind();
|
||||
}
|
||||
@@ -406,7 +404,7 @@ public:
|
||||
basic_registry &operator=(basic_registry &&other) noexcept {
|
||||
vars = std::move(other.vars);
|
||||
pools = std::move(other.pools);
|
||||
entities = std::move(other.entities);
|
||||
shortcut = std::move(other.shortcut);
|
||||
groups = std::move(other.groups);
|
||||
|
||||
rebind();
|
||||
@@ -423,7 +421,7 @@ public:
|
||||
|
||||
swap(vars, other.vars);
|
||||
swap(pools, other.pools);
|
||||
swap(entities, other.entities);
|
||||
swap(shortcut, other.shortcut);
|
||||
swap(groups, other.groups);
|
||||
|
||||
rebind();
|
||||
@@ -506,7 +504,7 @@ public:
|
||||
* @return Number of entities created so far.
|
||||
*/
|
||||
[[nodiscard]] size_type size() const noexcept {
|
||||
return entities->size();
|
||||
return shortcut->size();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,7 +512,7 @@ public:
|
||||
* @return Number of entities still in use.
|
||||
*/
|
||||
[[nodiscard]] size_type alive() const {
|
||||
return entities->in_use();
|
||||
return shortcut->in_use();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -522,7 +520,7 @@ public:
|
||||
* @param cap Desired capacity.
|
||||
*/
|
||||
void reserve(const size_type cap) {
|
||||
entities->reserve(cap);
|
||||
shortcut->reserve(cap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,7 +529,7 @@ public:
|
||||
* @return Capacity of the registry.
|
||||
*/
|
||||
[[nodiscard]] size_type capacity() const noexcept {
|
||||
return entities->capacity();
|
||||
return shortcut->capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,7 +553,7 @@ public:
|
||||
* @return A pointer to the array of entities.
|
||||
*/
|
||||
[[nodiscard]] const entity_type *data() const noexcept {
|
||||
return entities->data();
|
||||
return shortcut->data();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -563,7 +561,7 @@ public:
|
||||
* @return The number of released entities.
|
||||
*/
|
||||
[[nodiscard]] size_type released() const noexcept {
|
||||
return (entities->size() - entities->in_use());
|
||||
return (shortcut->size() - shortcut->in_use());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -572,7 +570,7 @@ public:
|
||||
* @return True if the identifier is valid, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool valid(const entity_type entt) const {
|
||||
return entities->contains(entt);
|
||||
return shortcut->contains(entt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -582,7 +580,7 @@ public:
|
||||
* version otherwise.
|
||||
*/
|
||||
[[nodiscard]] version_type current(const entity_type entt) const {
|
||||
return entities->current(entt);
|
||||
return shortcut->current(entt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,7 +588,7 @@ public:
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
[[nodiscard]] entity_type create() {
|
||||
return entities->spawn();
|
||||
return shortcut->spawn();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -603,7 +601,7 @@ public:
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
[[nodiscard]] entity_type create(const entity_type hint) {
|
||||
return entities->spawn(hint);
|
||||
return shortcut->spawn(hint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -617,7 +615,7 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
void create(It first, It last) {
|
||||
entities->spawn(std::move(first), std::move(last));
|
||||
shortcut->spawn(std::move(first), std::move(last));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,9 +637,9 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
void assign(It first, It last, const size_type destroyed) {
|
||||
ENTT_ASSERT(!entities->in_use(), "Non-empty registry");
|
||||
entities->push(first, last);
|
||||
entities->in_use(entities->size() - destroyed);
|
||||
ENTT_ASSERT(!shortcut->in_use(), "Non-empty registry");
|
||||
shortcut->push(first, last);
|
||||
shortcut->in_use(shortcut->size() - destroyed);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -657,8 +655,8 @@ public:
|
||||
*/
|
||||
version_type release(const entity_type entt) {
|
||||
ENTT_ASSERT(orphan(entt), "Non-orphan entity");
|
||||
entities->erase(entt);
|
||||
return entities->current(entt);
|
||||
shortcut->erase(entt);
|
||||
return shortcut->current(entt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -674,9 +672,10 @@ public:
|
||||
* @return The version actually assigned to the entity.
|
||||
*/
|
||||
version_type release(const entity_type entt, const version_type version) {
|
||||
release(entt);
|
||||
ENTT_ASSERT(orphan(entt), "Non-orphan entity");
|
||||
const auto vers = static_cast<version_type>(version + (version == traits_type::to_version(tombstone)));
|
||||
entities->bump(traits_type::construct(traits_type::to_entity(entt), vers));
|
||||
shortcut->erase(entt);
|
||||
shortcut->bump(traits_type::construct(traits_type::to_entity(entt), vers));
|
||||
return vers;
|
||||
}
|
||||
|
||||
@@ -691,7 +690,8 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
void release(It first, It last) {
|
||||
entities->erase(std::move(first), std::move(last));
|
||||
ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return orphan(entt); }), "Non-orphan entity");
|
||||
shortcut->erase(std::move(first), std::move(last));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -724,8 +724,10 @@ public:
|
||||
* @return The version actually assigned to the entity.
|
||||
*/
|
||||
version_type destroy(const entity_type entt, const version_type version) {
|
||||
for(size_type pos = pools.size(); pos; --pos) {
|
||||
pools.begin()[pos - 1u].second->remove(entt);
|
||||
ENTT_ASSERT(!pools.empty() && (pools.begin()->second.get() == shortcut), "Misplaced entity pool");
|
||||
|
||||
for(size_type pos = pools.size() - 1u; pos; --pos) {
|
||||
pools.begin()[pos].second->remove(entt);
|
||||
}
|
||||
|
||||
return release(entt, version);
|
||||
@@ -742,15 +744,17 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
void destroy(It first, It last) {
|
||||
const auto len = entities->pack(first, last);
|
||||
auto from = entities->each().cbegin().base();
|
||||
ENTT_ASSERT(!pools.empty() && (pools.begin()->second.get() == shortcut), "Misplaced entity pool");
|
||||
|
||||
const auto len = shortcut->pack(first, last);
|
||||
auto from = shortcut->each().cbegin().base();
|
||||
const auto to = from + len;
|
||||
|
||||
for(size_type pos = pools.size(); pos; --pos) {
|
||||
pools.begin()[pos - 1u].second->remove(from, to);
|
||||
for(size_type pos = pools.size() - 1u; pos; --pos) {
|
||||
pools.begin()[pos].second->remove(from, to);
|
||||
}
|
||||
|
||||
entities->erase(from, to);
|
||||
release(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1106,12 +1110,14 @@ public:
|
||||
template<typename... Type>
|
||||
void clear() {
|
||||
if constexpr(sizeof...(Type) == 0) {
|
||||
for(size_type pos = pools.size(); pos; --pos) {
|
||||
pools.begin()[pos - 1u].second->clear();
|
||||
ENTT_ASSERT(!pools.empty() && (pools.begin()->second.get() == shortcut), "Misplaced entity pool");
|
||||
|
||||
for(size_type pos = pools.size() - 1u; pos; --pos) {
|
||||
pools.begin()[pos].second->clear();
|
||||
}
|
||||
|
||||
auto iterable = entities->each();
|
||||
entities->erase(iterable.begin().base(), iterable.end().base());
|
||||
auto iterable = shortcut->each();
|
||||
shortcut->erase(iterable.begin().base(), iterable.end().base());
|
||||
} else {
|
||||
(assure<Type>().clear(), ...);
|
||||
}
|
||||
@@ -1133,7 +1139,7 @@ public:
|
||||
*/
|
||||
template<typename Func>
|
||||
void each(Func func) const {
|
||||
for(auto [entt]: entities->each()) {
|
||||
for(auto [entt]: shortcut->each()) {
|
||||
func(entt);
|
||||
}
|
||||
}
|
||||
@@ -1144,7 +1150,7 @@ public:
|
||||
* @return True if the entity has no components assigned, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool orphan(const entity_type entt) const {
|
||||
return std::none_of(pools.cbegin(), pools.cend(), [entt](auto &&curr) { return curr.second->contains(entt); });
|
||||
return std::none_of(++pools.cbegin(), pools.cend(), [entt](auto &&curr) { return curr.second->contains(entt); });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1481,7 +1487,7 @@ public:
|
||||
private:
|
||||
context vars;
|
||||
container_type pools;
|
||||
std::shared_ptr<storage_for_type<entity_type>> entities;
|
||||
storage_for_type<entity_type> *shortcut;
|
||||
std::vector<group_data, typename alloc_traits::template rebind_alloc<group_data>> groups;
|
||||
};
|
||||
|
||||
|
||||
@@ -171,10 +171,17 @@ TEST(BasicHandle, Component) {
|
||||
ASSERT_TRUE(registry.storage<double>().empty());
|
||||
ASSERT_EQ(0u, (handle.remove<char, double>()));
|
||||
|
||||
for(auto [id, pool]: handle.storage()) {
|
||||
ASSERT_EQ(id, entt::type_id<int>().hash());
|
||||
ASSERT_TRUE(pool.contains(handle.entity()));
|
||||
}
|
||||
auto it = handle.storage().begin();
|
||||
|
||||
ASSERT_NE(it, handle.storage().end());
|
||||
ASSERT_EQ(it->first, entt::type_id<entt::entity>().hash());
|
||||
ASSERT_TRUE(it->second.contains(handle.entity()));
|
||||
|
||||
ASSERT_NE(++it, handle.storage().end());
|
||||
ASSERT_EQ(it->first, entt::type_id<int>().hash());
|
||||
ASSERT_TRUE(it->second.contains(handle.entity()));
|
||||
|
||||
ASSERT_EQ(++it, handle.storage().end());
|
||||
|
||||
ASSERT_TRUE((handle.any_of<int, char, double>()));
|
||||
ASSERT_FALSE((handle.all_of<int, char, double>()));
|
||||
@@ -253,20 +260,37 @@ TEST(BasicHandle, Storage) {
|
||||
static_assert(std::is_same_v<decltype(*handle.storage().begin()), std::pair<entt::id_type, entt::sparse_set &>>);
|
||||
static_assert(std::is_same_v<decltype(*chandle.storage().begin()), std::pair<entt::id_type, const entt::sparse_set &>>);
|
||||
|
||||
ASSERT_EQ(handle.storage().begin(), handle.storage().end());
|
||||
ASSERT_EQ(chandle.storage().begin(), chandle.storage().end());
|
||||
auto it = handle.storage().begin();
|
||||
auto cit = chandle.storage().begin();
|
||||
|
||||
ASSERT_NE(it, handle.storage().end());
|
||||
ASSERT_EQ(++it, handle.storage().end());
|
||||
|
||||
ASSERT_NE(cit, chandle.storage().end());
|
||||
ASSERT_EQ(++cit, chandle.storage().end());
|
||||
|
||||
registry.storage<double>();
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
ASSERT_NE(handle.storage().begin(), handle.storage().end());
|
||||
ASSERT_NE(chandle.storage().begin(), chandle.storage().end());
|
||||
it = handle.storage().begin();
|
||||
cit = chandle.storage().begin();
|
||||
|
||||
ASSERT_EQ(++handle.storage().begin(), handle.storage().end());
|
||||
ASSERT_EQ(++chandle.storage().begin(), chandle.storage().end());
|
||||
ASSERT_EQ(it++, handle.storage().begin());
|
||||
ASSERT_NE(it, handle.storage().end());
|
||||
ASSERT_EQ(++it, handle.storage().end());
|
||||
|
||||
ASSERT_EQ(handle.storage().begin()->second.type(), entt::type_id<int>());
|
||||
ASSERT_EQ(chandle.storage().begin()->second.type(), entt::type_id<int>());
|
||||
ASSERT_EQ(cit++, chandle.storage().begin());
|
||||
ASSERT_NE(cit, chandle.storage().end());
|
||||
ASSERT_EQ(++cit, chandle.storage().end());
|
||||
|
||||
it = handle.storage().begin();
|
||||
cit = chandle.storage().begin();
|
||||
|
||||
ASSERT_EQ(it->second.type(), entt::type_id<entt::entity>());
|
||||
ASSERT_EQ((++it)->second.type(), entt::type_id<int>());
|
||||
|
||||
ASSERT_EQ(cit->second.type(), entt::type_id<entt::entity>());
|
||||
ASSERT_EQ((++cit)->second.type(), entt::type_id<int>());
|
||||
}
|
||||
|
||||
TEST(BasicHandle, HandleStorageIterator) {
|
||||
@@ -274,7 +298,6 @@ TEST(BasicHandle, HandleStorageIterator) {
|
||||
const auto entity = registry.create();
|
||||
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<double>(entity);
|
||||
|
||||
auto test = [](auto iterable) {
|
||||
auto end{iterable.begin()};
|
||||
|
||||
@@ -2116,23 +2116,22 @@ TEST(Registry, Storage) {
|
||||
auto &storage = registry.storage<int>("int"_hs);
|
||||
storage.emplace(entity);
|
||||
|
||||
for(auto [id, pool]: registry.storage()) {
|
||||
static_assert(std::is_same_v<decltype(pool), entt::sparse_set &>);
|
||||
static_assert(std::is_same_v<decltype(id), entt::id_type>);
|
||||
auto it = ++registry.storage().begin();
|
||||
auto cit = std::as_const(registry).storage().begin();
|
||||
|
||||
ASSERT_TRUE(pool.contains(entity));
|
||||
ASSERT_EQ(std::addressof(storage), std::addressof(pool));
|
||||
ASSERT_EQ(id, "int"_hs);
|
||||
}
|
||||
static_assert(std::is_same_v<decltype(it->first), entt::id_type>);
|
||||
static_assert(std::is_same_v<decltype(it->second), entt::sparse_set &>);
|
||||
|
||||
for(auto &&curr: std::as_const(registry).storage()) {
|
||||
static_assert(std::is_same_v<decltype(curr.second), const entt::sparse_set &>);
|
||||
static_assert(std::is_same_v<decltype(curr.first), entt::id_type>);
|
||||
static_assert(std::is_same_v<decltype(cit->first), entt::id_type>);
|
||||
static_assert(std::is_same_v<decltype(cit->second), const entt::sparse_set &>);
|
||||
|
||||
ASSERT_TRUE(curr.second.contains(entity));
|
||||
ASSERT_EQ(std::addressof(storage), std::addressof(curr.second));
|
||||
ASSERT_EQ(curr.first, "int"_hs);
|
||||
}
|
||||
ASSERT_TRUE(it->second.contains(entity));
|
||||
ASSERT_EQ(std::addressof(storage), std::addressof(it->second));
|
||||
ASSERT_EQ(it->first, "int"_hs);
|
||||
|
||||
ASSERT_TRUE(cit->second.contains(entity));
|
||||
ASSERT_NE(std::addressof(storage), std::addressof(cit->second));
|
||||
ASSERT_EQ(cit->first, entt::type_id<entt::entity>().hash());
|
||||
}
|
||||
|
||||
TEST(Registry, VoidType) {
|
||||
@@ -2154,7 +2153,6 @@ TEST(Registry, VoidType) {
|
||||
TEST(Registry, RegistryStorageIterator) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
auto test = [entity](auto iterable) {
|
||||
auto end{iterable.begin()};
|
||||
@@ -2193,7 +2191,7 @@ TEST(Registry, RegistryStorageIterator) {
|
||||
ASSERT_GT(end, begin);
|
||||
ASSERT_GE(end, iterable.end());
|
||||
|
||||
ASSERT_EQ(begin[0u].first, entt::type_id<int>().hash());
|
||||
ASSERT_EQ(begin[0u].first, entt::type_id<entt::entity>().hash());
|
||||
ASSERT_TRUE(begin[0u].second.contains(entity));
|
||||
};
|
||||
|
||||
@@ -2209,7 +2207,6 @@ TEST(Registry, RegistryStorageIterator) {
|
||||
TEST(Registry, RegistryStorageIteratorConversion) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
auto proxy = registry.storage();
|
||||
auto cproxy = std::as_const(registry).storage();
|
||||
@@ -2220,8 +2217,8 @@ TEST(Registry, RegistryStorageIteratorConversion) {
|
||||
static_assert(std::is_same_v<decltype(*it), std::pair<entt::id_type, entt::sparse_set &>>);
|
||||
static_assert(std::is_same_v<decltype(*cit), std::pair<entt::id_type, const entt::sparse_set &>>);
|
||||
|
||||
ASSERT_EQ(it->first, entt::type_id<int>().hash());
|
||||
ASSERT_EQ((*it).second.type(), entt::type_id<int>());
|
||||
ASSERT_EQ(it->first, entt::type_id<entt::entity>().hash());
|
||||
ASSERT_EQ((*it).second.type(), entt::type_id<entt::entity>());
|
||||
ASSERT_EQ(it->first, cit->first);
|
||||
ASSERT_EQ((*it).second.type(), (*cit).second.type());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user