1 #ifndef ENTT_ENTITY_SPARSE_SET_HPP 2 #define ENTT_ENTITY_SPARSE_SET_HPP 11 #include <type_traits> 55 template<
typename Entity>
60 using value_type = Entity;
62 Iterator(
const std::vector<Entity> *direct, std::size_t pos)
63 : direct{direct}, pos{pos}
66 Iterator & operator++() noexcept {
70 Iterator operator++(
int) noexcept {
71 Iterator orig = *
this;
72 return ++(*this), orig;
75 bool operator==(
const Iterator &other)
const noexcept {
76 return other.pos == pos && other.direct == direct;
79 bool operator!=(
const Iterator &other)
const noexcept {
80 return !(*
this == other);
83 value_type operator*()
const noexcept {
84 return (*direct)[pos-1];
88 const std::vector<Entity> *direct;
92 static constexpr Entity in_use = (Entity{1} << traits_type::entity_shift);
129 reverse.reserve(cap);
144 return direct.size();
152 return direct.empty();
171 return direct.data();
187 return Iterator{&direct, direct.size()};
204 return Iterator{&direct, 0};
215 const auto entt = promotion_type{entity} & traits_type::entity_mask;
217 return (
entt < reverse.size()) && (reverse[
entt] & in_use);
234 const auto entt = entity & traits_type::entity_mask;
236 return reverse[
entt] & ~in_use;
251 assert(!has(entity));
254 const auto entt = promotion_type{entity} & traits_type::entity_mask;
256 if(!(
entt < reverse.size())) {
263 direct.emplace_back(entity);
279 const auto entt = entity & traits_type::entity_mask;
280 const auto back = direct.back() & traits_type::entity_mask;
281 const auto pos = reverse[
entt] & ~in_use;
284 reverse[back] = pos | in_use;
287 direct[pos] = direct.back();
307 assert(lhs < direct.size());
308 assert(rhs < direct.size());
309 const auto src = direct[lhs] & traits_type::entity_mask;
310 const auto dst = direct[rhs] & traits_type::entity_mask;
311 std::swap(reverse[src], reverse[dst]);
312 std::swap(direct[lhs], direct[rhs]);
335 auto from = other.begin();
336 auto to = other.end();
340 while(pos > 0 && from != to) {
342 if(*from != direct[pos]) {
343 swap(pos,
get(*from));
362 std::vector<pos_type> reverse;
363 std::vector<entity_type> direct;
389 template<
typename Entity,
typename Type>
427 underlying_type::reserve(cap);
428 instances.reserve(cap);
447 return instances.data();
466 return instances.data();
482 return instances[underlying_type::get(entity)];
515 template<
typename... Args>
517 underlying_type::construct(entity);
519 instances.push_back({ std::forward<Args>(args)... });
520 return instances.back();
536 instances[underlying_type::get(entity)] = std::move(instances.back());
537 instances.pop_back();
538 underlying_type::destroy(entity);
563 template<
typename Compare>
565 std::vector<pos_type> copy(instances.size());
566 std::iota(copy.begin(), copy.end(), 0);
568 std::sort(copy.begin(), copy.end(), [
this, compare = std::move(compare)](
auto lhs,
auto rhs) {
569 return compare(const_cast<const object_type &>(instances[rhs]), const_cast<const object_type &>(instances[lhs]));
572 for(
pos_type pos = 0, last = copy.size(); pos < last; ++pos) {
574 auto next = copy[curr];
576 while(curr != next) {
577 auto lhs = copy[curr];
578 auto rhs = copy[next];
579 std::swap(instances[lhs], instances[rhs]);
580 underlying_type::swap(lhs, rhs);
611 auto from = other.begin();
612 auto to = other.end();
614 pos_type pos = underlying_type::size() - 1;
615 const auto *direct = underlying_type::data();
617 while(pos > 0 && from != to) {
618 if(underlying_type::has(*from)) {
619 if(*from != *(direct + pos)) {
620 auto candidate = underlying_type::get(*from);
621 std::swap(instances[pos], instances[candidate]);
622 underlying_type::swap(pos, candidate);
636 underlying_type::reset();
641 std::vector<object_type> instances;
648 #endif // ENTT_ENTITY_SPARSE_SET_HPP void sort(Compare compare)
Sort components according to the given comparison function.
virtual void reset()
Resets a sparse set.
void reset() override
Resets a sparse set.
const object_type * raw() const noexcept
Direct access to the array of objects.
bool empty() const noexcept
Checks whether a sparse set is empty.
void respect(const SparseSet< Entity > &other) noexcept override
Sort components according to the order of the entities in another sparse set.
std::size_t size_type
Unsigned integer type.
Extended sparse set implementation.
void destroy(entity_type entity) override
Removes an entity from a sparse set and destroies its object.
Entity entity_type
Underlying entity identifier.
Iterator iterator_type
Input iterator type.
Basic sparse set implementation.
bool has(entity_type entity) const noexcept
Checks if a sparse set contains an entity.
entity_type pos_type
Entity dependent position type.
Type object_type
Type of the objects associated to the entities.
const entity_type * data() const noexcept
Direct access to the internal packed array.
iterator_type end() const noexcept
Returns an iterator to the end.
virtual void destroy(entity_type entity)
Removes an entity from a sparse set.
iterator_type begin() const noexcept
Returns an iterator to the beginning.
void construct(entity_type entity)
Assigns an entity to a sparse set.
object_type & construct(entity_type entity, Args &&... args)
Assigns an entity to a sparse set and constructs its object.
size_type size() const noexcept
Returns the number of elements in a sparse set.
constexpr bool operator!=(const HashedString &lhs, const HashedString &rhs) noexcept
Compares two hashed strings.
virtual void respect(const SparseSet< Entity > &other) noexcept
Sort entities according to their order in another sparse set.
object_type * raw() noexcept
Direct access to the array of objects.
void swap(pos_type lhs, pos_type rhs) noexcept
Swaps the position of two entities in the internal packed array.