6 #ifndef ENTT_CORE_ALGORITHM_HPP
7 #define ENTT_CORE_ALGORITHM_HPP
15 #ifndef ENTT_CORE_UTILITY_HPP
16 #define ENTT_CORE_UTILITY_HPP
20 #ifndef ENTT_CONFIG_CONFIG_H
21 #define ENTT_CONFIG_CONFIG_H
25 #define ENTT_NOEXCEPT noexcept
26 #endif // ENTT_NOEXCEPT
29 #ifndef ENTT_HS_SUFFIX
30 #define ENTT_HS_SUFFIX _hs
31 #endif // ENTT_HS_SUFFIX
34 #ifndef ENTT_HWS_SUFFIX
35 #define ENTT_HWS_SUFFIX _hws
36 #endif // ENTT_HWS_SUFFIX
39 #ifndef ENTT_NO_ATOMIC
41 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
42 #else // ENTT_NO_ATOMIC
43 #define ENTT_MAYBE_ATOMIC(Type) Type
44 #endif // ENTT_NO_ATOMIC
47 #ifndef ENTT_DISABLE_ETO
48 #include <type_traits>
49 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
50 #else // ENTT_DISABLE_ETO
52 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
53 #endif // ENTT_DISABLE_ETO
58 #define ENTT_ID_TYPE std::uint32_t
59 #endif // ENTT_ID_TYPE
62 #ifndef ENTT_PAGE_SIZE
63 #define ENTT_PAGE_SIZE 32768
64 #endif // ENTT_PAGE_SIZE
67 #ifndef ENTT_DISABLE_ASSERT
69 #define ENTT_ASSERT(condition) assert(condition)
70 #else // ENTT_DISABLE_ASSERT
71 #define ENTT_ASSERT(...) ((void)0)
72 #endif // ENTT_DISABLE_ASSERT
75 #endif // ENTT_CONFIG_CONFIG_H
92 return std::forward<Type>(value);
104 template<
typename Type,
typename Class>
114 template<
typename Type>
122 template<
class... Func>
124 using Func::operator()...;
132 template<
class... Type>
147 func{std::move(recursive)}
156 template <
class... Args>
157 decltype(
auto) operator()(Args &&... args)
const {
158 return func(*
this, std::forward<Args>(args)...);
162 template <
class... Args>
163 decltype(
auto) operator()(Args &&... args) {
164 return func(*
this, std::forward<Args>(args)...);
175 #endif // ENTT_CORE_UTILITY_HPP
204 template<
typename It,
typename Compare = std::less<>,
typename... Args>
205 void operator()(It first, It last, Compare compare = Compare{}, Args &&... args)
const {
206 std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare));
224 template<
typename It,
typename Compare = std::less<>>
225 void operator()(It first, It last, Compare compare = Compare{})
const {
227 for(
auto it = first+1; it < last; ++it) {
228 auto value = std::move(*it);
231 for(; pre > first && compare(value, *(pre-1)); --pre) {
232 *pre = std::move(*(pre-1));
235 *pre = std::move(value);
247 template<std::
size_t Bit, std::
size_t N>
249 static_assert((N % Bit) == 0);
266 template<
typename It,
typename Getter =
identity>
267 void operator()(It first, It last, Getter getter = Getter{})
const {
269 static constexpr
auto mask = (1 << Bit) - 1;
270 static constexpr
auto buckets = 1 << Bit;
271 static constexpr
auto passes = N / Bit;
273 using value_type =
typename std::iterator_traits<It>::value_type;
276 auto part = [getter = std::move(getter)](
auto from,
auto to,
auto out,
auto start) {
277 std::size_t index[buckets]{};
278 std::size_t count[buckets]{};
280 std::for_each(from, to, [&getter, &count, start](
const value_type &item) {
281 ++count[(getter(item) >> start) & mask];
284 std::for_each(std::next(std::begin(index)), std::end(index), [index = std::begin(index), count = std::begin(count)](
auto &item)
mutable {
285 item = *(index++) + *(count++);
288 std::for_each(from, to, [&getter, &out, &index, start](value_type &item) {
289 out[index[(getter(item) >> start) & mask]++] = std::move(item);
293 for(std::size_t pass = 0; pass < (passes & ~1); pass += 2) {
294 part(first, last, aux.begin(), pass * Bit);
295 part(aux.begin(), aux.end(), first, (pass + 1) * Bit);
298 if constexpr(passes & 1) {
299 part(first, last, aux.begin(), (passes - 1) * Bit);
300 std::move(aux.begin(), aux.end(), first);
310 #endif // ENTT_CORE_ALGORITHM_HPP
313 #ifndef ENTT_CORE_FAMILY_HPP
314 #define ENTT_CORE_FAMILY_HPP
317 #include <type_traits>
332 template<
typename...>
341 template<
typename... Type>
350 #endif // ENTT_CORE_FAMILY_HPP
353 #ifndef ENTT_CORE_HASHED_STRING_HPP
354 #define ENTT_CORE_HASHED_STRING_HPP
379 struct fnv1a_traits<
std::uint32_t> {
380 static constexpr std::uint32_t offset = 2166136261;
381 static constexpr std::uint32_t prime = 16777619;
386 struct fnv1a_traits<
std::uint64_t> {
387 static constexpr std::uint64_t offset = 14695981039346656037ull;
388 static constexpr std::uint64_t prime = 1099511628211ull;
412 template<
typename Char>
414 using traits_type = internal::fnv1a_traits<ENTT_ID_TYPE>;
416 struct const_wrapper {
418 constexpr const_wrapper(
const Char *curr)
ENTT_NOEXCEPT: str{curr} {}
424 return curr[0] == 0 ? partial : helper((partial^curr[0])*traits_type::prime, curr+1);
448 template<std::
size_t N>
450 return helper(traits_type::offset, str);
459 return helper(traits_type::offset, wrapper.str);
470 while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
476 : str{
nullptr}, hash{}
493 template<std::
size_t N>
495 : str{curr}, hash{helper(traits_type::offset, curr)}
504 : str{wrapper.str}, hash{helper(traits_type::offset, wrapper.str)}
538 return hash == other.hash;
557 template<
typename Char, std::
size_t N>
569 template<
typename Char>
571 return !(lhs == rhs);
606 #endif // ENTT_CORE_HASHED_STRING_HPP
609 #ifndef ENTT_CORE_IDENT_HPP
610 #define ENTT_CORE_IDENT_HPP
615 #include <type_traits>
650 template<
typename... Types>
652 using tuple_type = std::tuple<std::decay_t<Types>...>;
654 template<
typename Type, std::size_t... Indexes>
656 static_assert(std::disjunction_v<std::is_same<Type, Types>...>);
657 return (0 + ... + (std::is_same_v<Type, std::tuple_element_t<Indexes, tuple_type>> ?
ENTT_ID_TYPE(Indexes) :
ENTT_ID_TYPE{}));
665 template<
typename Type>
673 #endif // ENTT_CORE_IDENT_HPP
676 #ifndef ENTT_CORE_MONOSTATE_HPP
677 #define ENTT_CORE_MONOSTATE_HPP
699 template<ENTT_ID_TYPE>
706 template<
typename Type>
716 template<
typename Type>
722 template<
typename Type>
723 inline static ENTT_MAYBE_ATOMIC(Type) value{};
731 template<ENTT_ID_TYPE Value>
738 #endif // ENTT_CORE_MONOSTATE_HPP
741 #ifndef ENTT_CORE_TYPE_TRAITS_HPP
742 #define ENTT_CORE_TYPE_TRAITS_HPP
746 #include <type_traits>
750 #ifndef ENTT_CORE_HASHED_STRING_HPP
751 #define ENTT_CORE_HASHED_STRING_HPP
756 #ifndef ENTT_CONFIG_CONFIG_H
757 #define ENTT_CONFIG_CONFIG_H
760 #ifndef ENTT_NOEXCEPT
761 #define ENTT_NOEXCEPT noexcept
762 #endif // ENTT_NOEXCEPT
765 #ifndef ENTT_HS_SUFFIX
766 #define ENTT_HS_SUFFIX _hs
767 #endif // ENTT_HS_SUFFIX
770 #ifndef ENTT_HWS_SUFFIX
771 #define ENTT_HWS_SUFFIX _hws
772 #endif // ENTT_HWS_SUFFIX
775 #ifndef ENTT_NO_ATOMIC
777 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
778 #else // ENTT_NO_ATOMIC
779 #define ENTT_MAYBE_ATOMIC(Type) Type
780 #endif // ENTT_NO_ATOMIC
783 #ifndef ENTT_DISABLE_ETO
784 #include <type_traits>
785 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
786 #else // ENTT_DISABLE_ETO
788 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
789 #endif // ENTT_DISABLE_ETO
794 #define ENTT_ID_TYPE std::uint32_t
795 #endif // ENTT_ID_TYPE
798 #ifndef ENTT_PAGE_SIZE
799 #define ENTT_PAGE_SIZE 32768
800 #endif // ENTT_PAGE_SIZE
803 #ifndef ENTT_DISABLE_ASSERT
805 #define ENTT_ASSERT(condition) assert(condition)
806 #else // ENTT_DISABLE_ASSERT
807 #define ENTT_ASSERT(...) ((void)0)
808 #endif // ENTT_DISABLE_ASSERT
811 #endif // ENTT_CONFIG_CONFIG_H
832 struct fnv1a_traits<
std::uint32_t> {
833 static constexpr std::uint32_t offset = 2166136261;
834 static constexpr std::uint32_t prime = 16777619;
839 struct fnv1a_traits<
std::uint64_t> {
840 static constexpr std::uint64_t offset = 14695981039346656037ull;
841 static constexpr std::uint64_t prime = 1099511628211ull;
865 template<
typename Char>
867 using traits_type = internal::fnv1a_traits<ENTT_ID_TYPE>;
869 struct const_wrapper {
871 constexpr const_wrapper(
const Char *curr)
ENTT_NOEXCEPT: str{curr} {}
877 return curr[0] == 0 ? partial : helper((partial^curr[0])*traits_type::prime, curr+1);
901 template<std::
size_t N>
903 return helper(traits_type::offset, str);
912 return helper(traits_type::offset, wrapper.str);
923 while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
929 : str{
nullptr}, hash{}
946 template<std::
size_t N>
948 : str{curr}, hash{helper(traits_type::offset, curr)}
957 : str{wrapper.str}, hash{helper(traits_type::offset, wrapper.str)}
991 return hash == other.hash;
1010 template<
typename Char, std::
size_t N>
1012 -> basic_hashed_string<Char>;
1022 template<
typename Char>
1023 constexpr
bool operator!=(
const basic_hashed_string<Char> &lhs,
const basic_hashed_string<Char> &rhs)
ENTT_NOEXCEPT {
1024 return !(lhs == rhs);
1059 #endif // ENTT_CORE_HASHED_STRING_HPP
1070 template<std::
size_t N>
1088 template<std::
size_t N>
1093 template<
typename...>
1106 template<
typename... Type>
1108 : std::integral_constant<std::size_t, sizeof...(Type)>
1116 template<
class List>
1121 template<
typename...>
1139 template<
typename... Type,
typename... Other,
typename... List>
1150 template<
typename... Type>
1161 template<
typename... List>
1175 template<
typename Type,
typename... Other>
1179 std::disjunction_v<std::is_same<Type, Other>...>,
1198 template<
typename Type>
1207 template<
typename Type,
typename = std::
void_t<>>
1212 template<
typename Type>
1220 template<
class Type>
1233 template<
typename Type>
1243 template<
typename Type>
1251 template<
class Type>
1260 template<
typename Type,
typename = std::
void_t<>>
1265 template<
typename Type>
1266 struct is_named_type<Type,
std::void_t<named_type_traits_t<std::decay_t<Type>>>>: std::true_type {};
1273 template<
class Type>
1283 #define ENTT_OPAQUE_TYPE(clazz, type)\
1284 enum class clazz: type {};\
1285 constexpr auto to_integer(const clazz id) ENTT_NOEXCEPT {\
1286 return std::underlying_type_t<clazz>(id);\
1301 #define ENTT_EXPAND(args) args
1321 #define ENTT_NAMED_TYPE(type)\
1323 struct entt::named_type_traits<type>\
1324 : std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#type)>>>>{#type}>\
1326 static_assert(std::is_same_v<std::remove_cv_t<type>, type>);\
1327 static_assert(std::is_object_v<type>);\
1336 #define ENTT_NAMED_STRUCT_ONLY(clazz, body)\
1338 ENTT_NAMED_TYPE(clazz)
1347 #define ENTT_NAMED_STRUCT_WITH_NAMESPACE(ns, clazz, body)\
1348 namespace ns { struct clazz body; }\
1349 ENTT_NAMED_TYPE(ns::clazz)
1353 #define ENTT_NAMED_STRUCT_OVERLOAD(_1, _2, _3, FUNC, ...) FUNC
1355 #define ENTT_NAMED_STRUCT(...) ENTT_EXPAND(ENTT_NAMED_STRUCT_OVERLOAD(__VA_ARGS__, ENTT_NAMED_STRUCT_WITH_NAMESPACE, ENTT_NAMED_STRUCT_ONLY,)(__VA_ARGS__))
1363 #define ENTT_NAMED_CLASS_ONLY(clazz, body)\
1365 ENTT_NAMED_TYPE(clazz)
1374 #define ENTT_NAMED_CLASS_WITH_NAMESPACE(ns, clazz, body)\
1375 namespace ns { class clazz body; }\
1376 ENTT_NAMED_TYPE(ns::clazz)
1380 #define ENTT_NAMED_CLASS_MACRO(_1, _2, _3, FUNC, ...) FUNC
1382 #define ENTT_NAMED_CLASS(...) ENTT_EXPAND(ENTT_NAMED_CLASS_MACRO(__VA_ARGS__, ENTT_NAMED_CLASS_WITH_NAMESPACE, ENTT_NAMED_CLASS_ONLY,)(__VA_ARGS__))
1385 #endif // ENTT_CORE_TYPE_TRAITS_HPP
1390 #ifndef ENTT_ENTITY_ACTOR_HPP
1391 #define ENTT_ENTITY_ACTOR_HPP
1396 #include <type_traits>
1398 #ifndef ENTT_CONFIG_CONFIG_H
1399 #define ENTT_CONFIG_CONFIG_H
1402 #ifndef ENTT_NOEXCEPT
1403 #define ENTT_NOEXCEPT noexcept
1404 #endif // ENTT_NOEXCEPT
1407 #ifndef ENTT_HS_SUFFIX
1408 #define ENTT_HS_SUFFIX _hs
1409 #endif // ENTT_HS_SUFFIX
1412 #ifndef ENTT_HWS_SUFFIX
1413 #define ENTT_HWS_SUFFIX _hws
1414 #endif // ENTT_HWS_SUFFIX
1417 #ifndef ENTT_NO_ATOMIC
1419 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
1420 #else // ENTT_NO_ATOMIC
1421 #define ENTT_MAYBE_ATOMIC(Type) Type
1422 #endif // ENTT_NO_ATOMIC
1425 #ifndef ENTT_DISABLE_ETO
1426 #include <type_traits>
1427 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
1428 #else // ENTT_DISABLE_ETO
1430 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
1431 #endif // ENTT_DISABLE_ETO
1434 #ifndef ENTT_ID_TYPE
1436 #define ENTT_ID_TYPE std::uint32_t
1437 #endif // ENTT_ID_TYPE
1440 #ifndef ENTT_PAGE_SIZE
1441 #define ENTT_PAGE_SIZE 32768
1442 #endif // ENTT_PAGE_SIZE
1445 #ifndef ENTT_DISABLE_ASSERT
1447 #define ENTT_ASSERT(condition) assert(condition)
1448 #else // ENTT_DISABLE_ASSERT
1449 #define ENTT_ASSERT(...) ((void)0)
1450 #endif // ENTT_DISABLE_ASSERT
1453 #endif // ENTT_CONFIG_CONFIG_H
1456 #ifndef ENTT_ENTITY_REGISTRY_HPP
1457 #define ENTT_ENTITY_REGISTRY_HPP
1466 #include <algorithm>
1467 #include <type_traits>
1471 #ifndef ENTT_CORE_FAMILY_HPP
1472 #define ENTT_CORE_FAMILY_HPP
1475 #include <type_traits>
1477 #ifndef ENTT_CONFIG_CONFIG_H
1478 #define ENTT_CONFIG_CONFIG_H
1481 #ifndef ENTT_NOEXCEPT
1482 #define ENTT_NOEXCEPT noexcept
1483 #endif // ENTT_NOEXCEPT
1486 #ifndef ENTT_HS_SUFFIX
1487 #define ENTT_HS_SUFFIX _hs
1488 #endif // ENTT_HS_SUFFIX
1491 #ifndef ENTT_HWS_SUFFIX
1492 #define ENTT_HWS_SUFFIX _hws
1493 #endif // ENTT_HWS_SUFFIX
1496 #ifndef ENTT_NO_ATOMIC
1498 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
1499 #else // ENTT_NO_ATOMIC
1500 #define ENTT_MAYBE_ATOMIC(Type) Type
1501 #endif // ENTT_NO_ATOMIC
1504 #ifndef ENTT_DISABLE_ETO
1505 #include <type_traits>
1506 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
1507 #else // ENTT_DISABLE_ETO
1509 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
1510 #endif // ENTT_DISABLE_ETO
1513 #ifndef ENTT_ID_TYPE
1515 #define ENTT_ID_TYPE std::uint32_t
1516 #endif // ENTT_ID_TYPE
1519 #ifndef ENTT_PAGE_SIZE
1520 #define ENTT_PAGE_SIZE 32768
1521 #endif // ENTT_PAGE_SIZE
1524 #ifndef ENTT_DISABLE_ASSERT
1526 #define ENTT_ASSERT(condition) assert(condition)
1527 #else // ENTT_DISABLE_ASSERT
1528 #define ENTT_ASSERT(...) ((void)0)
1529 #endif // ENTT_DISABLE_ASSERT
1532 #endif // ENTT_CONFIG_CONFIG_H
1546 template<
typename...>
1555 template<
typename... Type>
1557 inline static const family_type type = identifier++;
1564 #endif // ENTT_CORE_FAMILY_HPP
1567 #ifndef ENTT_CORE_ALGORITHM_HPP
1568 #define ENTT_CORE_ALGORITHM_HPP
1573 #include <algorithm>
1574 #include <functional>
1576 #ifndef ENTT_CORE_UTILITY_HPP
1577 #define ENTT_CORE_UTILITY_HPP
1595 template<
class Type>
1597 return std::forward<Type>(value);
1609 template<
typename Type,
typename Class>
1619 template<
typename Type>
1627 template<
class... Func>
1629 using Func::operator()...;
1637 template<
class... Type>
1645 template<
class Func>
1646 struct y_combinator {
1652 func{std::move(recursive)}
1661 template <
class... Args>
1662 decltype(
auto) operator()(Args &&... args)
const {
1663 return func(*
this, std::forward<Args>(args)...);
1667 template <
class... Args>
1668 decltype(
auto) operator()(Args &&... args) {
1669 return func(*
this, std::forward<Args>(args)...);
1680 #endif // ENTT_CORE_UTILITY_HPP
1709 template<
typename It,
typename Compare = std::less<>,
typename... Args>
1710 void operator()(It first, It last, Compare compare = Compare{}, Args &&... args)
const {
1711 std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare));
1717 struct insertion_sort {
1729 template<
typename It,
typename Compare = std::less<>>
1730 void operator()(It first, It last, Compare compare = Compare{})
const {
1732 for(
auto it = first+1; it < last; ++it) {
1733 auto value = std::move(*it);
1736 for(; pre > first && compare(value, *(pre-1)); --pre) {
1737 *pre = std::move(*(pre-1));
1740 *pre = std::move(value);
1752 template<std::
size_t Bit, std::
size_t N>
1754 static_assert((N % Bit) == 0);
1771 template<
typename It,
typename Getter =
identity>
1772 void operator()(It first, It last, Getter getter = Getter{})
const {
1774 static constexpr
auto mask = (1 << Bit) - 1;
1775 static constexpr
auto buckets = 1 << Bit;
1776 static constexpr
auto passes = N / Bit;
1778 using value_type =
typename std::iterator_traits<It>::value_type;
1781 auto part = [getter = std::move(getter)](
auto from,
auto to,
auto out,
auto start) {
1782 std::size_t index[buckets]{};
1783 std::size_t count[buckets]{};
1785 std::for_each(from, to, [&getter, &count, start](
const value_type &item) {
1786 ++count[(getter(item) >> start) & mask];
1789 std::for_each(std::next(std::begin(index)), std::end(index), [index = std::begin(index), count = std::begin(count)](
auto &item)
mutable {
1790 item = *(index++) + *(count++);
1793 std::for_each(from, to, [&getter, &out, &index, start](value_type &item) {
1794 out[index[(getter(item) >> start) & mask]++] = std::move(item);
1798 for(std::size_t pass = 0; pass < (passes & ~1); pass += 2) {
1799 part(first, last, aux.begin(), pass * Bit);
1800 part(aux.begin(), aux.end(), first, (pass + 1) * Bit);
1803 if constexpr(passes & 1) {
1804 part(first, last, aux.begin(), (passes - 1) * Bit);
1805 std::move(aux.begin(), aux.end(), first);
1815 #endif // ENTT_CORE_ALGORITHM_HPP
1818 #ifndef ENTT_CORE_TYPE_TRAITS_HPP
1819 #define ENTT_CORE_TYPE_TRAITS_HPP
1823 #include <type_traits>
1827 #ifndef ENTT_CORE_HASHED_STRING_HPP
1828 #define ENTT_CORE_HASHED_STRING_HPP
1833 #ifndef ENTT_CONFIG_CONFIG_H
1834 #define ENTT_CONFIG_CONFIG_H
1837 #ifndef ENTT_NOEXCEPT
1838 #define ENTT_NOEXCEPT noexcept
1839 #endif // ENTT_NOEXCEPT
1842 #ifndef ENTT_HS_SUFFIX
1843 #define ENTT_HS_SUFFIX _hs
1844 #endif // ENTT_HS_SUFFIX
1847 #ifndef ENTT_HWS_SUFFIX
1848 #define ENTT_HWS_SUFFIX _hws
1849 #endif // ENTT_HWS_SUFFIX
1852 #ifndef ENTT_NO_ATOMIC
1854 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
1855 #else // ENTT_NO_ATOMIC
1856 #define ENTT_MAYBE_ATOMIC(Type) Type
1857 #endif // ENTT_NO_ATOMIC
1860 #ifndef ENTT_DISABLE_ETO
1861 #include <type_traits>
1862 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
1863 #else // ENTT_DISABLE_ETO
1865 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
1866 #endif // ENTT_DISABLE_ETO
1869 #ifndef ENTT_ID_TYPE
1871 #define ENTT_ID_TYPE std::uint32_t
1872 #endif // ENTT_ID_TYPE
1875 #ifndef ENTT_PAGE_SIZE
1876 #define ENTT_PAGE_SIZE 32768
1877 #endif // ENTT_PAGE_SIZE
1880 #ifndef ENTT_DISABLE_ASSERT
1882 #define ENTT_ASSERT(condition) assert(condition)
1883 #else // ENTT_DISABLE_ASSERT
1884 #define ENTT_ASSERT(...) ((void)0)
1885 #endif // ENTT_DISABLE_ASSERT
1888 #endif // ENTT_CONFIG_CONFIG_H
1901 namespace internal {
1905 struct fnv1a_traits;
1909 struct fnv1a_traits<
std::uint32_t> {
1910 static constexpr std::uint32_t offset = 2166136261;
1911 static constexpr std::uint32_t prime = 16777619;
1916 struct fnv1a_traits<
std::uint64_t> {
1917 static constexpr std::uint64_t offset = 14695981039346656037ull;
1918 static constexpr std::uint64_t prime = 1099511628211ull;
1942 template<
typename Char>
1944 using traits_type = internal::fnv1a_traits<ENTT_ID_TYPE>;
1946 struct const_wrapper {
1948 constexpr const_wrapper(
const Char *curr)
ENTT_NOEXCEPT: str{curr} {}
1954 return curr[0] == 0 ? partial : helper((partial^curr[0])*traits_type::prime, curr+1);
1978 template<std::
size_t N>
1980 return helper(traits_type::offset, str);
1989 return helper(traits_type::offset, wrapper.str);
2000 while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
2006 : str{
nullptr}, hash{}
2023 template<std::
size_t N>
2025 : str{curr}, hash{helper(traits_type::offset, curr)}
2034 : str{wrapper.str}, hash{helper(traits_type::offset, wrapper.str)}
2068 return hash == other.hash;
2087 template<
typename Char, std::
size_t N>
2089 -> basic_hashed_string<Char>;
2099 template<
typename Char>
2100 constexpr
bool operator!=(
const basic_hashed_string<Char> &lhs,
const basic_hashed_string<Char> &rhs)
ENTT_NOEXCEPT {
2101 return !(lhs == rhs);
2136 #endif // ENTT_CORE_HASHED_STRING_HPP
2147 template<std::
size_t N>
2158 struct choice_t<0> {};
2165 template<std::
size_t N>
2166 constexpr choice_t<N>
choice{};
2170 template<
typename...>
2171 struct type_list {};
2176 struct type_list_size;
2183 template<
typename... Type>
2184 struct type_list_size<type_list<Type...>>
2185 : std::integral_constant<std::size_t, sizeof...(Type)>
2193 template<
class List>
2198 template<
typename...>
2199 struct type_list_cat;
2204 struct type_list_cat<> {
2206 using type = type_list<>;
2216 template<
typename... Type,
typename... Other,
typename... List>
2217 struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
2219 using type =
typename type_list_cat<type_list<Type..., Other...>, List...>::type;
2227 template<
typename... Type>
2228 struct type_list_cat<type_list<Type...>> {
2230 using type = type_list<Type...>;
2238 template<
typename... List>
2244 struct type_list_unique;
2252 template<
typename Type,
typename... Other>
2253 struct type_list_unique<type_list<Type, Other...>> {
2255 using type = std::conditional_t<
2256 std::disjunction_v<std::is_same<Type, Other>...>,
2257 typename type_list_unique<type_list<Other...>>::type,
2258 type_list_cat_t<type_list<Type>,
typename type_list_unique<type_list<Other...>>::type>
2265 struct type_list_unique<type_list<>> {
2267 using type = type_list<>;
2275 template<
typename Type>
2284 template<
typename Type,
typename = std::
void_t<>>
2285 struct is_equality_comparable: std::false_type {};
2289 template<
typename Type>
2290 struct is_equality_comparable<Type,
std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>: std::true_type {};
2297 template<
class Type>
2303 struct named_type_traits;
2310 template<
typename Type>
2311 struct named_type_traits<const Type>
2312 : named_type_traits<Type>
2320 template<
typename Type>
2328 template<
class Type>
2337 template<
typename Type,
typename = std::
void_t<>>
2338 struct is_named_type: std::false_type {};
2342 template<
typename Type>
2343 struct is_named_type<Type,
std::void_t<named_type_traits_t<std::decay_t<Type>>>>: std::true_type {};
2350 template<
class Type>
2360 #define ENTT_OPAQUE_TYPE(clazz, type)\
2361 enum class clazz: type {};\
2362 constexpr auto to_integer(const clazz id) ENTT_NOEXCEPT {\
2363 return std::underlying_type_t<clazz>(id);\
2378 #define ENTT_EXPAND(args) args
2398 #define ENTT_NAMED_TYPE(type)\
2400 struct entt::named_type_traits<type>\
2401 : std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#type)>>>>{#type}>\
2403 static_assert(std::is_same_v<std::remove_cv_t<type>, type>);\
2404 static_assert(std::is_object_v<type>);\
2413 #define ENTT_NAMED_STRUCT_ONLY(clazz, body)\
2415 ENTT_NAMED_TYPE(clazz)
2424 #define ENTT_NAMED_STRUCT_WITH_NAMESPACE(ns, clazz, body)\
2425 namespace ns { struct clazz body; }\
2426 ENTT_NAMED_TYPE(ns::clazz)
2430 #define ENTT_NAMED_STRUCT_OVERLOAD(_1, _2, _3, FUNC, ...) FUNC
2432 #define ENTT_NAMED_STRUCT(...) ENTT_EXPAND(ENTT_NAMED_STRUCT_OVERLOAD(__VA_ARGS__, ENTT_NAMED_STRUCT_WITH_NAMESPACE, ENTT_NAMED_STRUCT_ONLY,)(__VA_ARGS__))
2440 #define ENTT_NAMED_CLASS_ONLY(clazz, body)\
2442 ENTT_NAMED_TYPE(clazz)
2451 #define ENTT_NAMED_CLASS_WITH_NAMESPACE(ns, clazz, body)\
2452 namespace ns { class clazz body; }\
2453 ENTT_NAMED_TYPE(ns::clazz)
2457 #define ENTT_NAMED_CLASS_MACRO(_1, _2, _3, FUNC, ...) FUNC
2459 #define ENTT_NAMED_CLASS(...) ENTT_EXPAND(ENTT_NAMED_CLASS_MACRO(__VA_ARGS__, ENTT_NAMED_CLASS_WITH_NAMESPACE, ENTT_NAMED_CLASS_ONLY,)(__VA_ARGS__))
2462 #endif // ENTT_CORE_TYPE_TRAITS_HPP
2465 #ifndef ENTT_SIGNAL_DELEGATE_HPP
2466 #define ENTT_SIGNAL_DELEGATE_HPP
2472 #include <algorithm>
2473 #include <functional>
2474 #include <type_traits>
2476 #ifndef ENTT_CONFIG_CONFIG_H
2477 #define ENTT_CONFIG_CONFIG_H
2480 #ifndef ENTT_NOEXCEPT
2481 #define ENTT_NOEXCEPT noexcept
2482 #endif // ENTT_NOEXCEPT
2485 #ifndef ENTT_HS_SUFFIX
2486 #define ENTT_HS_SUFFIX _hs
2487 #endif // ENTT_HS_SUFFIX
2490 #ifndef ENTT_HWS_SUFFIX
2491 #define ENTT_HWS_SUFFIX _hws
2492 #endif // ENTT_HWS_SUFFIX
2495 #ifndef ENTT_NO_ATOMIC
2497 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
2498 #else // ENTT_NO_ATOMIC
2499 #define ENTT_MAYBE_ATOMIC(Type) Type
2500 #endif // ENTT_NO_ATOMIC
2503 #ifndef ENTT_DISABLE_ETO
2504 #include <type_traits>
2505 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
2506 #else // ENTT_DISABLE_ETO
2508 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
2509 #endif // ENTT_DISABLE_ETO
2512 #ifndef ENTT_ID_TYPE
2514 #define ENTT_ID_TYPE std::uint32_t
2515 #endif // ENTT_ID_TYPE
2518 #ifndef ENTT_PAGE_SIZE
2519 #define ENTT_PAGE_SIZE 32768
2520 #endif // ENTT_PAGE_SIZE
2523 #ifndef ENTT_DISABLE_ASSERT
2525 #define ENTT_ASSERT(condition) assert(condition)
2526 #else // ENTT_DISABLE_ASSERT
2527 #define ENTT_ASSERT(...) ((void)0)
2528 #endif // ENTT_DISABLE_ASSERT
2531 #endif // ENTT_CONFIG_CONFIG_H
2544 namespace internal {
2547 template<
typename Ret,
typename... Args>
2548 auto to_function_pointer(Ret(*)(Args...)) -> Ret(*)(Args...);
2551 template<
typename Ret,
typename... Args,
typename Type,
typename Payload,
typename = std::enable_if_t<std::is_convertible_v<const Payload *, const Type *>>>
2552 auto to_function_pointer(Ret(*)(Type &, Args...),
const Payload *) -> Ret(*)(Args...);
2555 template<
typename Ret,
typename... Args,
typename Type,
typename Payload,
typename = std::enable_if_t<std::is_convertible_v<const Payload *, const Type *>>>
2556 auto to_function_pointer(Ret(*)(Type *, Args...),
const Payload *) -> Ret(*)(Args...);
2559 template<
typename Class,
typename Ret,
typename... Args>
2560 auto to_function_pointer(Ret(Class:: *)(Args...),
const Class *) -> Ret(*)(Args...);
2563 template<
typename Class,
typename Ret,
typename... Args>
2564 auto to_function_pointer(Ret(Class:: *)(Args...)
const,
const Class *) -> Ret(*)(Args...);
2567 template<
typename Class,
typename Type>
2568 auto to_function_pointer(Type Class:: *,
const Class *) -> Type(*)();
2571 template<
typename... Type>
2572 using to_function_pointer_t = decltype(internal::to_function_pointer(std::declval<Type>()...));
2575 template<
typename Ret,
typename... Args>
2576 constexpr
auto index_sequence_for(Ret(*)(Args...)) {
2577 return std::index_sequence_for<Args...>{};
2623 template<
typename Ret,
typename... Args>
2625 using proto_fn_type = Ret(
const void *, std::tuple<Args &&...>);
2627 template<
auto Function, std::size_t... Index>
2629 static_assert(std::is_invocable_r_v<Ret, decltype(Function), std::tuple_element_t<Index, std::tuple<Args...>>...>);
2632 fn = [](
const void *, std::tuple<Args &&...> args) -> Ret {
2634 return Ret(std::invoke(Function, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
2638 template<
auto Candidate,
typename Type, std::size_t... Index>
2639 void connect(Type &value_or_instance, std::index_sequence<Index...>)
ENTT_NOEXCEPT {
2640 static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, std::tuple_element_t<Index, std::tuple<Args...>>...>);
2641 data = &value_or_instance;
2643 fn = [](
const void *payload, std::tuple<Args &&...> args) -> Ret {
2644 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
2646 return Ret(std::invoke(Candidate, *curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
2650 template<
auto Candidate,
typename Type, std::size_t... Index>
2651 void connect(Type *value_or_instance, std::index_sequence<Index...>)
ENTT_NOEXCEPT {
2652 static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, std::tuple_element_t<Index, std::tuple<Args...>>...>);
2653 data = value_or_instance;
2655 fn = [](
const void *payload, std::tuple<Args &&...> args) -> Ret {
2656 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
2658 return Ret(std::invoke(Candidate, curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
2668 : fn{
nullptr}, data{
nullptr}
2675 template<auto Function>
2679 connect<Function>();
2689 template<auto Cand
idate,
typename Type>
2693 connect<Candidate>(value_or_instance);
2703 template<auto Cand
idate,
typename Type>
2707 connect<Candidate>(value_or_instance);
2714 template<auto Function>
2716 connect<Function>(internal::index_sequence_for(internal::to_function_pointer_t<decltype(Function)>{}));
2734 template<auto Cand
idate,
typename Type>
2736 connect<Candidate>(value_or_instance, internal::index_sequence_for(internal::to_function_pointer_t<decltype(Candidate), Type *>{}));
2754 template<auto Cand
idate,
typename Type>
2756 connect<Candidate>(value_or_instance, internal::index_sequence_for(internal::to_function_pointer_t<decltype(Candidate), Type *>{}));
2793 return fn(data, std::forward_as_tuple(std::forward<Args>(args)...));
2811 return fn == other.fn && data == other.data;
2828 template<
typename Ret,
typename... Args>
2830 return !(lhs == rhs);
2842 template<auto Function>
2844 ->
delegate<std::remove_pointer_t<internal::to_function_pointer_t<decltype(Function)>>>;
2856 template<auto Cand
idate,
typename Type>
2858 ->
delegate<std::remove_pointer_t<internal::to_function_pointer_t<decltype(Candidate), Type *>>>;
2870 template<auto Cand
idate,
typename Type>
2872 ->
delegate<std::remove_pointer_t<internal::to_function_pointer_t<decltype(Candidate), Type *>>>;
2878 #endif // ENTT_SIGNAL_DELEGATE_HPP
2881 #ifndef ENTT_SIGNAL_SIGH_HPP
2882 #define ENTT_SIGNAL_SIGH_HPP
2888 #include <algorithm>
2889 #include <functional>
2890 #include <type_traits>
2896 #ifndef ENTT_SIGNAL_FWD_HPP
2897 #define ENTT_SIGNAL_FWD_HPP
2919 #endif // ENTT_SIGNAL_FWD_HPP
2934 template<
typename Function>
2946 template<
typename Function>
2965 template<
typename Ret,
typename... Args>
2968 friend class sink<Ret(Args...)>;
2980 template<
typename Class>
2988 return calls.size();
2996 return calls.empty();
3007 std::for_each(calls.cbegin(), calls.cend(), [&args...](
auto &&call) {
3026 template<
typename Func>
3028 for(
auto &&call: calls) {
3029 if constexpr(std::is_void_v<Ret>) {
3030 if constexpr(std::is_invocable_r_v<bool, Func>) {
3032 if(func()) {
break; }
3038 if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
3039 if(func(call(args...))) {
break; }
3041 func(call(args...));
3048 std::vector<
delegate<Ret(Args...)>> calls;
3065 : disconnect{fn}, signal{ref}
3082 std::swap(disconnect, other.disconnect);
3083 std::swap(signal, other.signal);
3095 if(
this != &other) {
3096 auto tmp{std::move(other)};
3097 disconnect = tmp.disconnect;
3098 signal = tmp.signal;
3109 return static_cast<bool>(disconnect);
3136 using connection::operator bool;
3189 static_cast<connection &
>(*this) = std::move(other);
3209 template<
typename Ret,
typename... Args>
3212 using difference_type =
typename std::iterator_traits<
typename decltype(signal_type::calls)::iterator>::difference_type;
3214 template<auto Cand
idate,
typename Type>
3215 static void release(Type value_or_instance,
void *signal) {
3216 sink{*
static_cast<signal_type *
>(signal)}.disconnect<Candidate>(value_or_instance);
3219 template<auto Function>
3220 static void release(
void *signal) {
3239 return signal->calls.empty();
3247 template<auto Function>
3250 call.template connect<Function>();
3252 const auto &calls = signal->calls;
3253 const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
3268 template<auto Cand
idate,
typename Type>
3271 call.template connect<Candidate>(value_or_instance);
3273 const auto &calls = signal->calls;
3274 const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
3289 template<auto Cand
idate,
typename Type>
3292 call.template connect<Candidate>(value_or_instance);
3294 const auto &calls = signal->calls;
3295 const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
3309 template<
typename Type>
3311 return before(&value_or_instance);
3321 template<
typename Type>
3325 if(value_or_instance) {
3326 const auto &calls = signal->calls;
3327 const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](
const auto &
delegate) {
3328 return delegate.instance() == value_or_instance;
3343 other.offset = signal->calls.size();
3356 template<auto Function>
3358 disconnect<Function>();
3361 call.template connect<Function>();
3362 signal->calls.insert(signal->calls.end() - offset, std::move(call));
3365 conn.template connect<&release<Function>>();
3366 return { std::move(conn), signal };
3386 template<auto Cand
idate,
typename Type>
3388 disconnect<Candidate>(value_or_instance);
3391 call.template connect<Candidate>(value_or_instance);
3392 signal->calls.insert(signal->calls.end() - offset, std::move(call));
3395 conn.template connect<&release<Candidate, Type &>>(value_or_instance);
3396 return { std::move(conn), signal };
3416 template<auto Cand
idate,
typename Type>
3418 disconnect<Candidate>(value_or_instance);
3421 call.template connect<Candidate>(value_or_instance);
3422 signal->calls.insert(signal->calls.end() - offset, std::move(call));
3425 conn.template connect<&release<Candidate, Type *>>(value_or_instance);
3426 return { std::move(conn), signal };
3433 template<auto Function>
3435 auto &calls = signal->calls;
3437 call.template connect<Function>();
3438 calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
3448 template<auto Cand
idate,
typename Type>
3450 auto &calls = signal->calls;
3452 call.template connect<Candidate>(value_or_instance);
3453 calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
3463 template<auto Cand
idate,
typename Type>
3465 auto &calls = signal->calls;
3467 call.template connect<Candidate>(value_or_instance);
3468 calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
3477 template<
typename Type>
3479 disconnect(&value_or_instance);
3488 template<
typename Type>
3490 if(value_or_instance) {
3491 auto &calls = signal->calls;
3492 calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](
const auto &
delegate) {
3493 return delegate.instance() == value_or_instance;
3500 signal->calls.clear();
3504 difference_type offset;
3505 signal_type *signal;
3518 template<
typename Ret,
typename... Args>
3525 #endif // ENTT_SIGNAL_SIGH_HPP
3528 #ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP
3529 #define ENTT_ENTITY_RUNTIME_VIEW_HPP
3536 #include <algorithm>
3537 #include <type_traits>
3541 #ifndef ENTT_ENTITY_SPARSE_SET_HPP
3542 #define ENTT_ENTITY_SPARSE_SET_HPP
3545 #include <algorithm>
3552 #include <type_traits>
3558 #ifndef ENTT_ENTITY_ENTITY_HPP
3559 #define ENTT_ENTITY_ENTITY_HPP
3563 #include <type_traits>
3599 static constexpr std::uint16_t entity_mask = 0xFFF;
3601 static constexpr std::uint16_t version_mask = 0xF;
3603 static constexpr
auto entity_shift = 12;
3625 static constexpr std::uint32_t entity_mask = 0xFFFFF;
3627 static constexpr std::uint32_t version_mask = 0xFFF;
3629 static constexpr
auto entity_shift = 20;
3651 static constexpr std::uint64_t entity_mask = 0xFFFFFFFF;
3653 static constexpr std::uint64_t version_mask = 0xFFFFFFFF;
3655 static constexpr
auto entity_shift = 32;
3665 namespace internal {
3669 template<
typename Entity>
3673 template<
typename Entity>
3675 return Entity{traits_type<Entity>::entity_mask};
3686 template<
typename Entity>
3687 constexpr
bool operator==(
const Entity entity)
const ENTT_NOEXCEPT {
3688 return (to_integer(entity) & traits_type<Entity>::entity_mask) == to_integer(
static_cast<Entity
>(*
this));
3691 template<
typename Entity>
3693 return !(entity == *
this);
3698 template<
typename Entity>
3699 constexpr
bool operator==(
const Entity entity,
null other)
ENTT_NOEXCEPT {
3700 return other == entity;
3704 template<
typename Entity>
3706 return other != entity;
3732 #endif // ENTT_ENTITY_ENTITY_HPP
3735 #ifndef ENTT_ENTITY_FWD_HPP
3736 #define ENTT_ENTITY_FWD_HPP
3752 template<
typename...>
3760 template<
typename...>
3811 template<
typename... Types>
3821 template<
typename... Types>
3828 #endif // ENTT_ENTITY_FWD_HPP
3862 template<
typename Entity>
3867 static constexpr
auto entt_per_page =
ENTT_PAGE_SIZE /
sizeof(
typename traits_type::entity_type);
3872 using direct_type =
const std::vector<Entity>;
3873 using index_type =
typename traits_type::difference_type;
3875 iterator(direct_type *ref,
const index_type idx)
ENTT_NOEXCEPT
3876 : direct{ref},
index{idx}
3880 using difference_type = index_type;
3881 using value_type = Entity;
3882 using pointer =
const value_type *;
3883 using reference =
const value_type &;
3884 using iterator_category = std::random_access_iterator_tag;
3889 return --
index, *
this;
3893 iterator orig = *
this;
3894 return ++(*this), orig;
3898 return ++
index, *
this;
3902 iterator orig = *
this;
3903 return --(*this), orig;
3906 iterator & operator+=(
const difference_type value)
ENTT_NOEXCEPT {
3912 return iterator{direct,
index-value};
3915 iterator & operator-=(
const difference_type value)
ENTT_NOEXCEPT {
3916 return (*
this += -value);
3920 return (*
this + -value);
3924 return other.index -
index;
3927 reference operator[](
const difference_type value)
const ENTT_NOEXCEPT {
3929 return (*direct)[pos];
3932 bool operator==(
const iterator &other)
const ENTT_NOEXCEPT {
3933 return other.index ==
index;
3937 return !(*
this == other);
3941 return index > other.index;
3945 return index < other.index;
3948 bool operator<=(
const iterator &other)
const ENTT_NOEXCEPT {
3949 return !(*
this > other);
3952 bool operator>=(
const iterator &other)
const ENTT_NOEXCEPT {
3953 return !(*
this < other);
3958 return &(*direct)[pos];
3962 return *operator->();
3966 direct_type *direct;
3970 void assure(
const std::size_t page) {
3971 if(!(page < reverse.size())) {
3972 reverse.resize(page+1);
3975 if(!reverse[page]) {
3976 reverse[page] = std::make_unique<entity_type[]>(entt_per_page);
3978 std::fill_n(reverse[page].
get(), entt_per_page,
null);
3983 const auto identifier = to_integer(
entt) & traits_type::entity_mask;
3984 const auto page =
size_type(identifier / entt_per_page);
3985 const auto offset =
size_type(identifier & (entt_per_page - 1));
3986 return std::make_pair(page, offset);
4006 direct{other.direct}
4008 for(
size_type pos{}, last = other.reverse.size(); pos < last; ++pos) {
4009 if(other.reverse[pos]) {
4011 std::copy_n(other.reverse[pos].get(), entt_per_page, reverse[pos].get());
4028 if(&other !=
this) {
4030 *
this = std::move(tmp);
4048 direct.reserve(cap);
4057 return direct.capacity();
4063 if(direct.empty()) {
4067 reverse.shrink_to_fit();
4068 direct.shrink_to_fit();
4082 return reverse.size() * entt_per_page;
4096 return direct.size();
4104 return direct.empty();
4123 return direct.data();
4140 const typename traits_type::difference_type pos = direct.size();
4178 auto [page, offset] = map(
entt);
4180 return (page < reverse.size() && reverse[page] && reverse[page][offset] !=
null);
4197 auto [page, offset] = map(
entt);
4198 return size_type(reverse[page][offset]);
4214 auto [page, offset] = map(
entt);
4216 reverse[page][offset] =
entity_type(direct.size());
4217 direct.push_back(
entt);
4233 template<
typename It>
4235 std::for_each(first, last, [
this, next = direct.size()](
const auto entt)
mutable {
4236 ENTT_ASSERT(!has(entt));
4237 auto [page, offset] = map(entt);
4239 reverse[page][offset] = entity_type(next++);
4242 direct.insert(direct.end(), first, last);
4258 auto [from_page, from_offset] = map(
entt);
4259 auto [to_page, to_offset] = map(direct.back());
4261 reverse[to_page][to_offset] = reverse[from_page][from_offset];
4262 reverse[from_page][from_offset] =
null;
4282 auto [src_page, src_offset] = map(lhs);
4283 auto [dst_page, dst_offset] = map(rhs);
4284 auto &from = reverse[src_page][src_offset];
4285 auto &to = reverse[dst_page][dst_offset];
4287 std::swap(from, to);
4329 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
4336 const auto to = direct.rend() - skip;
4337 const auto from = to - length;
4339 algo(from, to, std::move(compare), std::forward<Args>(args)...);
4342 auto [page, offset] = map(direct[pos]);
4374 template<
typename Apply,
typename Compare,
typename Sort = std_sort,
typename... Args>
4381 const auto to = direct.rend() - skip;
4382 const auto from = to - length;
4384 algo(from, to, std::move(compare), std::forward<Args>(args)...);
4388 auto next =
index(direct[curr]);
4390 while(curr != next) {
4391 apply(direct[curr], direct[next]);
4392 auto [page, offset] = map(direct[curr]);
4396 next =
index(direct[curr]);
4422 const auto to = other.end();
4423 auto from = other.begin();
4427 while(pos && from != to) {
4429 if(*from != direct[pos]) {
4430 swap(direct[pos], *from);
4449 std::vector<std::unique_ptr<entity_type[]>> reverse;
4450 std::vector<entity_type> direct;
4457 #endif // ENTT_ENTITY_SPARSE_SET_HPP
4506 template<
typename Entity>
4507 class basic_runtime_view {
4509 friend class basic_registry<Entity>;
4514 friend class basic_runtime_view<Entity>;
4516 iterator(underlying_iterator_type first, underlying_iterator_type last,
const sparse_set<Entity> *
const *others,
const sparse_set<Entity> *
const *length)
ENTT_NOEXCEPT
4528 return std::all_of(from, to, [
entt = *
begin](
const auto *
view) {
4534 using difference_type =
typename underlying_iterator_type::difference_type;
4535 using value_type =
typename underlying_iterator_type::value_type;
4536 using pointer =
typename underlying_iterator_type::pointer;
4537 using reference =
typename underlying_iterator_type::reference;
4538 using iterator_category = std::forward_iterator_tag;
4543 return (++
begin !=
end && !valid()) ? ++(*this) : *
this;
4547 iterator orig = *
this;
4548 return ++(*this), orig;
4551 bool operator==(
const iterator &other)
const ENTT_NOEXCEPT {
4552 return other.begin ==
begin;
4556 return !(*
this == other);
4560 return begin.operator->();
4564 return *operator->();
4568 underlying_iterator_type
begin;
4569 underlying_iterator_type
end;
4570 const sparse_set<Entity> *
const *from;
4575 : pools{std::move(others)}
4577 const auto it = std::min_element(pools.begin(), pools.end(), [](
const auto *lhs,
const auto *rhs) {
4578 return (!lhs && rhs) || (lhs && rhs && lhs->size() < rhs->size());
4582 std::rotate(pools.begin(), it, pools.end());
4586 return !pools.empty() && pools.front();
4602 return valid() ? pools.front()->size() :
size_type{};
4610 return !valid() || pools.front()->empty();
4631 const auto &pool = *pools.front();
4632 const auto *
const *data = pools.data();
4633 it = { pool.begin(), pool.end(), data + 1, data + pools.size() };
4658 const auto &pool = *pools.front();
4659 it = { pool.end(), pool.end(),
nullptr,
nullptr };
4671 return valid() && std::all_of(pools.cbegin(), pools.cend(), [
entt](
const auto *
view) {
4672 return view->find(entt) != view->end();
4691 template<
typename Func>
4693 std::for_each(
begin(),
end(), func);
4697 std::vector<const sparse_set<Entity> *> pools;
4704 #endif // ENTT_ENTITY_RUNTIME_VIEW_HPP
4709 #ifndef ENTT_ENTITY_SNAPSHOT_HPP
4710 #define ENTT_ENTITY_SNAPSHOT_HPP
4717 #include <type_traits>
4718 #include <unordered_map>
4740 template<
typename Entity>
4741 class basic_snapshot {
4743 friend class basic_registry<Entity>;
4746 using traits_type = entt_traits<std::underlying_type_t<Entity>>;
4754 template<
typename Component,
typename Archive,
typename It>
4755 void get(Archive &archive, std::size_t sz, It first, It last)
const {
4756 archive(
typename traits_type::entity_type(sz));
4758 while(first != last) {
4759 const auto entt = *(first++);
4761 if(reg->template has<Component>(
entt)) {
4762 if constexpr(std::is_empty_v<Component>) {
4765 archive(
entt, reg->template get<Component>(
entt));
4771 template<
typename... Component,
typename Archive,
typename It, std::size_t... Indexes>
4772 void component(Archive &archive, It first, It last, std::index_sequence<Indexes...>)
const {
4773 std::array<std::size_t,
sizeof...(Indexes)> size{};
4776 while(begin != last) {
4777 const auto entt = *(begin++);
4778 ((reg->template has<Component>(
entt) ? ++size[Indexes] : size[Indexes]), ...);
4781 (get<Component>(archive, size[Indexes], first, last), ...);
4801 template<
typename Archive>
4803 archive(
typename traits_type::entity_type(reg->
alive()));
4804 reg->
each([&archive](
const auto entt) { archive(
entt); });
4818 template<
typename Archive>
4821 archive(
typename traits_type::entity_type(size));
4827 for(--size; size; --size) {
4828 curr = follow(*reg, curr);
4847 template<
typename... Component,
typename Archive>
4849 (component<Component>(archive, reg->template data<Component>(), reg->template data<Component>() + reg->template size<Component>()), ...);
4867 template<
typename... Component,
typename Archive,
typename It>
4869 component<Component...>(archive, first, last, std::index_sequence_for<Component...>{});
4876 follow_fn_type *follow;
4890 template<
typename Entity>
4906 template<
typename Archive>
4907 void assure(Archive &archive,
bool discard)
const {
4908 typename traits_type::entity_type length{};
4914 force(*reg,
entt, discard);
4918 template<
typename Type,
typename Archive,
typename... Args>
4919 void assign(Archive &archive, Args... args)
const {
4920 typename traits_type::entity_type length{};
4924 static constexpr
auto discard =
false;
4927 if constexpr(std::is_empty_v<Type>) {
4929 force(*reg,
entt, discard);
4930 reg->template assign<Type>(args...,
entt);
4933 archive(
entt, instance);
4934 force(*reg,
entt, discard);
4935 reg->template assign<Type>(args...,
entt, std::as_const(instance));
4957 template<
typename Archive>
4959 static constexpr
auto discard =
false;
4960 assure(archive, discard);
4974 template<
typename Archive>
4976 static constexpr
auto discard =
true;
4977 assure(archive, discard);
4994 template<
typename... Component,
typename Archive>
4996 (assign<Component>(archive), ...);
5020 force_fn_type *force;
5040 template<
typename Entity>
5041 class basic_continuous_loader {
5042 using traits_type = entt_traits<std::underlying_type_t<Entity>>;
5044 void destroy(Entity
entt) {
5045 const auto it = remloc.find(
entt);
5047 if(it == remloc.cend()) {
5048 const auto local = reg->
create();
5049 remloc.emplace(
entt, std::make_pair(local,
true));
5054 void restore(Entity
entt) {
5055 const auto it = remloc.find(
entt);
5057 if(it == remloc.cend()) {
5058 const auto local = reg->
create();
5059 remloc.emplace(
entt, std::make_pair(local,
true));
5063 remloc[
entt].second =
true;
5067 template<
typename Container>
5068 auto update(
int, Container &container)
5069 -> decltype(
typename Container::mapped_type{}, void()) {
5073 for(
auto &&pair: container) {
5074 using first_type = std::remove_const_t<
typename std::decay_t<decltype(pair)>::first_type>;
5075 using second_type =
typename std::decay_t<decltype(pair)>::second_type;
5077 if constexpr(std::is_same_v<first_type, Entity> && std::is_same_v<second_type, Entity>) {
5078 other.emplace(
map(pair.first),
map(pair.second));
5079 }
else if constexpr(std::is_same_v<first_type, Entity>) {
5080 other.emplace(
map(pair.first), std::move(pair.second));
5082 static_assert(std::is_same_v<second_type, Entity>);
5083 other.emplace(std::move(pair.first),
map(pair.second));
5087 std::swap(container, other);
5090 template<
typename Container>
5091 auto update(
char, Container &container)
5092 -> decltype(
typename Container::value_type{}, void()) {
5094 static_assert(std::is_same_v<typename Container::value_type, Entity>);
5096 for(
auto &&
entt: container) {
5101 template<
typename Other,
typename Type,
typename Member>
5102 void update(Other &instance, Member Type:: *member) {
5103 if constexpr(!std::is_same_v<Other, Type>) {
5105 }
else if constexpr(std::is_same_v<Member, Entity>) {
5106 instance.*member =
map(instance.*member);
5109 update(0, instance.*member);
5113 template<
typename Archive>
5115 typename traits_type::entity_type length{};
5121 (this->*member)(
entt);
5125 template<
typename Component>
5127 for(
auto &&ref: remloc) {
5128 const auto local = ref.second.first;
5130 if(reg->
valid(local)) {
5131 reg->template reset<Component>(local);
5136 template<
typename Other,
typename Archive,
typename... Type,
typename... Member>
5137 void assign(Archive &archive, [[maybe_unused]] Member Type:: *... member) {
5138 typename traits_type::entity_type length{};
5144 if constexpr(std::is_empty_v<Other>) {
5147 reg->template assign_or_replace<Other>(
map(
entt));
5150 archive(
entt, instance);
5151 (update(instance, member), ...);
5153 reg->template assign_or_replace<Other>(
map(
entt), std::as_const(instance));
5186 template<
typename Archive>
5188 assure(archive, &basic_continuous_loader::restore);
5202 template<
typename Archive>
5204 assure(archive, &basic_continuous_loader::destroy);
5227 template<
typename... Component,
typename Archive,
typename... Type,
typename... Member>
5229 (reset<Component>(), ...);
5230 (assign<Component>(archive, member...), ...);
5243 auto it = remloc.begin();
5245 while(it != remloc.cend()) {
5246 const auto local = it->second.first;
5247 bool &dirty = it->second.second;
5253 if(reg->
valid(local)) {
5257 it = remloc.erase(it);
5288 return (remloc.find(
entt) != remloc.cend());
5297 const auto it = remloc.find(
entt);
5300 if(it != remloc.cend()) {
5301 other = it->second.first;
5308 std::unordered_map<entity_type, std::pair<entity_type, bool>> remloc;
5316 #endif // ENTT_ENTITY_SNAPSHOT_HPP
5319 #ifndef ENTT_ENTITY_STORAGE_HPP
5320 #define ENTT_ENTITY_STORAGE_HPP
5323 #include <algorithm>
5329 #include <type_traits>
5372 template<
typename Entity,
typename Type,
typename = std::
void_t<>>
5377 template<
bool Const>
5381 using instance_type = std::conditional_t<Const, const std::vector<Type>, std::vector<Type>>;
5382 using index_type =
typename traits_type::difference_type;
5384 iterator(instance_type *ref,
const index_type idx)
ENTT_NOEXCEPT
5385 : instances{ref},
index{idx}
5389 using difference_type = index_type;
5390 using value_type = Type;
5391 using pointer = std::conditional_t<Const, const value_type *, value_type *>;
5392 using reference = std::conditional_t<Const, const value_type &, value_type &>;
5393 using iterator_category = std::random_access_iterator_tag;
5398 return --
index, *
this;
5402 iterator orig = *
this;
5403 return ++(*this), orig;
5407 return ++
index, *
this;
5411 iterator orig = *
this;
5412 return --(*this), orig;
5415 iterator & operator+=(
const difference_type value)
ENTT_NOEXCEPT {
5421 return iterator{instances,
index-value};
5424 iterator & operator-=(
const difference_type value)
ENTT_NOEXCEPT {
5425 return (*
this += -value);
5429 return (*
this + -value);
5433 return other.index -
index;
5436 reference operator[](
const difference_type value)
const ENTT_NOEXCEPT {
5438 return (*instances)[pos];
5441 bool operator==(
const iterator &other)
const ENTT_NOEXCEPT {
5442 return other.index ==
index;
5446 return !(*
this == other);
5450 return index > other.index;
5454 return index < other.index;
5457 bool operator<=(
const iterator &other)
const ENTT_NOEXCEPT {
5458 return !(*
this > other);
5461 bool operator>=(
const iterator &other)
const ENTT_NOEXCEPT {
5462 return !(*
this < other);
5467 return &(*instances)[pos];
5471 return *operator->();
5475 instance_type *instances;
5501 instances.reserve(cap);
5507 instances.shrink_to_fit();
5526 return instances.data();
5531 return const_cast<object_type *
>(std::as_const(*this).raw());
5643 template<
typename... Args>
5645 if constexpr(std::is_aggregate_v<object_type>) {
5646 instances.emplace_back(Type{std::forward<Args>(args)...});
5648 instances.emplace_back(std::forward<Args>(args)...);
5653 return instances.back();
5677 template<
typename It,
typename... Args>
5679 if constexpr(
sizeof...(Args) == 0) {
5680 instances.resize(instances.size() +
std::distance(first, last));
5682 instances.resize(instances.size() +
std::distance(first, last), Type{std::forward<Args>(args)...});
5702 auto other = std::move(instances.back());
5704 instances.pop_back();
5770 template<
typename Compare,
typename Sort =
std_sort,
typename... Args>
5778 const auto apply = [
this](
const auto lhs,
const auto rhs) {
5782 if constexpr(std::is_invocable_v<Compare, const object_type &, const object_type &>) {
5783 underlying_type::arrange(from, to, std::move(apply), [
this, compare = std::move(compare)](
const auto lhs,
const auto rhs) {
5785 }, std::move(algo), std::forward<Args>(args)...);
5787 underlying_type::arrange(from, to, std::move(apply), std::move(compare), std::move(algo), std::forward<Args>(args)...);
5798 std::vector<object_type> instances;
5803 template<
typename Entity,
typename Type>
5811 using index_type =
typename traits_type::difference_type;
5818 using difference_type = index_type;
5819 using value_type = Type;
5820 using pointer =
const value_type *;
5821 using reference = value_type;
5822 using iterator_category = std::input_iterator_tag;
5827 return --
index, *
this;
5831 iterator orig = *
this;
5832 return ++(*this), orig;
5836 return ++
index, *
this;
5840 iterator orig = *
this;
5841 return --(*this), orig;
5844 iterator & operator+=(
const difference_type value)
ENTT_NOEXCEPT {
5850 return iterator{
index-value};
5853 iterator & operator-=(
const difference_type value)
ENTT_NOEXCEPT {
5854 return (*
this += -value);
5858 return (*
this + -value);
5862 return other.index -
index;
5865 reference operator[](
const difference_type)
const ENTT_NOEXCEPT {
5869 bool operator==(
const iterator &other)
const ENTT_NOEXCEPT {
5870 return other.index ==
index;
5874 return !(*
this == other);
5878 return index > other.index;
5882 return index < other.index;
5885 bool operator<=(
const iterator &other)
const ENTT_NOEXCEPT {
5886 return !(*
this > other);
5889 bool operator>=(
const iterator &other)
const ENTT_NOEXCEPT {
5890 return !(*
this < other);
5998 template<
typename It>
6005 template<
typename Compare,
typename Sort = std_sort,
typename... Args>
6018 template<
typename Entity,
typename Type>
6025 #endif // ENTT_ENTITY_STORAGE_HPP
6028 #ifndef ENTT_ENTITY_UTILITY_HPP
6029 #define ENTT_ENTITY_UTILITY_HPP
6043 template<
typename... Type>
6051 template<
typename... Type>
6059 template<
typename... Type>
6067 template<
typename... Type>
6074 #endif // ENTT_ENTITY_UTILITY_HPP
6079 #ifndef ENTT_ENTITY_GROUP_HPP
6080 #define ENTT_ENTITY_GROUP_HPP
6085 #include <type_traits>
6109 template<
typename...>
6152 template<
typename Entity,
typename... Exclude,
typename... Get>
6157 template<
typename Component>
6166 template<
typename Func,
typename... Weak>
6168 for(
const auto entt: *handler) {
6169 if constexpr(std::is_invocable_v<Func, decltype(get<Weak>({}))...>) {
6190 template<
typename Component>
6192 return std::get<pool_type<Component> *>(pools)->size();
6200 return handler->size();
6209 return handler->capacity();
6214 handler->shrink_to_fit();
6224 template<
typename... Component>
6226 if constexpr(
sizeof...(Component) == 0) {
6227 return handler->empty();
6229 return (
std::get<pool_type<Component> *>(pools)->empty() && ...);
6247 template<
typename Component>
6249 return std::get<pool_type<Component> *>(pools)->raw();
6266 template<
typename Component>
6268 return std::get<pool_type<Component> *>(pools)->data();
6284 return handler->data();
6302 return handler->begin();
6321 return handler->end();
6331 const auto it = handler->find(
entt);
6332 return it != end() && *it ==
entt ? it : end();
6341 return begin()[pos];
6350 return find(
entt) != end();
6370 template<
typename... Component>
6374 if constexpr(
sizeof...(Component) == 1) {
6377 return std::tuple<decltype(get<Component>({}))...>{get<Component>(
entt)...};
6404 template<
typename Func>
6429 template<
typename Func>
6432 traverse(std::move(func), get_type_list{});
6476 template<
typename... Component,
typename Compare,
typename Sort =
std_sort,
typename... Args>
6477 void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
6478 if constexpr(
sizeof...(Component) == 0) {
6479 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>);
6480 handler->sort(handler->begin(), handler->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
6481 }
else if constexpr(
sizeof...(Component) == 1) {
6482 handler->sort(handler->begin(), handler->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
6483 return compare((std::get<pool_type<Component> *>(pools)->get(lhs), ...), (std::get<pool_type<Component> *>(pools)->get(rhs), ...));
6484 }, std::move(algo), std::forward<Args>(args)...);
6486 handler->sort(handler->begin(), handler->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
6487 return compare(std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(lhs)...}, std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(rhs)...});
6488 }, std::move(algo), std::forward<Args>(args)...);
6508 template<
typename Component>
6510 handler->respect(*
std::get<pool_type<Component> *>(pools));
6515 const std::tuple<pool_type<Get> *...> pools;
6566 template<
typename Entity,
typename... Exclude,
typename... Get,
typename... Owned>
6571 template<
typename Component>
6574 template<
typename Component>
6575 using component_iterator_type = decltype(std::declval<pool_type<Component>>().begin());
6578 basic_group(
const std::size_t *ref,
const std::size_t *extent,
storage<Entity, std::remove_const_t<Owned>> *... opool,
storage<Entity, std::remove_const_t<Get>> *... gpool)
ENTT_NOEXCEPT
6579 : pools{opool..., gpool...},
6584 template<
typename Func,
typename... Strong,
typename... Weak>
6586 [[maybe_unused]]
auto it = std::make_tuple((
std::get<pool_type<Strong> *>(pools)->end() - *length)...);
6587 [[maybe_unused]]
auto data = std::get<0>(pools)->sparse_set<entity_type>::end() - *length;
6589 for(
auto next = *length; next; --next) {
6590 if constexpr(std::is_invocable_v<Func, decltype(get<Strong>({}))..., decltype(get<Weak>({}))...>) {
6591 if constexpr(
sizeof...(Weak) == 0) {
6592 func(*(
std::get<component_iterator_type<Strong>>(it)++)...);
6594 const auto entt = *(data++);
6595 func(*(
std::get<component_iterator_type<Strong>>(it)++)...,
std::get<pool_type<Weak> *>(pools)->
get(
entt)...);
6598 const auto entt = *(data++);
6617 template<
typename Component>
6619 return std::get<pool_type<Component> *>(pools)->size();
6637 template<
typename... Component>
6639 if constexpr(
sizeof...(Component) == 0) {
6642 return (
std::get<pool_type<Component> *>(pools)->empty() && ...);
6663 template<
typename Component>
6665 return std::get<pool_type<Component> *>(pools)->raw();
6685 template<
typename Component>
6687 return std::get<pool_type<Component> *>(pools)->data();
6703 return std::get<0>(pools)->data();
6721 return std::get<0>(pools)->sparse_set<entity_type>::end() - *length;
6740 return std::get<0>(pools)->sparse_set<entity_type>::end();
6750 const auto it = std::get<0>(pools)->find(
entt);
6751 return it != end() && it >= begin() && *it ==
entt ? it : end();
6760 return begin()[pos];
6769 return find(
entt) != end();
6789 template<
typename... Component>
6793 if constexpr(
sizeof...(Component) == 1) {
6796 return std::tuple<decltype(get<Component>({}))...>{get<Component>(
entt)...};
6823 template<
typename Func>
6848 template<
typename Func>
6852 traverse(std::move(func), owned_type_list{}, get_type_list{});
6860 constexpr
auto size =
sizeof...(Owned) +
sizeof...(Get) +
sizeof...(Exclude);
6861 return *super == size;
6906 template<
typename... Component,
typename Compare,
typename Sort =
std_sort,
typename... Args>
6907 void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
6909 auto *cpool = std::get<0>(pools);
6911 if constexpr(
sizeof...(Component) == 0) {
6912 static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>);
6913 cpool->sort(cpool->end()-*length, cpool->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
6914 }
else if constexpr(
sizeof...(Component) == 1) {
6915 cpool->sort(cpool->end()-*length, cpool->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
6916 return compare((std::get<pool_type<Component> *>(pools)->get(lhs), ...), (std::get<pool_type<Component> *>(pools)->get(rhs), ...));
6917 }, std::move(algo), std::forward<Args>(args)...);
6919 cpool->sort(cpool->end()-*length, cpool->end(), [
this, compare = std::move(compare)](
const entity_type lhs,
const entity_type rhs) {
6920 return compare(std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(lhs)...}, std::tuple<decltype(get<Component>({}))...>{std::get<pool_type<Component> *>(pools)->
get(rhs)...});
6921 }, std::move(algo), std::forward<Args>(args)...);
6924 [
this](
auto *head,
auto *... other) {
6925 for(
auto next = *length; next; --next) {
6926 const auto pos = next - 1;
6927 [[maybe_unused]]
const auto entt = head->data()[pos];
6928 (other->swap(other->data()[pos],
entt), ...);
6930 }(std::get<pool_type<Owned> *>(pools)...);
6934 const std::tuple<pool_type<Owned> *..., pool_type<Get> *...> pools;
6935 const size_type *length;
6943 #endif // ENTT_ENTITY_GROUP_HPP
6946 #ifndef ENTT_ENTITY_VIEW_HPP
6947 #define ENTT_ENTITY_VIEW_HPP
6954 #include <algorithm>
6955 #include <type_traits>
6981 template<
typename...>
7022 template<
typename Entity,
typename... Exclude,
typename... Component>
7027 template<
typename Comp>
7030 template<
typename Comp>
7031 using component_iterator_type = decltype(std::declval<pool_type<Comp>>().begin());
7034 using unchecked_type = std::array<const sparse_set<Entity> *, (
sizeof...(Component) - 1)>;
7035 using filter_type = std::array<const sparse_set<Entity> *,
sizeof...(Exclude)>;
7040 iterator(underlying_iterator_type first, underlying_iterator_type last, unchecked_type other, filter_type ignore)
ENTT_NOEXCEPT
7046 if(begin != end && !valid()) {
7052 return std::all_of(unchecked.cbegin(), unchecked.cend(), [
this](
const sparse_set<Entity> *
view) { return view->has(*begin); })
7053 && std::none_of(filter.cbegin(), filter.cend(), [
this](
const sparse_set<Entity> *
view) { return view->has(*begin); });
7057 using difference_type =
typename underlying_iterator_type::difference_type;
7058 using value_type =
typename underlying_iterator_type::value_type;
7059 using pointer =
typename underlying_iterator_type::pointer;
7060 using reference =
typename underlying_iterator_type::reference;
7061 using iterator_category = std::forward_iterator_tag;
7066 return (++begin != end && !valid()) ? ++(*this) : *
this;
7070 iterator orig = *
this;
7071 return ++(*this), orig;
7074 bool operator==(
const iterator &other)
const ENTT_NOEXCEPT {
7075 return other.begin == begin;
7079 return !(*
this == other);
7083 return begin.operator->();
7087 return *operator->();
7091 underlying_iterator_type begin;
7092 underlying_iterator_type end;
7093 unchecked_type unchecked;
7099 : pools{component...},
7103 const sparse_set<Entity> * candidate() const
ENTT_NOEXCEPT {
7104 return std::min({
static_cast<const sparse_set<Entity> *
>(std::get<pool_type<Component> *>(pools))... }, [](
const auto *lhs,
const auto *rhs) {
7105 return lhs->size() < rhs->size();
7111 unchecked_type other{};
7112 ((std::get<pool_type<Component> *>(pools) ==
view ?
nullptr : (other[pos++] =
std::get<pool_type<Component> *>(pools))), ...);
7116 template<
typename Comp,
typename Other>
7117 decltype(
auto)
get([[maybe_unused]] component_iterator_type<Comp> it, [[maybe_unused]] pool_type<Other> *cpool, [[maybe_unused]] const Entity
entt) const
ENTT_NOEXCEPT {
7118 if constexpr(std::is_same_v<Comp, Other>) {
7121 return cpool->get(
entt);
7125 template<
typename Comp,
typename Func,
typename... Other,
typename... Type>
7126 void traverse(Func func, type_list<Other...>, type_list<Type...>)
const {
7130 if constexpr(std::disjunction_v<std::is_same<Comp, Type>...>) {
7131 std::for_each(begin, end, [
this, raw =
std::get<pool_type<Comp> *>(pools)->begin(), &func](
const auto entity)
mutable {
7134 if((
std::get<pool_type<Other> *>(pools)->has(entity) && ...) && (!
std::get<pool_type<Exclude> *>(filter)->has(entity) && ...)) {
7135 if constexpr(std::is_invocable_v<Func, decltype(get<Type>({}))...>) {
7136 func(get<Comp, Type>(curr,
std::get<pool_type<Type> *>(pools), entity)...);
7138 func(entity, get<Comp, Type>(curr,
std::get<pool_type<Type> *>(pools), entity)...);
7143 std::for_each(begin, end, [
this, &func](
const auto entity) {
7144 if((
std::get<pool_type<Other> *>(pools)->has(entity) && ...) && (!
std::get<pool_type<Exclude> *>(filter)->has(entity) && ...)) {
7145 if constexpr(std::is_invocable_v<Func, decltype(get<Type>({}))...>) {
7146 func(
std::get<pool_type<Type> *>(pools)->
get(entity)...);
7148 func(entity,
std::get<pool_type<Type> *>(pools)->
get(entity)...);
7171 template<
typename Comp>
7173 return std::get<pool_type<Comp> *>(pools)->size();
7181 return std::min({ std::get<pool_type<Component> *>(pools)->size()... });
7196 template<
typename... Comp>
7198 if constexpr(
sizeof...(Comp) == 0) {
7199 return (
std::get<pool_type<Component> *>(pools)->empty() || ...);
7201 return (
std::get<pool_type<Comp> *>(pools)->empty() && ...);
7219 template<
typename Comp>
7221 return std::get<pool_type<Comp> *>(pools)->raw();
7238 template<
typename Comp>
7240 return std::get<pool_type<Comp> *>(pools)->data();
7258 const auto *
view = candidate();
7259 const filter_type ignore{std::get<pool_type<Exclude> *>(filter)...};
7279 const auto *
view = candidate();
7280 const filter_type ignore{std::get<pool_type<Exclude> *>(filter)...};
7291 const auto *
view = candidate();
7292 const filter_type ignore{std::get<pool_type<Exclude> *>(filter)...};
7294 return (it != end() && *it ==
entt) ? it : end();
7303 return find(
entt) != end();
7323 template<
typename... Comp>
7327 if constexpr(
sizeof...(Comp) == 0) {
7328 static_assert(
sizeof...(Component) == 1);
7330 }
else if constexpr(
sizeof...(Comp) == 1) {
7333 return std::tuple<decltype(get<Comp>({}))...>{get<Comp>(
entt)...};
7360 template<
typename Func>
7362 const auto *
view = candidate();
7363 ((std::get<pool_type<Component> *>(pools) ==
view ? each<Component>(std::move(func)) :
void()), ...);
7396 template<
typename Comp,
typename Func>
7399 traverse<Comp>(std::move(func), other_type{},
type_list<Component...>{});
7422 template<
typename Func>
7424 const auto *
view = candidate();
7425 ((std::get<pool_type<Component> *>(pools) ==
view ? less<Component>(std::move(func)) :
void()), ...);
7455 template<
typename Comp,
typename Func>
7459 traverse<Comp>(std::move(func), other_type{}, non_empty_type{});
7463 const std::tuple<pool_type<Component> *...> pools;
7464 const std::tuple<pool_type<Exclude> *...> filter;
7501 template<
typename Entity,
typename Component>
7527 return pool->size();
7535 return pool->empty();
7567 return pool->data();
7585 return pool->sparse_set<Entity>::begin();
7604 return pool->sparse_set<Entity>::end();
7614 const auto it = pool->find(
entt);
7615 return it != end() && *it ==
entt ? it : end();
7624 return begin()[pos];
7633 return find(
entt) != end();
7651 template<
typename Comp = Component>
7653 static_assert(std::is_same_v<Comp, Component>);
7655 return pool->get(
entt);
7681 template<
typename Func>
7683 if constexpr(std::is_invocable_v<Func, decltype(
get({}))>) {
7684 std::for_each(pool->begin(), pool->end(), std::move(func));
7686 std::for_each(pool->sparse_set<Entity>::begin(), pool->sparse_set<Entity>::end(), [&func, raw = pool->begin()](
const auto entt)
mutable {
7687 func(entt, *(raw++));
7720 template<
typename Func>
7723 if constexpr(std::is_invocable_v<Func>) {
7724 for(
auto pos = pool->size(); pos; --pos) {
7728 std::for_each(pool->sparse_set<Entity>::begin(), pool->sparse_set<Entity>::end(), std::move(func));
7731 each(std::move(func));
7743 #endif // ENTT_ENTITY_VIEW_HPP
7762 template<
typename Entity>
7763 class basic_registry {
7764 using context_family = family<struct internal_registry_context_family>;
7765 using component_family = family<struct internal_registry_component_family>;
7766 using traits_type = entt_traits<std::underlying_type_t<Entity>>;
7768 template<
typename Component>
7769 struct pool_handler: storage<Entity, Component> {
7770 std::size_t super{};
7772 template<
typename... Args>
7773 pool_handler(Args &&... args)
7774 : storage<Entity, Component>{std::forward<Args>(args)...},
7779 return sink{construction};
7783 return sink{update};
7787 return sink{destruction};
7790 template<
typename... Args>
7794 construction.publish(
entt, owner, Component{});
7795 return Component{std::forward<Args>(args)...};
7798 construction.publish(
entt, owner, component);
7803 template<
typename It,
typename... Args>
7807 if(!construction.empty()) {
7808 std::for_each(first, last, [
this, &owner, it](
const auto entt)
mutable {
7809 construction.publish(
entt, owner, *(it++));
7817 destruction.publish(
entt, owner);
7821 template<
typename... Args>
7825 update.publish(
entt, owner, Component{});
7826 return Component{std::forward<Args>(args)...};
7828 Component component{std::forward<Args>(args)...};
7829 update.publish(
entt, owner, component);
7835 using reference_type = std::conditional_t<
ENTT_ENABLE_ETO(Component),
const Component &, Component &>;
7836 sigh<void(
const Entity,
basic_registry &, reference_type)> construction{};
7837 sigh<void(
const Entity,
basic_registry &, reference_type)> update{};
7841 template<
typename Component>
7842 using pool_type = pool_handler<std::decay_t<Component>>;
7844 template<
typename...>
7845 struct group_handler;
7847 template<
typename... Exclude,
typename... Get>
7848 struct group_handler<exclude_t<Exclude...>, get_t<Get...>> {
7849 const std::tuple<pool_type<Get> *..., pool_type<Exclude> *...> cpools{};
7850 sparse_set<Entity>
set{};
7852 template<
typename Component>
7853 void maybe_valid_if(
const Entity
entt) {
7854 if constexpr(std::disjunction_v<std::is_same<Get, Component>...>) {
7855 if(((std::is_same_v<Component, Get> ||
std::get<pool_type<Get> *>(cpools)->
has(
entt)) && ...)
7861 }
else if constexpr(std::disjunction_v<std::is_same<Exclude, Component>...>) {
7863 && ((std::is_same_v<Exclude, Component> || !
std::get<pool_type<Exclude> *>(cpools)->
has(
entt)) && ...)
7871 void discard_if(
const Entity
entt) {
7878 template<
typename... Exclude,
typename... Get,
typename... Owned>
7879 struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
7880 const std::tuple<pool_type<Owned> *..., pool_type<Get> *..., pool_type<Exclude> *...> cpools{};
7881 std::size_t owned{};
7883 template<
typename Component>
7884 void maybe_valid_if(
const Entity
entt) {
7885 if constexpr(std::disjunction_v<std::is_same<Owned, Component>..., std::is_same<Get, Component>...>) {
7886 if(((std::is_same_v<Component, Owned> ||
std::get<pool_type<Owned> *>(cpools)->
has(
entt)) && ...)
7887 && ((std::is_same_v<Component, Get> ||
std::get<pool_type<Get> *>(cpools)->
has(
entt)) && ...)
7889 && !(std::get<0>(cpools)->index(
entt) < owned))
7891 const auto pos = owned++;
7892 (std::get<pool_type<Owned> *>(cpools)->swap(
std::get<pool_type<Owned> *>(cpools)->data()[pos],
entt), ...);
7894 }
else if constexpr(std::disjunction_v<std::is_same<Exclude, Component>...>) {
7897 && ((std::is_same_v<Exclude, Component> || !
std::get<pool_type<Exclude> *>(cpools)->
has(
entt)) && ...)
7898 && !(std::get<0>(cpools)->index(
entt) < owned))
7900 const auto pos = owned++;
7901 (std::get<pool_type<Owned> *>(cpools)->swap(
std::get<pool_type<Owned> *>(cpools)->data()[pos],
entt), ...);
7906 void discard_if(
const Entity
entt) {
7907 if(std::get<0>(cpools)->
has(
entt) && std::get<0>(cpools)->index(
entt) < owned) {
7908 const auto pos = --owned;
7909 (std::get<pool_type<Owned> *>(cpools)->swap(
std::get<pool_type<Owned> *>(cpools)->data()[pos],
entt), ...);
7915 std::unique_ptr<sparse_set<Entity>> pool;
7917 std::unique_ptr<sparse_set<Entity>>(* clone)(
const sparse_set<Entity> &);
7923 std::size_t extent[3];
7924 std::unique_ptr<void, void(*)(
void *)>
group;
7930 struct ctx_variable {
7931 std::unique_ptr<void, void(*)(
void *)> value;
7935 template<
typename Type,
typename Family>
7937 if constexpr(is_named_type_v<Type>) {
7938 return named_type_traits_v<Type>;
7940 return Family::template type<std::decay_t<Type>>;
7947 if(destroyed ==
null) {
7952 const auto curr = to_integer(destroyed);
7953 const auto version = to_integer(entities[curr]) & (traits_type::version_mask << traits_type::entity_shift);
7954 destroyed =
entity_type{to_integer(entities[curr]) & traits_type::entity_mask};
7956 entities[curr] =
entt;
7962 void release(
const Entity
entity) {
7964 const auto entt = to_integer(
entity) & traits_type::entity_mask;
7965 const auto version = ((to_integer(
entity) >> traits_type::entity_shift) + 1) << traits_type::entity_shift;
7966 const auto node = to_integer(destroyed) |
version;
7967 entities[
entt] = Entity{node};
7968 destroyed = Entity{
entt};
7971 template<
typename Component>
7972 const pool_type<Component> * assure()
const {
7973 const auto ctype = to_integer(type<Component>());
7974 pool_data *pdata =
nullptr;
7976 if constexpr(is_named_type_v<Component>) {
7977 const auto it = std::find_if(pools.begin()+skip_family_pools, pools.end(), [ctype](
const auto &candidate) {
7978 return candidate.runtime_type == ctype;
7981 pdata = (it == pools.cend() ? &pools.emplace_back() : &(*it));
7983 if(!(ctype < skip_family_pools)) {
7984 pools.reserve(pools.size()+ctype-skip_family_pools+1);
7986 while(!(ctype < skip_family_pools)) {
7987 pools.emplace(pools.begin()+(skip_family_pools++), pool_data{});
7991 pdata = &pools[ctype];
7995 pdata->runtime_type = ctype;
7996 pdata->pool = std::make_unique<pool_type<Component>>();
7998 pdata->remove = [](sparse_set<Entity> &cpool,
basic_registry &owner,
const Entity
entt) {
7999 static_cast<pool_type<Component> &
>(cpool).
remove(owner,
entt);
8002 if constexpr(std::is_copy_constructible_v<std::decay_t<Component>>) {
8003 pdata->clone = [](
const sparse_set<Entity> &cpool) -> std::unique_ptr<sparse_set<Entity>> {
8004 return std::make_unique<pool_type<Component>>(
static_cast<const pool_type<Component> &
>(cpool));
8007 pdata->stomp = [](
const sparse_set<Entity> &cpool,
const Entity from,
basic_registry &other,
const Entity to) {
8008 other.assign_or_replace<Component>(to,
static_cast<const pool_type<Component> &
>(cpool).
get(from));
8011 pdata->clone =
nullptr;
8012 pdata->stomp =
nullptr;
8016 return static_cast<pool_type<Component> *
>(pdata->pool.get());
8019 template<
typename Component>
8020 pool_type<Component> * assure() {
8021 return const_cast<pool_type<Component> *
>(std::as_const(*this).template assure<Component>());
8050 template<typename Component>
8052 return component{runtime_type<Component, component_family>()};
8059 template<
typename... Component>
8061 (assure<Component>(), ...);
8069 template<
typename Component>
8071 return assure<Component>()->size();
8079 return entities.size();
8087 auto sz = entities.size();
8088 auto curr = destroyed;
8090 for(; curr !=
null; --sz) {
8091 curr = entities[to_integer(curr) & traits_type::entity_mask];
8110 template<
typename... Component>
8112 if constexpr(
sizeof...(Component) == 0) {
8113 entities.reserve(cap);
8115 (assure<Component>()->reserve(cap), ...);
8124 template<
typename Component>
8126 return assure<Component>()->capacity();
8135 return entities.capacity();
8143 template<
typename... Component>
8145 (assure<Component>()->shrink_to_fit(), ...);
8159 template<
typename... Component>
8161 if constexpr(
sizeof...(Component) == 0) {
8164 return (assure<Component>()->
empty() && ...);
8185 template<
typename Component>
8187 return assure<Component>()->raw();
8191 template<
typename Component>
8193 return const_cast<Component *
>(std::as_const(*this).template raw<Component>());
8209 template<
typename Component>
8211 return assure<Component>()->data();
8220 const auto pos =
size_type(to_integer(
entity) & traits_type::entity_mask);
8221 return (pos < entities.size() && entities[pos] ==
entity);
8256 const auto pos =
size_type(to_integer(
entity) & traits_type::entity_mask);
8258 return version_type(to_integer(entities[pos]) >> traits_type::entity_shift);
8283 template<
typename... Component>
8285 if constexpr(
sizeof...(Component) == 0) {
8289 return std::tuple<entity_type, decltype(assign<Component>({}))...>{
entt, assign<Component>(
entt)...};
8309 template<
typename... Component,
typename It>
8311 std::generate(first, last, [
this]() {
return generate(); });
8313 if constexpr(
sizeof...(Component) > 0) {
8315 return std::make_tuple(assure<Component>()->batch(*
this, std::make_reverse_iterator(last), std::make_reverse_iterator(first))...);
8338 template<
typename... Component,
typename... Exclude>
8367 template<
typename... Component,
typename It,
typename... Exclude>
8371 if constexpr(
sizeof...(Component) == 0) {
8372 stomp<Component...>(first, last, src, other,
exclude<Exclude...>);
8374 static_assert(
sizeof...(Exclude) == 0);
8375 (assure<Component>()->batch(*
this, std::make_reverse_iterator(last), std::make_reverse_iterator(first), other.get<Component>(src)), ...);
8404 for(
auto pos = pools.size(); pos; --pos) {
8405 if(
auto &pdata = pools[pos-1]; pdata.pool && pdata.pool->has(
entity)) {
8406 pdata.remove(*pdata.pool, *
this,
entity);
8424 template<
typename It>
8450 template<
typename Component,
typename... Args>
8453 return assure<Component>()->assign(*
this,
entity, std::forward<Args>(args)...);
8469 template<
typename Component>
8472 assure<Component>()->remove(*
this,
entity);
8487 template<
typename... Component>
8490 return (assure<Component>()->
has(
entity) && ...);
8507 template<
typename... Component>
8511 if constexpr(
sizeof...(Component) == 1) {
8512 return (assure<Component>()->
get(
entity), ...);
8514 return std::tuple<decltype(get<Component>({}))...>{get<Component>(
entity)...};
8519 template<
typename... Component>
8523 if constexpr(
sizeof...(Component) == 1) {
8524 return (assure<Component>()->
get(
entity), ...);
8526 return std::tuple<decltype(get<Component>({}))...>{get<Component>(
entity)...};
8554 template<
typename Component,
typename... Args>
8557 auto *cpool = assure<Component>();
8558 return cpool->has(
entity) ? cpool->get(
entity) : cpool->assign(*
this,
entity, std::forward<Args>(args)...);
8573 template<
typename... Component>
8577 if constexpr(
sizeof...(Component) == 1) {
8580 return std::tuple<decltype(try_get<Component>({}))...>{try_get<Component>(
entity)...};
8585 template<
typename... Component>
8587 if constexpr(
sizeof...(Component) == 1) {
8590 return std::tuple<decltype(try_get<Component>({}))...>{try_get<Component>(
entity)...};
8614 template<
typename Component,
typename... Args>
8617 return assure<Component>()->replace(*
this,
entity, std::forward<Args>(args)...);
8642 template<
typename Component,
typename... Args>
8645 auto *cpool = assure<Component>();
8646 return cpool->has(
entity) ? cpool->replace(*
this,
entity, std::forward<Args>(args)...) : cpool->assign(*
this,
entity, std::forward<Args>(args)...);
8676 template<
typename Component>
8678 return assure<Component>()->on_construct();
8707 template<
typename Component>
8709 return assure<Component>()->on_replace();
8739 template<
typename Component>
8741 return assure<Component>()->on_destroy();
8791 template<
typename Component,
typename Compare,
typename Sort =
std_sort,
typename... Args>
8792 void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
8793 auto *cpool = assure<Component>();
8795 cpool->sort(cpool->begin(), cpool->end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
8833 template<
typename To,
typename From>
8835 auto *cpool = assure<To>();
8837 cpool->respect(*assure<From>());
8854 template<
typename Component>
8858 if(
auto *cpool = assure<Component>(); cpool->has(
entity)) {
8859 cpool->remove(*
this,
entity);
8871 template<
typename Component>
8873 if(
auto *cpool = assure<Component>(); cpool->on_destroy().
empty()) {
8878 cpool->remove(*
this,
entity);
8915 template<
typename Func>
8917 static_assert(std::is_invocable_v<Func, entity_type>);
8919 if(destroyed ==
null) {
8920 for(
auto pos = entities.size(); pos; --pos) {
8921 func(entities[pos-1]);
8924 for(
auto pos = entities.size(); pos; --pos) {
8926 const auto entity = entities[to_integer(curr)];
8945 for(std::size_t pos{}, last = pools.size(); pos < last &&
orphan; ++pos) {
8946 const auto &pdata = pools[pos];
8969 template<
typename Func>
8971 static_assert(std::is_invocable_v<Func, entity_type>);
9012 template<
typename... Component,
typename... Exclude>
9014 static_assert(
sizeof...(Component) > 0);
9015 return { assure<Component>()..., assure<Exclude>()... };
9019 template<
typename... Component,
typename... Exclude>
9021 static_assert(std::conjunction_v<std::is_const<Component>...>);
9031 template<
typename... Component>
9033 return !(assure<Component>()->super || ...);
9063 template<
typename... Owned,
typename... Get,
typename... Exclude>
9065 static_assert(
sizeof...(Owned) +
sizeof...(Get) > 0);
9066 static_assert(
sizeof...(Owned) +
sizeof...(Get) +
sizeof...(Exclude) > 1);
9068 using handler_type = group_handler<
exclude_t<Exclude...>,
get_t<Get...>, Owned...>;
9070 [[maybe_unused]] constexpr
auto size =
sizeof...(Owned) +
sizeof...(Get) +
sizeof...(Exclude);
9071 const auto cpools = std::make_tuple(assure<Owned>()..., assure<Get>()..., assure<Exclude>()...);
9072 const std::size_t extent[3]{
sizeof...(Owned),
sizeof...(Get),
sizeof...(Exclude)};
9073 handler_type *handler =
nullptr;
9075 if(
auto it = std::find_if(groups.cbegin(), groups.cend(), [&extent](
const auto &gdata) {
9076 return std::equal(std::begin(extent), std::end(extent), std::begin(gdata.extent))
9077 && (gdata.owned(type<Owned>()) && ...)
9078 && (gdata.get(type<Get>()) && ...)
9079 && (gdata.exclude(type<Exclude>()) && ...);
9080 }); it != groups.cend())
9082 handler =
static_cast<handler_type *
>(it->group.get());
9086 const void *maybe_valid_if =
nullptr;
9087 const void *discard_if =
nullptr;
9090 {
sizeof...(Owned),
sizeof...(Get),
sizeof...(Exclude) },
9091 decltype(
group_data::group){
new handler_type{cpools}, [](
void *gptr) {
delete static_cast<handler_type *
>(gptr); }},
9092 [](
const component ctype)
ENTT_NOEXCEPT {
return ((ctype == type<Owned>()) || ...); },
9093 [](
const component ctype)
ENTT_NOEXCEPT {
return ((ctype == type<Get>()) || ...); },
9094 [](
const component ctype)
ENTT_NOEXCEPT {
return ((ctype == type<Exclude>()) || ...); }
9097 if constexpr(
sizeof...(Owned) == 0) {
9098 handler =
static_cast<handler_type *
>(groups.emplace_back(std::move(gdata)).group.get());
9100 ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [&extent](
const auto &curr) {
9101 const std::size_t diff[3]{ (0u + ... + curr.owned(type<Owned>())), (0u + ... + curr.get(type<Get>())), (0u + ... + curr.exclude(type<Exclude>())) };
9102 return !diff[0] || ((std::equal(std::begin(diff), std::end(diff), extent) || std::equal(std::begin(diff), std::end(diff), curr.extent)));
9105 const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [&
size](
const auto &curr) {
9106 const std::size_t diff = (0u + ... + curr.owned(type<Owned>()));
9107 return !diff || (size > (curr.extent[0] + curr.extent[1] + curr.extent[2]));
9110 const auto prev = std::find_if(std::make_reverse_iterator(next), groups.crend(), [](
const auto &curr) {
9111 return (0u + ... + curr.owned(type<Owned>()));
9114 maybe_valid_if = (next == groups.cend() ? maybe_valid_if : next->group.get());
9115 discard_if = (prev == groups.crend() ? discard_if : prev->group.get());
9116 handler =
static_cast<handler_type *
>(groups.insert(next, std::move(gdata))->
group.
get());
9119 ((std::get<pool_type<Owned> *>(cpools)->super = std::max(
std::get<pool_type<Owned> *>(cpools)->super,
size)), ...);
9121 (std::get<pool_type<Owned> *>(cpools)->
on_construct().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<Owned>>(*handler), ...);
9122 (std::get<pool_type<Get> *>(cpools)->
on_construct().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<Get>>(*handler), ...);
9123 (std::get<pool_type<Exclude> *>(cpools)->
on_destroy().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<Exclude>>(*handler), ...);
9125 (std::get<pool_type<Owned> *>(cpools)->
on_destroy().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
9126 (std::get<pool_type<Get> *>(cpools)->
on_destroy().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
9127 (std::get<pool_type<Exclude> *>(cpools)->
on_construct().before(discard_if).template connect<&handler_type::discard_if>(*handler), ...);
9129 const auto *cpool = std::min({
9130 static_cast<sparse_set<Entity> *
>(std::get<pool_type<Owned> *>(cpools))...,
9131 static_cast<sparse_set<Entity> *
>(std::get<pool_type<Get> *>(cpools))...
9132 }, [](
const auto *lhs,
const auto *rhs) {
9133 return lhs->size() < rhs->size();
9137 std::for_each(cpool->data(), cpool->data() + cpool->size(), [cpools, handler](
const auto entity) {
9138 if((std::get<pool_type<Owned> *>(cpools)->has(entity) && ...)
9139 && (std::get<pool_type<Get> *>(cpools)->has(entity) && ...)
9140 && !(std::get<pool_type<Exclude> *>(cpools)->has(entity) || ...))
9142 if constexpr(sizeof...(Owned) == 0) {
9143 handler->set.construct(entity);
9145 if(!(std::get<0>(cpools)->index(entity) < handler->owned)) {
9146 const auto pos = handler->owned++;
9147 (std::get<pool_type<Owned> *>(cpools)->swap(std::get<pool_type<Owned> *>(cpools)->data()[pos], entity), ...);
9154 if constexpr(
sizeof...(Owned) == 0) {
9155 return { &handler->set, std::get<pool_type<Get> *>(cpools)... };
9157 return { &std::get<0>(cpools)->super, &handler->owned, std::get<pool_type<Owned> *>(cpools)... ,
std::get<pool_type<Get> *>(cpools)... };
9171 template<
typename... Owned,
typename... Get,
typename... Exclude>
9173 static_assert(std::conjunction_v<std::is_const<Owned>..., std::is_const<Get>...>);
9186 template<
typename... Owned,
typename... Exclude>
9188 return group<Owned...>(entt::get<>,
exclude<Exclude...>);
9200 template<
typename... Owned,
typename... Exclude>
9202 static_assert(std::conjunction_v<std::is_const<Owned>...>);
9226 template<
typename It>
9228 std::vector<const sparse_set<Entity> *> selected(
std::distance(first, last));
9230 std::transform(first, last, selected.begin(), [
this](
const component ctype) {
9231 auto it = std::find_if(pools.begin(), pools.end(), [ctype = to_integer(ctype)](const auto &pdata) {
9232 return pdata.pool && pdata.runtime_type == ctype;
9235 return it != pools.cend() && it->pool ? it->pool.get() :
nullptr;
9238 return { std::move(selected) };
9274 template<
typename... Component,
typename... Exclude>
9276 static_assert(std::conjunction_v<std::is_copy_constructible<Component>...>);
9279 other.pools.resize(pools.size());
9281 for(
auto pos = pools.size(); pos; --pos) {
9282 const auto &pdata = pools[pos-1];
9283 ENTT_ASSERT(!
sizeof...(Component) || !pdata.pool || pdata.clone);
9285 if(pdata.pool && pdata.clone
9286 && (!
sizeof...(Component) || ... || (pdata.runtime_type == to_integer(type<Component>())))
9287 && ((pdata.runtime_type != to_integer(type<Exclude>())) && ...))
9289 auto &curr = other.pools[pos-1];
9290 curr.remove = pdata.remove;
9291 curr.clone = pdata.clone;
9292 curr.stomp = pdata.stomp;
9293 curr.pool = pdata.clone ? pdata.clone(*pdata.pool) :
nullptr;
9294 curr.runtime_type = pdata.runtime_type;
9298 other.skip_family_pools = skip_family_pools;
9299 other.destroyed = destroyed;
9300 other.entities = entities;
9302 other.pools.erase(std::remove_if(other.pools.begin()+skip_family_pools, other.pools.end(), [](
const auto &pdata) {
9304 }), other.pools.end());
9339 template<
typename... Component,
typename... Exclude>
9341 const entity_type
entt[1]{dst};
9342 stomp<Component...>(std::begin(
entt), std::end(
entt), src, other,
exclude<Exclude...>);
9358 template<
typename... Component,
typename It,
typename... Exclude>
9360 static_assert(
sizeof...(Component) == 0 ||
sizeof...(Exclude) == 0);
9362 for(
auto pos = other.pools.size(); pos; --pos) {
9363 const auto &pdata = other.pools[pos-1];
9364 ENTT_ASSERT(!
sizeof...(Component) || !pdata.pool || pdata.stomp);
9366 if(pdata.pool && pdata.stomp
9367 && (!
sizeof...(Component) || ... || (pdata.runtime_type == to_integer(type<Component>())))
9368 && ((pdata.runtime_type != to_integer(type<Exclude>())) && ...)
9369 && pdata.pool->has(src))
9371 std::for_each(first, last, [
this, &pdata, src](
const auto entity) {
9372 pdata.stomp(*pdata.pool, src, *
this, entity);
9391 const auto head = to_integer(destroyed);
9392 const entity_type seed = (destroyed ==
null) ? destroyed :
entity_type{head | (to_integer(entities[head]) & (traits_type::version_mask << traits_type::entity_shift))};
9395 const auto &others = reg.entities;
9396 const auto entt = to_integer(entity) & traits_type::entity_mask;
9397 const auto curr = to_integer(others[
entt]) & traits_type::entity_mask;
9398 return entity_type{curr | (to_integer(others[curr]) & (traits_type::version_mask << traits_type::entity_shift))};
9401 return {
this, seed, follow };
9423 const auto entt = to_integer(entity) & traits_type::entity_mask;
9424 auto &others = reg.entities;
9426 if(!(
entt < others.size())) {
9427 auto curr = others.size();
9428 others.resize(
entt + 1);
9430 std::generate(others.data() + curr, others.data() +
entt, [curr]()
mutable {
9431 return entity_type(curr++);
9435 others[
entt] = entity;
9438 reg.destroy(entity);
9439 const auto version = to_integer(entity) & (traits_type::version_mask << traits_type::entity_shift);
9448 return {
this, force };
9462 template<
typename Type,
typename... Args>
9464 const auto ctype = runtime_type<Type, context_family>();
9465 auto it = std::find_if(vars.begin(), vars.end(), [ctype](
const auto &candidate) {
9466 return candidate.runtime_type == ctype;
9469 if(it == vars.cend()) {
9471 decltype(ctx_variable::value){
new Type{std::forward<Args>(args)...}, [](
void *ptr) {
delete static_cast<Type *
>(ptr); }},
9475 it = std::prev(vars.end());
9477 it->value.reset(
new Type{std::forward<Args>(args)...});
9480 return *
static_cast<Type *
>(it->value.get());
9487 template<
typename Type>
9489 vars.erase(std::remove_if(vars.begin(), vars.end(), [](
auto &var) {
9490 return var.runtime_type == runtime_type<Type, context_family>();
9505 template<
typename Type,
typename... Args>
9507 auto *value = try_ctx<Type>();
9508 return value ? *value : set<Type>(std::forward<Args>(args)...);
9517 template<
typename Type>
9519 const auto it = std::find_if(vars.begin(), vars.end(), [](
const auto &var) {
9520 return var.runtime_type == runtime_type<Type, context_family>();
9523 return (it == vars.cend()) ? nullptr :
static_cast<const Type *
>(it->value.get());
9527 template<
typename Type>
9529 return const_cast<Type *
>(std::as_const(*this).template try_ctx<Type>());
9544 template<
typename Type>
9546 const auto *instance = try_ctx<Type>();
9552 template<
typename Type>
9554 return const_cast<Type &
>(std::as_const(*this).template ctx<Type>());
9558 mutable std::size_t skip_family_pools{};
9559 mutable std::vector<pool_data> pools{};
9560 std::vector<group_data> groups{};
9561 std::vector<ctx_variable> vars{};
9562 std::vector<entity_type> entities{};
9563 entity_type destroyed{
null};
9570 #endif // ENTT_ENTITY_REGISTRY_HPP
9591 template<
typename Entity>
9592 struct basic_actor {
9638 :
entt{other.entt}, reg{other.reg}
9654 if(
this != &other) {
9655 auto tmp{std::move(other)};
9656 std::swap(reg, tmp.reg);
9657 std::swap(
entt, tmp.entt);
9677 template<
typename Component,
typename... Args>
9679 return reg->template assign_or_replace<Component>(
entt, std::forward<Args>(args)...);
9686 template<
typename Component>
9688 reg->template remove<Component>(
entt);
9696 template<
typename... Component>
9698 return (reg->template has<Component>(
entt) && ...);
9706 template<
typename... Component>
9708 return std::as_const(*reg).template get<Component...>(
entt);
9712 template<
typename... Component>
9714 return reg->template
get<Component...>(
entt);
9722 template<
typename... Component>
9724 return std::as_const(*reg).template try_get<Component...>(
entt);
9728 template<
typename... Component>
9743 return const_cast<registry_type &
>(std::as_const(*this).backend());
9771 #endif // ENTT_ENTITY_ACTOR_HPP
9778 #ifndef ENTT_ENTITY_HELPER_HPP
9779 #define ENTT_ENTITY_HELPER_HPP
9782 #include <type_traits>
9799 template<
bool Const,
typename Entity>
9816 template<
typename Exclude,
typename... Component>
9818 return reg.template
view<Component...>(Exclude{});
9834 template<
typename Entity>
9839 template<
typename Entity>
9848 template<
bool Const,
typename Entity>
9866 template<
typename Exclude,
typename Get,
typename... Owned>
9868 return reg.template
group<Owned...>(Get{}, Exclude{});
9884 template<
typename Entity>
9889 template<
typename Entity>
9912 template<ENTT_ID_TYPE Value>
9913 using tag = std::integral_constant<ENTT_ID_TYPE, Value>;
9919 #endif // ENTT_ENTITY_HELPER_HPP
9922 #ifndef ENTT_ENTITY_OBSERVER_HPP
9923 #define ENTT_ENTITY_OBSERVER_HPP
9930 #include <algorithm>
9931 #include <type_traits>
9950 template<
typename...>
9960 template<
typename...>
9980 template<
typename... AllOf,
typename... NoneOf>
9990 template<
typename AnyOf>
10004 template<
typename... Reject,
typename... Require,
typename... Rule,
typename... Other>
10015 template<
typename... AllOf,
typename... NoneOf>
10025 template<
typename AnyOf>
10036 template<
typename... AllOf,
typename... NoneOf>
10097 template<
typename Entity>
10098 class basic_observer {
10099 using payload_type = std::uint32_t;
10102 struct matcher_handler;
10104 template<
typename... Reject,
typename... Require,
typename AnyOf>
10105 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
10106 template<std::
size_t Index>
10107 static void maybe_valid_if(
basic_observer &obs,
const Entity
entt,
const basic_registry<Entity> ®) {
10108 if(reg.template has<Require...>(
entt) && !(reg.template has<Reject>(
entt) || ...)) {
10109 auto *comp = obs.view.try_get(
entt);
10110 (comp ? *comp : obs.view.construct(
entt)) |= (1 << Index);
10114 template<std::
size_t Index>
10116 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
10117 obs.view.destroy(
entt);
10121 template<std::
size_t Index>
10122 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
10123 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
10124 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
10125 reg.template on_replace<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
10126 reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
10130 (reg.template on_destroy<Require>().disconnect(obs), ...);
10131 (reg.template on_construct<Reject>().disconnect(obs), ...);
10132 reg.template on_replace<AnyOf>().disconnect(obs);
10133 reg.template on_destroy<AnyOf>().disconnect(obs);
10137 template<
typename... Reject,
typename... Require,
typename... NoneOf,
typename... AllOf>
10138 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
10139 template<std::
size_t Index>
10140 static void maybe_valid_if(
basic_observer &obs,
const Entity
entt,
const basic_registry<Entity> ®) {
10141 if(reg.template has<AllOf..., Require...>(
entt) && !(reg.template has<NoneOf>(
entt) || ...) && !(reg.template has<Reject>(
entt) || ...)) {
10142 auto *comp = obs.view.try_get(
entt);
10143 (comp ? *comp : obs.view.construct(
entt)) |= (1 << Index);
10147 template<std::
size_t Index>
10149 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
10150 obs.view.destroy(
entt);
10154 template<std::
size_t Index>
10155 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
10156 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
10157 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
10158 (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
10159 (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
10160 (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
10161 (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
10165 (reg.template on_destroy<Require>().disconnect(obs), ...);
10166 (reg.template on_construct<Reject>().disconnect(obs), ...);
10167 (reg.template on_construct<AllOf>().disconnect(obs), ...);
10168 (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
10169 (reg.template on_destroy<AllOf>().disconnect(obs), ...);
10170 (reg.template on_construct<NoneOf>().disconnect(obs), ...);
10174 template<
typename... Matcher>
10176 (matcher_handler<Matcher>::disconnect(obs, reg), ...);
10179 template<
typename... Matcher, std::size_t... Index>
10180 void connect(basic_registry<Entity> ®, std::index_sequence<Index...>) {
10181 static_assert(
sizeof...(Matcher) < std::numeric_limits<payload_type>::digits);
10182 (matcher_handler<Matcher>::template connect<Index>(*
this, reg), ...);
10196 : target{}, release{}, view{}
10209 template<
typename... Matcher>
10215 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
10238 template<
typename... Matcher>
10241 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
10249 release(*
this, *target);
10259 return view.size();
10267 return view.empty();
10283 return view.data();
10295 return view.sparse_set<entity_type>::begin();
10309 return view.sparse_set<entity_type>::end();
10331 template<
typename Func>
10333 static_assert(std::is_invocable_v<Func, entity_type>);
10334 std::for_each(
begin(),
end(), std::move(func));
10351 template<
typename Func>
10353 std::as_const(*this).each(std::move(func));
10367 #endif // ENTT_ENTITY_OBSERVER_HPP
10384 #ifndef ENTT_LOCATOR_LOCATOR_HPP
10385 #define ENTT_LOCATOR_LOCATOR_HPP
10391 #ifndef ENTT_CONFIG_CONFIG_H
10392 #define ENTT_CONFIG_CONFIG_H
10395 #ifndef ENTT_NOEXCEPT
10396 #define ENTT_NOEXCEPT noexcept
10397 #endif // ENTT_NOEXCEPT
10400 #ifndef ENTT_HS_SUFFIX
10401 #define ENTT_HS_SUFFIX _hs
10402 #endif // ENTT_HS_SUFFIX
10405 #ifndef ENTT_HWS_SUFFIX
10406 #define ENTT_HWS_SUFFIX _hws
10407 #endif // ENTT_HWS_SUFFIX
10410 #ifndef ENTT_NO_ATOMIC
10412 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
10413 #else // ENTT_NO_ATOMIC
10414 #define ENTT_MAYBE_ATOMIC(Type) Type
10415 #endif // ENTT_NO_ATOMIC
10418 #ifndef ENTT_DISABLE_ETO
10419 #include <type_traits>
10420 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
10421 #else // ENTT_DISABLE_ETO
10423 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
10424 #endif // ENTT_DISABLE_ETO
10427 #ifndef ENTT_ID_TYPE
10429 #define ENTT_ID_TYPE std::uint32_t
10430 #endif // ENTT_ID_TYPE
10433 #ifndef ENTT_PAGE_SIZE
10434 #define ENTT_PAGE_SIZE 32768
10435 #endif // ENTT_PAGE_SIZE
10438 #ifndef ENTT_DISABLE_ASSERT
10440 #define ENTT_ASSERT(condition) assert(condition)
10441 #else // ENTT_DISABLE_ASSERT
10442 #define ENTT_ASSERT(...) ((void)0)
10443 #endif // ENTT_DISABLE_ASSERT
10446 #endif // ENTT_CONFIG_CONFIG_H
10464 template<
typename Service>
10479 return !
static_cast<bool>(service);
10520 template<
typename Impl = Service,
typename... Args>
10521 static void set(Args &&... args) {
10522 service = std::make_shared<Impl>(std::forward<Args>(args)...);
10529 static void set(std::shared_ptr<Service> ptr) {
10531 service = std::move(ptr);
10544 inline static std::shared_ptr<Service> service =
nullptr;
10551 #endif // ENTT_LOCATOR_LOCATOR_HPP
10554 #ifndef ENTT_META_FACTORY_HPP
10555 #define ENTT_META_FACTORY_HPP
10562 #include <functional>
10563 #include <type_traits>
10565 #ifndef ENTT_CONFIG_CONFIG_H
10566 #define ENTT_CONFIG_CONFIG_H
10569 #ifndef ENTT_NOEXCEPT
10570 #define ENTT_NOEXCEPT noexcept
10571 #endif // ENTT_NOEXCEPT
10574 #ifndef ENTT_HS_SUFFIX
10575 #define ENTT_HS_SUFFIX _hs
10576 #endif // ENTT_HS_SUFFIX
10579 #ifndef ENTT_HWS_SUFFIX
10580 #define ENTT_HWS_SUFFIX _hws
10581 #endif // ENTT_HWS_SUFFIX
10584 #ifndef ENTT_NO_ATOMIC
10586 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
10587 #else // ENTT_NO_ATOMIC
10588 #define ENTT_MAYBE_ATOMIC(Type) Type
10589 #endif // ENTT_NO_ATOMIC
10592 #ifndef ENTT_DISABLE_ETO
10593 #include <type_traits>
10594 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
10595 #else // ENTT_DISABLE_ETO
10597 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
10598 #endif // ENTT_DISABLE_ETO
10601 #ifndef ENTT_ID_TYPE
10603 #define ENTT_ID_TYPE std::uint32_t
10604 #endif // ENTT_ID_TYPE
10607 #ifndef ENTT_PAGE_SIZE
10608 #define ENTT_PAGE_SIZE 32768
10609 #endif // ENTT_PAGE_SIZE
10612 #ifndef ENTT_DISABLE_ASSERT
10614 #define ENTT_ASSERT(condition) assert(condition)
10615 #else // ENTT_DISABLE_ASSERT
10616 #define ENTT_ASSERT(...) ((void)0)
10617 #endif // ENTT_DISABLE_ASSERT
10620 #endif // ENTT_CONFIG_CONFIG_H
10623 #ifndef ENTT_CORE_TYPE_TRAITS_HPP
10624 #define ENTT_CORE_TYPE_TRAITS_HPP
10628 #include <type_traits>
10630 #ifndef ENTT_CONFIG_CONFIG_H
10631 #define ENTT_CONFIG_CONFIG_H
10634 #ifndef ENTT_NOEXCEPT
10635 #define ENTT_NOEXCEPT noexcept
10636 #endif // ENTT_NOEXCEPT
10639 #ifndef ENTT_HS_SUFFIX
10640 #define ENTT_HS_SUFFIX _hs
10641 #endif // ENTT_HS_SUFFIX
10644 #ifndef ENTT_HWS_SUFFIX
10645 #define ENTT_HWS_SUFFIX _hws
10646 #endif // ENTT_HWS_SUFFIX
10649 #ifndef ENTT_NO_ATOMIC
10651 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
10652 #else // ENTT_NO_ATOMIC
10653 #define ENTT_MAYBE_ATOMIC(Type) Type
10654 #endif // ENTT_NO_ATOMIC
10657 #ifndef ENTT_DISABLE_ETO
10658 #include <type_traits>
10659 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
10660 #else // ENTT_DISABLE_ETO
10662 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
10663 #endif // ENTT_DISABLE_ETO
10666 #ifndef ENTT_ID_TYPE
10668 #define ENTT_ID_TYPE std::uint32_t
10669 #endif // ENTT_ID_TYPE
10672 #ifndef ENTT_PAGE_SIZE
10673 #define ENTT_PAGE_SIZE 32768
10674 #endif // ENTT_PAGE_SIZE
10677 #ifndef ENTT_DISABLE_ASSERT
10679 #define ENTT_ASSERT(condition) assert(condition)
10680 #else // ENTT_DISABLE_ASSERT
10681 #define ENTT_ASSERT(...) ((void)0)
10682 #endif // ENTT_DISABLE_ASSERT
10685 #endif // ENTT_CONFIG_CONFIG_H
10688 #ifndef ENTT_CORE_HASHED_STRING_HPP
10689 #define ENTT_CORE_HASHED_STRING_HPP
10694 #ifndef ENTT_CONFIG_CONFIG_H
10695 #define ENTT_CONFIG_CONFIG_H
10698 #ifndef ENTT_NOEXCEPT
10699 #define ENTT_NOEXCEPT noexcept
10700 #endif // ENTT_NOEXCEPT
10703 #ifndef ENTT_HS_SUFFIX
10704 #define ENTT_HS_SUFFIX _hs
10705 #endif // ENTT_HS_SUFFIX
10708 #ifndef ENTT_HWS_SUFFIX
10709 #define ENTT_HWS_SUFFIX _hws
10710 #endif // ENTT_HWS_SUFFIX
10713 #ifndef ENTT_NO_ATOMIC
10715 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
10716 #else // ENTT_NO_ATOMIC
10717 #define ENTT_MAYBE_ATOMIC(Type) Type
10718 #endif // ENTT_NO_ATOMIC
10721 #ifndef ENTT_DISABLE_ETO
10722 #include <type_traits>
10723 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
10724 #else // ENTT_DISABLE_ETO
10726 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
10727 #endif // ENTT_DISABLE_ETO
10730 #ifndef ENTT_ID_TYPE
10732 #define ENTT_ID_TYPE std::uint32_t
10733 #endif // ENTT_ID_TYPE
10736 #ifndef ENTT_PAGE_SIZE
10737 #define ENTT_PAGE_SIZE 32768
10738 #endif // ENTT_PAGE_SIZE
10741 #ifndef ENTT_DISABLE_ASSERT
10743 #define ENTT_ASSERT(condition) assert(condition)
10744 #else // ENTT_DISABLE_ASSERT
10745 #define ENTT_ASSERT(...) ((void)0)
10746 #endif // ENTT_DISABLE_ASSERT
10749 #endif // ENTT_CONFIG_CONFIG_H
10762 namespace internal {
10766 struct fnv1a_traits;
10770 struct fnv1a_traits<
std::uint32_t> {
10771 static constexpr std::uint32_t offset = 2166136261;
10772 static constexpr std::uint32_t prime = 16777619;
10777 struct fnv1a_traits<
std::uint64_t> {
10778 static constexpr std::uint64_t offset = 14695981039346656037ull;
10779 static constexpr std::uint64_t prime = 1099511628211ull;
10803 template<
typename Char>
10805 using traits_type = internal::fnv1a_traits<ENTT_ID_TYPE>;
10807 struct const_wrapper {
10809 constexpr const_wrapper(
const Char *curr)
ENTT_NOEXCEPT: str{curr} {}
10815 return curr[0] == 0 ? partial : helper((partial^curr[0])*traits_type::prime, curr+1);
10839 template<std::
size_t N>
10841 return helper(traits_type::offset, str);
10850 return helper(traits_type::offset, wrapper.str);
10861 while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
10867 : str{
nullptr}, hash{}
10884 template<std::
size_t N>
10886 : str{curr}, hash{helper(traits_type::offset, curr)}
10895 : str{wrapper.str}, hash{helper(traits_type::offset, wrapper.str)}
10929 return hash == other.hash;
10948 template<
typename Char, std::
size_t N>
10950 -> basic_hashed_string<Char>;
10960 template<
typename Char>
10961 constexpr
bool operator!=(
const basic_hashed_string<Char> &lhs,
const basic_hashed_string<Char> &rhs)
ENTT_NOEXCEPT {
10962 return !(lhs == rhs);
10997 #endif // ENTT_CORE_HASHED_STRING_HPP
11008 template<std::
size_t N>
11019 struct choice_t<0> {};
11026 template<std::
size_t N>
11027 constexpr choice_t<N>
choice{};
11031 template<
typename...>
11032 struct type_list {};
11037 struct type_list_size;
11044 template<
typename... Type>
11045 struct type_list_size<type_list<Type...>>
11046 : std::integral_constant<std::size_t, sizeof...(Type)>
11054 template<
class List>
11059 template<
typename...>
11060 struct type_list_cat;
11065 struct type_list_cat<> {
11067 using type = type_list<>;
11077 template<
typename... Type,
typename... Other,
typename... List>
11078 struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
11080 using type =
typename type_list_cat<type_list<Type..., Other...>, List...>::type;
11088 template<
typename... Type>
11089 struct type_list_cat<type_list<Type...>> {
11091 using type = type_list<Type...>;
11099 template<
typename... List>
11105 struct type_list_unique;
11113 template<
typename Type,
typename... Other>
11114 struct type_list_unique<type_list<Type, Other...>> {
11116 using type = std::conditional_t<
11117 std::disjunction_v<std::is_same<Type, Other>...>,
11118 typename type_list_unique<type_list<Other...>>::type,
11119 type_list_cat_t<type_list<Type>,
typename type_list_unique<type_list<Other...>>::type>
11126 struct type_list_unique<type_list<>> {
11128 using type = type_list<>;
11136 template<
typename Type>
11145 template<
typename Type,
typename = std::
void_t<>>
11146 struct is_equality_comparable: std::false_type {};
11150 template<
typename Type>
11151 struct is_equality_comparable<Type,
std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>: std::true_type {};
11158 template<
class Type>
11164 struct named_type_traits;
11171 template<
typename Type>
11172 struct named_type_traits<const Type>
11173 : named_type_traits<Type>
11181 template<
typename Type>
11189 template<
class Type>
11198 template<
typename Type,
typename = std::
void_t<>>
11199 struct is_named_type: std::false_type {};
11203 template<
typename Type>
11204 struct is_named_type<Type,
std::void_t<named_type_traits_t<std::decay_t<Type>>>>: std::true_type {};
11211 template<
class Type>
11221 #define ENTT_OPAQUE_TYPE(clazz, type)\
11222 enum class clazz: type {};\
11223 constexpr auto to_integer(const clazz id) ENTT_NOEXCEPT {\
11224 return std::underlying_type_t<clazz>(id);\
11226 static_assert(true)
11239 #define ENTT_EXPAND(args) args
11259 #define ENTT_NAMED_TYPE(type)\
11261 struct entt::named_type_traits<type>\
11262 : std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#type)>>>>{#type}>\
11264 static_assert(std::is_same_v<std::remove_cv_t<type>, type>);\
11265 static_assert(std::is_object_v<type>);\
11274 #define ENTT_NAMED_STRUCT_ONLY(clazz, body)\
11275 struct clazz body;\
11276 ENTT_NAMED_TYPE(clazz)
11285 #define ENTT_NAMED_STRUCT_WITH_NAMESPACE(ns, clazz, body)\
11286 namespace ns { struct clazz body; }\
11287 ENTT_NAMED_TYPE(ns::clazz)
11291 #define ENTT_NAMED_STRUCT_OVERLOAD(_1, _2, _3, FUNC, ...) FUNC
11293 #define ENTT_NAMED_STRUCT(...) ENTT_EXPAND(ENTT_NAMED_STRUCT_OVERLOAD(__VA_ARGS__, ENTT_NAMED_STRUCT_WITH_NAMESPACE, ENTT_NAMED_STRUCT_ONLY,)(__VA_ARGS__))
11301 #define ENTT_NAMED_CLASS_ONLY(clazz, body)\
11303 ENTT_NAMED_TYPE(clazz)
11312 #define ENTT_NAMED_CLASS_WITH_NAMESPACE(ns, clazz, body)\
11313 namespace ns { class clazz body; }\
11314 ENTT_NAMED_TYPE(ns::clazz)
11318 #define ENTT_NAMED_CLASS_MACRO(_1, _2, _3, FUNC, ...) FUNC
11320 #define ENTT_NAMED_CLASS(...) ENTT_EXPAND(ENTT_NAMED_CLASS_MACRO(__VA_ARGS__, ENTT_NAMED_CLASS_WITH_NAMESPACE, ENTT_NAMED_CLASS_ONLY,)(__VA_ARGS__))
11323 #endif // ENTT_CORE_TYPE_TRAITS_HPP
11326 #ifndef ENTT_META_POLICY_HPP
11327 #define ENTT_META_POLICY_HPP
11352 #endif // ENTT_META_POLICY_HPP
11355 #ifndef ENTT_META_META_HPP
11356 #define ENTT_META_META_HPP
11363 #include <type_traits>
11369 #ifndef ENTT_CORE_UTILITY_HPP
11370 #define ENTT_CORE_UTILITY_HPP
11388 template<
class Type>
11390 return std::forward<Type>(value);
11402 template<
typename Type,
typename Class>
11412 template<
typename Type>
11420 template<
class... Func>
11422 using Func::operator()...;
11430 template<
class... Type>
11438 template<
class Func>
11439 struct y_combinator {
11445 func{std::move(recursive)}
11454 template <
class... Args>
11455 decltype(
auto)
operator()(Args &&... args)
const {
11456 return func(*
this, std::forward<Args>(args)...);
11460 template <
class... Args>
11461 decltype(
auto)
operator()(Args &&... args) {
11462 return func(*
this, std::forward<Args>(args)...);
11473 #endif // ENTT_CORE_UTILITY_HPP
11491 namespace internal {
11494 struct meta_type_node;
11497 struct meta_prop_node {
11498 meta_prop_node * next;
11499 meta_any(*
const key)();
11500 meta_any(*
const value)();
11504 struct meta_base_node {
11505 meta_type_node *
const parent;
11506 meta_base_node * next;
11512 struct meta_conv_node {
11513 meta_type_node *
const parent;
11514 meta_conv_node * next;
11516 meta_any(* const conv)(const
void *);
11520 struct meta_ctor_node {
11521 using size_type = std::size_t;
11522 meta_type_node *
const parent;
11523 meta_ctor_node * next;
11524 meta_prop_node * prop;
11525 const size_type size;
11527 meta_any(*
const invoke)(meta_any *
const);
11531 struct meta_dtor_node {
11532 meta_type_node *
const parent;
11533 bool(*
const invoke)(meta_handle);
11537 struct meta_data_node {
11539 meta_type_node *
const parent;
11540 meta_data_node * next;
11541 meta_prop_node * prop;
11542 const bool is_const;
11543 const bool is_static;
11545 bool(* const set)(meta_handle, meta_any, meta_any);
11546 meta_any(* const
get)(meta_handle, meta_any);
11550 struct meta_func_node {
11551 using size_type = std::size_t;
11553 meta_type_node *
const parent;
11554 meta_func_node * next;
11555 meta_prop_node * prop;
11556 const size_type size;
11557 const bool is_const;
11558 const bool is_static;
11561 meta_any(* const invoke)(meta_handle, meta_any *);
11565 struct meta_type_node {
11566 using size_type = std::size_t;
11568 meta_type_node * next;
11569 meta_prop_node * prop;
11570 const bool is_void;
11571 const bool is_integral;
11572 const bool is_floating_point;
11573 const bool is_array;
11574 const bool is_enum;
11575 const bool is_union;
11576 const bool is_class;
11577 const bool is_pointer;
11578 const bool is_function_pointer;
11579 const bool is_member_object_pointer;
11580 const bool is_member_function_pointer;
11581 const size_type extent;
11582 bool(*
const compare)(
const void *,
const void *);
11585 meta_base_node *base{
nullptr};
11586 meta_conv_node *conv{
nullptr};
11587 meta_ctor_node *ctor{
nullptr};
11588 meta_dtor_node *dtor{
nullptr};
11589 meta_data_node *data{
nullptr};
11590 meta_func_node *func{
nullptr};
11594 template<
typename Type,
typename Op,
typename Node>
11603 template<auto Member,
typename Type,
typename Op>
11604 void iterate(Op op,
const meta_type_node *node)
ENTT_NOEXCEPT {
11606 auto *curr = node->base;
11607 iterate<Type>(op, node->*Member);
11610 iterate<Member, Type>(op, curr->type());
11617 template<
typename Op,
typename Node>
11619 while(curr && !op(curr)) {
11627 template<auto Member,
typename Op>
11628 auto find_if(Op op,
const meta_type_node *node)
ENTT_NOEXCEPT
11629 -> decltype(find_if(op, node->*Member)) {
11630 decltype(find_if(op, node->*Member)) ret =
nullptr;
11633 ret = find_if(op, node->*Member);
11634 auto *curr = node->base;
11636 while(curr && !ret) {
11637 ret = find_if<Member>(op, curr->type());
11646 template<
typename Type>
11647 static bool compare(
const void *lhs,
const void *rhs) {
11648 if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
11649 return *
static_cast<const Type *
>(lhs) == *
static_cast<const Type *
>(rhs);
11656 template<
typename...>
11661 struct meta_node<> {
11662 inline static meta_type_node *local =
nullptr;
11663 inline static meta_type_node **global = &local;
11667 template<
typename Type>
11668 struct meta_node<Type> {
11669 static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>);
11672 auto *
const node =
resolve();
11673 auto **it = meta_node<>::global;
11675 while(*it && *it != node) {
11683 const auto unregister_all = y_combinator{
11684 [](
auto &&
self,
auto **curr,
auto... member) {
11686 auto *prev = *curr;
11687 (
self(&(prev->*member)), ...);
11688 *curr = prev->next;
11689 prev->next =
nullptr;
11694 unregister_all(&node->prop);
11695 unregister_all(&node->base);
11696 unregister_all(&node->conv);
11697 unregister_all(&node->ctor, &internal::meta_ctor_node::prop);
11698 unregister_all(&node->data, &internal::meta_data_node::prop);
11699 unregister_all(&node->func, &internal::meta_func_node::prop);
11701 node->identifier = {};
11702 node->dtor =
nullptr;
11703 node->next =
nullptr;
11707 static meta_type_node node{
11711 std::is_void_v<Type>,
11712 std::is_integral_v<Type>,
11713 std::is_floating_point_v<Type>,
11714 std::is_array_v<Type>,
11715 std::is_enum_v<Type>,
11716 std::is_union_v<Type>,
11717 std::is_class_v<Type>,
11718 std::is_pointer_v<Type>,
11719 std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
11720 std::is_member_object_pointer_v<Type>,
11721 std::is_member_function_pointer_v<Type>,
11722 std::extent_v<Type>,
11725 return meta_node<std::remove_const_t<std::remove_pointer_t<Type>>>
::resolve();
11728 return meta_node<std::remove_const_t<std::remove_extent_t<Type>>>
::resolve();
11732 if constexpr(is_named_type_v<Type>) {
11733 auto *candidate = internal::find_if([](
auto *curr) {
11734 return curr->identifier == named_type_traits_v<Type>;
11735 }, *meta_node<>::global);
11737 return candidate ? candidate : &node;
11745 template<
typename... Type>
11746 struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...> {};
11777 using storage_type = std::aligned_storage_t<
sizeof(
void *),
alignof(
void *)>;
11778 using copy_fn_type =
void *(storage_type &,
const void *);
11779 using destroy_fn_type = void(
void *);
11780 using steal_fn_type =
void *(storage_type &,
void *, destroy_fn_type *);
11782 template<
typename Type>
11783 static Type * release(Type *instance) {
11785 [[maybe_unused]]
const bool destroyed = (!node->dtor || node->dtor->invoke(*instance));
11790 template<
typename Type,
typename = std::
void_t<>>
11791 struct type_traits {
11792 template<
typename... Args>
11793 static void * instance(storage_type &
storage, Args &&... args) {
11794 auto instance = std::make_unique<Type>(std::forward<Args>(args)...);
11795 new (&
storage) Type *{instance.get()};
11796 return instance.release();
11799 static void destroy(
void *instance) {
11800 delete release<Type>(
static_cast<Type *
>(instance));
11803 static void * copy(storage_type &storage,
const void *other) {
11804 auto instance = std::make_unique<Type>(*
static_cast<const Type *
>(other));
11805 new (&storage) Type *{instance.get()};
11806 return instance.release();
11809 static void * steal(storage_type &to,
void *from, destroy_fn_type *) {
11810 auto *
const instance =
static_cast<Type *
>(from);
11811 new (&to) Type *{instance};
11816 template<
typename Type>
11817 struct type_traits<Type,
std::enable_if_t<sizeof(Type) <= sizeof(void *) && std::is_nothrow_move_constructible_v<Type>>> {
11818 template<
typename... Args>
11819 static void * instance(storage_type &storage, Args &&... args) {
11820 return new (&storage) Type{std::forward<Args>(args)...};
11823 static void destroy(
void *instance) {
11824 release<Type>(
static_cast<Type *
>(instance))->~Type();
11827 static void * copy(storage_type &storage,
const void *instance) {
11828 return new (&storage) Type{*
static_cast<const Type *
>(instance)};
11831 static void * steal(storage_type &to,
void *from, destroy_fn_type *destroy_fn) {
11832 void *
const instance =
new (&to) Type{std::move(*
static_cast<Type *
>(from))};
11844 destroy_fn{
nullptr},
11855 template<
typename Type,
typename... Args>
11856 explicit meta_any(std::in_place_type_t<Type>, [[maybe_unused]] Args &&... args)
11861 if constexpr(!std::is_void_v<Type>) {
11862 using traits_type = type_traits<std::remove_cv_t<std::remove_reference_t<Type>>>;
11863 static_assert(std::is_copy_constructible_v<Type>);
11865 instance = traits_type::instance(
storage, std::forward<Args>(args)...);
11866 destroy_fn = &traits_type::destroy;
11867 copy_fn = &traits_type::copy;
11868 steal_fn = &traits_type::steal;
11877 template<
typename Type>
11882 instance = &type.get();
11896 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>>>
11898 :
meta_any{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(type)}
11909 instance = other.copy_fn ? other.copy_fn(
storage, other.instance) : other.instance;
11910 destroy_fn = other.destroy_fn;
11911 copy_fn = other.copy_fn;
11912 steal_fn = other.steal_fn;
11927 swap(*
this, other);
11933 destroy_fn(instance);
11943 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>>>
11945 return (*
this =
meta_any{std::forward<Type>(type)});
11984 return const_cast<void *
>(std::as_const(*this).data());
11992 template<
typename Type>
11995 void *ret =
nullptr;
12000 const auto *base = internal::find_if<&internal::meta_type_node::base>([type](
auto *candidate) {
12001 return candidate->type() == type;
12004 ret = base ? base->cast(instance) :
nullptr;
12007 return static_cast<const Type *
>(ret);
12011 template<
typename Type>
12013 return const_cast<Type *
>(std::as_const(*this).try_cast<Type>());
12030 template<
typename Type>
12032 auto *
const actual = try_cast<Type>();
12038 template<
typename Type>
12040 return const_cast<Type &
>(std::as_const(*this).cast<Type>());
12049 template<
typename Type>
12054 any = *
static_cast<const Type *
>(instance);
12056 const auto *
const conv = internal::find_if<&internal::meta_type_node::conv>([type](
auto *other) {
12057 return other->type() == type;
12061 any = conv->conv(instance);
12073 template<
typename Type>
12078 if(
auto any = std::as_const(*this).convert<Type>(); any) {
12094 template<
typename Type,
typename... Args>
12096 *
this =
meta_any{std::in_place_type_t<Type>{}, std::forward<Args>(args)...};
12114 return node == other.node && (!node || node->compare(instance, other.instance));
12123 if(lhs.steal_fn && rhs.steal_fn) {
12124 storage_type buffer;
12125 auto *
const temp = lhs.steal_fn(buffer, lhs.instance, lhs.destroy_fn);
12126 lhs.instance = rhs.steal_fn(lhs.storage, rhs.instance, rhs.destroy_fn);
12127 rhs.instance = lhs.steal_fn(rhs.storage, temp, lhs.destroy_fn);
12128 }
else if(lhs.steal_fn) {
12129 lhs.instance = lhs.steal_fn(rhs.storage, lhs.instance, lhs.destroy_fn);
12130 std::swap(rhs.instance, lhs.instance);
12131 }
else if(rhs.steal_fn) {
12132 rhs.instance = rhs.steal_fn(lhs.storage, rhs.instance, rhs.destroy_fn);
12133 std::swap(rhs.instance, lhs.instance);
12135 std::swap(lhs.instance, rhs.instance);
12138 std::swap(lhs.node, rhs.node);
12139 std::swap(lhs.destroy_fn, rhs.destroy_fn);
12140 std::swap(lhs.copy_fn, rhs.copy_fn);
12141 std::swap(lhs.steal_fn, rhs.steal_fn);
12147 const internal::meta_type_node *node;
12148 destroy_fn_type *destroy_fn;
12149 copy_fn_type *copy_fn;
12150 steal_fn_type *steal_fn;
12179 instance{any.instance}
12187 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_handle>>>
12203 return const_cast<void *
>(std::as_const(*this).data());
12215 const internal::meta_type_node *node;
12227 return !(lhs == rhs);
12246 return node->key();
12254 return node->value();
12272 return node == other.node;
12276 const internal::meta_prop_node *node;
12287 return !(lhs == rhs);
12313 return node->cast(instance);
12326 return node == other.node;
12330 const internal::meta_base_node *node;
12336 return !(lhs == rhs);
12359 return node->conv(instance);
12372 return node == other.node;
12376 const internal::meta_conv_node *node;
12382 return !(lhs == rhs);
12425 template<
typename... Args>
12427 std::array<
meta_any,
sizeof...(Args)> arguments{{std::forward<Args>(args)...}};
12430 if(
sizeof...(Args) == size()) {
12431 any = node->invoke(arguments.data());
12442 template<
typename Op>
12443 std::enable_if_t<std::is_invocable_v<Op, meta_prop>,
void>
12445 internal::iterate<meta_prop>(std::move(op), node->prop);
12454 return internal::find_if([key = std::move(key)](
auto *candidate) {
12455 return candidate->key() == key;
12469 return node == other.node;
12473 const internal::meta_ctor_node *node;
12479 return !(lhs == rhs);
12504 return node->invoke(
handle);
12517 return node == other.node;
12521 const internal::meta_dtor_node *node;
12527 return !(lhs == rhs);
12540 return node->identifier;
12551 return node->is_const;
12563 return node->is_static;
12583 template<typename Type>
12585 return node->set(
handle,
meta_any{}, std::forward<Type>(value));
12603 template<
typename Type>
12606 return node->set(
handle, index, std::forward<Type>(value));
12634 return node->get(
handle, index);
12642 template<
typename Op>
12643 std::enable_if_t<std::is_invocable_v<Op, meta_prop>,
void>
12645 internal::iterate<meta_prop>(std::move(op), node->prop);
12654 return internal::find_if([key = std::move(key)](
auto *candidate) {
12655 return candidate->key() == key;
12669 return node == other.node;
12673 const internal::meta_data_node *node;
12679 return !(lhs == rhs);
12695 return node->identifier;
12714 return node->is_const;
12726 return node->is_static;
12757 template<typename... Args>
12763 if(
sizeof...(Args) == size()) {
12764 any = node->invoke(
handle, arguments.data());
12775 template<
typename Op>
12776 std::enable_if_t<std::is_invocable_v<Op, meta_prop>,
void>
12778 internal::iterate<meta_prop>(std::move(op), node->prop);
12787 return internal::find_if([key = std::move(key)](
auto *candidate) {
12788 return candidate->key() == key;
12802 return node == other.node;
12806 const internal::meta_func_node *node;
12812 return !(lhs == rhs);
12818 template<
typename... Args, std::size_t... Indexes>
12819 auto ctor(std::index_sequence<Indexes...>)
const ENTT_NOEXCEPT {
12820 return internal::find_if([](
auto *candidate) {
12821 return candidate->size ==
sizeof...(Args) && ([](
auto *from,
auto *to) {
12822 return (from == to) || internal::find_if<&internal::meta_type_node::base>([to](
auto *curr) {
return curr->type() == to; }, from)
12823 || internal::find_if<&internal::meta_type_node::conv>([to](
auto *curr) {
return curr->type() == to; }, from);
12842 return node->identifier;
12850 return node->is_void;
12859 return node->is_integral;
12869 return node->is_floating_point;
12878 return node->is_array;
12886 return node->is_enum;
12894 return node->is_union;
12902 return node->is_class;
12910 return node->is_pointer;
12920 return node->is_function_pointer;
12930 return node->is_member_object_pointer;
12940 return node->is_member_function_pointer;
12950 return node->extent;
12959 return node->remove_pointer();
12968 return node->remove_extent();
12979 template<
typename Op>
12980 std::enable_if_t<std::is_invocable_v<Op, meta_base>,
void>
12982 internal::iterate<&internal::meta_type_node::base, meta_base>(std::move(op), node);
12994 return internal::find_if<&internal::meta_type_node::base>([
identifier](
auto *candidate) {
13008 template<
typename Op>
13010 internal::iterate<&internal::meta_type_node::conv, meta_conv>(std::move(op), node);
13023 template<
typename Type>
13026 return candidate->type() == type;
13035 template<
typename Op>
13037 internal::iterate<meta_ctor>(std::move(op), node->ctor);
13045 template<
typename... Args>
13047 return ctor<Args...>(std::index_sequence_for<Args...>{});
13067 template<
typename Op>
13068 std::enable_if_t<std::is_invocable_v<Op, meta_data>,
void>
13070 internal::iterate<&internal::meta_type_node::data, meta_data>(std::move(op), node);
13084 return internal::find_if<&internal::meta_type_node::data>([
identifier](
auto *candidate) {
13099 template<
typename Op>
13100 std::enable_if_t<std::is_invocable_v<Op, meta_func>,
void>
13102 internal::iterate<&internal::meta_type_node::func, meta_func>(std::move(op), node);
13116 return internal::find_if<&internal::meta_type_node::func>([
identifier](
auto *candidate) {
13132 template<
typename... Args>
13134 std::array<
meta_any,
sizeof...(Args)> arguments{{std::forward<Args>(args)...}};
13137 internal::find_if<&internal::meta_type_node::ctor>([data = arguments.data(), &any](
auto *curr) ->
bool {
13138 if(curr->size == sizeof...(args)) {
13139 any = curr->invoke(data);
13142 return static_cast<bool>(any);
13161 return (
handle.type() == node) && (!node->dtor || node->dtor->invoke(
handle));
13173 template<
typename Op>
13174 std::enable_if_t<std::is_invocable_v<Op, meta_prop>,
void>
13176 internal::iterate<&internal::meta_type_node::prop, meta_prop>(std::move(op), node);
13190 return internal::find_if<&internal::meta_type_node::prop>([key = std::move(key)](
auto *candidate) {
13191 return candidate->key() == key;
13205 return node == other.node;
13209 const internal::meta_type_node *node;
13220 internal::meta_info<>::global = other.ctx;
13224 internal::meta_type_node **ctx{&internal::meta_info<>::local};
13230 return !(lhs == rhs);
13238 instance =
handle.instance;
13253 return node->parent;
13258 return node->type();
13263 return node->parent;
13268 return node->type();
13273 return node->parent;
13278 return index < size() ? node->arg(index) :
nullptr;
13283 return node->parent;
13288 return node->parent;
13293 return node->type();
13298 return node->parent;
13303 return node->ret();
13308 return index < size() ? node->arg(index) :
nullptr;
13315 #endif // ENTT_META_META_HPP
13328 namespace internal {
13332 struct meta_function_helper;
13335 template<
typename Ret,
typename... Args>
13336 struct meta_function_helper<Ret(Args...)> {
13337 using return_type = std::remove_cv_t<std::remove_reference_t<Ret>>;
13338 using args_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
13340 static constexpr std::index_sequence_for<Args...> index_sequence{};
13341 static constexpr
auto is_const =
false;
13343 static auto arg(
typename internal::meta_func_node::size_type index)
ENTT_NOEXCEPT {
13349 template<
typename Ret,
typename... Args>
13350 struct meta_function_helper<Ret(Args...) const>: meta_function_helper<Ret(Args...)> {
13351 static constexpr
auto is_const =
true;
13355 template<
typename Ret,
typename... Args,
typename Class>
13356 constexpr meta_function_helper<Ret(Args...)>
13357 to_meta_function_helper(Ret(Class:: *)(Args...));
13360 template<
typename Ret,
typename... Args,
typename Class>
13361 constexpr meta_function_helper<Ret(Args...) const>
13362 to_meta_function_helper(Ret(Class:: *)(Args...) const);
13365 template<typename Ret, typename... Args>
13366 constexpr meta_function_helper<Ret(Args...)>
13367 to_meta_function_helper(Ret(*)(Args...));
13370 constexpr
void to_meta_function_helper(...);
13373 template<typename Candidate>
13374 using meta_function_helper_t = decltype(to_meta_function_helper(
std::declval<Candidate>()));
13377 template<typename Type, typename... Args,
std::
size_t... Indexes>
13378 meta_any construct(meta_any * const args,
std::index_sequence<Indexes...>) {
13379 [[maybe_unused]]
auto direct = std::make_tuple((args+Indexes)->try_cast<Args>()...);
13382 if(((std::get<Indexes>(direct) || (args+Indexes)->convert<Args>()) && ...)) {
13383 any = Type{(std::get<Indexes>(direct) ? *std::get<Indexes>(direct) : (args+Indexes)->cast<Args>())...};
13390 template<
bool Const,
typename Type, auto Data>
13391 bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index, [[maybe_unused]] meta_any value) {
13392 bool accepted =
false;
13394 if constexpr(!Const) {
13395 if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(
Data)>>> || std::is_member_function_pointer_v<decltype(
Data)>) {
13396 using helper_type = meta_function_helper_t<decltype(
Data)>;
13397 using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(
Data)>,
typename helper_type::args_type>;
13398 static_assert(std::is_invocable_v<decltype(
Data), Type &, data_type>);
13399 auto *
const clazz = meta_any{handle}.try_cast<Type>();
13400 auto *
const direct = value.try_cast<data_type>();
13402 if(clazz && (direct || value.convert<data_type>())) {
13403 std::invoke(
Data, *clazz, direct ? *direct : value.cast<data_type>());
13406 }
else if constexpr(std::is_member_object_pointer_v<decltype(
Data)>) {
13407 using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*
Data)>>;
13408 static_assert(std::is_invocable_v<decltype(
Data), Type *>);
13409 auto *
const clazz = meta_any{handle}.try_cast<Type>();
13411 if constexpr(std::is_array_v<data_type>) {
13412 using underlying_type = std::remove_extent_t<data_type>;
13413 auto *
const direct = value.try_cast<underlying_type>();
13414 auto *
const idx = index.try_cast<std::size_t>();
13416 if(clazz && idx && (direct || value.convert<underlying_type>())) {
13417 std::invoke(
Data, clazz)[*idx] = direct ? *direct : value.cast<underlying_type>();
13421 auto *
const direct = value.try_cast<data_type>();
13423 if(clazz && (direct || value.convert<data_type>())) {
13424 std::invoke(
Data, clazz) = (direct ? *direct : value.cast<data_type>());
13429 static_assert(std::is_pointer_v<decltype(
Data)>);
13430 using data_type = std::remove_cv_t<std::remove_reference_t<decltype(*
Data)>>;
13432 if constexpr(std::is_array_v<data_type>) {
13433 using underlying_type = std::remove_extent_t<data_type>;
13434 auto *
const direct = value.try_cast<underlying_type>();
13435 auto *
const idx = index.try_cast<std::size_t>();
13437 if(idx && (direct || value.convert<underlying_type>())) {
13438 (*Data)[*idx] = (direct ? *direct : value.cast<underlying_type>());
13442 auto *
const direct = value.try_cast<data_type>();
13444 if(direct || value.convert<data_type>()) {
13445 *
Data = (direct ? *direct : value.cast<data_type>());
13456 template<
typename Type, auto Data,
typename Policy>
13457 meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index) {
13458 auto dispatch = [](
auto &&value) {
13459 if constexpr(std::is_same_v<Policy, as_void_t>) {
13460 return meta_any{std::in_place_type<void>};
13461 }
else if constexpr(std::is_same_v<Policy, as_alias_t>) {
13462 return meta_any{std::ref(std::forward<decltype(value)>(value))};
13464 static_assert(std::is_same_v<Policy, as_is_t>);
13465 return meta_any{std::forward<decltype(value)>(value)};
13469 if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(
Data)>>> || std::is_member_function_pointer_v<decltype(
Data)>) {
13470 static_assert(std::is_invocable_v<decltype(
Data), Type &>);
13471 auto *
const clazz = meta_any{handle}.try_cast<Type>();
13472 return clazz ? dispatch(std::invoke(
Data, *clazz)) : meta_any{};
13473 }
else if constexpr(std::is_member_object_pointer_v<decltype(
Data)>) {
13474 using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*
Data)>>;
13475 static_assert(std::is_invocable_v<decltype(
Data), Type *>);
13476 auto *
const clazz = meta_any{handle}.try_cast<Type>();
13478 if constexpr(std::is_array_v<data_type>) {
13479 auto *
const idx = index.try_cast<std::size_t>();
13480 return (clazz && idx) ? dispatch(std::invoke(
Data, clazz)[*idx]) : meta_any{};
13482 return clazz ? dispatch(std::invoke(
Data, clazz)) : meta_any{};
13485 static_assert(std::is_pointer_v<std::decay_t<decltype(
Data)>>);
13487 if constexpr(std::is_array_v<std::remove_pointer_t<decltype(
Data)>>) {
13488 auto *
const idx = index.try_cast<std::size_t>();
13489 return idx ? dispatch((*
Data)[*idx]) : meta_any{};
13491 return dispatch(*
Data);
13497 template<
typename Type,
auto Candidate,
typename Policy, std::size_t... Indexes>
13498 meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_sequence<Indexes...>) {
13499 using helper_type = meta_function_helper_t<decltype(Candidate)>;
13501 auto dispatch = [](
auto *... params) {
13502 if constexpr(std::is_void_v<typename helper_type::return_type> || std::is_same_v<Policy, as_void_t>) {
13503 std::invoke(Candidate, *params...);
13504 return meta_any{std::in_place_type<void>};
13505 }
else if constexpr(std::is_same_v<Policy, as_alias_t>) {
13506 return meta_any{std::ref(std::invoke(Candidate, *params...))};
13508 static_assert(std::is_same_v<Policy, as_is_t>);
13509 return meta_any{std::invoke(Candidate, *params...)};
13513 [[maybe_unused]]
const auto direct = std::make_tuple([](meta_any *any,
auto *instance) {
13514 using arg_type = std::remove_reference_t<decltype(*instance)>;
13516 if(!instance && any->convert<arg_type>()) {
13517 instance = any->try_cast<arg_type>();
13521 }(args+Indexes, (args+Indexes)->try_cast<std::tuple_element_t<Indexes, typename helper_type::args_type>>())...);
13523 if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Candidate)>>>) {
13524 return (std::get<Indexes>(direct) && ...) ? dispatch(std::get<Indexes>(direct)...) : meta_any{};
13526 auto *
const clazz = meta_any{handle}.try_cast<Type>();
13527 return (clazz && (std::get<Indexes>(direct) && ...)) ? dispatch(clazz, std::get<Indexes>(direct)...) : meta_any{};
13541 template<
typename,
typename...>
13555 template<
typename Type>
13557 template<
typename Node>
13558 bool duplicate(
const Node *candidate,
const Node *node)
ENTT_NOEXCEPT {
13559 return node && (node == candidate || duplicate(candidate, node->next));
13562 template<
typename Node>
13571 ENTT_ASSERT(!duplicate(node, *internal::meta_info<>::global));
13573 node->next = *internal::meta_info<>::global;
13574 *internal::meta_info<>::global = node;
13589 static_assert(!is_named_type_v<Type>);
13601 static_assert(is_named_type_v<Type>);
13613 template<
typename Base>
13615 static_assert(std::is_base_of_v<Base, Type>);
13618 static internal::meta_base_node node{
13623 return static_cast<Base *
>(
static_cast<Type *
>(instance));
13628 node.next = type->base;
13629 type->base = &node;
13643 template<
typename To>
13645 static_assert(std::is_convertible_v<Type, To>);
13648 static internal::meta_conv_node node{
13652 [](
const void *instance) ->
meta_any {
13653 return static_cast<To
>(*
static_cast<const Type *
>(instance));
13658 node.next = type->conv;
13659 type->conv = &node;
13676 template<auto Cand
idate>
13678 using conv_type = std::invoke_result_t<decltype(Candidate), Type &>;
13681 static internal::meta_conv_node node{
13685 [](
const void *instance) ->
meta_any {
13686 return std::invoke(Candidate, *
static_cast<const Type *
>(instance));
13691 node.next = type->conv;
13692 type->conv = &node;
13710 template<auto Func,
typename Policy = as_is_t>
13712 using helper_type = internal::meta_function_helper_t<decltype(Func)>;
13713 static_assert(std::is_same_v<typename helper_type::return_type, Type>);
13716 static internal::meta_ctor_node node{
13720 helper_type::index_sequence.size(),
13723 return internal::invoke<Type, Func, Policy>({}, any, helper_type::index_sequence);
13728 node.next = type->ctor;
13729 type->ctor = &node;
13744 template<
typename... Args>
13746 using helper_type = internal::meta_function_helper_t<Type(*)(Args...)>;
13749 static internal::meta_ctor_node node{
13753 helper_type::index_sequence.size(),
13756 return internal::construct<Type, std::remove_cv_t<std::remove_reference_t<Args>>...>(any, helper_type::index_sequence);
13761 node.next = type->ctor;
13762 type->ctor = &node;
13783 template<auto Func>
13785 static_assert(std::is_invocable_v<decltype(Func), Type &>);
13788 static internal::meta_dtor_node node{
13802 type->dtor = &node;
13820 template<auto Data,
typename Policy = as_is_t>
13823 internal::meta_data_node *curr =
nullptr;
13825 if constexpr(std::is_same_v<Type, decltype(
Data)>) {
13826 static_assert(std::is_same_v<Policy, as_is_t>);
13828 static internal::meta_data_node node{
13841 }
else if constexpr(std::is_member_object_pointer_v<decltype(
Data)>) {
13842 using data_type = std::remove_reference_t<decltype(std::declval<Type>().*
Data)>;
13844 static internal::meta_data_node node{
13849 std::is_const_v<data_type>,
13850 !std::is_member_object_pointer_v<decltype(
Data)>,
13852 &internal::setter<std::is_const_v<data_type>, Type,
Data>,
13853 &internal::getter<Type, Data, Policy>
13858 static_assert(std::is_pointer_v<std::decay_t<decltype(
Data)>>);
13859 using data_type = std::remove_pointer_t<std::decay_t<decltype(
Data)>>;
13861 static internal::meta_data_node node{
13866 std::is_const_v<data_type>,
13867 !std::is_member_object_pointer_v<decltype(
Data)>,
13869 &internal::setter<std::is_const_v<data_type>, Type,
Data>,
13870 &internal::getter<Type, Data, Policy>
13879 curr->next = type->data;
13905 template<auto Setter, auto Getter,
typename Policy = as_is_t>
13907 using underlying_type = std::invoke_result_t<decltype(Getter), Type &>;
13908 static_assert(std::is_invocable_v<decltype(Setter), Type &, underlying_type>);
13911 static internal::meta_data_node node{
13919 &internal::setter<false, Type, Setter>,
13920 &internal::getter<Type, Getter, Policy>
13926 node.next = type->data;
13927 type->data = &node;
13929 return extended_meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.
prop};
13945 template<auto Cand
idate,
typename Policy = as_is_t>
13947 using helper_type = internal::meta_function_helper_t<decltype(Candidate)>;
13950 static internal::meta_func_node node{
13955 helper_type::index_sequence.size(),
13956 helper_type::is_const,
13957 !std::is_member_function_pointer_v<decltype(Candidate)>,
13958 &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void,
typename helper_type::return_type>>
::resolve,
13961 return internal::invoke<Type, Candidate, Policy>(
handle, any, helper_type::index_sequence);
13968 node.next = type->func;
13969 type->func = &node;
13983 internal::meta_info<Type>::reset();
13993 template<
typename Type,
typename... Spec>
13994 class extended_meta_factory:
public meta_factory<Type> {
13995 bool duplicate(
const meta_any &key,
const internal::meta_prop_node *node)
ENTT_NOEXCEPT {
13996 return node && (node->key() == key || duplicate(key, node->next));
13999 template<std::size_t Step = 0, std::size_t... Index,
typename... Property,
typename... Other>
14000 void unpack(std::index_sequence<Index...>, std::tuple<Property...> property, Other &&... other) {
14001 unroll<Step>(choice<3>, std::move(std::get<Index>(property))..., std::forward<Other>(other)...);
14004 template<std::size_t Step = 0,
typename... Property,
typename... Other>
14005 void unroll(choice_t<3>, std::tuple<Property...> property, Other &&... other) {
14006 unpack<Step>(std::index_sequence_for<Property...>{}, std::move(property), std::forward<Other>(other)...);
14009 template<std::size_t Step = 0,
typename... Property,
typename... Other>
14010 void unroll(choice_t<2>, std::pair<Property...> property, Other &&... other) {
14011 assign<Step>(std::move(property.first), std::move(property.second));
14012 unroll<Step+1>(choice<3>, std::forward<Other>(other)...);
14015 template<std::size_t Step = 0,
typename Property,
typename... Other>
14016 std::enable_if_t<!std::is_invocable_v<Property>>
14017 unroll(choice_t<1>, Property &&property, Other &&... other) {
14018 assign<Step>(std::forward<Property>(property));
14019 unroll<Step+1>(choice<3>, std::forward<Other>(other)...);
14022 template<std::size_t Step = 0,
typename Func,
typename... Other>
14023 void unroll(choice_t<0>, Func &&invocable, Other &&... other) {
14024 unroll<Step>(choice<3>, std::forward<Func>(invocable)(), std::forward<Other>(other)...);
14027 template<std::
size_t>
14028 void unroll(choice_t<0>) {}
14030 template<std::size_t = 0,
typename Key,
typename... Value>
14031 void assign(
Key &&key, Value &&... value) {
14032 static auto property{std::make_tuple(std::forward<Key>(key), std::forward<Value>(value)...)};
14034 static internal::meta_prop_node node{
14037 return std::get<0>(property);
14040 if constexpr(
sizeof...(Value) == 0) {
14043 return std::get<1>(property);
14073 template<
typename PropertyOrKey,
typename... Value>
14074 auto prop(PropertyOrKey &&property_or_key, Value &&... value) && {
14075 if constexpr(
sizeof...(Value) == 0) {
14076 unroll(choice<3>, std::forward<PropertyOrKey>(property_or_key));
14078 assign(std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
14094 template <
typename... Property>
14096 unroll(choice<3>, std::forward<Property>(property)...);
14101 entt::internal::meta_prop_node **curr{
nullptr};
14116 template<
typename Type>
14127 template<
typename Type>
14139 return internal::find_if([
identifier](
auto *node) {
14141 }, *internal::meta_info<>::global);
14150 template<
typename Op>
14151 inline std::enable_if_t<std::is_invocable_v<Op, meta_type>,
void>
14153 internal::iterate<meta_type>(std::move(op), *internal::meta_info<>::global);
14160 #endif // ENTT_META_FACTORY_HPP
14167 #ifndef ENTT_PROCESS_PROCESS_HPP
14168 #define ENTT_PROCESS_PROCESS_HPP
14172 #include <type_traits>
14174 #ifndef ENTT_CONFIG_CONFIG_H
14175 #define ENTT_CONFIG_CONFIG_H
14178 #ifndef ENTT_NOEXCEPT
14179 #define ENTT_NOEXCEPT noexcept
14180 #endif // ENTT_NOEXCEPT
14183 #ifndef ENTT_HS_SUFFIX
14184 #define ENTT_HS_SUFFIX _hs
14185 #endif // ENTT_HS_SUFFIX
14188 #ifndef ENTT_HWS_SUFFIX
14189 #define ENTT_HWS_SUFFIX _hws
14190 #endif // ENTT_HWS_SUFFIX
14193 #ifndef ENTT_NO_ATOMIC
14195 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
14196 #else // ENTT_NO_ATOMIC
14197 #define ENTT_MAYBE_ATOMIC(Type) Type
14198 #endif // ENTT_NO_ATOMIC
14201 #ifndef ENTT_DISABLE_ETO
14202 #include <type_traits>
14203 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
14204 #else // ENTT_DISABLE_ETO
14206 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
14207 #endif // ENTT_DISABLE_ETO
14210 #ifndef ENTT_ID_TYPE
14212 #define ENTT_ID_TYPE std::uint32_t
14213 #endif // ENTT_ID_TYPE
14216 #ifndef ENTT_PAGE_SIZE
14217 #define ENTT_PAGE_SIZE 32768
14218 #endif // ENTT_PAGE_SIZE
14221 #ifndef ENTT_DISABLE_ASSERT
14223 #define ENTT_ASSERT(condition) assert(condition)
14224 #else // ENTT_DISABLE_ASSERT
14225 #define ENTT_ASSERT(...) ((void)0)
14226 #endif // ENTT_DISABLE_ASSERT
14229 #endif // ENTT_CONFIG_CONFIG_H
14295 template<
typename Derived,
typename Delta>
14297 enum class state: unsigned int {
14307 template<state value>
14308 using state_value_t = std::integral_constant<state, value>;
14310 template<
typename Target = Derived>
14311 auto tick(
int, state_value_t<state::UNINITIALIZED>)
14312 -> decltype(std::declval<Target>().init()) {
14313 static_cast<Target *
>(
this)->init();
14316 template<
typename Target = Derived>
14317 auto tick(
int, state_value_t<state::RUNNING>, Delta delta,
void *data)
14318 -> decltype(std::declval<Target>().update(delta, data)) {
14319 static_cast<Target *
>(
this)->update(delta, data);
14322 template<
typename Target = Derived>
14323 auto tick(
int, state_value_t<state::SUCCEEDED>)
14324 -> decltype(std::declval<Target>().succeeded()) {
14325 static_cast<Target *
>(
this)->succeeded();
14328 template<
typename Target = Derived>
14329 auto tick(
int, state_value_t<state::FAILED>)
14330 -> decltype(std::declval<Target>().failed()) {
14331 static_cast<Target *
>(
this)->failed();
14334 template<
typename Target = Derived>
14335 auto tick(
int, state_value_t<state::ABORTED>)
14336 -> decltype(std::declval<Target>().aborted()) {
14337 static_cast<Target *
>(
this)->aborted();
14340 template<state value,
typename... Args>
14341 void tick(
char, state_value_t<value>, Args &&...)
const ENTT_NOEXCEPT {}
14352 current = state::SUCCEEDED;
14364 current = state::FAILED;
14375 if(current == state::RUNNING) {
14376 current = state::PAUSED;
14387 if(current == state::PAUSED) {
14388 current = state::RUNNING;
14398 static_assert(std::is_base_of_v<process, Derived>);
14411 current = state::ABORTED;
14424 return current == state::RUNNING || current == state::PAUSED;
14432 return current == state::FINISHED;
14440 return current == state::PAUSED;
14456 void tick(
const Delta delta,
void *data =
nullptr) {
14458 case state::UNINITIALIZED:
14459 tick(0, state_value_t<state::UNINITIALIZED>{});
14460 current = state::RUNNING;
14462 case state::RUNNING:
14463 tick(0, state_value_t<state::RUNNING>{}, delta, data);
14472 case state::SUCCEEDED:
14473 tick(0, state_value_t<state::SUCCEEDED>{});
14474 current = state::FINISHED;
14476 case state::FAILED:
14477 tick(0, state_value_t<state::FAILED>{});
14478 current = state::FINISHED;
14481 case state::ABORTED:
14482 tick(0, state_value_t<state::ABORTED>{});
14483 current = state::FINISHED;
14493 state current{state::UNINITIALIZED};
14494 bool stopped{
false};
14537 template<
typename Func,
typename Delta>
14544 template<
typename... Args>
14546 : Func{std::forward<Args>(args)...}
14555 Func::operator()(delta, data, [
this]() { this->succeed(); }, [
this]() { this->fail(); });
14563 #endif // ENTT_PROCESS_PROCESS_HPP
14566 #ifndef ENTT_PROCESS_SCHEDULER_HPP
14567 #define ENTT_PROCESS_SCHEDULER_HPP
14573 #include <algorithm>
14574 #include <type_traits>
14610 template<
typename Delta>
14612 struct process_handler {
14613 using instance_type = std::unique_ptr<void, void(*)(
void *)>;
14614 using update_fn_type = bool(process_handler &, Delta,
void *);
14615 using abort_fn_type = void(process_handler &,
bool);
14616 using next_type = std::unique_ptr<process_handler>;
14618 instance_type instance;
14619 update_fn_type *update;
14620 abort_fn_type *abort;
14624 struct continuation {
14625 continuation(process_handler *ref)
14631 template<
typename Proc,
typename... Args>
14632 continuation then(Args &&... args) {
14634 auto proc =
typename process_handler::instance_type{
new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
14635 handler->next.reset(
new process_handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>,
nullptr});
14636 handler = handler->next.get();
14640 template<
typename Func>
14641 continuation then(Func &&func) {
14642 return then<process_adaptor<std::decay_t<Func>, Delta>>(std::forward<Func>(func));
14646 process_handler *handler;
14649 template<
typename Proc>
14650 static bool update(process_handler &handler,
const Delta delta,
void *data) {
14651 auto *
process =
static_cast<Proc *
>(handler.instance.get());
14658 handler = std::move(*handler.next);
14660 dead = handler.update(handler, {},
nullptr);
14662 handler.instance.reset();
14669 template<
typename Proc>
14670 static void abort(process_handler &handler,
const bool immediately) {
14671 static_cast<Proc *
>(handler.instance.get())->abort(immediately);
14674 template<
typename Proc>
14675 static void deleter(
void *proc) {
14676 delete static_cast<Proc *
>(proc);
14697 return handlers.size();
14705 return handlers.empty();
14743 template<
typename Proc,
typename... Args>
14746 auto proc =
typename process_handler::instance_type{
new Proc{std::forward<Args>(args)...}, &scheduler::deleter<Proc>};
14747 process_handler handler{std::move(proc), &scheduler::update<Proc>, &scheduler::abort<Proc>,
nullptr};
14749 handler.update(handler, {},
nullptr);
14750 return continuation{&handlers.emplace_back(std::move(handler))};
14804 template<
typename Func>
14807 return attach<Proc>(std::forward<Func>(func));
14821 void update(
const Delta delta,
void *data =
nullptr) {
14822 bool clean =
false;
14824 for(
auto pos = handlers.size(); pos; --pos) {
14825 auto &handler = handlers[pos-1];
14826 const bool dead = handler.update(handler, delta, data);
14827 clean = clean || dead;
14831 handlers.erase(std::remove_if(handlers.begin(), handlers.end(), [](
auto &handler) {
14832 return !handler.instance;
14833 }), handlers.end());
14847 void abort(
const bool immediately =
false) {
14848 decltype(handlers) exec;
14849 exec.swap(handlers);
14851 std::for_each(exec.begin(), exec.end(), [immediately](
auto &handler) {
14852 handler.abort(handler, immediately);
14855 std::move(handlers.begin(), handlers.end(), std::back_inserter(exec));
14856 handlers.swap(exec);
14860 std::vector<process_handler> handlers{};
14867 #endif // ENTT_PROCESS_SCHEDULER_HPP
14870 #ifndef ENTT_RESOURCE_CACHE_HPP
14871 #define ENTT_RESOURCE_CACHE_HPP
14876 #include <type_traits>
14877 #include <unordered_map>
14879 #ifndef ENTT_CONFIG_CONFIG_H
14880 #define ENTT_CONFIG_CONFIG_H
14883 #ifndef ENTT_NOEXCEPT
14884 #define ENTT_NOEXCEPT noexcept
14885 #endif // ENTT_NOEXCEPT
14888 #ifndef ENTT_HS_SUFFIX
14889 #define ENTT_HS_SUFFIX _hs
14890 #endif // ENTT_HS_SUFFIX
14893 #ifndef ENTT_HWS_SUFFIX
14894 #define ENTT_HWS_SUFFIX _hws
14895 #endif // ENTT_HWS_SUFFIX
14898 #ifndef ENTT_NO_ATOMIC
14900 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
14901 #else // ENTT_NO_ATOMIC
14902 #define ENTT_MAYBE_ATOMIC(Type) Type
14903 #endif // ENTT_NO_ATOMIC
14906 #ifndef ENTT_DISABLE_ETO
14907 #include <type_traits>
14908 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
14909 #else // ENTT_DISABLE_ETO
14911 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
14912 #endif // ENTT_DISABLE_ETO
14915 #ifndef ENTT_ID_TYPE
14917 #define ENTT_ID_TYPE std::uint32_t
14918 #endif // ENTT_ID_TYPE
14921 #ifndef ENTT_PAGE_SIZE
14922 #define ENTT_PAGE_SIZE 32768
14923 #endif // ENTT_PAGE_SIZE
14926 #ifndef ENTT_DISABLE_ASSERT
14928 #define ENTT_ASSERT(condition) assert(condition)
14929 #else // ENTT_DISABLE_ASSERT
14930 #define ENTT_ASSERT(...) ((void)0)
14931 #endif // ENTT_DISABLE_ASSERT
14934 #endif // ENTT_CONFIG_CONFIG_H
14937 #ifndef ENTT_RESOURCE_HANDLE_HPP
14938 #define ENTT_RESOURCE_HANDLE_HPP
14946 #ifndef ENTT_RESOURCE_FWD_HPP
14947 #define ENTT_RESOURCE_FWD_HPP
14962 template<
typename,
typename>
14969 #endif // ENTT_RESOURCE_FWD_HPP
14988 template<
typename Resource>
14991 friend struct cache<Resource>;
14994 : resource{std::move(res)}
15018 return const_cast<Resource &
>(std::as_const(*this).get());
15046 return resource.get();
15051 return const_cast<Resource *
>(std::as_const(*this).operator->());
15058 explicit operator bool()
const {
return static_cast<bool>(resource); }
15061 std::shared_ptr<Resource> resource;
15068 #endif // ENTT_RESOURCE_HANDLE_HPP
15071 #ifndef ENTT_RESOURCE_LOADER_HPP
15072 #define ENTT_RESOURCE_LOADER_HPP
15115 template<
typename Loader,
typename Resource>
15118 friend struct cache<Resource>;
15126 template<
typename... Args>
15127 std::shared_ptr<Resource>
get(Args &&... args)
const {
15128 return static_cast<const Loader *
>(
this)->load(std::forward<Args>(args)...);
15136 #endif // ENTT_RESOURCE_LOADER_HPP
15155 template<
typename Resource>
15178 return resources.size();
15186 return resources.empty();
15221 template<
typename Loader,
typename... Args>
15226 if(
auto it = resources.find(
id); it == resources.cend()) {
15227 if(
auto instance = Loader{}.get(std::forward<Args>(args)...); instance) {
15228 resources[id] = instance;
15229 resource = std::move(instance);
15232 resource = it->second;
15261 template<
typename Loader,
typename... Args>
15263 return (discard(
id), load<Loader>(
id, std::forward<Args>(args)...));
15278 template<
typename Loader,
typename... Args>
15280 return { Loader{}.get(std::forward<Args>(args)...) };
15297 auto it = resources.find(
id);
15298 return { it == resources.end() ? nullptr : it->second };
15307 return (resources.find(
id) != resources.cend());
15319 if(
auto it = resources.find(
id); it != resources.end()) {
15320 resources.erase(it);
15341 template <
typename Func>
15343 auto begin = resources.begin();
15344 auto end = resources.end();
15346 while(begin != end) {
15347 auto curr = begin++;
15349 if constexpr(std::is_invocable_v<Func, id_type>) {
15360 std::unordered_map<id_type, std::shared_ptr<Resource>> resources;
15367 #endif // ENTT_RESOURCE_CACHE_HPP
15374 #ifndef ENTT_SIGNAL_DELEGATE_HPP
15375 #define ENTT_SIGNAL_DELEGATE_HPP
15381 #include <algorithm>
15382 #include <functional>
15383 #include <type_traits>
15385 #ifndef ENTT_CONFIG_CONFIG_H
15386 #define ENTT_CONFIG_CONFIG_H
15389 #ifndef ENTT_NOEXCEPT
15390 #define ENTT_NOEXCEPT noexcept
15391 #endif // ENTT_NOEXCEPT
15394 #ifndef ENTT_HS_SUFFIX
15395 #define ENTT_HS_SUFFIX _hs
15396 #endif // ENTT_HS_SUFFIX
15399 #ifndef ENTT_HWS_SUFFIX
15400 #define ENTT_HWS_SUFFIX _hws
15401 #endif // ENTT_HWS_SUFFIX
15404 #ifndef ENTT_NO_ATOMIC
15406 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
15407 #else // ENTT_NO_ATOMIC
15408 #define ENTT_MAYBE_ATOMIC(Type) Type
15409 #endif // ENTT_NO_ATOMIC
15412 #ifndef ENTT_DISABLE_ETO
15413 #include <type_traits>
15414 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
15415 #else // ENTT_DISABLE_ETO
15417 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
15418 #endif // ENTT_DISABLE_ETO
15421 #ifndef ENTT_ID_TYPE
15423 #define ENTT_ID_TYPE std::uint32_t
15424 #endif // ENTT_ID_TYPE
15427 #ifndef ENTT_PAGE_SIZE
15428 #define ENTT_PAGE_SIZE 32768
15429 #endif // ENTT_PAGE_SIZE
15432 #ifndef ENTT_DISABLE_ASSERT
15434 #define ENTT_ASSERT(condition) assert(condition)
15435 #else // ENTT_DISABLE_ASSERT
15436 #define ENTT_ASSERT(...) ((void)0)
15437 #endif // ENTT_DISABLE_ASSERT
15440 #endif // ENTT_CONFIG_CONFIG_H
15453 namespace internal {
15456 template<
typename Ret,
typename... Args>
15457 auto to_function_pointer(Ret(*)(Args...)) -> Ret(*)(Args...);
15460 template<
typename Ret,
typename... Args,
typename Type,
typename Payload,
typename = std::enable_if_t<std::is_convertible_v<const Payload *, const Type *>>>
15461 auto to_function_pointer(Ret(*)(Type &, Args...),
const Payload *) -> Ret(*)(Args...);
15464 template<
typename Ret,
typename... Args,
typename Type,
typename Payload,
typename = std::enable_if_t<std::is_convertible_v<const Payload *, const Type *>>>
15465 auto to_function_pointer(Ret(*)(Type *, Args...),
const Payload *) -> Ret(*)(Args...);
15468 template<
typename Class,
typename Ret,
typename... Args>
15469 auto to_function_pointer(Ret(Class:: *)(Args...),
const Class *) -> Ret(*)(Args...);
15472 template<
typename Class,
typename Ret,
typename... Args>
15473 auto to_function_pointer(Ret(Class:: *)(Args...)
const,
const Class *) -> Ret(*)(Args...);
15476 template<
typename Class,
typename Type>
15477 auto to_function_pointer(Type Class:: *,
const Class *) -> Type(*)();
15480 template<
typename... Type>
15481 using to_function_pointer_t = decltype(internal::to_function_pointer(std::declval<Type>()...));
15484 template<
typename Ret,
typename... Args>
15485 constexpr
auto index_sequence_for(Ret(*)(Args...)) {
15486 return std::index_sequence_for<Args...>{};
15501 struct connect_arg_t {};
15505 template<auto Func>
15532 template<
typename Ret,
typename... Args>
15534 using proto_fn_type = Ret(
const void *, std::tuple<Args &&...>);
15536 template<
auto Function, std::size_t... Index>
15537 void connect(std::index_sequence<Index...>)
ENTT_NOEXCEPT {
15538 static_assert(std::is_invocable_r_v<Ret, decltype(Function), std::tuple_element_t<Index, std::tuple<Args...>>...>);
15541 fn = [](
const void *, std::tuple<Args &&...> args) -> Ret {
15543 return Ret(std::invoke(Function, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
15547 template<
auto Candidate,
typename Type, std::size_t... Index>
15548 void connect(Type &value_or_instance, std::index_sequence<Index...>)
ENTT_NOEXCEPT {
15549 static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, std::tuple_element_t<Index, std::tuple<Args...>>...>);
15550 data = &value_or_instance;
15552 fn = [](
const void *payload, std::tuple<Args &&...> args) -> Ret {
15553 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
15555 return Ret(std::invoke(Candidate, *curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
15559 template<
auto Candidate,
typename Type, std::size_t... Index>
15560 void connect(Type *value_or_instance, std::index_sequence<Index...>)
ENTT_NOEXCEPT {
15561 static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, std::tuple_element_t<Index, std::tuple<Args...>>...>);
15562 data = value_or_instance;
15564 fn = [](
const void *payload, std::tuple<Args &&...> args) -> Ret {
15565 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
15567 return Ret(std::invoke(Candidate, curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
15573 using function_type = Ret(Args...);
15577 : fn{
nullptr}, data{
nullptr}
15584 template<auto Function>
15588 connect<Function>();
15598 template<auto Cand
idate,
typename Type>
15602 connect<Candidate>(value_or_instance);
15612 template<auto Cand
idate,
typename Type>
15616 connect<Candidate>(value_or_instance);
15623 template<auto Function>
15625 connect<Function>(internal::index_sequence_for(internal::to_function_pointer_t<decltype(Function)>{}));
15643 template<auto Cand
idate,
typename Type>
15645 connect<Candidate>(value_or_instance, internal::index_sequence_for(internal::to_function_pointer_t<decltype(Candidate), Type *>{}));
15663 template<auto Cand
idate,
typename Type>
15665 connect<Candidate>(value_or_instance, internal::index_sequence_for(internal::to_function_pointer_t<decltype(Candidate), Type *>{}));
15700 Ret operator()(Args... args)
const {
15702 return fn(data, std::forward_as_tuple(std::forward<Args>(args)...));
15720 return fn == other.fn && data == other.data;
15737 template<
typename Ret,
typename... Args>
15739 return !(lhs == rhs);
15751 template<auto Function>
15753 ->
delegate<std::remove_pointer_t<internal::to_function_pointer_t<decltype(Function)>>>;
15765 template<auto Cand
idate,
typename Type>
15767 ->
delegate<std::remove_pointer_t<internal::to_function_pointer_t<decltype(Candidate), Type *>>>;
15779 template<auto Cand
idate,
typename Type>
15781 ->
delegate<std::remove_pointer_t<internal::to_function_pointer_t<decltype(Candidate), Type *>>>;
15787 #endif // ENTT_SIGNAL_DELEGATE_HPP
15790 #ifndef ENTT_SIGNAL_DISPATCHER_HPP
15791 #define ENTT_SIGNAL_DISPATCHER_HPP
15798 #include <algorithm>
15799 #include <type_traits>
15803 #ifndef ENTT_CORE_FAMILY_HPP
15804 #define ENTT_CORE_FAMILY_HPP
15807 #include <type_traits>
15809 #ifndef ENTT_CONFIG_CONFIG_H
15810 #define ENTT_CONFIG_CONFIG_H
15813 #ifndef ENTT_NOEXCEPT
15814 #define ENTT_NOEXCEPT noexcept
15815 #endif // ENTT_NOEXCEPT
15818 #ifndef ENTT_HS_SUFFIX
15819 #define ENTT_HS_SUFFIX _hs
15820 #endif // ENTT_HS_SUFFIX
15823 #ifndef ENTT_HWS_SUFFIX
15824 #define ENTT_HWS_SUFFIX _hws
15825 #endif // ENTT_HWS_SUFFIX
15828 #ifndef ENTT_NO_ATOMIC
15830 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
15831 #else // ENTT_NO_ATOMIC
15832 #define ENTT_MAYBE_ATOMIC(Type) Type
15833 #endif // ENTT_NO_ATOMIC
15836 #ifndef ENTT_DISABLE_ETO
15837 #include <type_traits>
15838 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
15839 #else // ENTT_DISABLE_ETO
15841 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
15842 #endif // ENTT_DISABLE_ETO
15845 #ifndef ENTT_ID_TYPE
15847 #define ENTT_ID_TYPE std::uint32_t
15848 #endif // ENTT_ID_TYPE
15851 #ifndef ENTT_PAGE_SIZE
15852 #define ENTT_PAGE_SIZE 32768
15853 #endif // ENTT_PAGE_SIZE
15856 #ifndef ENTT_DISABLE_ASSERT
15858 #define ENTT_ASSERT(condition) assert(condition)
15859 #else // ENTT_DISABLE_ASSERT
15860 #define ENTT_ASSERT(...) ((void)0)
15861 #endif // ENTT_DISABLE_ASSERT
15864 #endif // ENTT_CONFIG_CONFIG_H
15878 template<
typename...>
15887 template<
typename... Type>
15889 inline static const family_type type = identifier++;
15896 #endif // ENTT_CORE_FAMILY_HPP
15899 #ifndef ENTT_CORE_TYPE_TRAITS_HPP
15900 #define ENTT_CORE_TYPE_TRAITS_HPP
15904 #include <type_traits>
15908 #ifndef ENTT_CORE_HASHED_STRING_HPP
15909 #define ENTT_CORE_HASHED_STRING_HPP
15914 #ifndef ENTT_CONFIG_CONFIG_H
15915 #define ENTT_CONFIG_CONFIG_H
15918 #ifndef ENTT_NOEXCEPT
15919 #define ENTT_NOEXCEPT noexcept
15920 #endif // ENTT_NOEXCEPT
15923 #ifndef ENTT_HS_SUFFIX
15924 #define ENTT_HS_SUFFIX _hs
15925 #endif // ENTT_HS_SUFFIX
15928 #ifndef ENTT_HWS_SUFFIX
15929 #define ENTT_HWS_SUFFIX _hws
15930 #endif // ENTT_HWS_SUFFIX
15933 #ifndef ENTT_NO_ATOMIC
15935 #define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type>
15936 #else // ENTT_NO_ATOMIC
15937 #define ENTT_MAYBE_ATOMIC(Type) Type
15938 #endif // ENTT_NO_ATOMIC
15941 #ifndef ENTT_DISABLE_ETO
15942 #include <type_traits>
15943 #define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
15944 #else // ENTT_DISABLE_ETO
15946 #define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
15947 #endif // ENTT_DISABLE_ETO
15950 #ifndef ENTT_ID_TYPE
15952 #define ENTT_ID_TYPE std::uint32_t
15953 #endif // ENTT_ID_TYPE
15956 #ifndef ENTT_PAGE_SIZE
15957 #define ENTT_PAGE_SIZE 32768
15958 #endif // ENTT_PAGE_SIZE
15961 #ifndef ENTT_DISABLE_ASSERT
15963 #define ENTT_ASSERT(condition) assert(condition)
15964 #else // ENTT_DISABLE_ASSERT
15965 #define ENTT_ASSERT(...) ((void)0)
15966 #endif // ENTT_DISABLE_ASSERT
15969 #endif // ENTT_CONFIG_CONFIG_H
15982 namespace internal {
15986 struct fnv1a_traits;
15990 struct fnv1a_traits<
std::uint32_t> {
15991 static constexpr std::uint32_t offset = 2166136261;
15992 static constexpr std::uint32_t prime = 16777619;
15997 struct fnv1a_traits<
std::uint64_t> {
15998 static constexpr std::uint64_t offset = 14695981039346656037ull;
15999 static constexpr std::uint64_t prime = 1099511628211ull;
16023 template<
typename Char>
16025 using traits_type = internal::fnv1a_traits<ENTT_ID_TYPE>;
16027 struct const_wrapper {
16029 constexpr const_wrapper(
const Char *curr)
ENTT_NOEXCEPT: str{curr} {}
16035 return curr[0] == 0 ? partial : helper((partial^curr[0])*traits_type::prime, curr+1);
16040 using value_type = Char;
16059 template<std::
size_t N>
16060 static constexpr hash_type to_value(
const value_type (&str)[N])
ENTT_NOEXCEPT {
16061 return helper(traits_type::offset, str);
16069 static hash_type to_value(const_wrapper wrapper)
ENTT_NOEXCEPT {
16070 return helper(traits_type::offset, wrapper.str);
16079 static hash_type to_value(
const value_type *str, std::size_t size)
ENTT_NOEXCEPT {
16081 while(size--) { partial = (partial^(str++)[0])*traits_type::prime; }
16087 : str{
nullptr}, hash{}
16104 template<std::
size_t N>
16106 : str{curr}, hash{helper(traits_type::offset, curr)}
16115 : str{wrapper.str}, hash{helper(traits_type::offset, wrapper.str)}
16138 constexpr
operator const value_type *()
const ENTT_NOEXCEPT {
return str; }
16141 constexpr
operator hash_type() const
ENTT_NOEXCEPT {
return hash; }
16149 return hash == other.hash;
16153 const value_type *str;
16168 template<
typename Char, std::
size_t N>
16170 -> basic_hashed_string<Char>;
16180 template<
typename Char>
16181 constexpr
bool operator!=(
const basic_hashed_string<Char> &lhs,
const basic_hashed_string<Char> &rhs)
ENTT_NOEXCEPT {
16182 return !(lhs == rhs);
16217 #endif // ENTT_CORE_HASHED_STRING_HPP
16228 template<std::
size_t N>
16239 struct choice_t<0> {};
16246 template<std::
size_t N>
16247 constexpr choice_t<N>
choice{};
16251 template<
typename...>
16252 struct type_list {};
16257 struct type_list_size;
16264 template<
typename... Type>
16265 struct type_list_size<type_list<Type...>>
16266 : std::integral_constant<std::size_t, sizeof...(Type)>
16274 template<
class List>
16279 template<
typename...>
16280 struct type_list_cat;
16285 struct type_list_cat<> {
16287 using type = type_list<>;
16297 template<
typename... Type,
typename... Other,
typename... List>
16298 struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> {
16300 using type =
typename type_list_cat<type_list<Type..., Other...>, List...>::type;
16308 template<
typename... Type>
16309 struct type_list_cat<type_list<Type...>> {
16311 using type = type_list<Type...>;
16319 template<
typename... List>
16325 struct type_list_unique;
16333 template<
typename Type,
typename... Other>
16334 struct type_list_unique<type_list<Type, Other...>> {
16336 using type = std::conditional_t<
16337 std::disjunction_v<std::is_same<Type, Other>...>,
16338 typename type_list_unique<type_list<Other...>>::type,
16339 type_list_cat_t<type_list<Type>,
typename type_list_unique<type_list<Other...>>::type>
16346 struct type_list_unique<type_list<>> {
16348 using type = type_list<>;
16356 template<
typename Type>
16365 template<
typename Type,
typename = std::
void_t<>>
16366 struct is_equality_comparable: std::false_type {};
16370 template<
typename Type>
16371 struct is_equality_comparable<Type,
std::void_t<decltype(std::declval<Type>() == std::declval<Type>())>>: std::true_type {};
16378 template<
class Type>
16384 struct named_type_traits;
16391 template<
typename Type>
16392 struct named_type_traits<const Type>
16393 : named_type_traits<Type>
16401 template<
typename Type>
16409 template<
class Type>
16418 template<
typename Type,
typename = std::
void_t<>>
16419 struct is_named_type: std::false_type {};
16423 template<
typename Type>
16424 struct is_named_type<Type,
std::void_t<named_type_traits_t<std::decay_t<Type>>>>: std::true_type {};
16431 template<
class Type>
16441 #define ENTT_OPAQUE_TYPE(clazz, type)\
16442 enum class clazz: type {};\
16443 constexpr auto to_integer(const clazz id) ENTT_NOEXCEPT {\
16444 return std::underlying_type_t<clazz>(id);\
16446 static_assert(true)
16459 #define ENTT_EXPAND(args) args
16479 #define ENTT_NAMED_TYPE(type)\
16481 struct entt::named_type_traits<type>\
16482 : std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#type)>>>>{#type}>\
16484 static_assert(std::is_same_v<std::remove_cv_t<type>, type>);\
16485 static_assert(std::is_object_v<type>);\
16494 #define ENTT_NAMED_STRUCT_ONLY(clazz, body)\
16495 struct clazz body;\
16496 ENTT_NAMED_TYPE(clazz)
16505 #define ENTT_NAMED_STRUCT_WITH_NAMESPACE(ns, clazz, body)\
16506 namespace ns { struct clazz body; }\
16507 ENTT_NAMED_TYPE(ns::clazz)
16511 #define ENTT_NAMED_STRUCT_OVERLOAD(_1, _2, _3, FUNC, ...) FUNC
16513 #define ENTT_NAMED_STRUCT(...) ENTT_EXPAND(ENTT_NAMED_STRUCT_OVERLOAD(__VA_ARGS__, ENTT_NAMED_STRUCT_WITH_NAMESPACE, ENTT_NAMED_STRUCT_ONLY,)(__VA_ARGS__))
16521 #define ENTT_NAMED_CLASS_ONLY(clazz, body)\
16523 ENTT_NAMED_TYPE(clazz)
16532 #define ENTT_NAMED_CLASS_WITH_NAMESPACE(ns, clazz, body)\
16533 namespace ns { class clazz body; }\
16534 ENTT_NAMED_TYPE(ns::clazz)
16538 #define ENTT_NAMED_CLASS_MACRO(_1, _2, _3, FUNC, ...) FUNC
16540 #define ENTT_NAMED_CLASS(...) ENTT_EXPAND(ENTT_NAMED_CLASS_MACRO(__VA_ARGS__, ENTT_NAMED_CLASS_WITH_NAMESPACE, ENTT_NAMED_CLASS_ONLY,)(__VA_ARGS__))
16543 #endif // ENTT_CORE_TYPE_TRAITS_HPP
16546 #ifndef ENTT_SIGNAL_SIGH_HPP
16547 #define ENTT_SIGNAL_SIGH_HPP
16552 #include <iterator>
16553 #include <algorithm>
16554 #include <functional>
16555 #include <type_traits>
16561 #ifndef ENTT_SIGNAL_FWD_HPP
16562 #define ENTT_SIGNAL_FWD_HPP
16584 #endif // ENTT_SIGNAL_FWD_HPP
16599 template<
typename Function>
16611 template<
typename Function>
16630 template<
typename Ret,
typename... Args>
16631 class sigh<Ret(Args...)> {
16633 friend class sink<Ret(Args...)>;
16637 using size_type = std::size_t;
16645 template<
typename Class>
16646 using instance_type = Class *;
16653 return calls.size();
16661 return calls.empty();
16671 void publish(Args... args)
const {
16672 std::for_each(calls.cbegin(), calls.cend(), [&args...](
auto &&call) {
16691 template<
typename Func>
16692 void collect(Func func, Args... args)
const {
16693 for(
auto &&call: calls) {
16694 if constexpr(std::is_void_v<Ret>) {
16695 if constexpr(std::is_invocable_r_v<bool, Func>) {
16697 if(func()) {
break; }
16703 if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
16704 if(func(call(args...))) {
break; }
16706 func(call(args...));
16713 std::vector<
delegate<Ret(Args...)>> calls;
16729 connection(
delegate<
void(
void *)> fn,
void *ref)
16730 : disconnect{fn}, signal{ref}
16735 connection() =
default;
16738 connection(
const connection &) =
default;
16744 connection(connection &&other)
16747 std::swap(disconnect, other.disconnect);
16748 std::swap(signal, other.signal);
16752 connection & operator=(
const connection &) =
default;
16759 connection & operator=(connection &&other) {
16760 if(
this != &other) {
16761 auto tmp{std::move(other)};
16762 disconnect = tmp.disconnect;
16763 signal = tmp.signal;
16774 return static_cast<bool>(disconnect);
16780 disconnect(signal);
16781 disconnect.reset();
16786 delegate<void(
void *)> disconnect;
16800 struct scoped_connection:
private connection {
16801 using connection::operator bool;
16805 scoped_connection() =
default;
16811 scoped_connection(
const connection &conn)
16816 scoped_connection(
const scoped_connection &) =
delete;
16819 scoped_connection(scoped_connection &&) =
default;
16822 ~scoped_connection() {
16830 scoped_connection & operator=(
const scoped_connection &) =
delete;
16836 scoped_connection & operator=(scoped_connection &&) =
default;
16843 scoped_connection & operator=(
const connection &other) {
16844 static_cast<connection &
>(*this) = other;
16853 scoped_connection & operator=(connection &&other) {
16854 static_cast<connection &
>(*this) = std::move(other);
16874 template<
typename Ret,
typename... Args>
16875 class sink<Ret(Args...)> {
16876 using signal_type = sigh<Ret(Args...)>;
16877 using difference_type =
typename std::iterator_traits<
typename decltype(signal_type::calls)::iterator>::difference_type;
16879 template<auto Cand
idate,
typename Type>
16880 static void release(Type value_or_instance,
void *signal) {
16881 sink{*
static_cast<signal_type *
>(signal)}.disconnect<Candidate>(value_or_instance);
16884 template<auto Function>
16885 static void release(
void *signal) {
16886 sink{*
static_cast<signal_type *
>(signal)}.disconnect<Function>();
16904 return signal->calls.empty();
16912 template<auto Function>
16915 call.template connect<Function>();
16917 const auto &calls = signal->calls;
16918 const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
16933 template<auto Cand
idate,
typename Type>
16934 sink before(Type &value_or_instance) {
16936 call.template connect<Candidate>(value_or_instance);
16938 const auto &calls = signal->calls;
16939 const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
16954 template<auto Cand
idate,
typename Type>
16955 sink before(Type *value_or_instance) {
16957 call.template connect<Candidate>(value_or_instance);
16959 const auto &calls = signal->calls;
16960 const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
16974 template<
typename Type>
16975 sink before(Type &value_or_instance) {
16976 return before(&value_or_instance);
16986 template<
typename Type>
16987 sink before(Type *value_or_instance) {
16990 if(value_or_instance) {
16991 const auto &calls = signal->calls;
16992 const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](
const auto &
delegate) {
16993 return delegate.instance() == value_or_instance;
17008 other.offset = signal->calls.size();
17021 template<auto Function>
17022 connection connect() {
17023 disconnect<Function>();
17026 call.template connect<Function>();
17027 signal->calls.insert(signal->calls.end() - offset, std::move(call));
17030 conn.template connect<&release<Function>>();
17031 return { std::move(conn), signal };
17051 template<auto Cand
idate,
typename Type>
17052 connection connect(Type &value_or_instance) {
17053 disconnect<Candidate>(value_or_instance);
17056 call.template connect<Candidate>(value_or_instance);
17057 signal->calls.insert(signal->calls.end() - offset, std::move(call));
17060 conn.template connect<&release<Candidate, Type &>>(value_or_instance);
17061 return { std::move(conn), signal };
17081 template<auto Cand
idate,
typename Type>
17082 connection connect(Type *value_or_instance) {
17083 disconnect<Candidate>(value_or_instance);
17086 call.template connect<Candidate>(value_or_instance);
17087 signal->calls.insert(signal->calls.end() - offset, std::move(call));
17090 conn.template connect<&release<Candidate, Type *>>(value_or_instance);
17091 return { std::move(conn), signal };
17098 template<auto Function>
17099 void disconnect() {
17100 auto &calls = signal->calls;
17102 call.template connect<Function>();
17103 calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
17113 template<auto Cand
idate,
typename Type>
17114 void disconnect(Type &value_or_instance) {
17115 auto &calls = signal->calls;
17117 call.template connect<Candidate>(value_or_instance);
17118 calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
17128 template<auto Cand
idate,
typename Type>
17129 void disconnect(Type *value_or_instance) {
17130 auto &calls = signal->calls;
17132 call.template connect<Candidate>(value_or_instance);
17133 calls.erase(std::remove(calls.begin(), calls.end(), std::move(call)), calls.end());
17142 template<
typename Type>
17143 void disconnect(Type &value_or_instance) {
17144 disconnect(&value_or_instance);
17153 template<
typename Type>
17154 void disconnect(Type *value_or_instance) {
17155 if(value_or_instance) {
17156 auto &calls = signal->calls;
17157 calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](
const auto &
delegate) {
17158 return delegate.instance() == value_or_instance;
17164 void disconnect() {
17165 signal->calls.clear();
17169 difference_type offset;
17170 signal_type *signal;
17183 template<
typename Ret,
typename... Args>
17190 #endif // ENTT_SIGNAL_SIGH_HPP
17213 template<
typename Class,
typename Event>
17214 using instance_type =
typename sigh<void(
const Event &)>::template instance_type<Class>;
17216 struct base_wrapper {
17217 virtual ~base_wrapper() =
default;
17218 virtual void publish() = 0;
17219 virtual void clear() = 0;
17222 template<
typename Event>
17223 struct signal_wrapper: base_wrapper {
17224 using signal_type =
sigh<void(
const Event &)>;
17225 using sink_type =
typename signal_type::sink_type;
17227 void publish()
override {
17228 const auto length = events.size();
17230 for(std::size_t pos{}; pos < length; ++pos) {
17231 signal.publish(events[pos]);
17234 events.erase(events.cbegin(), events.cbegin()+length);
17237 void clear()
override {
17245 template<
typename... Args>
17246 void trigger(Args &&... args) {
17247 signal.publish({ std::forward<Args>(args)... });
17250 template<
typename... Args>
17251 void enqueue(Args &&... args) {
17252 events.emplace_back(std::forward<Args>(args)...);
17256 signal_type signal{};
17257 std::vector<Event> events;
17260 struct wrapper_data {
17261 std::unique_ptr<base_wrapper> wrapper;
17265 template<
typename Event>
17267 if constexpr(is_named_type_v<Event>) {
17268 return named_type_traits_v<Event>;
17270 return event_family::type<std::decay_t<Event>>;
17274 template<
typename Event>
17275 signal_wrapper<Event> & assure() {
17276 const auto wtype = type<Event>();
17277 wrapper_data *wdata =
nullptr;
17279 if constexpr(is_named_type_v<Event>) {
17280 const auto it = std::find_if(wrappers.begin(), wrappers.end(), [wtype](
const auto &candidate) {
17281 return candidate.wrapper && candidate.runtime_type == wtype;
17284 wdata = (it == wrappers.cend() ? &wrappers.emplace_back() : &(*it));
17286 if(!(wtype < wrappers.size())) {
17287 wrappers.resize(wtype+1);
17290 wdata = &wrappers[wtype];
17292 if(wdata->wrapper && wdata->runtime_type != wtype) {
17293 wrappers.emplace_back();
17294 std::swap(wrappers[wtype], wrappers.back());
17295 wdata = &wrappers[wtype];
17299 if(!wdata->wrapper) {
17300 wdata->wrapper = std::make_unique<signal_wrapper<Event>>();
17301 wdata->runtime_type = wtype;
17304 return static_cast<signal_wrapper<Event> &
>(*wdata->wrapper);
17309 template<
typename Event>
17329 template<
typename Event>
17331 return assure<Event>().sink();
17344 template<
typename Event,
typename... Args>
17346 assure<Event>().trigger(std::forward<Args>(args)...);
17358 template<
typename Event>
17360 assure<std::decay_t<Event>>().trigger(std::forward<Event>(event));
17373 template<
typename Event,
typename... Args>
17375 assure<Event>().enqueue(std::forward<Args>(args)...);
17387 template<
typename Event>
17389 assure<std::decay_t<Event>>().enqueue(std::forward<Event>(event));
17400 template<
typename... Event>
17402 if constexpr(
sizeof...(Event) == 0) {
17403 std::for_each(wrappers.begin(), wrappers.end(), [](
auto &&wdata) {
17404 if(wdata.wrapper) {
17405 wdata.wrapper->clear();
17409 (assure<std::decay_t<Event>>().clear(), ...);
17422 template<
typename Event>
17424 assure<Event>().publish();
17435 for(
auto pos = wrappers.size(); pos; --pos) {
17436 if(
auto &wdata = wrappers[pos-1]; wdata.wrapper) {
17437 wdata.wrapper->publish();
17443 std::vector<wrapper_data> wrappers;
17450 #endif // ENTT_SIGNAL_DISPATCHER_HPP
17453 #ifndef ENTT_SIGNAL_EMITTER_HPP
17454 #define ENTT_SIGNAL_EMITTER_HPP
17457 #include <type_traits>
17458 #include <functional>
17459 #include <algorithm>
17496 template<
typename Derived>
17500 struct base_handler {
17501 virtual ~base_handler() =
default;
17506 template<
typename Event>
17507 struct event_handler: base_handler {
17508 using listener_type = std::function<void(
const Event &, Derived &)>;
17509 using element_type = std::pair<bool, listener_type>;
17510 using container_type = std::list<element_type>;
17511 using connection_type =
typename container_type::iterator;
17514 auto pred = [](
auto &&element) {
return element.first; };
17516 return std::all_of(once_list.cbegin(), once_list.cend(), pred) &&
17517 std::all_of(on_list.cbegin(), on_list.cend(), pred);
17522 auto func = [](
auto &&element) { element.first =
true; };
17523 std::for_each(once_list.begin(), once_list.end(), func);
17524 std::for_each(on_list.begin(), on_list.end(), func);
17531 connection_type once(listener_type
listener) {
17532 return once_list.emplace(once_list.cend(),
false, std::move(
listener));
17535 connection_type on(listener_type
listener) {
17536 return on_list.emplace(on_list.cend(),
false, std::move(
listener));
17540 conn->first =
true;
17543 auto pred = [](
auto &&element) {
return element.first; };
17544 once_list.remove_if(pred);
17545 on_list.remove_if(pred);
17549 void publish(
const Event &event, Derived &ref) {
17550 container_type swap_list;
17551 once_list.swap(swap_list);
17553 auto func = [&event, &ref](
auto &&element) {
17554 return element.first ? void() : element.second(event, ref);
17559 std::for_each(on_list.rbegin(), on_list.rend(), func);
17560 std::for_each(swap_list.rbegin(), swap_list.rend(), func);
17562 publishing =
false;
17564 on_list.remove_if([](
auto &&element) {
return element.first; });
17568 bool publishing{
false};
17569 container_type once_list{};
17570 container_type on_list{};
17573 struct handler_data {
17574 std::unique_ptr<base_handler> handler;
17578 template<
typename Event>
17580 if constexpr(is_named_type_v<Event>) {
17581 return named_type_traits_v<Event>;
17583 return handler_family::type<std::decay_t<Event>>;
17587 template<
typename Event>
17589 const auto htype = type<Event>();
17590 handler_data *hdata =
nullptr;
17592 if constexpr(is_named_type_v<Event>) {
17593 const auto it = std::find_if(handlers.begin(), handlers.end(), [htype](
const auto &candidate) {
17594 return candidate.handler && candidate.runtime_type == htype;
17597 hdata = (it == handlers.cend() ? &handlers.emplace_back() : &(*it));
17599 if(!(htype < handlers.size())) {
17600 handlers.resize(htype+1);
17603 hdata = &handlers[htype];
17605 if(hdata->handler && hdata->runtime_type != htype) {
17606 handlers.emplace_back();
17607 std::swap(handlers[htype], handlers.back());
17608 hdata = &handlers[htype];
17612 if(!hdata->handler) {
17613 hdata->handler = std::make_unique<event_handler<Event>>();
17614 hdata->runtime_type = htype;
17617 return static_cast<event_handler<Event> *
>(hdata->handler.get());
17622 template<
typename Event>
17623 using listener =
typename event_handler<Event>::listener_type;
17634 template<
typename Event>
17647 : event_handler<Event>::connection_type{std::move(conn)}
17676 template<
typename Event,
typename... Args>
17678 assure<Event>()->publish({ std::forward<Args>(args)... }, *
static_cast<Derived *
>(
this));
17701 template<
typename Event>
17703 return assure<Event>()->on(std::move(instance));
17726 template<
typename Event>
17728 return assure<Event>()->once(std::move(instance));
17740 template<
typename Event>
17742 assure<Event>()->erase(std::move(conn));
17753 template<
typename Event>
17755 assure<Event>()->clear();
17765 std::for_each(handlers.begin(), handlers.end(), [](
auto &&hdata) {
17766 return hdata.handler ? hdata.handler->clear() : void();
17775 template<
typename Event>
17777 return assure<Event>()->empty();
17785 return std::all_of(handlers.cbegin(), handlers.cend(), [](
auto &&hdata) {
17786 return !hdata.handler || hdata.handler->empty();
17791 mutable std::vector<handler_data> handlers{};
17798 #endif // ENTT_SIGNAL_EMITTER_HPP