1#ifndef ENTT_ENTITY_SNAPSHOT_HPP
2#define ENTT_ENTITY_SNAPSHOT_HPP
4#include "../config/config.h"
5#include "../container/dense_map.hpp"
6#include "../core/type_traits.hpp"
7#include "../stl/concepts.hpp"
8#include "../stl/cstddef.hpp"
9#include "../stl/iterator.hpp"
10#include "../stl/tuple.hpp"
11#include "../stl/type_traits.hpp"
12#include "../stl/utility.hpp"
22template<
typename Registry>
23void orphans(Registry ®istry) {
24 for(
auto &storage =
registry.template storage<typename Registry::entity_type>();
auto entt: storage) {
44template<
typename Registry>
46 static_assert(!stl::is_const_v<Registry>,
"Non-const registry type required");
91 template<typename Type, typename Archive>
94 const typename registry_type::common_type &base = *storage;
96 archive(static_cast<traits_type::entity_type>(storage->size()));
98 if constexpr(stl::is_same_v<Type, entity_type>) {
99 archive(static_cast<traits_type::entity_type>(storage->free_list()));
101 for(auto first = base.rbegin(), last = base.rend(); first != last; ++first) {
105 for(auto it = base.rbegin(), last = base.rend(); it != last; ++it) {
106 if(const auto entt = *it; entt == tombstone) {
107 archive(static_cast<entity_type>(null));
110 stl::apply([&archive](auto &&...args) { (archive(stl::forward<decltype(args)>(args)), ...); }, storage->get_as_tuple(entt));
114 for(
auto elem:
storage->reach()) {
115 stl::apply([&archive](
auto &&...args) { (archive(stl::forward<
decltype(args)>(args)), ...); }, elem);
119 archive(
typename traits_type::entity_type{});
136 template<
typename Type,
typename Archive>
138 static_assert(!stl::is_same_v<Type, entity_type>,
"Entity types not supported");
143 for(; first != last; ++first) {
146 stl::apply([&archive](
auto &&...args) { (archive(stl::forward<
decltype(args)>(args)), ...); },
storage->get_as_tuple(
entt));
159 const registry_type *reg;
172template<
typename Registry>
174 static_assert(!stl::is_const_v<Registry>,
"Non-const registry type required");
222 template<typename Type, typename Archive>
229 if constexpr(stl::is_same_v<Type, entity_type>) {
239 placeholder = (
entity > placeholder) ?
entity : placeholder;
251 ENTT_ASSERT(
entity ==
entt,
"Entity not available for use");
253 if constexpr(stl::tuple_size_v<
decltype(
storage.get_as_tuple({}))> == 0u) {
278 internal::orphans(*reg);
302template<
typename Registry>
304 static_assert(!stl::is_const_v<Registry>,
"Non-const registry type required");
307 void restore(Registry::entity_type
entt) {
309 if(!reg->valid(remloc[
entity].second)) {
310 remloc[
entity].second = reg->create();
313 remloc.insert_or_assign(
entity, stl::make_pair(
entt, reg->create()));
317 template<
typename Container>
318 auto update(
int, Container &container) ->
decltype(
typename Container::mapped_type{}, void()) {
322 for(
auto &&pair: container) {
323 using first_type = stl::remove_const_t<
typename stl::decay_t<
decltype(pair)>::first_type>;
324 using second_type = stl::decay_t<
decltype(pair)>::second_type;
326 if constexpr(stl::is_same_v<first_type, entity_type> && stl::is_same_v<second_type, entity_type>) {
327 other.emplace(
map(pair.first),
map(pair.second));
328 }
else if constexpr(stl::is_same_v<first_type, entity_type>) {
329 other.emplace(
map(pair.first), stl::move(pair.second));
331 static_assert(stl::is_same_v<second_type, entity_type>,
"Neither the key nor the value are of entity type");
332 other.emplace(stl::move(pair.first),
map(pair.second));
337 swap(container, other);
340 template<
typename Container>
341 auto update(
char, Container &container) ->
decltype(
typename Container::value_type{}, void()) {
343 static_assert(stl::is_same_v<typename Container::value_type, entity_type>,
"Invalid value type");
345 for(
auto &&
entt: container) {
350 template<
typename Component,
typename Other,
typename Member>
351 void update([[maybe_unused]] Component &instance, [[maybe_unused]] Member Other::*member) {
352 if constexpr(!stl::is_same_v<Component, Other>) {
354 }
else if constexpr(stl::is_same_v<Member, entity_type>) {
355 instance.*member =
map(instance.*member);
358 update(0, instance.*member);
373 : remloc{source.get_allocator()},
411 template<typename Type, typename Archive>
419 if constexpr(stl::is_same_v<Type, entity_type>) {
425 for(stl::size_t pos{}; pos < in_use; ++pos) {
430 for(stl::size_t pos = in_use; pos < length; ++pos) {
434 if(reg->valid(remloc[
entity].second)) {
435 reg->destroy(remloc[
entity].second);
442 for(
auto &&
ref: remloc) {
450 if constexpr(stl::tuple_size_v<
decltype(
storage.get_as_tuple({}))> == 0u) {
475 internal::orphans(*reg);
486 return it != remloc.cend() && it->second.first ==
entt;
495 if(
const auto it = remloc.find(
to_entity(
entt)); it != remloc.cend() && it->second.first ==
entt) {
496 return it->second.second;
basic_continuous_loader(const basic_continuous_loader &)=delete
Default copy constructor, deleted on purpose.
basic_continuous_loader(registry_type &source) noexcept
Constructs an instance that is bound to a given registry.
basic_continuous_loader(basic_continuous_loader &&) noexcept=default
Default move constructor.
bool contains(entity_type entt) const noexcept
Tests if a loader knows about a given entity.
registry_type::entity_type entity_type
entity_type map(entity_type entt) const noexcept
Returns the identifier to which an entity refers.
basic_continuous_loader & get(Archive &archive, const id_type id=type_hash< Type >::value())
basic_continuous_loader & orphans()
Destroys those entities that have no elements.
static constexpr value_type next(const value_type value) noexcept
internal::entt_traits< Type >::entity_type entity_type
bool orphan(const entity_type entt) const
Checks if an entity has elements assigned.
traits_type::value_type entity_type
basic_snapshot_loader(registry_type &source) noexcept
Constructs an instance that is bound to a given registry.
basic_snapshot_loader & get(Archive &archive, const id_type id=type_hash< Type >::value())
basic_snapshot_loader(basic_snapshot_loader &&) noexcept=default
Default move constructor.
registry_type::entity_type entity_type
basic_snapshot_loader & orphans()
Destroys those entities that have no elements.
basic_snapshot_loader(const basic_snapshot_loader &)=delete
Default copy constructor, deleted on purpose.
basic_snapshot(const registry_type &source) noexcept
Constructs an instance that is bound to a given registry.
registry_type::entity_type entity_type
basic_snapshot(const basic_snapshot &)=delete
Default copy constructor, deleted on purpose.
const basic_snapshot & get(Archive &archive, const id_type id=type_hash< Type >::value()) const
const basic_snapshot & get(Archive &archive, stl::input_iterator auto first, stl::input_iterator auto last, const id_type id=type_hash< Type >::value()) const
Serializes all elements of a type with associated identifiers for the entities in a range.
basic_snapshot(basic_snapshot &&) noexcept=default
Default move constructor.
void erase(const entity_type entt)
Erases an entity from a sparse set.
Associative container for key-value pairs with unique keys.
entity
Default entity identifier.
constexpr entt_traits< Entity >::entity_type to_entity(const Entity value) noexcept
Returns the entity part once converted to the underlying type.
@ in_place
In-place deletion policy.
constexpr void swap(compressed_pair< First, Second > &lhs, compressed_pair< First, Second > &rhs) noexcept
Swaps two compressed pair objects.
constexpr null_t null
Compile-time constant for null entities.
basic_registry<> registry
Alias declaration for the most common use case.
@ ref
Aliasing mode, non-const reference.
stl::uint32_t id_type
Alias declaration for type identifiers.
basic_storage< Type > storage
Alias declaration for the most common use case.
static constexpr id_type value() noexcept
Returns the numeric representation of a given type.