EnTT  3.7.0
observer.hpp
1 #ifndef ENTT_ENTITY_OBSERVER_HPP
2 #define ENTT_ENTITY_OBSERVER_HPP
3 
4 
5 #include <limits>
6 #include <cstddef>
7 #include <cstdint>
8 #include <utility>
9 #include <type_traits>
10 #include "../config/config.h"
11 #include "../core/type_traits.hpp"
12 #include "../signal/delegate.hpp"
13 #include "registry.hpp"
14 #include "storage.hpp"
15 #include "utility.hpp"
16 #include "entity.hpp"
17 #include "fwd.hpp"
18 
19 
20 namespace entt {
21 
22 
24 template<typename...>
25 struct matcher {};
26 
27 
34 template<typename...>
36 
37 
46 template<>
54  template<typename... AllOf, typename... NoneOf>
55  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
56  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{};
57  }
58 
64  template<typename AnyOf>
65  static constexpr auto update() ENTT_NOEXCEPT {
67  }
68 };
69 
78 template<typename... Reject, typename... Require, typename... Rule, typename... Other>
79 struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> {
81  using current_type = matcher<type_list<Reject...>, type_list<Require...>, Rule...>;
82 
89  template<typename... AllOf, typename... NoneOf>
90  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
91  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
92  }
93 
99  template<typename AnyOf>
100  static constexpr auto update() ENTT_NOEXCEPT {
101  return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{};
102  }
103 
110  template<typename... AllOf, typename... NoneOf>
111  static constexpr auto where(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
112  using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
113  return basic_collector<extended_type, Other...>{};
114  }
115 };
116 
117 
119 inline constexpr basic_collector<> collector{};
120 
121 
171 template<typename Entity>
173  using payload_type = std::uint32_t;
174 
175  template<typename>
176  struct matcher_handler;
177 
178  template<typename... Reject, typename... Require, typename AnyOf>
179  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
180  template<std::size_t Index>
181  static void maybe_valid_if(basic_observer &obs, basic_registry<Entity> &reg, const Entity entt) {
182  if(reg.template all_of<Require...>(entt) && !reg.template any_of<Reject...>(entt)) {
183  if(!obs.storage.contains(entt)) {
184  obs.storage.emplace(entt);
185  }
186 
187  obs.storage.get(entt) |= (1 << Index);
188  }
189  }
190 
191  template<std::size_t Index>
192  static void discard_if(basic_observer &obs, basic_registry<Entity> &, const Entity entt) {
193  if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) {
194  obs.storage.remove(entt);
195  }
196  }
197 
198  template<std::size_t Index>
199  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
200  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
201  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
202  reg.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
203  reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
204  }
205 
206  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
207  (reg.template on_destroy<Require>().disconnect(obs), ...);
208  (reg.template on_construct<Reject>().disconnect(obs), ...);
209  reg.template on_update<AnyOf>().disconnect(obs);
210  reg.template on_destroy<AnyOf>().disconnect(obs);
211  }
212  };
213 
214  template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
215  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
216  template<std::size_t Index, typename... Ignore>
217  static void maybe_valid_if(basic_observer &obs, basic_registry<Entity> &reg, const Entity entt) {
218  if([&reg, entt]() {
219  if constexpr(sizeof...(Ignore) == 0) {
220  return reg.template all_of<AllOf..., Require...>(entt) && !reg.template any_of<NoneOf..., Reject...>(entt);
221  } else {
222  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);
223  }
224  }())
225  {
226  if(!obs.storage.contains(entt)) {
227  obs.storage.emplace(entt);
228  }
229 
230  obs.storage.get(entt) |= (1 << Index);
231  }
232  }
233 
234  template<std::size_t Index>
235  static void discard_if(basic_observer &obs, basic_registry<Entity> &, const Entity entt) {
236  if(obs.storage.contains(entt) && !(obs.storage.get(entt) &= (~(1 << Index)))) {
237  obs.storage.remove(entt);
238  }
239  }
240 
241  template<std::size_t Index>
242  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
243  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
244  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
245  (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
246  (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(obs), ...);
247  (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
248  (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
249  }
250 
251  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
252  (reg.template on_destroy<Require>().disconnect(obs), ...);
253  (reg.template on_construct<Reject>().disconnect(obs), ...);
254  (reg.template on_construct<AllOf>().disconnect(obs), ...);
255  (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
256  (reg.template on_destroy<AllOf>().disconnect(obs), ...);
257  (reg.template on_construct<NoneOf>().disconnect(obs), ...);
258  }
259  };
260 
261  template<typename... Matcher>
262  static void disconnect(basic_registry<Entity> &reg, basic_observer &obs) {
263  (matcher_handler<Matcher>::disconnect(obs, reg), ...);
264  }
265 
266  template<typename... Matcher, std::size_t... Index>
267  void connect(basic_registry<Entity> &reg, std::index_sequence<Index...>) {
268  static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits, "Too many matchers");
269  (matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
270  release.template connect<&basic_observer::disconnect<Matcher...>>(reg);
271  }
272 
273 public:
275  using entity_type = Entity;
277  using size_type = std::size_t;
280 
283  : release{},
284  storage{}
285  {}
286 
288  basic_observer(const basic_observer &) = delete;
291 
297  template<typename... Matcher>
299  : basic_observer{}
300  {
301  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
302  }
303 
305  ~basic_observer() = default;
306 
312 
318 
324  template<typename... Matcher>
326  disconnect();
327  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
328  storage.clear();
329  }
330 
332  void disconnect() {
333  if(release) {
334  release(*this);
335  release.reset();
336  }
337  }
338 
343  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
344  return storage.size();
345  }
346 
351  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
352  return storage.empty();
353  }
354 
367  [[nodiscard]] const entity_type * data() const ENTT_NOEXCEPT {
368  return storage.data();
369  }
370 
379  [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
380  return storage.basic_sparse_set<entity_type>::begin();
381  }
382 
393  [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
394  return storage.basic_sparse_set<entity_type>::end();
395  }
396 
398  void clear() ENTT_NOEXCEPT {
399  storage.clear();
400  }
401 
415  template<typename Func>
416  void each(Func func) const {
417  for(const auto entity: *this) {
418  func(entity);
419  }
420  }
421 
431  template<typename Func>
432  void each(Func func) {
433  std::as_const(*this).each(std::move(func));
434  clear();
435  }
436 
437 private:
438  delegate<void(basic_observer &)> release;
440 };
441 
442 
443 }
444 
445 
446 #endif
entt::basic_observer
Observer.
Definition: observer.hpp:172
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::where
static constexpr auto where(exclude_t< NoneOf... >={}) noexcept
Updates the filter of the last added matcher.
Definition: observer.hpp:111
entt::type_list
A class to use to push around lists of types, nothing more.
Definition: type_traits.hpp:127
entt::basic_collector<>
Collector.
Definition: observer.hpp:47
entt::basic_observer::begin
iterator begin() const noexcept
Returns an iterator to the first entity of the observer.
Definition: observer.hpp:379
entt::basic_observer::end
iterator end() const noexcept
Returns an iterator that is past the last entity of the observer.
Definition: observer.hpp:393
entt::matcher
Grouping matcher.
Definition: observer.hpp:25
entt::basic_observer::each
void each(Func func)
Iterates entities and applies the given function object to them, then clears the observer.
Definition: observer.hpp:432
entt::basic_observer::empty
bool empty() const noexcept
Checks whether an observer is empty.
Definition: observer.hpp:351
entt::exclude_t
Alias for exclusion lists.
Definition: utility.hpp:16
entt::basic_observer::entity_type
Entity entity_type
Underlying entity identifier.
Definition: observer.hpp:275
entt::basic_storage
Basic storage implementation.
Definition: storage.hpp:52
entt::basic_collector<>::update
static constexpr auto update() noexcept
Adds an observing matcher to the collector.
Definition: observer.hpp:65
entt::basic_observer::clear
void clear() noexcept
Clears the underlying container.
Definition: observer.hpp:398
entt::basic_observer::each
void each(Func func) const
Iterates entities and applies the given function object to them.
Definition: observer.hpp:416
entt::basic_observer::basic_observer
basic_observer(basic_registry< entity_type > &reg, basic_collector< Matcher... >)
Creates an observer and connects it to a given registry.
Definition: observer.hpp:298
entt::basic_observer::iterator
typename basic_sparse_set< Entity >::iterator iterator
Random access iterator type.
Definition: observer.hpp:279
entt::basic_observer::basic_observer
basic_observer(basic_observer &&)=delete
Default move constructor, deleted on purpose.
entt::basic_storage::emplace
value_type & emplace(const entity_type entt, Args &&... args)
Assigns an entity to a storage and constructs its object.
Definition: storage.hpp:368
entt::basic_sparse_set::iterator
sparse_set_iterator iterator
Random access iterator type.
Definition: sparse_set.hpp:188
entt
EnTT default namespace.
Definition: algorithm.hpp:13
entt::basic_storage::get
const value_type & get(const entity_type entt) const
Returns the object assigned to an entity.
Definition: storage.hpp:342
entt::basic_collector<>::group
static constexpr auto group(exclude_t< NoneOf... >={}) noexcept
Adds a grouping matcher to the collector.
Definition: observer.hpp:55
entt::basic_observer::basic_observer
basic_observer(const basic_observer &)=delete
Default copy constructor, deleted on purpose.
entt::basic_observer::data
const entity_type * data() const noexcept
Direct access to the list of entities of the observer.
Definition: observer.hpp:367
entt::basic_observer::operator=
basic_observer & operator=(basic_observer &&)=delete
Default move assignment operator, deleted on purpose.
entt::basic_collector
Collector.
Definition: observer.hpp:35
entt::basic_observer::~basic_observer
~basic_observer()=default
Default destructor.
entt::collector
constexpr basic_collector collector
Variable template used to ease the definition of collectors.
Definition: observer.hpp:119
entt::basic_observer::size_type
std::size_t size_type
Unsigned integer type.
Definition: observer.hpp:277
entt::basic_registry
Fast and reliable entity-component system.
Definition: registry.hpp:44
entt::basic_observer::connect
void connect(basic_registry< entity_type > &reg, basic_collector< Matcher... >)
Connects an observer to a given registry.
Definition: observer.hpp:325
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::group
static constexpr auto group(exclude_t< NoneOf... >={}) noexcept
Adds a grouping matcher to the collector.
Definition: observer.hpp:90
entt::basic_observer::size
size_type size() const noexcept
Returns the number of elements in an observer.
Definition: observer.hpp:343
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::update
static constexpr auto update() noexcept
Adds an observing matcher to the collector.
Definition: observer.hpp:100
entt::basic_observer::operator=
basic_observer & operator=(const basic_observer &)=delete
Default copy assignment operator, deleted on purpose.
entt::delegate
Basic delegate implementation.
Definition: delegate.hpp:82
entt::entity
entity
Default entity identifier.
Definition: fwd.hpp:60
entt::basic_observer::basic_observer
basic_observer()
Default constructor.
Definition: observer.hpp:282
entt::basic_observer::disconnect
void disconnect()
Disconnects an observer from the registry it keeps track of.
Definition: observer.hpp:332