handle.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. #ifndef ENTT_ENTITY_HANDLE_HPP
  2. #define ENTT_ENTITY_HANDLE_HPP
  3. #include <tuple>
  4. #include <type_traits>
  5. #include <utility>
  6. #include "../config/config.h"
  7. #include "../core/type_traits.hpp"
  8. #include "fwd.hpp"
  9. #include "registry.hpp"
  10. namespace entt {
  11. /**
  12. * @brief Non-owning handle to an entity.
  13. *
  14. * Tiny wrapper around a registry and an entity.
  15. *
  16. * @tparam Entity A valid entity type (see entt_traits for more details).
  17. * @tparam Type Types to which to restrict the scope of a handle.
  18. */
  19. template<typename Entity, typename... Type>
  20. struct basic_handle {
  21. /*! @brief Type of registry accepted by the handle. */
  22. using registry_type = constness_as_t<basic_registry<std::remove_const_t<Entity>>, Entity>;
  23. /*! @brief Underlying entity identifier. */
  24. using entity_type = typename registry_type::entity_type;
  25. /*! @brief Underlying version type. */
  26. using version_type = typename registry_type::version_type;
  27. /*! @brief Unsigned integer type. */
  28. using size_type = typename registry_type::size_type;
  29. /*! @brief Constructs an invalid handle. */
  30. basic_handle() ENTT_NOEXCEPT
  31. : reg{}, entt{null}
  32. {}
  33. /**
  34. * @brief Constructs a handle from a given registry and entity.
  35. * @param ref An instance of the registry class.
  36. * @param value A valid identifier.
  37. */
  38. basic_handle(registry_type &ref, entity_type value) ENTT_NOEXCEPT
  39. : reg{&ref}, entt{value}
  40. {}
  41. /**
  42. * @brief Compares two handles.
  43. * @tparam Args Template parameters of the handle with which to compare.
  44. * @param other Handle with which to compare.
  45. * @return True if both handles refer to the same registry and the same
  46. * entity, false otherwise.
  47. */
  48. template<typename... Args>
  49. [[nodiscard]] bool operator==(const basic_handle<Args...> &other) const ENTT_NOEXCEPT {
  50. return reg == other.registry() && entt == other.entity();
  51. }
  52. /**
  53. * @brief Constructs a const handle from a non-const one.
  54. * @tparam Other A valid entity type (see entt_traits for more details).
  55. * @tparam Args Scope of the handle to construct.
  56. * @return A const handle referring to the same registry and the same
  57. * entity.
  58. */
  59. template<typename Other, typename... Args>
  60. operator basic_handle<Other, Args...>() const ENTT_NOEXCEPT {
  61. static_assert(
  62. (std::is_same_v<Other, Entity> || std::is_same_v<std::remove_const_t<Other>, Entity>)
  63. && (sizeof...(Type) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Type)) && ... && (type_list_contains_v<type_list<Type...>, Args>))),
  64. "Invalid conversion between different handles"
  65. );
  66. return reg ? basic_handle<Other, Args...>{*reg, entt} : basic_handle<Other, Args...>{};
  67. }
  68. /**
  69. * @brief Converts a handle to its underlying entity.
  70. * @return The contained identifier.
  71. */
  72. [[nodiscard]] operator entity_type() const ENTT_NOEXCEPT {
  73. return entity();
  74. }
  75. /**
  76. * @brief Checks if a handle refers to non-null registry pointer and entity.
  77. * @return True if the handle refers to non-null registry and entity, false otherwise.
  78. */
  79. [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
  80. return reg && reg->valid(entt);
  81. }
  82. /**
  83. * @brief Checks if a handle refers to a valid entity or not.
  84. * @return True if the handle refers to a valid entity, false otherwise.
  85. */
  86. [[nodiscard]] bool valid() const {
  87. return reg->valid(entt);
  88. }
  89. /**
  90. * @brief Returns a pointer to the underlying registry, if any.
  91. * @return A pointer to the underlying registry, if any.
  92. */
  93. [[nodiscard]] registry_type * registry() const ENTT_NOEXCEPT {
  94. return reg;
  95. }
  96. /**
  97. * @brief Returns the entity associated with a handle.
  98. * @return The entity associated with the handle.
  99. */
  100. [[nodiscard]] entity_type entity() const ENTT_NOEXCEPT {
  101. return entt;
  102. }
  103. /**
  104. * @brief Destroys the entity associated with a handle.
  105. * @sa basic_registry::destroy
  106. */
  107. void destroy() {
  108. reg->destroy(entt);
  109. }
  110. /**
  111. * @brief Destroys the entity associated with a handle.
  112. * @sa basic_registry::destroy
  113. * @param version A desired version upon destruction.
  114. */
  115. void destroy(const version_type version) {
  116. reg->destroy(entt, version);
  117. }
  118. /**
  119. * @brief Assigns the given component to a handle.
  120. * @sa basic_registry::emplace
  121. * @tparam Component Type of component to create.
  122. * @tparam Args Types of arguments to use to construct the component.
  123. * @param args Parameters to use to initialize the component.
  124. * @return A reference to the newly created component.
  125. */
  126. template<typename Component, typename... Args>
  127. decltype(auto) emplace(Args &&... args) const {
  128. static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
  129. return reg->template emplace<Component>(entt, std::forward<Args>(args)...);
  130. }
  131. /**
  132. * @brief Assigns or replaces the given component for a handle.
  133. * @sa basic_registry::emplace_or_replace
  134. * @tparam Component Type of component to assign or replace.
  135. * @tparam Args Types of arguments to use to construct the component.
  136. * @param args Parameters to use to initialize the component.
  137. * @return A reference to the newly created component.
  138. */
  139. template<typename Component, typename... Args>
  140. decltype(auto) emplace_or_replace(Args &&... args) const {
  141. static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
  142. return reg->template emplace_or_replace<Component>(entt, std::forward<Args>(args)...);
  143. }
  144. /**
  145. * @brief Patches the given component for a handle.
  146. * @sa basic_registry::patch
  147. * @tparam Component Type of component to patch.
  148. * @tparam Func Types of the function objects to invoke.
  149. * @param func Valid function objects.
  150. * @return A reference to the patched component.
  151. */
  152. template<typename Component, typename... Func>
  153. decltype(auto) patch(Func &&... func) const {
  154. static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
  155. return reg->template patch<Component>(entt, std::forward<Func>(func)...);
  156. }
  157. /**
  158. * @brief Replaces the given component for a handle.
  159. * @sa basic_registry::replace
  160. * @tparam Component Type of component to replace.
  161. * @tparam Args Types of arguments to use to construct the component.
  162. * @param args Parameters to use to initialize the component.
  163. * @return A reference to the component being replaced.
  164. */
  165. template<typename Component, typename... Args>
  166. decltype(auto) replace(Args &&... args) const {
  167. static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
  168. return reg->template replace<Component>(entt, std::forward<Args>(args)...);
  169. }
  170. /**
  171. * @brief Removes the given components from a handle.
  172. * @sa basic_registry::remove
  173. * @tparam Component Types of components to remove.
  174. * @return The number of components actually removed.
  175. */
  176. template<typename... Component>
  177. size_type remove() const {
  178. static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
  179. return reg->template remove<Component...>(entt);
  180. }
  181. /**
  182. * @brief Erases the given components from a handle.
  183. * @sa basic_registry::erase
  184. * @tparam Component Types of components to erase.
  185. */
  186. template<typename... Component>
  187. void erase() const {
  188. static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
  189. reg->template erase<Component...>(entt);
  190. }
  191. /**
  192. * @brief Checks if a handle has all the given components.
  193. * @sa basic_registry::all_of
  194. * @tparam Component Components for which to perform the check.
  195. * @return True if the handle has all the components, false otherwise.
  196. */
  197. template<typename... Component>
  198. [[nodiscard]] decltype(auto) all_of() const {
  199. return reg->template all_of<Component...>(entt);
  200. }
  201. /**
  202. * @brief Checks if a handle has at least one of the given components.
  203. * @sa basic_registry::any_of
  204. * @tparam Component Components for which to perform the check.
  205. * @return True if the handle has at least one of the given components,
  206. * false otherwise.
  207. */
  208. template<typename... Component>
  209. [[nodiscard]] decltype(auto) any_of() const {
  210. return reg->template any_of<Component...>(entt);
  211. }
  212. /**
  213. * @brief Returns references to the given components for a handle.
  214. * @sa basic_registry::get
  215. * @tparam Component Types of components to get.
  216. * @return References to the components owned by the handle.
  217. */
  218. template<typename... Component>
  219. [[nodiscard]] decltype(auto) get() const {
  220. static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
  221. return reg->template get<Component...>(entt);
  222. }
  223. /**
  224. * @brief Returns a reference to the given component for a handle.
  225. * @sa basic_registry::get_or_emplace
  226. * @tparam Component Type of component to get.
  227. * @tparam Args Types of arguments to use to construct the component.
  228. * @param args Parameters to use to initialize the component.
  229. * @return Reference to the component owned by the handle.
  230. */
  231. template<typename Component, typename... Args>
  232. [[nodiscard]] decltype(auto) get_or_emplace(Args &&... args) const {
  233. static_assert(((sizeof...(Type) == 0) || ... || std::is_same_v<Component, Type>), "Invalid type");
  234. return reg->template get_or_emplace<Component>(entt, std::forward<Args>(args)...);
  235. }
  236. /**
  237. * @brief Returns pointers to the given components for a handle.
  238. * @sa basic_registry::try_get
  239. * @tparam Component Types of components to get.
  240. * @return Pointers to the components owned by the handle.
  241. */
  242. template<typename... Component>
  243. [[nodiscard]] auto try_get() const {
  244. static_assert(sizeof...(Type) == 0 || (type_list_contains_v<type_list<Type...>, Component> && ...), "Invalid type");
  245. return reg->template try_get<Component...>(entt);
  246. }
  247. /**
  248. * @brief Checks if a handle has components assigned.
  249. * @return True if the handle has no components assigned, false otherwise.
  250. */
  251. [[nodiscard]] bool orphan() const {
  252. return reg->orphan(entt);
  253. }
  254. /**
  255. * @brief Visits a handle and returns the types for its components.
  256. * @sa basic_registry::visit
  257. * @tparam Func Type of the function object to invoke.
  258. * @param func A valid function object.
  259. */
  260. template<typename Func>
  261. void visit(Func &&func) const {
  262. reg->visit(entt, std::forward<Func>(func));
  263. }
  264. private:
  265. registry_type *reg;
  266. entity_type entt;
  267. };
  268. /**
  269. * @brief Compares two handles.
  270. * @tparam Type A valid entity type (see entt_traits for more details).
  271. * @tparam Other A valid entity type (see entt_traits for more details).
  272. * @param lhs A valid handle.
  273. * @param rhs A valid handle.
  274. * @return False if both handles refer to the same registry and the same
  275. * entity, true otherwise.
  276. */
  277. template<typename Type, typename Other>
  278. bool operator!=(const basic_handle<Type> &lhs, const basic_handle<Other> &rhs) ENTT_NOEXCEPT {
  279. return !(lhs == rhs);
  280. }
  281. /**
  282. * @brief Deduction guide.
  283. * @tparam Entity A valid entity type (see entt_traits for more details).
  284. */
  285. template<typename Entity>
  286. basic_handle(basic_registry<Entity> &, Entity)
  287. -> basic_handle<Entity>;
  288. /**
  289. * @brief Deduction guide.
  290. * @tparam Entity A valid entity type (see entt_traits for more details).
  291. */
  292. template<typename Entity>
  293. basic_handle(const basic_registry<Entity> &, Entity)
  294. -> basic_handle<const Entity>;
  295. }
  296. #endif