EnTT  3.3.2
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 "registry.hpp"
13 #include "storage.hpp"
14 #include "entity.hpp"
15 #include "fwd.hpp"
16 
17 
18 namespace entt {
19 
20 
22 template<typename...>
23 struct matcher {};
24 
25 
32 template<typename...>
34 
35 
44 template<>
52  template<typename... AllOf, typename... NoneOf>
53  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
54  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{};
55  }
56 
62  template<typename AnyOf>
63  static constexpr auto replace() ENTT_NOEXCEPT {
65  }
66 };
67 
76 template<typename... Reject, typename... Require, typename... Rule, typename... Other>
77 struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> {
79  using current_type = matcher<type_list<Reject...>, type_list<Require...>, Rule...>;
80 
87  template<typename... AllOf, typename... NoneOf>
88  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
89  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
90  }
91 
97  template<typename AnyOf>
98  static constexpr auto replace() ENTT_NOEXCEPT {
99  return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{};
100  }
101 
108  template<typename... AllOf, typename... NoneOf>
109  static constexpr auto where(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
110  using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
111  return basic_collector<extended_type, Other...>{};
112  }
113 };
114 
115 
118 
119 
169 template<typename Entity>
170 class basic_observer {
171  using payload_type = std::uint32_t;
172 
173  template<typename>
174  struct matcher_handler;
175 
176  template<typename... Reject, typename... Require, typename AnyOf>
177  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
178  template<std::size_t Index>
179  static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
180  if(reg.template has<Require...>(entt) && !reg.template any<Reject...>(entt)) {
181  if(auto *comp = obs.view.try_get(entt); !comp) {
182  obs.view.construct(entt);
183  }
184 
185  obs.view.get(entt) |= (1 << Index);
186  }
187  }
188 
189  template<std::size_t Index>
190  static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
191  if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
192  obs.view.destroy(entt);
193  }
194  }
195 
196  template<std::size_t Index>
197  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
198  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
199  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
200  reg.template on_replace<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
201  reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
202  }
203 
204  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
205  (reg.template on_destroy<Require>().disconnect(obs), ...);
206  (reg.template on_construct<Reject>().disconnect(obs), ...);
207  reg.template on_replace<AnyOf>().disconnect(obs);
208  reg.template on_destroy<AnyOf>().disconnect(obs);
209  }
210  };
211 
212  template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
213  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
214  template<std::size_t Index>
215  static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
216  if(reg.template has<AllOf..., Require...>(entt) && !reg.template any<NoneOf..., Reject...>(entt)) {
217  if(auto *comp = obs.view.try_get(entt); !comp) {
218  obs.view.construct(entt);
219  }
220 
221  obs.view.get(entt) |= (1 << Index);
222  }
223  }
224 
225  template<std::size_t Index>
226  static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
227  if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
228  obs.view.destroy(entt);
229  }
230  }
231 
232  template<std::size_t Index>
233  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
234  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
235  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
236  (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
237  (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
238  (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
239  (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
240  }
241 
242  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
243  (reg.template on_destroy<Require>().disconnect(obs), ...);
244  (reg.template on_construct<Reject>().disconnect(obs), ...);
245  (reg.template on_construct<AllOf>().disconnect(obs), ...);
246  (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
247  (reg.template on_destroy<AllOf>().disconnect(obs), ...);
248  (reg.template on_construct<NoneOf>().disconnect(obs), ...);
249  }
250  };
251 
252  template<typename... Matcher>
253  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
254  (matcher_handler<Matcher>::disconnect(obs, reg), ...);
255  }
256 
257  template<typename... Matcher, std::size_t... Index>
258  void connect(basic_registry<Entity> &reg, std::index_sequence<Index...>) {
259  static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits);
260  (matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
261  release = &basic_observer::disconnect<Matcher...>;
262  }
263 
264 public:
266  using entity_type = Entity;
268  using size_type = std::size_t;
271 
274  : target{}, release{}, view{}
275  {}
276 
278  basic_observer(const basic_observer &) = delete;
280  basic_observer(basic_observer &&) = delete;
281 
287  template<typename... Matcher>
289  : target{&reg},
290  release{},
291  view{}
292  {
293  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
294  }
295 
297  ~basic_observer() = default;
298 
303  basic_observer & operator=(const basic_observer &) = delete;
304 
309  basic_observer & operator=(basic_observer &&) = delete;
310 
316  template<typename... Matcher>
318  disconnect();
319  connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
320  target = &reg;
321  view.clear();
322  }
323 
325  void disconnect() {
326  if(release) {
327  release(*this, *target);
328  release = nullptr;
329  }
330  }
331 
336  size_type size() const ENTT_NOEXCEPT {
337  return view.size();
338  }
339 
344  bool empty() const ENTT_NOEXCEPT {
345  return view.empty();
346  }
347 
360  const entity_type * data() const ENTT_NOEXCEPT {
361  return view.data();
362  }
363 
372  iterator_type begin() const ENTT_NOEXCEPT {
373  return view.sparse_set<entity_type>::begin();
374  }
375 
386  iterator_type end() const ENTT_NOEXCEPT {
387  return view.sparse_set<entity_type>::end();
388  }
389 
391  void clear() ENTT_NOEXCEPT {
392  view.clear();
393  }
394 
408  template<typename Func>
409  void each(Func func) const {
410  static_assert(std::is_invocable_v<Func, entity_type>);
411 
412  for(const auto entity: *this) {
413  func(entity);
414  }
415  }
416 
426  template<typename Func>
427  void each(Func func) {
428  std::as_const(*this).each(std::move(func));
429  clear();
430  }
431 
432 private:
434  void(* release)(basic_observer &, basic_registry<entity_type> &);
436 };
437 
438 
439 }
440 
441 
442 #endif
entt::basic_observer
Observer.
Definition: fwd.hpp:62
entt::type_list
A class to use to push around lists of types, nothing more.
Definition: type_traits.hpp:43
entt::basic_collector<>
Collector.
Definition: observer.hpp:45
entt::basic_observer::end
iterator_type end() const ENTT_NOEXCEPT
Returns an iterator that is past the last entity of the observer.
Definition: observer.hpp:386
entt::matcher
Grouping matcher.
Definition: observer.hpp:23
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:427
entt::basic_observer::empty
bool empty() const ENTT_NOEXCEPT
Checks whether an observer is empty.
Definition: observer.hpp:344
entt::exclude_t
Alias for exclusion lists.
Definition: fwd.hpp:17
entt::basic_observer::entity_type
Entity entity_type
Underlying entity identifier.
Definition: observer.hpp:266
entt::basic_observer::begin
iterator_type begin() const ENTT_NOEXCEPT
Returns an iterator to the first entity of the observer.
Definition: observer.hpp:372
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::where
static constexpr auto where(exclude_t< NoneOf... >={}) ENTT_NOEXCEPT
Updates the filter of the last added matcher.
Definition: observer.hpp:109
entt::basic_observer::each
void each(Func func) const
Iterates entities and applies the given function object to them.
Definition: observer.hpp:409
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:288
entt
EnTT default namespace.
Definition: algorithm.hpp:13
entt::storage< entity_type, payload_type >
entt::basic_observer::data
const entity_type * data() const ENTT_NOEXCEPT
Direct access to the list of entities of the observer.
Definition: observer.hpp:360
entt::basic_collector
Collector.
Definition: observer.hpp:33
entt::basic_observer::clear
void clear() ENTT_NOEXCEPT
Clears the underlying container.
Definition: observer.hpp:391
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:117
entt::basic_observer::size_type
std::size_t size_type
Unsigned integer type.
Definition: observer.hpp:268
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::group
static constexpr auto group(exclude_t< NoneOf... >={}) ENTT_NOEXCEPT
Adds a grouping matcher to the collector.
Definition: observer.hpp:88
entt::basic_registry< entity_type >
entt::basic_collector<>::group
static constexpr auto group(exclude_t< NoneOf... >={}) ENTT_NOEXCEPT
Adds a grouping matcher to the collector.
Definition: observer.hpp:53
entt::basic_observer::connect
void connect(basic_registry< entity_type > &reg, basic_collector< Matcher... >)
Connects an observer to a given registry.
Definition: observer.hpp:317
entt::basic_collector<>::replace
static constexpr auto replace() ENTT_NOEXCEPT
Adds an observing matcher to the collector.
Definition: observer.hpp:63
entt::basic_view
View.
Definition: fwd.hpp:50
entt::basic_collector< matcher< type_list< Reject... >, type_list< Require... >, Rule... >, Other... >::replace
static constexpr auto replace() ENTT_NOEXCEPT
Adds an observing matcher to the collector.
Definition: observer.hpp:98
entt::basic_observer::operator=
basic_observer & operator=(const basic_observer &)=delete
Default copy assignment operator, deleted on purpose.
entt::basic_observer::size
size_type size() const ENTT_NOEXCEPT
Returns the number of elements in an observer.
Definition: observer.hpp:336
entt::sparse_set::iterator_type
iterator iterator_type
Random access iterator type.
Definition: sparse_set.hpp:184
entt::basic_observer::basic_observer
basic_observer()
Default constructor.
Definition: observer.hpp:273
entt::basic_observer::disconnect
void disconnect()
Disconnects an observer from the registry it keeps track of.
Definition: observer.hpp:325
entt::basic_observer::iterator_type
typename sparse_set< Entity >::iterator_type iterator_type
Input iterator type.
Definition: observer.hpp:270