Compare commits

...

11 Commits

Author SHA1 Message Date
Michele Caini
7821307565 update single include file 2024-04-10 08:52:08 +02:00
Michele Caini
27efd6fdf4 snapshot: suppress a warning by clang 2024-04-10 08:29:17 +02:00
Michele Caini
4dc3f650e8 snapshot: full support to stable types - close #1118 2024-04-10 08:29:14 +02:00
Michele Caini
d5a2e353cd sigh_mixin: avoid using weak ranges twice - close #1123 2024-04-10 08:29:10 +02:00
Michele Caini
3fd8b84d04 now working on version v3.13.2 2024-04-10 08:28:47 +02:00
Michele Caini
2909e7ab1f update single include file 2024-02-02 10:09:52 +01:00
Ezekiel Warren
60703f6845 build: don't install include/BUILD.bazel (#1107) 2024-01-22 09:55:58 +01:00
Michele Caini
062c95fc11 test: avoid warnings due to unused variables 2024-01-19 14:35:45 +01:00
Michele Caini
15ce55bc60 group: avoid swapping observed types - close #1100 2024-01-19 14:23:02 +01:00
Michele Caini
2d3fa3e51a snapshot: refine the check in the constructor of the loader class - close #1106 2024-01-19 09:22:58 +01:00
Michele Caini
7f49768739 now working on version v3.13.1 2024-01-19 08:52:00 +01:00
9 changed files with 222 additions and 106 deletions

View File

@@ -282,7 +282,13 @@ install(
DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
)
install(DIRECTORY src/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(
DIRECTORY src/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING
PATTERN "*.h"
PATTERN "*.hpp"
)
export(PACKAGE EnTT)

View File

@@ -19,7 +19,7 @@
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -127,7 +127,7 @@
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -169,7 +169,7 @@
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -296,7 +296,7 @@
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -5248,7 +5248,7 @@ struct radix_sort {
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -10297,7 +10297,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -10419,7 +10419,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -18188,27 +18188,28 @@ class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> fin
using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
using entity_type = typename base_type::entity_type;
void swap_elements(const std::size_t pos, const entity_type entt) {
std::apply([pos, entt](auto *...cpool) { (cpool->swap_elements(cpool->data()[pos], entt), ...); }, pools);
template<std::size_t... Index>
void swap_elements(const std::size_t pos, const entity_type entt, std::index_sequence<Index...>) {
(std::get<Index>(pools)->swap_elements(std::get<Index>(pools)->data()[pos], entt), ...);
}
void push_on_construct(const entity_type entt) {
if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
&& std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
swap_elements(len++, entt);
swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
}
}
void push_on_destroy(const entity_type entt) {
if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
&& std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
swap_elements(len++, entt);
swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
}
}
void remove_if(const entity_type entt) {
if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < len)) {
swap_elements(--len, entt);
swap_elements(--len, entt, std::index_sequence_for<Owned...>{});
}
}
@@ -18242,13 +18243,11 @@ public:
return len;
}
template<typename Type>
Type pools_as() const noexcept {
auto pools_as_tuple() const noexcept {
return pools;
}
template<typename Type>
Type filter_as() const noexcept {
auto filter_as_tuple() const noexcept {
return filter;
}
@@ -18310,13 +18309,11 @@ public:
return elem;
}
template<typename Type>
Type pools_as() const noexcept {
auto pools_as_tuple() const noexcept {
return pools;
}
template<typename Type>
Type filter_as() const noexcept {
auto filter_as_tuple() const noexcept {
return filter;
}
@@ -18370,12 +18367,12 @@ class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
auto pools() const noexcept {
using return_type = std::tuple<Get *...>;
return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
return descriptor ? descriptor->pools_as_tuple() : return_type{};
}
auto filter() const noexcept {
using return_type = std::tuple<Exclude *...>;
return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
return descriptor ? descriptor->filter_as_tuple() : return_type{};
}
public:
@@ -18791,12 +18788,12 @@ class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
auto pools() const noexcept {
using return_type = std::tuple<Owned *..., Get *...>;
return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
return descriptor ? descriptor->pools_as_tuple() : return_type{};
}
auto filter() const noexcept {
using return_type = std::tuple<Exclude *...>;
return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
return descriptor ? descriptor->filter_as_tuple() : return_type{};
}
public:
@@ -19569,7 +19566,7 @@ template<typename... Args, typename... Other>
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -19688,7 +19685,7 @@ template<typename... Args, typename... Other>
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -21214,27 +21211,28 @@ class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> fin
using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
using entity_type = typename base_type::entity_type;
void swap_elements(const std::size_t pos, const entity_type entt) {
std::apply([pos, entt](auto *...cpool) { (cpool->swap_elements(cpool->data()[pos], entt), ...); }, pools);
template<std::size_t... Index>
void swap_elements(const std::size_t pos, const entity_type entt, std::index_sequence<Index...>) {
(std::get<Index>(pools)->swap_elements(std::get<Index>(pools)->data()[pos], entt), ...);
}
void push_on_construct(const entity_type entt) {
if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
&& std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
swap_elements(len++, entt);
swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
}
}
void push_on_destroy(const entity_type entt) {
if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
&& std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
swap_elements(len++, entt);
swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
}
}
void remove_if(const entity_type entt) {
if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < len)) {
swap_elements(--len, entt);
swap_elements(--len, entt, std::index_sequence_for<Owned...>{});
}
}
@@ -21268,13 +21266,11 @@ public:
return len;
}
template<typename Type>
Type pools_as() const noexcept {
auto pools_as_tuple() const noexcept {
return pools;
}
template<typename Type>
Type filter_as() const noexcept {
auto filter_as_tuple() const noexcept {
return filter;
}
@@ -21336,13 +21332,11 @@ public:
return elem;
}
template<typename Type>
Type pools_as() const noexcept {
auto pools_as_tuple() const noexcept {
return pools;
}
template<typename Type>
Type filter_as() const noexcept {
auto filter_as_tuple() const noexcept {
return filter;
}
@@ -21396,12 +21390,12 @@ class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
auto pools() const noexcept {
using return_type = std::tuple<Get *...>;
return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
return descriptor ? descriptor->pools_as_tuple() : return_type{};
}
auto filter() const noexcept {
using return_type = std::tuple<Exclude *...>;
return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
return descriptor ? descriptor->filter_as_tuple() : return_type{};
}
public:
@@ -21817,12 +21811,12 @@ class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
auto pools() const noexcept {
using return_type = std::tuple<Owned *..., Get *...>;
return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
return descriptor ? descriptor->pools_as_tuple() : return_type{};
}
auto filter() const noexcept {
using return_type = std::tuple<Exclude *...>;
return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
return descriptor ? descriptor->filter_as_tuple() : return_type{};
}
public:
@@ -24509,11 +24503,12 @@ public:
*/
template<typename It, typename... Args>
void insert(It first, It last, Args &&...args) {
auto from = underlying_type::size();
underlying_type::insert(first, last, std::forward<Args>(args)...);
if(auto &reg = owner_or_assert(); !construction.empty()) {
for(; first != last; ++first) {
construction.publish(reg, *first);
for(const auto to = underlying_type::size(); from != to; ++from) {
construction.publish(reg, underlying_type::operator[](from));
}
}
}
@@ -25126,7 +25121,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -25446,7 +25441,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -25952,7 +25947,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -26079,7 +26074,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -33480,7 +33475,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -33607,7 +33602,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -37658,11 +37653,12 @@ public:
*/
template<typename It, typename... Args>
void insert(It first, It last, Args &&...args) {
auto from = underlying_type::size();
underlying_type::insert(first, last, std::forward<Args>(args)...);
if(auto &reg = owner_or_assert(); !construction.empty()) {
for(; first != last; ++first) {
construction.publish(reg, *first);
for(const auto to = underlying_type::size(); from != to; ++from) {
construction.publish(reg, underlying_type::operator[](from));
}
}
}
@@ -39272,6 +39268,17 @@ public:
for(auto first = storage->data(), last = first + storage->size(); first != last; ++first) {
archive(*first);
}
} else if constexpr(component_traits<Type>::in_place_delete) {
const typename registry_type::common_type &base = *storage;
for(auto it = base.rbegin(), last = base.rend(); it != last; ++it) {
if(const auto entt = *it; entt == tombstone) {
archive(static_cast<entity_type>(null));
} else {
archive(entt);
std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, storage->get_as_tuple(entt));
}
}
} else {
for(auto elem: storage->reach()) {
std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, elem);
@@ -39350,7 +39357,7 @@ public:
basic_snapshot_loader(registry_type &source) noexcept
: reg{&source} {
// restoring a snapshot as a whole requires a clean registry
ENTT_ASSERT(reg->template storage<entity_type>().empty() && (reg->storage().begin() == reg->storage().end()), "Registry must be empty");
ENTT_ASSERT(reg->template storage<entity_type>().free_list() == 0u, "Registry must be empty");
}
/*! @brief Default move constructor. */
@@ -42964,7 +42971,7 @@ basic_view(std::tuple<Get &...>, std::tuple<Exclude &...> = {}) -> basic_view<ge
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -43284,7 +43291,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -43851,7 +43858,7 @@ void dot(std::ostream &out, const Graph &graph) {
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -43978,7 +43985,7 @@ void dot(std::ostream &out, const Graph &graph) {
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -50681,7 +50688,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -50998,7 +51005,7 @@ struct adl_meta_pointer_like {
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -51125,7 +51132,7 @@ struct adl_meta_pointer_like {
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -55838,7 +55845,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -56122,7 +56129,7 @@ class meta_ctx: private internal::meta_context {
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -59830,7 +59837,7 @@ struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_e
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -67805,7 +67812,7 @@ using invoke_result_t = typename std::invoke_result<Func, Args...>::type;
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -71981,7 +71988,7 @@ struct process_adaptor: process<process_adaptor<Func, Delta>, Delta>, private Fu
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -72108,7 +72115,7 @@ struct process_adaptor: process<process_adaptor<Func, Delta>, Delta>, private Fu
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -74120,7 +74127,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -74247,7 +74254,7 @@ private:
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -78034,7 +78041,7 @@ struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator>
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -80659,7 +80666,7 @@ template<typename Lhs, typename Rhs>
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -80778,7 +80785,7 @@ template<typename Lhs, typename Rhs>
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -82225,7 +82232,7 @@ delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate<Ret
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \
@@ -82352,7 +82359,7 @@ delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate<Ret
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \

View File

@@ -5,7 +5,7 @@
#define ENTT_VERSION_MAJOR 3
#define ENTT_VERSION_MINOR 13
#define ENTT_VERSION_PATCH 0
#define ENTT_VERSION_PATCH 2
#define ENTT_VERSION \
ENTT_XSTR(ENTT_VERSION_MAJOR) \

View File

@@ -109,27 +109,28 @@ class group_handler<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> fin
using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>;
using entity_type = typename base_type::entity_type;
void swap_elements(const std::size_t pos, const entity_type entt) {
std::apply([pos, entt](auto *...cpool) { (cpool->swap_elements(cpool->data()[pos], entt), ...); }, pools);
template<std::size_t... Index>
void swap_elements(const std::size_t pos, const entity_type entt, std::index_sequence<Index...>) {
(std::get<Index>(pools)->swap_elements(std::get<Index>(pools)->data()[pos], entt), ...);
}
void push_on_construct(const entity_type entt) {
if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
&& std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
swap_elements(len++, entt);
swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
}
}
void push_on_destroy(const entity_type entt) {
if(std::apply([entt, len = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < len) && (other->contains(entt) && ...); }, pools)
&& std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) {
swap_elements(len++, entt);
swap_elements(len++, entt, std::index_sequence_for<Owned...>{});
}
}
void remove_if(const entity_type entt) {
if(std::get<0>(pools)->contains(entt) && (std::get<0>(pools)->index(entt) < len)) {
swap_elements(--len, entt);
swap_elements(--len, entt, std::index_sequence_for<Owned...>{});
}
}
@@ -163,13 +164,11 @@ public:
return len;
}
template<typename Type>
Type pools_as() const noexcept {
auto pools_as_tuple() const noexcept {
return pools;
}
template<typename Type>
Type filter_as() const noexcept {
auto filter_as_tuple() const noexcept {
return filter;
}
@@ -231,13 +230,11 @@ public:
return elem;
}
template<typename Type>
Type pools_as() const noexcept {
auto pools_as_tuple() const noexcept {
return pools;
}
template<typename Type>
Type filter_as() const noexcept {
auto filter_as_tuple() const noexcept {
return filter;
}
@@ -291,12 +288,12 @@ class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
auto pools() const noexcept {
using return_type = std::tuple<Get *...>;
return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
return descriptor ? descriptor->pools_as_tuple() : return_type{};
}
auto filter() const noexcept {
using return_type = std::tuple<Exclude *...>;
return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
return descriptor ? descriptor->filter_as_tuple() : return_type{};
}
public:
@@ -712,12 +709,12 @@ class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
auto pools() const noexcept {
using return_type = std::tuple<Owned *..., Get *...>;
return descriptor ? descriptor->template pools_as<return_type>() : return_type{};
return descriptor ? descriptor->pools_as_tuple() : return_type{};
}
auto filter() const noexcept {
using return_type = std::tuple<Exclude *...>;
return descriptor ? descriptor->template filter_as<return_type>() : return_type{};
return descriptor ? descriptor->filter_as_tuple() : return_type{};
}
public:

View File

@@ -271,11 +271,12 @@ public:
*/
template<typename It, typename... Args>
void insert(It first, It last, Args &&...args) {
auto from = underlying_type::size();
underlying_type::insert(first, last, std::forward<Args>(args)...);
if(auto &reg = owner_or_assert(); !construction.empty()) {
for(; first != last; ++first) {
construction.publish(reg, *first);
for(const auto to = underlying_type::size(); from != to; ++from) {
construction.publish(reg, underlying_type::operator[](from));
}
}
}

View File

@@ -86,6 +86,17 @@ public:
for(auto first = storage->data(), last = first + storage->size(); first != last; ++first) {
archive(*first);
}
} else if constexpr(component_traits<Type>::in_place_delete) {
const typename registry_type::common_type &base = *storage;
for(auto it = base.rbegin(), last = base.rend(); it != last; ++it) {
if(const auto entt = *it; entt == tombstone) {
archive(static_cast<entity_type>(null));
} else {
archive(entt);
std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, storage->get_as_tuple(entt));
}
}
} else {
for(auto elem: storage->reach()) {
std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, elem);
@@ -164,7 +175,7 @@ public:
basic_snapshot_loader(registry_type &source) noexcept
: reg{&source} {
// restoring a snapshot as a whole requires a clean registry
ENTT_ASSERT(reg->template storage<entity_type>().empty() && (reg->storage().begin() == reg->storage().end()), "Registry must be empty");
ENTT_ASSERT(reg->template storage<entity_type>().free_list() == 0u, "Registry must be empty");
}
/*! @brief Default move constructor. */

View File

@@ -1503,6 +1503,25 @@ TEST(OwningGroup, PreventEarlyOptOut) {
});
}
TEST(OwningGroup, SwapElements) {
entt::registry registry;
std::array entity{registry.create(), registry.create(), registry.create()};
registry.emplace<int>(entity[1u]);
registry.emplace<int>(entity[0u]);
registry.emplace<char>(entity[2u]);
registry.emplace<char>(entity[0u]);
ASSERT_EQ(registry.storage<int>().index(entity[0u]), 1u);
ASSERT_EQ(registry.storage<char>().index(entity[0u]), 1u);
registry.group<int>(entt::get<char>);
ASSERT_EQ(registry.storage<int>().index(entity[0u]), 0u);
ASSERT_EQ(registry.storage<char>().index(entity[0u]), 1u);
}
TEST(OwningGroup, SwappingValuesIsAllowed) {
entt::registry registry;
const auto group = registry.group<test::boxed_int>(entt::get<test::empty>);

View File

@@ -175,6 +175,23 @@ TEST(SighMixin, StableType) {
ASSERT_EQ(pool.size(), 0u);
}
TYPED_TEST(SighMixin, InsertWeakRange) {
using value_type = typename TestFixture::type;
entt::registry registry;
auto &pool = registry.storage<value_type>();
const auto view = registry.view<entt::entity>(entt::exclude<value_type>);
[[maybe_unused]] const std::array entity{registry.create(), registry.create()};
std::size_t on_construct{};
ASSERT_EQ(on_construct, 0u);
pool.on_construct().template connect<&listener<entt::registry>>(on_construct);
pool.insert(view.begin(), view.end());
ASSERT_EQ(on_construct, 2u);
}
TEST(SighMixin, NonDefaultConstructibleType) {
entt::entity entity[2u]{entt::entity{3}, entt::entity{42}}; // NOLINT
entt::sigh_mixin<entt::storage<test::non_default_constructible>> pool;

View File

@@ -11,6 +11,7 @@
#include <entt/signal/sigh.hpp>
#include "../common/config.h"
#include "../common/empty.h"
#include "../common/pointer_stable.h"
struct shadow {
entt::entity target{entt::null};
@@ -88,12 +89,13 @@ TEST(BasicSnapshot, GetType) {
entt::registry registry;
const entt::basic_snapshot snapshot{registry};
const auto &storage = registry.storage<int>();
constexpr auto number_of_entities = 3u;
entt::entity entity[3u]; // NOLINT
const int values[3u]{1, 2, 3}; // NOLINT
std::array<entt::entity, number_of_entities> entity{};
const std::array value{1, 2, 3};
registry.create(std::begin(entity), std::end(entity));
registry.insert<int>(std::begin(entity), std::end(entity), std::begin(values));
registry.insert<int>(std::begin(entity), std::end(entity), std::begin(value));
registry.destroy(entity[1u]);
std::vector<entt::any> data{};
@@ -118,13 +120,63 @@ TEST(BasicSnapshot, GetType) {
ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entity[0u]);
ASSERT_NE(entt::any_cast<int>(&data[2u]), nullptr);
ASSERT_EQ(entt::any_cast<int>(data[2u]), values[0u]);
ASSERT_EQ(entt::any_cast<int>(data[2u]), value[0u]);
ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), entity[2u]);
ASSERT_NE(entt::any_cast<int>(&data[4u]), nullptr);
ASSERT_EQ(entt::any_cast<int>(data[4u]), values[2u]);
ASSERT_EQ(entt::any_cast<int>(data[4u]), value[2u]);
}
TEST(BasicSnapshot, GetPointerStableType) {
using namespace entt::literals;
using traits_type = entt::entt_traits<entt::entity>;
entt::registry registry;
const entt::basic_snapshot snapshot{registry};
const auto &storage = registry.storage<test::pointer_stable>();
constexpr auto number_of_entities = 3u;
std::array<entt::entity, number_of_entities> entity{};
const std::array<test::pointer_stable, number_of_entities> value{1, 2, 3};
registry.create(entity.begin(), entity.end());
registry.insert<test::pointer_stable>(entity.begin(), entity.end(), value.begin());
registry.destroy(entity[1u]);
std::vector<entt::any> data{};
auto archive = [&data](auto &&elem) { data.emplace_back(std::forward<decltype(elem)>(elem)); };
snapshot.get<test::pointer_stable>(archive, "other"_hs);
ASSERT_EQ(data.size(), 1u);
ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), 0u);
data.clear();
snapshot.get<test::pointer_stable>(archive);
ASSERT_EQ(data.size(), 6u);
ASSERT_NE(entt::any_cast<typename traits_type::entity_type>(&data[0u]), nullptr);
ASSERT_EQ(entt::any_cast<typename traits_type::entity_type>(data[0u]), storage.size());
ASSERT_NE(entt::any_cast<entt::entity>(&data[1u]), nullptr);
ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entity[0u]);
ASSERT_NE(entt::any_cast<test::pointer_stable>(&data[2u]), nullptr);
ASSERT_EQ(entt::any_cast<test::pointer_stable>(data[2u]), value[0u]);
ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), static_cast<entt::entity>(entt::null));
ASSERT_NE(entt::any_cast<entt::entity>(&data[4u]), nullptr);
ASSERT_EQ(entt::any_cast<entt::entity>(data[4u]), entity[2u]);
ASSERT_NE(entt::any_cast<test::pointer_stable>(&data[5u]), nullptr);
ASSERT_EQ(entt::any_cast<test::pointer_stable>(data[5u]), value[2u]);
}
TEST(BasicSnapshot, GetEmptyType) {
@@ -172,12 +224,13 @@ TEST(BasicSnapshot, GetTypeSparse) {
entt::registry registry;
const entt::basic_snapshot snapshot{registry};
constexpr auto number_of_entities = 3u;
entt::entity entity[3u]; // NOLINT
const int values[3u]{1, 2, 3}; // NOLINT
std::array<entt::entity, number_of_entities> entity{};
const std::array value{1, 2, 3};
registry.create(std::begin(entity), std::end(entity));
registry.insert<int>(std::begin(entity), std::end(entity), std::begin(values));
registry.insert<int>(std::begin(entity), std::end(entity), std::begin(value));
registry.destroy(entity[1u]);
std::vector<entt::any> data{};
@@ -202,7 +255,7 @@ TEST(BasicSnapshot, GetTypeSparse) {
ASSERT_EQ(entt::any_cast<entt::entity>(data[1u]), entity[0u]);
ASSERT_NE(entt::any_cast<int>(&data[2u]), nullptr);
ASSERT_EQ(entt::any_cast<int>(data[2u]), values[0u]);
ASSERT_EQ(entt::any_cast<int>(data[2u]), value[0u]);
ASSERT_NE(entt::any_cast<entt::entity>(&data[3u]), nullptr);
ASSERT_EQ(entt::any_cast<entt::entity>(data[3u]), static_cast<entt::entity>(entt::null));
@@ -211,7 +264,7 @@ TEST(BasicSnapshot, GetTypeSparse) {
ASSERT_EQ(entt::any_cast<entt::entity>(data[4u]), entity[2u]);
ASSERT_NE(entt::any_cast<int>(&data[5u]), nullptr);
ASSERT_EQ(entt::any_cast<int>(data[5u]), values[2u]);
ASSERT_EQ(entt::any_cast<int>(data[5u]), value[2u]);
}
TEST(BasicSnapshotLoader, Constructors) {
@@ -222,6 +275,11 @@ TEST(BasicSnapshotLoader, Constructors) {
static_assert(std::is_move_assignable_v<entt::basic_snapshot_loader<entt::registry>>, "Move assignable type required");
entt::registry registry;
// helps stress the check in the constructor
registry.emplace<int>(registry.create(), 0);
registry.clear();
entt::basic_snapshot_loader loader{registry};
entt::basic_snapshot_loader other{std::move(loader)};