|
|
@@ -169,10 +169,10 @@ class sparse_set<Entity> {
|
|
|
reverse.resize(page+1);
|
|
|
}
|
|
|
|
|
|
- if(!reverse[page]) {
|
|
|
- reverse[page] = std::make_unique<entity_type[]>(entt_per_page);
|
|
|
+ if(!reverse[page].first) {
|
|
|
+ reverse[page].first = std::make_unique<entity_type[]>(entt_per_page);
|
|
|
// null is safe in all cases for our purposes
|
|
|
- std::fill_n(reverse[page].get(), entt_per_page, null);
|
|
|
+ std::fill_n(reverse[page].first.get(), entt_per_page, null);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -199,13 +199,14 @@ public:
|
|
|
* @param other The instance to copy from.
|
|
|
*/
|
|
|
sparse_set(const sparse_set &other)
|
|
|
- : reverse(),
|
|
|
+ : reverse{},
|
|
|
direct{other.direct}
|
|
|
{
|
|
|
for(size_type i = {}, last = other.reverse.size(); i < last; ++i) {
|
|
|
- if(other.reverse[i]) {
|
|
|
+ if(other.reverse[i].first) {
|
|
|
assure(i);
|
|
|
- std::copy_n(other.reverse[i].get(), entt_per_page, reverse[i].get());
|
|
|
+ std::copy_n(other.reverse[i].first.get(), entt_per_page, reverse[i].first.get());
|
|
|
+ reverse[i].second = other.reverse[i].second;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -254,6 +255,22 @@ public:
|
|
|
return direct.capacity();
|
|
|
}
|
|
|
|
|
|
+ /*! @brief Requests the removal of unused capacity. */
|
|
|
+ virtual void shrink_to_fit() {
|
|
|
+ while(!reverse.empty() && !reverse.back().second) {
|
|
|
+ reverse.pop_back();
|
|
|
+ }
|
|
|
+
|
|
|
+ for(auto &&data: reverse) {
|
|
|
+ if(!data.second) {
|
|
|
+ data.first.reset();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ reverse.shrink_to_fit();
|
|
|
+ direct.shrink_to_fit();
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @brief Returns the extent of a sparse set.
|
|
|
*
|
|
|
@@ -361,7 +378,7 @@ public:
|
|
|
bool has(const entity_type entt) const ENTT_NOEXCEPT {
|
|
|
auto [page, offset] = index(entt);
|
|
|
// testing against null permits to avoid accessing the direct vector
|
|
|
- return (page < reverse.size() && reverse[page] && reverse[page][offset] != null);
|
|
|
+ return (page < reverse.size() && reverse[page].second && reverse[page].first[offset] != null);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -379,7 +396,7 @@ public:
|
|
|
size_type get(const entity_type entt) const ENTT_NOEXCEPT {
|
|
|
ENTT_ASSERT(has(entt));
|
|
|
auto [page, offset] = index(entt);
|
|
|
- return size_type(reverse[page][offset]);
|
|
|
+ return size_type(reverse[page].first[offset]);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -397,7 +414,8 @@ public:
|
|
|
ENTT_ASSERT(!has(entt));
|
|
|
auto [page, offset] = index(entt);
|
|
|
assure(page);
|
|
|
- reverse[page][offset] = entity_type(direct.size());
|
|
|
+ reverse[page].first[offset] = entity_type(direct.size());
|
|
|
+ reverse[page].second++;
|
|
|
direct.push_back(entt);
|
|
|
}
|
|
|
|
|
|
@@ -420,7 +438,8 @@ public:
|
|
|
ENTT_ASSERT(!has(entt));
|
|
|
auto [page, offset] = index(entt);
|
|
|
assure(page);
|
|
|
- reverse[page][offset] = next++;
|
|
|
+ reverse[page].first[offset] = next++;
|
|
|
+ reverse[page].second++;
|
|
|
});
|
|
|
|
|
|
direct.insert(direct.end(), first, last);
|
|
|
@@ -441,9 +460,10 @@ public:
|
|
|
ENTT_ASSERT(has(entt));
|
|
|
auto [from_page, from_offset] = index(entt);
|
|
|
auto [to_page, to_offset] = index(direct.back());
|
|
|
- std::swap(direct[size_type(reverse[from_page][from_offset])], direct.back());
|
|
|
- std::swap(reverse[from_page][from_offset], reverse[to_page][to_offset]);
|
|
|
- reverse[from_page][from_offset] = null;
|
|
|
+ std::swap(direct[size_type(reverse[from_page].first[from_offset])], direct.back());
|
|
|
+ std::swap(reverse[from_page].first[from_offset], reverse[to_page].first[to_offset]);
|
|
|
+ reverse[from_page].first[from_offset] = null;
|
|
|
+ reverse[from_page].second--;
|
|
|
direct.pop_back();
|
|
|
}
|
|
|
|
|
|
@@ -467,7 +487,7 @@ public:
|
|
|
ENTT_ASSERT(rhs < direct.size());
|
|
|
auto [src_page, src_offset] = index(direct[lhs]);
|
|
|
auto [dst_page, dst_offset] = index(direct[rhs]);
|
|
|
- std::swap(reverse[src_page][src_offset], reverse[dst_page][dst_offset]);
|
|
|
+ std::swap(reverse[src_page].first[src_offset], reverse[dst_page].first[dst_offset]);
|
|
|
std::swap(direct[lhs], direct[rhs]);
|
|
|
}
|
|
|
|
|
|
@@ -530,7 +550,7 @@ public:
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- std::vector<std::unique_ptr<entity_type[]>> reverse;
|
|
|
+ std::vector<std::pair<std::unique_ptr<entity_type[]>, size_type>> reverse;
|
|
|
std::vector<entity_type> direct;
|
|
|
};
|
|
|
|
|
|
@@ -792,6 +812,21 @@ public:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Requests the removal of unused capacity.
|
|
|
+ *
|
|
|
+ * @note
|
|
|
+ * Empty components aren't explicitly instantiated. Only one instance of the
|
|
|
+ * given type is created. Therefore, this function does nothing.
|
|
|
+ */
|
|
|
+ void shrink_to_fit() override {
|
|
|
+ underlying_type::shrink_to_fit();
|
|
|
+
|
|
|
+ if constexpr(!std::is_empty_v<object_type>) {
|
|
|
+ instances.shrink_to_fit();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @brief Direct access to the array of objects.
|
|
|
*
|