🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
5.2 KiB

  1. #ifndef ENTT_ENTITY_HELPER_HPP
  2. #define ENTT_ENTITY_HELPER_HPP
  3. #include <type_traits>
  4. #include "../config/config.h"
  5. #include "../core/fwd.hpp"
  6. #include "../core/type_traits.hpp"
  7. #include "../signal/delegate.hpp"
  8. #include "fwd.hpp"
  9. #include "registry.hpp"
  10. namespace entt {
  11. /**
  12. * @brief Converts a registry to a view.
  13. * @tparam Entity A valid entity type (see entt_traits for more details).
  14. */
  15. template<typename Entity>
  16. struct as_view {
  17. /*! @brief Underlying entity identifier. */
  18. using entity_type = std::remove_const_t<Entity>;
  19. /*! @brief Type of registry to convert. */
  20. using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
  21. /**
  22. * @brief Constructs a converter for a given registry.
  23. * @param source A valid reference to a registry.
  24. */
  25. as_view(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
  26. /**
  27. * @brief Conversion function from a registry to a view.
  28. * @tparam Exclude Types of components used to filter the view.
  29. * @tparam Component Type of components used to construct the view.
  30. * @return A newly created view.
  31. */
  32. template<typename Exclude, typename... Component>
  33. operator basic_view<entity_type, get_t<Component...>, Exclude>() const {
  34. return reg.template view<Component...>(Exclude{});
  35. }
  36. private:
  37. registry_type &reg;
  38. };
  39. /**
  40. * @brief Deduction guide.
  41. * @tparam Entity A valid entity type (see entt_traits for more details).
  42. */
  43. template<typename Entity>
  44. as_view(basic_registry<Entity> &) -> as_view<Entity>;
  45. /**
  46. * @brief Deduction guide.
  47. * @tparam Entity A valid entity type (see entt_traits for more details).
  48. */
  49. template<typename Entity>
  50. as_view(const basic_registry<Entity> &) -> as_view<const Entity>;
  51. /**
  52. * @brief Converts a registry to a group.
  53. * @tparam Entity A valid entity type (see entt_traits for more details).
  54. */
  55. template<typename Entity>
  56. struct as_group {
  57. /*! @brief Underlying entity identifier. */
  58. using entity_type = std::remove_const_t<Entity>;
  59. /*! @brief Type of registry to convert. */
  60. using registry_type = constness_as_t<basic_registry<entity_type>, Entity>;
  61. /**
  62. * @brief Constructs a converter for a given registry.
  63. * @param source A valid reference to a registry.
  64. */
  65. as_group(registry_type &source) ENTT_NOEXCEPT: reg{source} {}
  66. /**
  67. * @brief Conversion function from a registry to a group.
  68. * @tparam Get Types of components observed by the group.
  69. * @tparam Exclude Types of components used to filter the group.
  70. * @tparam Owned Types of components owned by the group.
  71. * @return A newly created group.
  72. */
  73. template<typename Get, typename Exclude, typename... Owned>
  74. operator basic_group<entity_type, owned_t<Owned...>, Get, Exclude>() const {
  75. if constexpr(std::is_const_v<registry_type>) {
  76. return reg.template group_if_exists<Owned...>(Get{}, Exclude{});
  77. } else {
  78. return reg.template group<Owned...>(Get{}, Exclude{});
  79. }
  80. }
  81. private:
  82. registry_type &reg;
  83. };
  84. /**
  85. * @brief Deduction guide.
  86. * @tparam Entity A valid entity type (see entt_traits for more details).
  87. */
  88. template<typename Entity>
  89. as_group(basic_registry<Entity> &) -> as_group<Entity>;
  90. /**
  91. * @brief Deduction guide.
  92. * @tparam Entity A valid entity type (see entt_traits for more details).
  93. */
  94. template<typename Entity>
  95. as_group(const basic_registry<Entity> &) -> as_group<const Entity>;
  96. /**
  97. * @brief Helper to create a listener that directly invokes a member function.
  98. * @tparam Member Member function to invoke on a component of the given type.
  99. * @tparam Entity A valid entity type (see entt_traits for more details).
  100. * @param reg A registry that contains the given entity and its components.
  101. * @param entt Entity from which to get the component.
  102. */
  103. template<auto Member, typename Entity = entity>
  104. void invoke(basic_registry<Entity> &reg, const Entity entt) {
  105. static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function");
  106. delegate<void(basic_registry<Entity> &, const Entity)> func;
  107. func.template connect<Member>(reg.template get<member_class_t<decltype(Member)>>(entt));
  108. func(reg, entt);
  109. }
  110. /**
  111. * @brief Returns the entity associated with a given component.
  112. *
  113. * @warning
  114. * Currently, this function only works correctly with the default pool as it
  115. * makes assumptions about how the components are laid out.
  116. *
  117. * @tparam Entity A valid entity type (see entt_traits for more details).
  118. * @tparam Component Type of component.
  119. * @param reg A registry that contains the given entity and its components.
  120. * @param instance A valid component instance.
  121. * @return The entity associated with the given component.
  122. */
  123. template<typename Entity, typename Component>
  124. Entity to_entity(const basic_registry<Entity> &reg, const Component &instance) {
  125. const auto &storage = reg.template storage<Component>();
  126. const typename basic_registry<Entity>::base_type &base = storage;
  127. const auto *addr = std::addressof(instance);
  128. for(auto it = base.rbegin(), last = base.rend(); it < last; it += ENTT_PACKED_PAGE) {
  129. if(const auto dist = (addr - std::addressof(storage.get(*it))); dist >= 0 && dist < ENTT_PACKED_PAGE) {
  130. return *(it + dist);
  131. }
  132. }
  133. return null;
  134. }
  135. } // namespace entt
  136. #endif