1#ifndef ENTT_ENTITY_OBSERVER_HPP
2#define ENTT_ENTITY_OBSERVER_HPP
9#include "../core/type_traits.hpp"
44 template<
typename... AllOf,
typename... NoneOf>
54 template<
typename AnyOf>
55 static constexpr auto update() noexcept {
68template<
typename... Reject,
typename... Require,
typename... Rule,
typename... Other>
79 template<
typename... AllOf,
typename... NoneOf>
89 template<
typename AnyOf>
90 static constexpr auto update() noexcept {
100 template<
typename... AllOf,
typename... NoneOf>
159template<
typename Registry,
typename Allocator>
161 using mask_type = std::uint64_t;
164 template<std::
size_t Index>
172 struct matcher_handler;
174 template<
typename... Reject,
typename... Require,
typename AnyOf>
176 template<std::
size_t Index>
177 static void maybe_valid_if(
storage_type &
storage, Registry &parent,
const typename Registry::entity_type
entt) {
178 if(parent.template all_of<Require...>(
entt) && !parent.template any_of<Reject...>(
entt)) {
187 template<std::
size_t Index>
189 (parent.template on_destroy<Require>().template connect<&discard_if<Index>>(
storage), ...);
190 (parent.template on_construct<Reject>().template connect<&discard_if<Index>>(
storage), ...);
191 parent.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(
storage);
192 parent.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(
storage);
196 (parent.template on_destroy<Require>().disconnect(&
storage), ...);
197 (parent.template on_construct<Reject>().disconnect(&
storage), ...);
198 parent.template on_update<AnyOf>().disconnect(&
storage);
199 parent.template on_destroy<AnyOf>().disconnect(&
storage);
203 template<
typename... Reject,
typename... Require,
typename... NoneOf,
typename... AllOf>
205 template<std::size_t Index,
typename... Ignore>
206 static void maybe_valid_if(
storage_type &
storage, Registry &parent,
const typename Registry::entity_type
entt) {
209 if constexpr(
sizeof...(Ignore) == 0) {
210 guard = parent.template all_of<AllOf..., Require...>(
entt) && !parent.template any_of<NoneOf..., Reject...>(
entt);
212 guard = parent.template all_of<AllOf..., Require...>(
entt) && ((std::is_same_v<Ignore..., NoneOf> || !parent.template any_of<NoneOf>(
entt)) && ...) && !parent.template any_of<Reject...>(
entt);
224 template<std::
size_t Index>
226 (parent.template on_destroy<Require>().template connect<&discard_if<Index>>(
storage), ...);
227 (parent.template on_construct<Reject>().template connect<&discard_if<Index>>(
storage), ...);
228 (parent.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(
storage), ...);
229 (parent.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(
storage), ...);
230 (parent.template on_destroy<AllOf>().template connect<&discard_if<Index>>(
storage), ...);
231 (parent.template on_construct<NoneOf>().template connect<&discard_if<Index>>(
storage), ...);
235 (parent.template on_destroy<Require>().disconnect(&
storage), ...);
236 (parent.template on_construct<Reject>().disconnect(&
storage), ...);
237 (parent.template on_construct<AllOf>().disconnect(&
storage), ...);
238 (parent.template on_destroy<NoneOf>().disconnect(&
storage), ...);
239 (parent.template on_destroy<AllOf>().disconnect(&
storage), ...);
240 (parent.template on_construct<NoneOf>().disconnect(&
storage), ...);
244 template<
typename... Matcher>
246 (matcher_handler<Matcher>::disconnect(
storage, parent), ...);
249 template<
typename... Matcher, std::size_t... Index>
250 static void connect(Registry &parent,
storage_type &
storage, std::index_sequence<Index...>) {
251 static_assert(
sizeof...(Matcher) < std::numeric_limits<mask_type>::digits,
"Too many matchers");
252 (matcher_handler<Matcher>::template connect<Index>(
storage, parent), ...);
265 using iterator =
typename registry_type::common_type::iterator;
292 template<
typename... Matcher>
297 connect<Matcher...>(reg,
storage, std::index_sequence_for<Matcher...>{});
320 template<
typename... Matcher>
327 connect<Matcher...>(reg,
storage, std::index_sequence_for<Matcher...>{});
350 [[nodiscard]]
bool empty() const noexcept {
378 return storage.storage_type::base_type::begin();
387 return storage.storage_type::base_type::end();
408 template<
typename Func>
410 for(
const auto entity: *
this) {
424 template<
typename Func>
426 std::as_const(*this).each(std::move(func));
bool empty() const noexcept
Checks whether an observer is empty.
typename registry_type::common_type::iterator iterator
Random access iterator type.
basic_observer()
Default constructor.
void clear() noexcept
Clears the underlying container.
iterator begin() const noexcept
Returns an iterator to the first entity of the observer.
typename registry_type::entity_type entity_type
Underlying entity identifier.
void connect(registry_type ®, basic_collector< Matcher... >)
Connects an observer to a given registry.
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.
basic_observer & operator=(basic_observer &&)=delete
Default move assignment operator, deleted on purpose.
basic_observer(basic_observer &&)=delete
Default move constructor, deleted on purpose.
void each(Func func)
Iterates entities and applies the given function object to them, then clears the observer.
~basic_observer()=default
Default destructor.
void each(Func func) const
Iterates entities and applies the given function object to them.
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.
const entity_type * data() const noexcept
Direct access to the list of entities of the observer.
basic_observer(const basic_observer &)=delete
Default copy constructor, deleted on purpose.
std::size_t size_type
Unsigned integer type.
size_type size() const noexcept
Returns the number of elements in an observer.
basic_observer(registry_type ®, basic_collector< Matcher... >, const allocator_type &allocator=allocator_type{})
Creates an observer and connects it to a given registry.
Allocator allocator_type
Allocator type.
void erase(const entity_type entt)
Erases an entity from a sparse set.
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 contains(const entity_type entt) const noexcept
Checks if a sparse set contains an entity.
bool empty() const noexcept
Checks whether a sparse set is empty.
const value_type & get(const entity_type entt) const noexcept
Returns the object assigned to an entity.
value_type & emplace(const entity_type entt, Args &&...args)
Assigns an entity to a storage and constructs its object.
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.
Provides a common way to define storage types.
A class to use to push around lists of types, nothing more.