1 #ifndef ENTT_ENTITY_OBSERVER_HPP
2 #define ENTT_ENTITY_OBSERVER_HPP
10 #include <type_traits>
11 #include "../config/config.h"
12 #include "../core/type_traits.hpp"
13 #include "registry.hpp"
14 #include "storage.hpp"
53 template<
typename... AllOf,
typename... NoneOf>
63 template<
typename AnyOf>
64 static constexpr
auto replace() ENTT_NOEXCEPT {
77 template<
typename... Reject,
typename... Require,
typename... Rule,
typename... Other>
88 template<
typename... AllOf,
typename... NoneOf>
98 template<
typename AnyOf>
99 static constexpr
auto replace() ENTT_NOEXCEPT {
109 template<
typename... AllOf,
typename... NoneOf>
170 template<
typename Entity>
171 class basic_observer {
172 using payload_type = std::uint32_t;
175 struct matcher_handler;
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 Entity
entt,
const basic_registry<Entity> ®) {
181 if(reg.template has<Require...>(
entt) && !(reg.template has<Reject>(
entt) || ...)) {
182 auto *comp = obs.view.try_get(
entt);
183 (comp ? *comp : obs.view.construct(
entt)) |= (1 << Index);
187 template<std::
size_t Index>
189 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
190 obs.view.destroy(
entt);
194 template<std::
size_t Index>
195 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
196 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
197 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
198 reg.template on_replace<AnyOf>().template connect<&maybe_valid_if<Index>>(obs);
199 reg.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(obs);
203 (reg.template on_destroy<Require>().disconnect(obs), ...);
204 (reg.template on_construct<Reject>().disconnect(obs), ...);
205 reg.template on_replace<AnyOf>().disconnect(obs);
206 reg.template on_destroy<AnyOf>().disconnect(obs);
210 template<
typename... Reject,
typename... Require,
typename... NoneOf,
typename... AllOf>
211 struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> {
212 template<std::
size_t Index>
213 static void maybe_valid_if(
basic_observer &obs,
const Entity
entt,
const basic_registry<Entity> ®) {
214 if(reg.template has<AllOf..., Require...>(
entt) && !(reg.template has<NoneOf>(
entt) || ...) && !(reg.template has<Reject>(
entt) || ...)) {
215 auto *comp = obs.view.try_get(
entt);
216 (comp ? *comp : obs.view.construct(
entt)) |= (1 << Index);
220 template<std::
size_t Index>
222 if(
auto *value = obs.view.try_get(
entt); value && !(*value &= (~(1 << Index)))) {
223 obs.view.destroy(
entt);
227 template<std::
size_t Index>
228 static void connect(
basic_observer &obs, basic_registry<Entity> ®) {
229 (reg.template on_destroy<Require>().template connect<&discard_if<Index>>(obs), ...);
230 (reg.template on_construct<Reject>().template connect<&discard_if<Index>>(obs), ...);
231 (reg.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
232 (reg.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index>>(obs), ...);
233 (reg.template on_destroy<AllOf>().template connect<&discard_if<Index>>(obs), ...);
234 (reg.template on_construct<NoneOf>().template connect<&discard_if<Index>>(obs), ...);
238 (reg.template on_destroy<Require>().disconnect(obs), ...);
239 (reg.template on_construct<Reject>().disconnect(obs), ...);
240 (reg.template on_construct<AllOf>().disconnect(obs), ...);
241 (reg.template on_destroy<NoneOf>().disconnect(obs), ...);
242 (reg.template on_destroy<AllOf>().disconnect(obs), ...);
243 (reg.template on_construct<NoneOf>().disconnect(obs), ...);
247 template<
typename... Matcher>
249 (matcher_handler<Matcher>::disconnect(obs, reg), ...);
252 template<
typename... Matcher, std::size_t... Index>
253 void connect(basic_registry<Entity> ®, std::index_sequence<Index...>) {
254 static_assert(
sizeof...(Matcher) < std::numeric_limits<payload_type>::digits);
255 (matcher_handler<Matcher>::template connect<Index>(*
this, reg), ...);
269 : target{}, release{}, view{}
282 template<
typename... Matcher>
288 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
311 template<
typename... Matcher>
314 connect<Matcher...>(reg, std::index_sequence_for<Matcher...>{});
322 release(*
this, *target);
368 return view.sparse_set<entity_type>::begin();
382 return view.sparse_set<entity_type>::end();
404 template<
typename Func>
406 static_assert(std::is_invocable_v<Func, entity_type>);
407 std::for_each(
begin(),
end(), std::move(func));
424 template<
typename Func>
426 std::as_const(*this).each(std::move(func));
440 #endif // ENTT_ENTITY_OBSERVER_HPP