🛠️🐜 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.

177 lines
5.8 KiB

  1. #ifndef ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
  2. #define ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP
  3. #include <utility>
  4. #include "../config/config.h"
  5. #include "../core/any.hpp"
  6. #include "../signal/sigh.hpp"
  7. #include "fwd.hpp"
  8. namespace entt {
  9. /**
  10. * @brief Mixin type used to add signal support to storage types.
  11. *
  12. * The function type of a listener is equivalent to:
  13. *
  14. * @code{.cpp}
  15. * void(basic_registry<entity_type> &, entity_type);
  16. * @endcode
  17. *
  18. * This applies to all signals made available.
  19. *
  20. * @tparam Type The type of the underlying storage.
  21. */
  22. template<typename Type>
  23. class sigh_storage_mixin final: public Type {
  24. using basic_iterator = typename Type::basic_iterator;
  25. template<typename Func>
  26. void notify_destruction(basic_iterator first, basic_iterator last, Func func) {
  27. ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
  28. for(; first != last; ++first) {
  29. const auto entt = *first;
  30. destruction.publish(*owner, entt);
  31. const auto it = Type::find(entt);
  32. func(it, it + 1u);
  33. }
  34. }
  35. void swap_and_pop(basic_iterator first, basic_iterator last) final {
  36. notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::swap_and_pop(args...); });
  37. }
  38. void in_place_pop(basic_iterator first, basic_iterator last) final {
  39. notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::in_place_pop(args...); });
  40. }
  41. basic_iterator try_emplace(const typename Type::entity_type entt, const bool force_back, const void *value) final {
  42. ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
  43. Type::try_emplace(entt, force_back, value);
  44. construction.publish(*owner, entt);
  45. return Type::find(entt);
  46. }
  47. public:
  48. /*! @brief Underlying entity identifier. */
  49. using entity_type = typename Type::entity_type;
  50. /*! @brief Inherited constructors. */
  51. using Type::Type;
  52. /**
  53. * @brief Returns a sink object.
  54. *
  55. * The sink returned by this function can be used to receive notifications
  56. * whenever a new instance is created and assigned to an entity.<br/>
  57. * Listeners are invoked after the object has been assigned to the entity.
  58. *
  59. * @sa sink
  60. *
  61. * @return A temporary sink object.
  62. */
  63. [[nodiscard]] auto on_construct() ENTT_NOEXCEPT {
  64. return sink{construction};
  65. }
  66. /**
  67. * @brief Returns a sink object.
  68. *
  69. * The sink returned by this function can be used to receive notifications
  70. * whenever an instance is explicitly updated.<br/>
  71. * Listeners are invoked after the object has been updated.
  72. *
  73. * @sa sink
  74. *
  75. * @return A temporary sink object.
  76. */
  77. [[nodiscard]] auto on_update() ENTT_NOEXCEPT {
  78. return sink{update};
  79. }
  80. /**
  81. * @brief Returns a sink object.
  82. *
  83. * The sink returned by this function can be used to receive notifications
  84. * whenever an instance is removed from an entity and thus destroyed.<br/>
  85. * Listeners are invoked before the object has been removed from the entity.
  86. *
  87. * @sa sink
  88. *
  89. * @return A temporary sink object.
  90. */
  91. [[nodiscard]] auto on_destroy() ENTT_NOEXCEPT {
  92. return sink{destruction};
  93. }
  94. /**
  95. * @brief Assigns entities to a storage.
  96. * @tparam Args Types of arguments to use to construct the object.
  97. * @param entt A valid identifier.
  98. * @param args Parameters to use to initialize the object.
  99. * @return A reference to the newly created object.
  100. */
  101. template<typename... Args>
  102. decltype(auto) emplace(const entity_type entt, Args &&...args) {
  103. ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
  104. Type::emplace(entt, std::forward<Args>(args)...);
  105. construction.publish(*owner, entt);
  106. return this->get(entt);
  107. }
  108. /**
  109. * @brief Patches the given instance for an entity.
  110. * @tparam Func Types of the function objects to invoke.
  111. * @param entt A valid identifier.
  112. * @param func Valid function objects.
  113. * @return A reference to the patched instance.
  114. */
  115. template<typename... Func>
  116. decltype(auto) patch(const entity_type entt, Func &&...func) {
  117. ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
  118. Type::patch(entt, std::forward<Func>(func)...);
  119. update.publish(*owner, entt);
  120. return this->get(entt);
  121. }
  122. /**
  123. * @brief Assigns entities to a storage.
  124. * @tparam It Type of input iterator.
  125. * @tparam Args Types of arguments to use to construct the objects assigned
  126. * to the entities.
  127. * @param first An iterator to the first element of the range of entities.
  128. * @param last An iterator past the last element of the range of entities.
  129. * @param args Parameters to use to initialize the objects assigned to the
  130. * entities.
  131. */
  132. template<typename It, typename... Args>
  133. void insert(It first, It last, Args &&...args) {
  134. ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
  135. Type::insert(first, last, std::forward<Args>(args)...);
  136. for(auto it = construction.empty() ? last : first; it != last; ++it) {
  137. construction.publish(*owner, *it);
  138. }
  139. }
  140. /**
  141. * @brief Forwards variables to mixins, if any.
  142. * @param value A variable wrapped in an opaque container.
  143. */
  144. void bind(any value) ENTT_NOEXCEPT final {
  145. auto *reg = any_cast<basic_registry<entity_type>>(&value);
  146. owner = reg ? reg : owner;
  147. Type::bind(std::move(value));
  148. }
  149. private:
  150. sigh<void(basic_registry<entity_type> &, const entity_type)> construction{};
  151. sigh<void(basic_registry<entity_type> &, const entity_type)> destruction{};
  152. sigh<void(basic_registry<entity_type> &, const entity_type)> update{};
  153. basic_registry<entity_type> *owner{};
  154. };
  155. } // namespace entt
  156. #endif