sparse_set: faster remove/range-remove
This commit is contained in:
@@ -174,6 +174,8 @@ class basic_sparse_set {
|
||||
}
|
||||
|
||||
virtual void swap_at(const std::size_t, const std::size_t) {}
|
||||
virtual void swap_and_pop(const std::size_t) {}
|
||||
virtual void clear_all() {}
|
||||
|
||||
public:
|
||||
/*! @brief Underlying entity identifier. */
|
||||
@@ -419,14 +421,18 @@ public:
|
||||
*
|
||||
* @param entt A valid entity identifier.
|
||||
*/
|
||||
virtual void remove(const entity_type entt) {
|
||||
void remove(const entity_type entt) {
|
||||
ENTT_ASSERT(contains(entt));
|
||||
const auto curr = page(entt);
|
||||
const auto pos = offset(entt);
|
||||
packed[size_type{to_integral(sparse[curr][pos])}] = packed.back();
|
||||
sparse[page(packed.back())][offset(packed.back())] = sparse[curr][pos];
|
||||
sparse[curr][pos] = null;
|
||||
auto &ref = sparse[page(entt)][offset(entt)];
|
||||
const auto pos = size_type{to_integral(ref)};
|
||||
const auto other = packed.back();
|
||||
|
||||
sparse[page(other)][offset(other)] = ref;
|
||||
packed[pos] = other;
|
||||
ref = null;
|
||||
|
||||
packed.pop_back();
|
||||
swap_and_pop(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,9 +469,9 @@ public:
|
||||
void swap(const entity_type lhs, const entity_type rhs) {
|
||||
const auto from = index(lhs);
|
||||
const auto to = index(rhs);
|
||||
swap_at(from, to);
|
||||
std::swap(sparse[page(lhs)][offset(lhs)], sparse[page(rhs)][offset(rhs)]);
|
||||
std::swap(packed[from], packed[to]);
|
||||
swap_at(from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,12 +575,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears a sparse set.
|
||||
*/
|
||||
virtual void clear() ENTT_NOEXCEPT {
|
||||
/*! @brief Clears a sparse set. */
|
||||
void clear() ENTT_NOEXCEPT {
|
||||
sparse.clear();
|
||||
packed.clear();
|
||||
clear_all();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -160,6 +160,15 @@ class basic_storage: public basic_sparse_set<Entity> {
|
||||
std::swap(instances[lhs], instances[rhs]);
|
||||
}
|
||||
|
||||
void swap_and_pop(const std::size_t pos) final {
|
||||
instances[pos] = std::move(instances.back());
|
||||
instances.pop_back();
|
||||
}
|
||||
|
||||
void clear_all() ENTT_NOEXCEPT final {
|
||||
instances.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Type of the objects associated with the entities. */
|
||||
using value_type = Type;
|
||||
@@ -413,33 +422,6 @@ public:
|
||||
underlying_type::insert(first, last);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes an entity from a storage and destroys its object.
|
||||
*
|
||||
* @warning
|
||||
* Attempting to use an entity that doesn't belong to the storage results in
|
||||
* undefined behavior.
|
||||
*
|
||||
* @param entt A valid entity identifier.
|
||||
*/
|
||||
void remove(const entity_type entt) final {
|
||||
auto other = std::move(instances.back());
|
||||
instances[underlying_type::index(entt)] = std::move(other);
|
||||
instances.pop_back();
|
||||
underlying_type::remove(entt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes multiple entities from a storage.
|
||||
* @tparam It Type of input iterator.
|
||||
* @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.
|
||||
*/
|
||||
template<typename It>
|
||||
void remove(It first, It last) {
|
||||
underlying_type::remove(first, last);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sort elements according to the given comparison function.
|
||||
*
|
||||
@@ -503,12 +485,6 @@ public:
|
||||
sort_n(size(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/*! @brief Clears a storage. */
|
||||
void clear() ENTT_NOEXCEPT final {
|
||||
underlying_type::clear();
|
||||
instances.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<value_type> instances;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user