1#include "gaia/config/config.h"
5#include "gaia/ecs/chunk_iterator.h"
6#include "gaia/ecs/id.h"
7#include "gaia/ecs/query.h"
8#include "gaia/mt/jobhandle.h"
10#if GAIA_SYSTEMS_ENABLED
15 inline constexpr const char* sc_system_query_func_str =
"System_exec";
16 util::str_view entity_name(
const World& world, Entity entity);
27 Entity entity = EntityBad;
31 QueryExecType execType = QueryExecType::Default;
33 mt::JobHandle jobHandle = mt::JobNull;
44 if (jobHandle != (mt::JobHandle)mt::JobNull_t{}) {
59 void exec(World& world) {
60 [[maybe_unused]]
auto& queryInfo = query.fetch();
63 const auto name = entity_name(*queryInfo.world(), entity);
64 const char* pScopeName = !name.empty() ? name.data() : sc_system_query_func_str;
65 GAIA_PROF_SCOPE2(pScopeName);
68 auto* pRuntime = world.systems().data_try(entity);
69 GAIA_ASSERT(pRuntime !=
nullptr);
70 if (pRuntime ==
nullptr || !pRuntime->on_each_func)
73 static_cast<void>(pRuntime->on_each_func(query, execType, SystemRuntimeData::RunMode::Immediate));
83 GAIA_NODISCARD mt::JobHandle job_handle(World& world) {
84 if (jobHandle == (mt::JobHandle)mt::JobNull_t{}) {
87 syncJob.func = [
this, &world]() {
90 syncJob.flags = mt::JobCreationFlags::ManualDelete;
91 jobHandle = tp.add(GAIA_MOV(syncJob));
105 GAIA_NODISCARD SchedJob job(World& world) {
106 auto* pRuntime = world.systems().data_try(entity);
107 GAIA_ASSERT(pRuntime !=
nullptr);
108 if (pRuntime ==
nullptr || !pRuntime->on_each_func)
111 return pRuntime->on_each_func(query, execType, SystemRuntimeData::RunMode::DeferredJob);
117 template <
typename Serializer>
118 void save(Serializer& s)
const {
124 template <
typename Serializer>
125 void load(Serializer& s) {
137 class SystemBuilder {
144 void validate()
const {
145 GAIA_ASSERT(m_world.valid(m_entity));
151 auto ss = m_world.acc_mut(m_entity);
152 auto& sys = ss.smut<System_>();
158 const System_& data()
const {
159 auto ss = m_world.acc(m_entity);
160 const auto& sys = ss.get<System_>();
166 SystemRuntimeData& runtime_data() {
167 return m_world.systems().data(m_entity);
172 const SystemRuntimeData& runtime_data()
const {
173 return m_world.systems().data(m_entity);
180 SystemBuilder(World& world, Entity entity): m_world(world), m_entity(entity) {}
191 SystemBuilder& kind(QueryCacheKind kind) {
193 data().query.kind(kind);
201 SystemBuilder& scope(QueryCacheScope scope) {
203 data().query.scope(scope);
217 SystemBuilder& add(QueryInput item) {
219 data().query.add(item);
229 SystemBuilder& is(Entity entity,
const QueryTermOptions& options = {}) {
230 return all(Pair(Is, entity), options);
239 SystemBuilder& in(Entity entity, QueryTermOptions options = {}) {
241 return all(Pair(Is, entity), options);
250 SystemBuilder& all(Entity entity,
const QueryTermOptions& options = {}) {
252 data().query.all(entity, options);
260 SystemBuilder& any(Entity entity,
const QueryTermOptions& options = {}) {
262 data().query.any(entity, options);
270 SystemBuilder& or_(Entity entity,
const QueryTermOptions& options = {}) {
272 data().query.or_(entity, options);
280 SystemBuilder& no(Entity entity,
const QueryTermOptions& options = {}) {
282 data().query.no(entity, options);
288 SystemBuilder& match_prefab() {
290 data().query.match_prefab();
297 SystemBuilder& changed(Entity entity) {
299 data().query.changed(entity);
307 template <
typename T>
308 SystemBuilder& all(
const QueryTermOptions& options);
314 template <
typename T>
315 SystemBuilder& any(
const QueryTermOptions& options);
321 template <
typename T>
322 SystemBuilder& or_(
const QueryTermOptions& options);
328 template <
typename T>
329 SystemBuilder& no(
const QueryTermOptions& options);
336 template <
typename T>
337 SystemBuilder& all();
342 template <
typename T>
343 SystemBuilder& any();
348 template <
typename T>
349 SystemBuilder& or_();
354 template <
typename T>
360 template <
typename T>
361 SystemBuilder& changed();
373 SystemBuilder& depth_order(Entity relation = ChildOf) {
374 data().query.depth_order(relation);
381 template <
typename Rel>
382 SystemBuilder& depth_order();
391 SystemBuilder& group_by(Entity entity, TGroupByFunc func = group_by_func_default) {
392 data().query.group_by(entity, func);
400 template <
typename T>
401 SystemBuilder& group_by(TGroupByFunc func = group_by_func_default);
408 template <
typename Rel,
typename Tgt>
409 SystemBuilder& group_by(TGroupByFunc func = group_by_func_default);
417 SystemBuilder& group_dep(Entity relation) {
418 data().query.group_dep(relation);
426 template <
typename Rel>
427 SystemBuilder& group_dep();
434 SystemBuilder& group_id(GroupId groupId) {
435 data().query.group_id(groupId);
442 SystemBuilder& group_id(Entity entity) {
443 GAIA_ASSERT(!entity.pair());
444 data().query.group_id(entity.id());
451 template <
typename T>
452 SystemBuilder& group_id();
464 SystemBuilder& name(
const char* name, uint32_t len = 0) {
465 m_world.name(m_entity, name, len);
473 SystemBuilder& name_raw(
const char* name, uint32_t len = 0) {
474 m_world.name_raw(m_entity, name, len);
492 SystemBuilder& phase(Entity phaseEntity) {
494 GAIA_ASSERT(m_world.valid(phaseEntity));
495 GAIA_ASSERT(!phaseEntity.pair());
496 m_world.add(m_entity, {ChildOf, phaseEntity});
497 m_world.add(m_entity, {DependsOn, phaseEntity});
510 SystemBuilder& mode(QueryExecType type) {
529 SystemBuilder& ctx(
void* pCtx) {
531 data().query.ctx(pCtx);
537 GAIA_NODISCARD
void* ctx()
const {
539 return data().query.ctx();
549 SystemBuilder& main_thread(
bool required =
true) {
551 data().query.main_thread(required);
562 SystemBuilder& reads(Entity entity) {
564 data().query.reads(entity);
572 template <
typename T>
573 SystemBuilder& reads() {
575 data().query.template reads<T>();
583 SystemBuilder& writes(Entity entity) {
585 data().query.writes(entity);
593 template <
typename T>
594 SystemBuilder& writes() {
596 data().query.template writes<T>();
606 template <
typename Func, std::enable_if_t<detail::is_query_iter_callback_v<Func>,
int> = 0>
607 SystemBuilder& on_each(Func func) {
610 auto& runtime = runtime_data();
611 runtime.on_each_func = [func](Query& query, QueryExecType execType, SystemRuntimeData::RunMode mode)
mutable {
612 if (mode == SystemRuntimeData::RunMode::DeferredJob)
613 return query.job(func, execType);
615 query.each_runtime_erased(
616 execType,
static_cast<void*
>(&func), &detail::QueryImpl::template invoke_runtime_iter<Func, Iter>,
617 Constraints::EnabledOnly);
621 return (SystemBuilder&)*
this;
630 template <
typename Func, std::enable_if_t<!detail::is_query_iter_callback_v<Func>,
int> = 0>
631 SystemBuilder& on_each(Func func);
635 GAIA_NODISCARD Entity entity()
const {
655 GAIA_NODISCARD SchedJob job() {
657 return ctx.job(m_world);
662 GAIA_NODISCARD mt::JobHandle job_handle() {
664 return ctx.job_handle(m_world);
672 #include "gaia/ecs/system_typed.inl"
static ThreadPool & get()
Returns the process-wide thread-pool instance.
Definition threadpool.h:161
void load(Reader &reader, T &data)
Read data using Reader at compile-time.
Definition ser_ct.h:112
void save(Writer &writer, const T &data)
Write data using Writer at compile-time.
Definition ser_ct.h:101
Definition system.inl:676