EnTT  3.5.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 "utility.hpp"
15 #include "entity.hpp"
16 #include "fwd.hpp"
17 
18 
19 namespace entt {
20 
21 
23 template<typename...>
24 struct matcher {};
25 
26 
33 template<typename...>
35 
36 
45 template<>
53  template<typename... AllOf, typename... NoneOf>
54  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
55  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{};
56  }
57 
63  template<typename AnyOf>
64  static constexpr auto update() ENTT_NOEXCEPT {
66  }
67 };
68 
77 template<typename... Reject, typename... Require, typename... Rule, typename... Other>
78 struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> {
80  using current_type = matcher<type_list<Reject...>, type_list<Require...>, Rule...>;
81 
88  template<typename... AllOf, typename... NoneOf>
89  static constexpr auto group(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
90  return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{};
91  }
92 
98  template<typename AnyOf>
99  static constexpr auto update() ENTT_NOEXCEPT {
100  return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{};
101  }
102 
109  template<typename... AllOf, typename... NoneOf>
110  static constexpr auto where(exclude_t<NoneOf...> = {}) ENTT_NOEXCEPT {
111  using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>;
112  return basic_collector<extended_type, Other...>{};
113  }
114 };
115 
116 
118 inline constexpr basic_collector<> collector{};
119 
120 
170 template<typename Entity>
172  using payload_type = std::uint32_t;
173 
174  template<typename>
175  struct matcher_handler;
176 
177  template<typename... Reject, typename... Require, typename AnyOf>
178  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> {
179  template<std::size_t Index>
180  static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
181  if(reg.template has<Require...>(entt) && !reg.template any<Reject...>(entt)) {
182  if(auto *comp = obs.view.try_get(entt); !comp) {
183  obs.view.emplace(entt);
184  }
185 
186  obs.view.get(entt) |= (1 << Index);
187  }
188  }
189 
190  template<std::size_t Index>
191  static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
192  if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
193  obs.view.erase(entt);
194  }
195  }
196 
197  template<std::size_t Index>
198  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
199  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
200  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
201  reg.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
202  reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
203  }
204 
205  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
206  (reg.template on_destroy<Require>().disconnect(obs), ...);
207  (reg.template on_construct<Reject>().disconnect(obs), ...);
208  reg.template on_update<AnyOf>().disconnect(obs);
209  reg.template on_destroy<AnyOf>().disconnect(obs);
210  }
211  };
212 
213  template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf>
214  struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
215  template<std::size_t Index, typename... Ignore>
216  static void maybe_valid_if(basic_observer &obs, const basic_registry<Entity> &reg, const Entity entt) {
217  if([&reg, entt]() {
218  if constexpr(sizeof...(Ignore) == 0) {
219  return reg.template has<AllOf..., Require...>(entt) && !reg.template any<NoneOf..., Reject...>(entt);
220  } else {
221  return reg.template has<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !reg.template any<NoneOf>(entt)) && ...) && !reg.template any<Reject...>(entt);
222  }
223  }())
224  {
225  if(auto *comp = obs.view.try_get(entt); !comp) {
226  obs.view.emplace(entt);
227  }
228 
229  obs.view.get(entt) |= (1 << Index);
230  }
231  }
232 
233  template<std::size_t Index>
234  static void discard_if(basic_observer &obs, const basic_registry<Entity> &, const Entity entt) {
235  if(auto *value = obs.view.try_get(entt); value && !(*value &= (~(1 << Index)))) {
236  obs.view.erase(entt);
237  }
238  }
239 
240  template<std::size_t Index>
241  static void connect(basic_observer &obs, basic_registry<Entity> &reg) {
242  (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
243  (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
244  (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
245  (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(obs), ...);
246  (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
247  (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
248  }
249 
250  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
251  (reg.template on_destroy<Require>().disconnect(obs), ...);
252  (reg.template on_construct<Reject>().disconnect(obs), ...);
253  (reg.template on_construct<AllOf>().disconnect(obs), ...);
254  (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
255  (reg.template on_destroy<AllOf>().disconnect(obs), ...);
256  (reg.template on_construct<NoneOf>().disconnect(obs), ...);
257  }
258  };
259 
260  template<typename... Matcher>
261  static void disconnect(basic_observer &obs, basic_registry<Entity> &reg) {
262  (matcher_handler<Matcher>::disconnect(obs, reg), ...);
263  }
264 
265  template<typename... Matcher, std::size_t... Index>
266  void connect(basic_registry<Entity> &reg, std::index_sequence<Index...>) {
267  static_assert(sizeof...(Matcher) < std::numeric_limits<payload_type>::digits, "Too many matchers");
268  (matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
269  release = &basic_observer::disconnect<Matcher...>;
270  }
271 
272 public:
274  using entity_type = Entity;
276  using size_type = std::size_t;
279 
282  : target{}, release{}, view{}
283  {}
284 
286  basic_observer(const basic_observer &) = delete;
289 
295  template<typename... Matcher>
297  : target{&reg},
298  release{},
299  view{}
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  target = &reg;
329  view.clear();
330  }
331 
333  void disconnect() {
334  if(release) {
335  release(*this, *target);
336  release = nullptr;
337  }
338  }
339 
344  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
345  return view.size();
346  }
347 
352  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
353  return view.empty();
354  }
355 
368  [[nodiscard]] const entity_type * data() const ENTT_NOEXCEPT {
369  return view.data();
370  }
371 
380  [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
381  return view.sparse_set<entity_type>::begin();
382  }
383 
394  [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
395  return view.sparse_set<entity_type>::end();
396  }
397 
399  void clear() ENTT_NOEXCEPT {
400  view.clear();
401  }
402 
416  template<typename Func>
417  void each(Func func) const {
418  for(const auto entity: *this) {
419  func(entity);
420  }
421  }
422 
432  template<typename Func>
433  void each(Func func) {
434  std::as_const(*this).each(std::move(func));
435  clear();
436  }
437 
438 private:
440  void(* release)(basic_observer &, basic_registry<entity_type> &);
442 };
443 
444 
445 }
446 
447 
448 #endif
entt::basic_observer
Observer.
Definition: observer.hpp:171
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:110
entt::type_list
A class to use to push around lists of types, nothing more.
Definition: type_traits.hpp:77
entt::basic_collector<>
Collector.
Definition: observer.hpp:46
entt::basic_observer::begin
iterator begin() const noexcept
Returns an iterator to the first entity of the observer.
Definition: observer.hpp:380
entt::basic_observer::end
iterator end() const noexcept
Returns an iterator that is past the last entity of the observer.
Definition: observer.hpp:394
entt::matcher
Grouping matcher.
Definition: observer.hpp:24
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:433
entt::storage::get
const object_type & get(const entity_type entt) const
Returns the object associated with an entity.
Definition: storage.hpp:322
entt::basic_observer::empty
bool empty() const noexcept
Checks whether an observer is empty.
Definition: observer.hpp:352
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:274
entt::storage::try_get
const object_type * try_get(const entity_type entt) const
Returns a pointer to the object associated with an entity, if any.
Definition: storage.hpp:336
entt::basic_collector<>::update
static constexpr auto update() noexcept
Adds an observing matcher to the collector.
Definition: observer.hpp:64
entt::sparse_set::iterator
sparse_set_iterator iterator
Random access iterator type.
Definition: sparse_set.hpp:182
entt::basic_observer::clear
void clear() noexcept
Clears the underlying container.
Definition: observer.hpp:399
entt::basic_observer::each
void each(Func func) const
Iterates entities and applies the given function object to them.
Definition: observer.hpp:417
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:296
entt::basic_observer::basic_observer
basic_observer(basic_observer &&)=delete
Default move constructor, deleted on purpose.
entt::basic_observer::iterator
typename sparse_set< Entity >::iterator iterator
Random access iterator type.
Definition: observer.hpp:278
entt
EnTT default namespace.
Definition: algorithm.hpp:13
entt::basic_collector<>::group
static constexpr auto group(exclude_t< NoneOf... >={}) noexcept
Adds a grouping matcher to the collector.
Definition: observer.hpp:54
entt::storage::erase
void erase(const entity_type entt)
Removes an entity from a storage and destroys its object.
Definition: storage.hpp:427
entt::basic_observer::basic_observer
basic_observer(const basic_observer &)=delete
Default copy constructor, deleted on purpose.
entt::storage< entity_type, payload_type >
entt::basic_observer::data
const entity_type * data() const noexcept
Direct access to the list of entities of the observer.
Definition: observer.hpp:368
entt::basic_observer::operator=
basic_observer & operator=(basic_observer &&)=delete
Default move assignment operator, deleted on purpose.
entt::basic_collector
Collector.
Definition: observer.hpp:34
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:118
entt::basic_observer::size_type
std::size_t size_type
Unsigned integer type.
Definition: observer.hpp:276
entt::basic_registry
Fast and reliable entity-component system.
Definition: registry.hpp:43
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:89
entt::basic_observer::size
size_type size() const noexcept
Returns the number of elements in an observer.
Definition: observer.hpp:344
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:99
entt::storage::emplace
void emplace(const entity_type entt, Args &&... args)
Assigns an entity to a storage and constructs its object.
Definition: storage.hpp:363
entt::basic_view
View.
Definition: fwd.hpp:16
entt::basic_observer::operator=
basic_observer & operator=(const basic_observer &)=delete
Default copy assignment operator, deleted on purpose.
entt::entity
entity
Default entity identifier.
Definition: fwd.hpp:52
entt::basic_observer::basic_observer
basic_observer()
Default constructor.
Definition: observer.hpp:281
entt::basic_observer::disconnect
void disconnect()
Disconnects an observer from the registry it keeps track of.
Definition: observer.hpp:333