1#ifndef ENTT_ENTITY_OBSERVER_HPP
2#define ENTT_ENTITY_OBSERVER_HPP
9#include "../core/type_traits.hpp"
10#include "../signal/delegate.hpp"
45 template<
typename... AllOf,
typename... NoneOf>
55 template<
typename AnyOf>
56 static constexpr auto update() noexcept {
69template<
typename... Reject,
typename... Require,
typename... Rule,
typename... Other>
80 template<
typename... AllOf,
typename... NoneOf>
90 template<
typename AnyOf>
91 static constexpr auto update() noexcept {
101 template<
typename... AllOf,
typename... NoneOf>
161template<
typename Registry,
typename Mask,
typename Allocator>
166 struct matcher_handler;
168 template<
typename... Reject,
typename... Require,
typename AnyOf>
170 template<std::
size_t Index>
171 static void maybe_valid_if(
basic_observer &obs, Registry ®,
const typename Registry::entity_type
entt) {
172 if(reg.template all_of<Require...>(
entt) && !reg.template any_of<Reject...>(
entt)) {
173 if(!obs.contains(
entt)) {
177 obs.get(
entt) |= (1 << Index);
181 template<std::
size_t Index>
182 static void discard_if(
basic_observer &obs, Registry &,
const typename Registry::entity_type
entt) {
183 if(obs.contains(
entt) && !(obs.get(
entt) &= (~(1 << Index)))) {
188 template<std::
size_t Index>
190 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
191 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
192 reg.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
193 reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
197 (reg.template on_destroy<Require>().disconnect(&obs), ...);
198 (reg.template on_construct<Reject>().disconnect(&obs), ...);
199 reg.template on_update<AnyOf>().disconnect(&obs);
200 reg.template on_destroy<AnyOf>().disconnect(&obs);
204 template<
typename... Reject,
typename... Require,
typename... NoneOf,
typename... AllOf>
206 template<std::size_t Index,
typename... Ignore>
207 static void maybe_valid_if(
basic_observer &obs, Registry ®,
const typename Registry::entity_type
entt) {
208 auto condition = [®,
entt]() {
209 if constexpr(
sizeof...(Ignore) == 0) {
210 return reg.template all_of<AllOf..., Require...>(
entt) && !reg.template any_of<NoneOf..., Reject...>(
entt);
212 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);
217 if(!obs.contains(
entt)) {
221 obs.get(
entt) |= (1 << Index);
225 template<std::
size_t Index>
226 static void discard_if(
basic_observer &obs, Registry &,
const typename Registry::entity_type
entt) {
227 if(obs.contains(
entt) && !(obs.get(
entt) &= (~(1 << Index)))) {
232 template<std::
size_t Index>
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, NoneOf>>(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), ...);
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), ...);
252 template<
typename... Matcher>
254 (matcher_handler<Matcher>::disconnect(obs, reg), ...);
257 template<
typename... Matcher, std::size_t... Index>
258 void connect(Registry ®, std::index_sequence<Index...>) {
259 static_assert(
sizeof...(Matcher) < std::numeric_limits<typename base_type::value_type>::digits,
"Too many matchers");
260 (matcher_handler<Matcher>::template connect<Index>(*
this, reg), ...);
274 using iterator =
typename registry_type::common_type::iterator;
300 template<
typename... Matcher>
303 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
323 template<
typename... Matcher>
326 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
350 [[nodiscard]]
bool empty() const noexcept {
408 template<
typename Func>
410 for(
const auto entity: *
this) {
424 template<
typename Func>
426 std::as_const(*this).each(std::move(func));
void each(Func func)
Iterates entities and applies the given function object to them, then clears the observer.
basic_observer(const allocator_type &allocator)
Constructs an empty storage with a given allocator.
void disconnect()
Disconnects an observer from the registry it keeps track of.
const entity_type * data() const noexcept
Direct access to the list of entities of the observer.
iterator end() const noexcept
Returns an iterator that is past the last entity of the observer.
basic_observer & operator=(const basic_observer &)=delete
Default copy assignment operator, deleted on purpose.
iterator begin() const noexcept
Returns an iterator to the first entity of the observer.
basic_observer(basic_observer &&)=delete
Default move constructor, deleted on purpose.
typename registry_type::common_type::iterator iterator
Random access iterator type.
bool empty() const noexcept
Checks whether an observer is empty.
Allocator allocator_type
Allocator type.
basic_observer & operator=(basic_observer &&)=delete
Default move assignment operator, deleted on purpose.
basic_observer(registry_type ®, basic_collector< Matcher... >, const allocator_type &allocator=allocator_type{})
Creates an observer and connects it to a given registry.
void each(Func func) const
Iterates entities and applies the given function object to them.
basic_observer()
Default constructor.
size_type size() const noexcept
Returns the number of elements in an observer.
typename registry_type::entity_type entity_type
Underlying entity identifier.
void clear() noexcept
Clears the underlying container.
void connect(registry_type ®, basic_collector< Matcher... >)
Connects an observer to a given registry.
basic_observer(const basic_observer &)=delete
Default copy constructor, deleted on purpose.
std::size_t size_type
Unsigned integer type.
pointer data() const noexcept
Direct access to the internal packed array.
void clear()
Clears a sparse set.
size_type size() const noexcept
Returns the number of elements in a sparse set.
bool empty() const noexcept
Checks whether a sparse set is empty.
Basic storage implementation.
const_iterator end() const noexcept
Returns an iterator to the end.
const_iterator begin() const noexcept
Returns an iterator to the beginning.
Basic delegate implementation.
entity
Default entity identifier.
constexpr basic_collector collector
Variable template used to ease the definition of collectors.
static constexpr auto update() noexcept
Adds an observing matcher to the collector.
static constexpr auto group(exclude_t< NoneOf... >=exclude_t{}) noexcept
Adds a grouping matcher to the collector.
static constexpr auto where(exclude_t< NoneOf... >=exclude_t{}) noexcept
Updates the filter of the last added matcher.
static constexpr auto update() noexcept
Adds an observing matcher to the collector.
static constexpr auto group(exclude_t< NoneOf... >=exclude_t{}) noexcept
Adds a grouping matcher to the collector.
Alias for exclusion lists.
A class to use to push around lists of types, nothing more.