EnTT  3.10.0
observer.hpp
1 #ifndef ENTT_ENTITY_OBSERVER_HPP
2 #define ENTT_ENTITY_OBSERVER_HPP
3 
4 #include <cstddef>
5 #include <cstdint>
6 #include <limits>
7 #include <type_traits>
8 #include <utility>
9 #include "../config/config.h"
10 #include "../core/type_traits.hpp"
11 #include "../signal/delegate.hpp"
12 #include "entity.hpp"
13 #include "fwd.hpp"
14 #include "registry.hpp"
15 #include "storage.hpp"
16 #include "utility.hpp"
17 
18 namespace entt {
19 
21 template<typename...>
22 struct matcher {};
23 
30 template<typename...>
32 
41 template<>
49  template<typename... AllOf, typename... NoneOf>
50  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
51  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{};
52  }
53 
59  template<typename AnyOf>
60  static constexpr auto update() ENTT_NOEXCEPT {
62  }
63 };
64 
73 template<typename... Reject, typename... Require, typename... Rule, typename... Other>
74 struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> {
76  using current_type = matcher<type_list<Reject...>, type_list<Require...>, Rule...>;
77 
84  template<typename... AllOf, typename... NoneOf>
85  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
86  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
87  }
88 
94  template<typename AnyOf>
95  static constexpr auto update() ENTT_NOEXCEPT {
96  return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{};
97  }
98 
105  template<typename... AllOf, typename... NoneOf>
106  static constexpr auto where(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
107  using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
108  return basic_collector<extended_type, Other...>{};
109  }
110 };
111 
113 inline constexpr basic_collector<> collector{};
114 
164 template<typename Entity>
166  using payload_type = std::uint32_t;
167 
168  template<typename>
169  struct matcher_handler;
170 
171  template<typename... Reject, typename... Require, typename AnyOf>
172  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
173  template<std::size_t Index>
174  static void maybe_valid_if(basic_observer &obs, basic_registry<Entity> &reg, const Entity entt) {
175  if(reg.template all_of<Require...>(entt) && !reg.template any_of<Reject...>(entt)) {
176  if(!obs.storage.contains(entt)) {
177  obs.storage.emplace(entt);
178  }
179 
180  obs.storage.get(entt) |= (1 << Index);
181  }
182  }
183 
184  template<std::size_t Index>
185  static void discard_if(basic_observer &obs, basic_registry<Entity> &, const Entity entt) {
186  if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) {
187  obs.storage.erase(entt);
188  }
189  }
190 
191  template<std::size_t Index>
192  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
193  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
194  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
195  reg.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
196  reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
197  }
198 
199  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
200  (reg.template on_destroy<Require>().disconnect(obs), ...);
201  (reg.template on_construct<Reject>().disconnect(obs), ...);
202  reg.template on_update<AnyOf>().disconnect(obs);
203  reg.template on_destroy<AnyOf>().disconnect(obs);
204  }
205  };
206 
207  template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
208  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
209  template<std::size_t Index, typename... Ignore>
210  static void maybe_valid_if(basic_observer &obs, basic_registry<Entity> &reg, const Entity entt) {
211  auto condition = [&reg, entt]() {
212  if constexpr(sizeof...(Ignore) == 0) {
213  return reg.template all_of<AllOf..., Require...>(entt) && !reg.template any_of<NoneOf..., Reject...>(entt);
214  } else {
215  return reg.template all_of<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !reg.template any_of<NoneOf>(entt)) && ...) && !reg.template any_of<Reject...>(entt);
216  }
217  };
218 
219  if(condition()) {
220  if(!obs.storage.contains(entt)) {
221  obs.storage.emplace(entt);
222  }
223 
224  obs.storage.get(entt) |= (1 << Index);
225  }
226  }
227 
228  template<std::size_t Index>
229  static void discard_if(basic_observer &obs, basic_registry<Entity> &, const Entity entt) {
230  if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) {
231  obs.storage.erase(entt);
232  }
233  }
234 
235  template<std::size_t Index>
236  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
237  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
238  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
239  (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
240  (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(obs), ...);
241  (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
242  (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
243  }
244 
245  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
246  (reg.template on_destroy<Require>().disconnect(obs), ...);
247  (reg.template on_construct<Reject>().disconnect(obs), ...);
248  (reg.template on_construct<AllOf>().disconnect(obs), ...);
249  (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
250  (reg.template on_destroy<AllOf>().disconnect(obs), ...);
251  (reg.template on_construct<NoneOf>().disconnect(obs), ...);
252  }
253  };
254 
255  template<typename... Matcher>
256  static void disconnect(basic_registry<Entity> &reg, basic_observer &obs) {
257  (matcher_handler<Matcher>::disconnect(obs, reg), ...);
258  }
259 
260  template<typename... Matcher, std::size_t... Index>
261  void connect(basic_registry<Entity> &reg, std::index_sequence<Index...>) {
262  static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits, "Too many matchers");
263  (matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
264  release.template connect<&basic_observer::disconnect<Matcher...>>(reg);
265  }
266 
267 public:
269  using entity_type = Entity;
271  using size_type = std::size_t;
274 
277  : release{},
278  storage{} {}
279 
281  basic_observer(const basic_observer &) = delete;
284 
290  template<typename... Matcher>
292  : basic_observer{} {
293  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
294  }
295 
297  ~basic_observer() = default;
298 
304 
310 
316  template<typename... Matcher>
318  disconnect();
319  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
320  storage.clear();
321  }
322 
324  void disconnect() {
325  if(release) {
326  release(*this);
327  release.reset();
328  }
329  }
330 
335  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
336  return storage.size();
337  }
338 
343  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
344  return storage.empty();
345  }
346 
359  [[nodiscard]] const entity_type *data() const ENTT_NOEXCEPT {
360  return storage.data();
361  }
362 
371  [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
372  return storage.basic_sparse_set<entity_type>::begin();
373  }
374 
385  [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
386  return storage.basic_sparse_set<entity_type>::end();
387  }
388 
390  void clear() ENTT_NOEXCEPT {
391  storage.clear();
392  }
393 
407  template<typename Func>
408  void each(Func func) const {
409  for(const auto entity: *this) {
410  func(entity);
411  }
412  }
413 
423  template<typename Func>
424  void each(Func func) {
425  std::as_const(*this).each(std::move(func));
426  clear();
427  }
428 
429 private:
430  delegate<void(basic_observer &)> release;
432 };
433 
434 } // namespace entt
435 
436 #endif
basic_observer & operator=(const basic_observer &)=delete
Default copy assignment operator, deleted on purpose.
void disconnect()
Disconnects an observer from the registry it keeps track of.
Definition: observer.hpp:324
std::size_t size_type
Unsigned integer type.
Definition: observer.hpp:271
void each(Func func) const
Iterates entities and applies the given function object to them.
Definition: observer.hpp:408
iterator begin() const
Returns an iterator to the first entity of the observer.
Definition: observer.hpp:371
typename basic_sparse_set< Entity >::iterator iterator
Random access iterator type.
Definition: observer.hpp:273
void each(Func func)
Iterates entities and applies the given function object to them, then clears the observer.
Definition: observer.hpp:424
bool empty() const
Checks whether an observer is empty.
Definition: observer.hpp:343
iterator end() const
Returns an iterator that is past the last entity of the observer.
Definition: observer.hpp:385
void connect(basic_registry< entity_type > &reg, basic_collector< Matcher... >)
Connects an observer to a given registry.
Definition: observer.hpp:317
basic_observer & operator=(basic_observer &&)=delete
Default move assignment operator, deleted on purpose.
const entity_type * data() const
Direct access to the list of entities of the observer.
Definition: observer.hpp:359
basic_observer(const basic_observer &)=delete
Default copy constructor, deleted on purpose.
size_type size() const
Returns the number of elements in an observer.
Definition: observer.hpp:335
basic_observer(basic_registry< entity_type > &reg, basic_collector< Matcher... >)
Creates an observer and connects it to a given registry.
Definition: observer.hpp:291
basic_observer(basic_observer &&)=delete
Default move constructor, deleted on purpose.
void clear()
Clears the underlying container.
Definition: observer.hpp:390
basic_observer()
Default constructor.
Definition: observer.hpp:276
Entity entity_type
Underlying entity identifier.
Definition: observer.hpp:269
~basic_observer()=default
Default destructor.
Fast and reliable entity-component system.
Definition: registry.hpp:221
void erase(const entity_type entt)
Erases an entity from a sparse set.
Definition: sparse_set.hpp:710
bool empty() const
Checks whether a sparse set is empty.
Definition: sparse_set.hpp:473
void clear()
Clears a sparse set.
Definition: sparse_set.hpp:922
basic_iterator iterator
Random access iterator type.
Definition: sparse_set.hpp:298
size_type size() const
Returns the number of elements in a sparse set.
Definition: sparse_set.hpp:465
bool contains(const entity_type entt) const
Checks if a sparse set contains an entity.
Definition: sparse_set.hpp:576
pointer data() const
Direct access to the internal packed array.
Definition: sparse_set.hpp:481
Basic storage implementation.
Definition: storage.hpp:234
value_type & emplace(const entity_type entt, Args &&...args)
Assigns an entity to a storage and constructs its object.
Definition: storage.hpp:661
const value_type & get(const entity_type entt) const
Returns the object assigned to an entity.
Definition: storage.hpp:625
Basic delegate implementation.
Definition: delegate.hpp:67
EnTT default namespace.
Definition: dense_map.hpp:22
entity
Default entity identifier.
Definition: fwd.hpp:47
constexpr basic_collector collector
Variable template used to ease the definition of collectors.
Definition: observer.hpp:113
static constexpr auto where(exclude_t< NoneOf... >={})
Updates the filter of the last added matcher.
Definition: observer.hpp:106
static constexpr auto group(exclude_t< NoneOf... >={})
Adds a grouping matcher to the collector.
Definition: observer.hpp:85
static constexpr auto update()
Adds an observing matcher to the collector.
Definition: observer.hpp:95
static constexpr auto group(exclude_t< NoneOf... >={})
Adds a grouping matcher to the collector.
Definition: observer.hpp:50
static constexpr auto update()
Adds an observing matcher to the collector.
Definition: observer.hpp:60
Alias for exclusion lists.
Definition: utility.hpp:13
Grouping matcher.
Definition: observer.hpp:22
A class to use to push around lists of types, nothing more.