1 #ifndef ENTT_ENTITY_SPARSE_SET_HPP 2 #define ENTT_ENTITY_SPARSE_SET_HPP 12 #include <type_traits> 13 #include "../config/config.h" 14 #include "../core/algorithm.hpp" 15 #include "entt_traits.hpp" 59 template<
typename Entity>
63 class Iterator
final {
66 using direct_type =
const std::vector<Entity>;
67 using index_type =
typename traits_type::difference_type;
69 Iterator(direct_type *direct, index_type index) ENTT_NOEXCEPT
70 : direct{direct}, index{index}
74 using difference_type = index_type;
75 using value_type =
const Entity;
76 using pointer = value_type *;
77 using reference = value_type &;
78 using iterator_category = std::random_access_iterator_tag;
80 Iterator() ENTT_NOEXCEPT =
default;
82 Iterator(
const Iterator &) ENTT_NOEXCEPT =
default;
83 Iterator & operator=(
const Iterator &) ENTT_NOEXCEPT =
default;
85 Iterator & operator++() ENTT_NOEXCEPT {
86 return --index, *
this;
89 Iterator operator++(
int) ENTT_NOEXCEPT {
90 Iterator orig = *
this;
91 return ++(*this), orig;
94 Iterator & operator--() ENTT_NOEXCEPT {
95 return ++index, *
this;
98 Iterator operator--(
int) ENTT_NOEXCEPT {
99 Iterator orig = *
this;
100 return --(*this), orig;
103 Iterator & operator+=(
const difference_type value) ENTT_NOEXCEPT {
108 Iterator operator+(
const difference_type value)
const ENTT_NOEXCEPT {
109 return Iterator{direct, index-value};
112 inline Iterator & operator-=(
const difference_type value) ENTT_NOEXCEPT {
113 return (*
this += -value);
116 inline Iterator operator-(
const difference_type value)
const ENTT_NOEXCEPT {
117 return (*
this + -value);
120 difference_type operator-(
const Iterator &other)
const ENTT_NOEXCEPT {
121 return other.index - index;
124 reference operator[](
const difference_type value)
const ENTT_NOEXCEPT {
125 const auto pos =
size_type(index-value-1);
126 return (*direct)[pos];
129 bool operator==(
const Iterator &other)
const ENTT_NOEXCEPT {
130 return other.index == index;
133 inline bool operator!=(
const Iterator &other)
const ENTT_NOEXCEPT {
134 return !(*
this == other);
137 bool operator<(
const Iterator &other)
const ENTT_NOEXCEPT {
138 return index > other.index;
141 bool operator>(
const Iterator &other)
const ENTT_NOEXCEPT {
142 return index < other.index;
145 inline bool operator<=(
const Iterator &other)
const ENTT_NOEXCEPT {
146 return !(*
this > other);
149 inline bool operator>=(
const Iterator &other)
const ENTT_NOEXCEPT {
150 return !(*
this < other);
153 pointer operator->()
const ENTT_NOEXCEPT {
155 return &(*direct)[pos];
158 inline reference operator*()
const ENTT_NOEXCEPT {
159 return *operator->();
181 virtual ~
SparseSet() ENTT_NOEXCEPT = default;
211 return direct.capacity();
225 return reverse.size();
239 return direct.size();
247 return direct.empty();
266 return direct.data();
282 const typename traits_type::difference_type pos = direct.size();
375 return cbegin()[pos];
384 const auto pos =
size_type(entity & traits_type::entity_mask);
386 return (pos < reverse.size()) && (reverse[pos] !=
null);
407 const auto pos =
size_type(entity & traits_type::entity_mask);
408 assert(pos < reverse.size());
410 return (reverse[pos] !=
null);
427 const auto pos =
size_type(entity & traits_type::entity_mask);
443 assert(!has(entity));
444 const auto pos =
size_type(entity & traits_type::entity_mask);
446 if(!(pos < reverse.size())) {
448 reverse.resize(pos+1,
null);
452 direct.push_back(entity);
468 const auto back = direct.back();
469 auto &candidate = reverse[
size_type(entity & traits_type::entity_mask)];
471 reverse[back & traits_type::entity_mask] = candidate;
493 assert(lhs < direct.size());
494 assert(rhs < direct.size());
495 auto &src = direct[lhs];
496 auto &dst = direct[rhs];
497 std::swap(reverse[src & traits_type::entity_mask], reverse[dst & traits_type::entity_mask]);
521 auto from = other.cbegin();
522 auto to = other.cend();
526 while(pos && from != to) {
528 if(*from != direct[pos]) {
529 swap(pos,
get(*from));
548 std::vector<entity_type> reverse;
549 std::vector<entity_type> direct;
575 template<
typename Entity,
typename Type>
581 class Iterator final {
584 using instance_type = std::conditional_t<Const, const std::vector<Type>, std::vector<Type>>;
585 using index_type =
typename traits_type::difference_type;
587 Iterator(instance_type *instances, index_type index) ENTT_NOEXCEPT
588 : instances{instances}, index{index}
592 using difference_type = index_type;
593 using value_type = std::conditional_t<Const, const Type, Type>;
594 using pointer = value_type *;
595 using reference = value_type &;
596 using iterator_category = std::random_access_iterator_tag;
598 Iterator() ENTT_NOEXCEPT =
default;
600 Iterator(
const Iterator &) ENTT_NOEXCEPT =
default;
601 Iterator & operator=(
const Iterator &) ENTT_NOEXCEPT =
default;
603 Iterator & operator++() ENTT_NOEXCEPT {
604 return --index, *
this;
607 Iterator operator++(
int) ENTT_NOEXCEPT {
608 Iterator orig = *
this;
609 return ++(*this), orig;
612 Iterator & operator--() ENTT_NOEXCEPT {
613 return ++index, *
this;
616 Iterator operator--(
int) ENTT_NOEXCEPT {
617 Iterator orig = *
this;
618 return --(*this), orig;
621 Iterator & operator+=(
const difference_type value) ENTT_NOEXCEPT {
626 Iterator operator+(
const difference_type value)
const ENTT_NOEXCEPT {
627 return Iterator{instances, index-value};
630 inline Iterator & operator-=(
const difference_type value) ENTT_NOEXCEPT {
631 return (*
this += -value);
634 inline Iterator operator-(
const difference_type value)
const ENTT_NOEXCEPT {
635 return (*
this + -value);
638 difference_type operator-(
const Iterator &other)
const ENTT_NOEXCEPT {
639 return other.index - index;
642 reference operator[](
const difference_type value)
const ENTT_NOEXCEPT {
643 const auto pos =
size_type(index-value-1);
644 return (*instances)[pos];
647 bool operator==(
const Iterator &other)
const ENTT_NOEXCEPT {
648 return other.index == index;
651 inline bool operator!=(
const Iterator &other)
const ENTT_NOEXCEPT {
652 return !(*
this == other);
655 bool operator<(
const Iterator &other)
const ENTT_NOEXCEPT {
656 return index > other.index;
659 bool operator>(
const Iterator &other)
const ENTT_NOEXCEPT {
660 return index < other.index;
663 inline bool operator<=(
const Iterator &other)
const ENTT_NOEXCEPT {
664 return !(*
this > other);
667 inline bool operator>=(
const Iterator &other)
const ENTT_NOEXCEPT {
668 return !(*
this < other);
671 pointer operator->()
const ENTT_NOEXCEPT {
673 return &(*instances)[pos];
676 inline reference operator*()
const ENTT_NOEXCEPT {
677 return *operator->();
681 instance_type *instances;
719 underlying_type::reserve(cap);
720 instances.reserve(cap);
739 return instances.data();
758 return instances.data();
774 const typename traits_type::difference_type pos = instances.size();
807 const typename traits_type::difference_type pos = instances.size();
871 return cbegin()[pos];
896 return instances[underlying_type::get(entity)];
935 template<
typename... Args>
936 std::enable_if_t<std::is_constructible<Type, Args...>::value,
object_type &>
938 underlying_type::construct(entity);
939 instances.emplace_back(std::forward<Args>(args)...);
940 return instances.back();
963 template<
typename... Args>
964 std::enable_if_t<!std::is_constructible<Type, Args...>::value,
object_type &>
966 underlying_type::construct(entity);
967 instances.emplace_back(Type{std::forward<Args>(args)...});
968 return instances.back();
985 auto tmp = std::move(instances.back());
986 instances[underlying_type::get(entity)] = std::move(tmp);
987 instances.pop_back();
988 underlying_type::destroy(entity);
1032 template<
typename Compare,
typename Sort =
StdSort,
typename... Args>
1033 void sort(Compare compare, Sort sort = Sort{}, Args &&... args) {
1034 std::vector<size_type> copy(instances.size());
1035 std::iota(copy.begin(), copy.end(), 0);
1037 sort(copy.begin(), copy.end(), [
this, compare = std::move(compare)](
const auto lhs,
const auto rhs) {
1038 return compare(const_cast<const object_type &>(instances[rhs]), const_cast<const object_type &>(instances[lhs]));
1039 }, std::forward<Args>(args)...);
1041 for(
size_type pos = 0, last = copy.size(); pos < last; ++pos) {
1043 auto next = copy[curr];
1045 while(curr != next) {
1046 const auto lhs = copy[curr];
1047 const auto rhs = copy[next];
1048 std::swap(instances[lhs], instances[rhs]);
1049 underlying_type::swap(lhs, rhs);
1081 auto from = other.cbegin();
1082 auto to = other.cend();
1084 size_type pos = underlying_type::size() - 1;
1085 const auto *local = underlying_type::data();
1087 while(pos && from != to) {
1088 const auto curr = *from;
1090 if(underlying_type::has(curr)) {
1091 if(curr != *(local + pos)) {
1092 auto candidate = underlying_type::get(curr);
1093 std::swap(instances[pos], instances[candidate]);
1094 underlying_type::swap(pos, candidate);
1108 underlying_type::reset();
1113 std::vector<object_type> instances;
1120 #endif // ENTT_ENTITY_SPARSE_SET_HPP void swap(const size_type lhs, const size_type rhs) ENTT_NOEXCEPT
Swaps the position of two entities in the internal packed array.
constexpr bool operator!=(const HashedString &lhs, const HashedString &rhs) ENTT_NOEXCEPT
Compares two hashed strings.
const_iterator_type cbegin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
size_type capacity() const ENTT_NOEXCEPT
Returns the number of elements that a sparse set has currently allocated space for.
object_type & operator[](const size_type pos) ENTT_NOEXCEPT
Returns a reference to the element at the given position.
bool empty() const ENTT_NOEXCEPT
Checks whether a sparse set is empty.
std::enable_if_t<!std::is_constructible< Type, Args... >::value, object_type & > construct(const entity_type entity, Args &&... args)
Assigns an entity to a sparse set and constructs its object.
bool fast(const entity_type entity) const ENTT_NOEXCEPT
Checks if a sparse set contains an entity (unsafe).
virtual void reset()
Resets a sparse set.
const object_type * raw() const ENTT_NOEXCEPT
Direct access to the array of objects.
void reset() override
Resets a sparse set.
const_iterator_type cend() const ENTT_NOEXCEPT
Returns an iterator to the end.
bool has(const entity_type entity) const ENTT_NOEXCEPT
Checks if a sparse set contains an entity.
const_iterator_type begin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
void destroy(const entity_type entity) override
Removes an entity from a sparse set and destroies its object.
const_iterator_type begin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
std::enable_if_t< std::is_constructible< Type, Args... >::value, object_type & > construct(const entity_type entity, Args &&... args)
Assigns an entity to a sparse set and constructs its object.
constexpr auto null
Null entity.
std::size_t size_type
Unsigned integer type.
size_type extent() const ENTT_NOEXCEPT
Returns the extent of a sparse set.
iterator_type begin() ENTT_NOEXCEPT
Returns an iterator to the beginning.
void sort(Compare compare, Sort sort=Sort{}, Args &&... args)
Sort components according to the given comparison function.
iterator_type end() ENTT_NOEXCEPT
Returns an iterator to the end.
iterator_type end() ENTT_NOEXCEPT
Returns an iterator to the end.
Entity entity_type
Underlying entity identifier.
Iterator iterator_type
Input iterator type.
Basic sparse set implementation.
void respect(const SparseSet< Entity > &other) ENTT_NOEXCEPT
Sort components according to the order of the entities in another sparse set.
Iterator const_iterator_type
Constant input iterator type.
Type object_type
Type of the objects associated to the entities.
size_type size() const ENTT_NOEXCEPT
Returns the number of elements in a sparse set.
const_iterator_type cend() const ENTT_NOEXCEPT
Returns an iterator to the end.
const_iterator_type end() const ENTT_NOEXCEPT
Returns an iterator to the end.
Function object to wrap std::sort in a class type.
virtual void destroy(const entity_type entity)
Removes an entity from a sparse set.
object_type * raw() ENTT_NOEXCEPT
Direct access to the array of objects.
void respect(const SparseSet< Entity > &other) ENTT_NOEXCEPT
Sort entities according to their order in another sparse set.
iterator_type begin() ENTT_NOEXCEPT
Returns an iterator to the beginning.
const entity_type * data() const ENTT_NOEXCEPT
Direct access to the internal packed array.
const_iterator_type cbegin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
const_iterator_type end() const ENTT_NOEXCEPT
Returns an iterator to the end.
void construct(const entity_type entity)
Assigns an entity to a sparse set.
const entity_type & operator[](const size_type pos) const ENTT_NOEXCEPT
Returns a reference to the element at the given position.
const object_type & operator[](const size_type pos) const ENTT_NOEXCEPT
Returns a reference to the element at the given position.