storage: uniform interface to simplify mixin implementation
This commit is contained in:
1
TODO
1
TODO
@@ -15,7 +15,6 @@ TODO (high prio):
|
||||
* check natvis files (periodically :)
|
||||
* remove the static storage from the const assure in the registry
|
||||
* pop_if to improve further destroying entities (drastically)
|
||||
* improve sigh mixin for entity storage (split basic + entt/entt spec)
|
||||
* doc: exclude only views, storage entity (and diff between iterator and each based iteration), bump entities, signals on entity creation/destruction
|
||||
* registry::destroy avoid pack if entity storage iterators already
|
||||
* registry: replace destroy with a drop-all method that doesn't care about validity
|
||||
|
||||
@@ -192,18 +192,46 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns entities to a storage.
|
||||
* @tparam Args Types of arguments to use to construct the object.
|
||||
* @param entt A valid identifier.
|
||||
* @param args Parameters to use to initialize the object.
|
||||
* @return A reference to the newly created object.
|
||||
* @brief Emplace elements into a storage.
|
||||
*
|
||||
* The behavior of this operation depends on the underlying storage type
|
||||
* (for example, components vs entities).<br/>
|
||||
* Refer to the specific documentation for more details.
|
||||
*
|
||||
* @return A return value as returned by the underlying storage.
|
||||
*/
|
||||
auto emplace() {
|
||||
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
|
||||
const auto entt = Type::emplace();
|
||||
construction.publish(*owner, entt);
|
||||
return entt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Emplace elements into a storage.
|
||||
*
|
||||
* The behavior of this operation depends on the underlying storage type
|
||||
* (for example, components vs entities).<br/>
|
||||
* Refer to the specific documentation for more details.
|
||||
*
|
||||
* @tparam Args Types of arguments to forward to the underlying storage.
|
||||
* @param hint A valid identifier.
|
||||
* @param args Parameters to forward to the underlying storage.
|
||||
* @return A return value as returned by the underlying storage.
|
||||
*/
|
||||
template<typename... Args>
|
||||
decltype(auto) emplace(const entity_type entt, Args &&...args) {
|
||||
decltype(auto) emplace(const entity_type hint, Args &&...args) {
|
||||
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
|
||||
Type::emplace(entt, std::forward<Args>(args)...);
|
||||
construction.publish(*owner, entt);
|
||||
return this->get(entt);
|
||||
|
||||
if constexpr(std::is_same_v<typename Type::value_type, typename Type::entity_type>) {
|
||||
const auto entt = Type::emplace(hint, std::forward<Args>(args)...);
|
||||
construction.publish(*owner, entt);
|
||||
return entt;
|
||||
} else {
|
||||
Type::emplace(hint, std::forward<Args>(args)...);
|
||||
construction.publish(*owner, hint);
|
||||
return this->get(hint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,14 +250,17 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns entities to a storage.
|
||||
* @tparam It Type of input iterator.
|
||||
* @tparam Args Types of arguments to use to construct the objects assigned
|
||||
* to the entities.
|
||||
* @param first An iterator to the first element of the range of entities.
|
||||
* @param last An iterator past the last element of the range of entities.
|
||||
* @param args Parameters to use to initialize the objects assigned to the
|
||||
* entities.
|
||||
* @brief Emplace elements into a storage.
|
||||
*
|
||||
* The behavior of this operation depends on the underlying storage type
|
||||
* (for example, components vs entities).<br/>
|
||||
* Refer to the specific documentation for more details.
|
||||
*
|
||||
* @tparam It Iterator type (as required by the underlying storage type).
|
||||
* @tparam Args Types of arguments to forward to the underlying storage.
|
||||
* @param first An iterator to the first element of the range.
|
||||
* @param last An iterator past the last element of the range.
|
||||
* @param args Parameters to use to forward to the underlying storage.
|
||||
*/
|
||||
template<typename It, typename... Args>
|
||||
void insert(It first, It last, Args &&...args) {
|
||||
@@ -244,52 +275,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new identifier or recycles a destroyed one.
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
entity_type spawn() {
|
||||
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
|
||||
const auto entt = Type::spawn();
|
||||
construction.publish(*owner, entt);
|
||||
return entt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new identifier or recycles a destroyed one.
|
||||
*
|
||||
* If the requested identifier isn't in use, the suggested one is used.
|
||||
* Otherwise, a new identifier is returned.
|
||||
*
|
||||
* @param hint Required identifier.
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
entity_type spawn(const entity_type hint) {
|
||||
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
|
||||
const auto entt = Type::spawn(hint);
|
||||
construction.publish(*owner, entt);
|
||||
return entt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns each element in a range an identifier.
|
||||
* @tparam It Type of mutable forward iterator.
|
||||
* @param first An iterator to the first element of the range to generate.
|
||||
* @param last An iterator past the last element of the range to generate.
|
||||
*/
|
||||
template<typename It>
|
||||
void spawn(It first, It last) {
|
||||
Type::spawn(first, last);
|
||||
|
||||
if(!construction.empty()) {
|
||||
ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
|
||||
|
||||
for(; first != last; ++first) {
|
||||
construction.publish(*owner, *first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Forwards variables to derived classes, if any.
|
||||
* @param value A variable wrapped in an opaque container.
|
||||
|
||||
@@ -588,7 +588,7 @@ public:
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
[[nodiscard]] entity_type create() {
|
||||
return shortcut->spawn();
|
||||
return shortcut->emplace();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,7 +601,7 @@ public:
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
[[nodiscard]] entity_type create(const entity_type hint) {
|
||||
return shortcut->spawn(hint);
|
||||
return shortcut->emplace(hint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,7 +615,7 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
void create(It first, It last) {
|
||||
shortcut->spawn(std::move(first), std::move(last));
|
||||
shortcut->insert(std::move(first), std::move(last));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -964,7 +964,7 @@ protected:
|
||||
* @return Iterator pointing to the emplaced element.
|
||||
*/
|
||||
underlying_iterator try_emplace(const Entity hint, const bool, const void *) override {
|
||||
return base_type::find(spawn(hint));
|
||||
return base_type::find(emplace(hint));
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1068,7 +1068,7 @@ public:
|
||||
* @brief Creates a new identifier or recycles a destroyed one.
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
entity_type spawn() {
|
||||
entity_type emplace() {
|
||||
if(length == base_type::size()) {
|
||||
return *base_type::try_emplace(entity_at(length++), true);
|
||||
}
|
||||
@@ -1085,9 +1085,9 @@ public:
|
||||
* @param hint Required identifier.
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
entity_type spawn(const entity_type hint) {
|
||||
entity_type emplace(const entity_type hint) {
|
||||
if(hint == null || hint == tombstone) {
|
||||
return spawn();
|
||||
return emplace();
|
||||
} else if(const auto curr = local_traits_type::construct(local_traits_type::to_entity(hint), base_type::current(hint)); curr == tombstone) {
|
||||
const auto pos = static_cast<size_type>(local_traits_type::to_entity(hint));
|
||||
|
||||
@@ -1097,7 +1097,7 @@ public:
|
||||
|
||||
base_type::swap_at(pos, length++);
|
||||
} else if(const auto idx = base_type::index(curr); idx < length) {
|
||||
return spawn();
|
||||
return emplace();
|
||||
} else {
|
||||
base_type::swap_at(idx, length++);
|
||||
}
|
||||
@@ -1114,7 +1114,7 @@ public:
|
||||
* @param last An iterator past the last element of the range to generate.
|
||||
*/
|
||||
template<typename It>
|
||||
void spawn(It first, It last) {
|
||||
void insert(It first, It last) {
|
||||
for(const auto sz = base_type::size(); first != last && length != sz; ++first, ++length) {
|
||||
*first = base_type::operator[](length);
|
||||
}
|
||||
|
||||
@@ -510,11 +510,11 @@ TEST(SighMixin, StorageEntity) {
|
||||
ASSERT_EQ(on_construct.value, 3);
|
||||
ASSERT_EQ(on_destroy.value, 3);
|
||||
|
||||
pool.spawn();
|
||||
pool.spawn(entt::entity{0});
|
||||
pool.emplace();
|
||||
pool.emplace(entt::entity{0});
|
||||
|
||||
entt::entity entities[1u]{};
|
||||
pool.spawn(entities, entities + 1u);
|
||||
pool.insert(entities, entities + 1u);
|
||||
|
||||
ASSERT_EQ(on_construct.value, 6);
|
||||
ASSERT_EQ(on_destroy.value, 3);
|
||||
|
||||
@@ -45,7 +45,7 @@ TEST(StorageEntity, Functionalities) {
|
||||
|
||||
ENTT_DEBUG_TEST(StorageEntityDeathTest, Get) {
|
||||
entt::storage<entt::entity> pool;
|
||||
pool.spawn(entt::entity{99});
|
||||
pool.emplace(entt::entity{99});
|
||||
|
||||
ASSERT_DEATH(pool.get(entt::entity{3}), "");
|
||||
ASSERT_DEATH([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{3}), "");
|
||||
@@ -187,18 +187,18 @@ TEST(StorageEntity, Push) {
|
||||
ASSERT_EQ(*pool.push(entt::null), entt::entity{7});
|
||||
}
|
||||
|
||||
TEST(StorageEntity, Spawn) {
|
||||
TEST(StorageEntity, Emplace) {
|
||||
using traits_type = entt::entt_traits<entt::entity>;
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
entt::entity entities[2u]{};
|
||||
|
||||
ASSERT_EQ(pool.spawn(), entt::entity{0});
|
||||
ASSERT_EQ(pool.spawn(entt::null), entt::entity{1});
|
||||
ASSERT_EQ(pool.spawn(entt::tombstone), entt::entity{2});
|
||||
ASSERT_EQ(pool.spawn(entt::entity{0}), entt::entity{3});
|
||||
ASSERT_EQ(pool.spawn(traits_type::construct(1, 1)), entt::entity{4});
|
||||
ASSERT_EQ(pool.spawn(traits_type::construct(6, 3)), traits_type::construct(6, 3));
|
||||
ASSERT_EQ(pool.emplace(), entt::entity{0});
|
||||
ASSERT_EQ(pool.emplace(entt::null), entt::entity{1});
|
||||
ASSERT_EQ(pool.emplace(entt::tombstone), entt::entity{2});
|
||||
ASSERT_EQ(pool.emplace(entt::entity{0}), entt::entity{3});
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(1, 1)), entt::entity{4});
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(6, 3)), traits_type::construct(6, 3));
|
||||
|
||||
ASSERT_LT(pool.index(entt::entity{0}), pool.in_use());
|
||||
ASSERT_LT(pool.index(entt::entity{1}), pool.in_use());
|
||||
@@ -208,15 +208,15 @@ TEST(StorageEntity, Spawn) {
|
||||
ASSERT_GE(pool.index(entt::entity{5}), pool.in_use());
|
||||
ASSERT_LT(pool.index(traits_type::construct(6, 3)), pool.in_use());
|
||||
|
||||
ASSERT_EQ(pool.spawn(traits_type::construct(5, 42)), traits_type::construct(5, 42));
|
||||
ASSERT_EQ(pool.spawn(traits_type::construct(5, 43)), entt::entity{7});
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(5, 42)), traits_type::construct(5, 42));
|
||||
ASSERT_EQ(pool.emplace(traits_type::construct(5, 43)), entt::entity{7});
|
||||
|
||||
pool.erase(entt::entity{2});
|
||||
|
||||
ASSERT_EQ(pool.spawn(), traits_type::construct(2, 1));
|
||||
ASSERT_EQ(pool.emplace(), traits_type::construct(2, 1));
|
||||
|
||||
pool.erase(traits_type::construct(2, 1));
|
||||
pool.spawn(entities, entities + 2u);
|
||||
pool.insert(entities, entities + 2u);
|
||||
|
||||
ASSERT_EQ(entities[0u], traits_type::construct(2, 2));
|
||||
ASSERT_EQ(entities[1u], entt::entity{8});
|
||||
@@ -256,9 +256,9 @@ TEST(StorageEntity, Iterable) {
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.spawn(entt::entity{1});
|
||||
pool.spawn(entt::entity{3});
|
||||
pool.spawn(entt::entity{42});
|
||||
pool.emplace(entt::entity{1});
|
||||
pool.emplace(entt::entity{3});
|
||||
pool.emplace(entt::entity{42});
|
||||
|
||||
pool.erase(entt::entity{3});
|
||||
|
||||
@@ -300,9 +300,9 @@ TEST(StorageEntity, ConstIterable) {
|
||||
|
||||
entt::storage<entt::entity> pool;
|
||||
|
||||
pool.spawn(entt::entity{1});
|
||||
pool.spawn(entt::entity{3});
|
||||
pool.spawn(entt::entity{42});
|
||||
pool.emplace(entt::entity{1});
|
||||
pool.emplace(entt::entity{3});
|
||||
pool.emplace(entt::entity{42});
|
||||
|
||||
pool.erase(entt::entity{3});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user