Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
system.inl
1#include "gaia/config/config.h"
2
3#include <cinttypes>
4
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"
9
10#if GAIA_SYSTEMS_ENABLED
11namespace gaia {
12 namespace ecs {
13
14 #if GAIA_PROFILER_CPU
15 inline constexpr const char* sc_system_query_func_str = "System_exec";
16 util::str_view entity_name(const World& world, Entity entity);
17 #endif
18
25 struct System_ {
27 Entity entity = EntityBad;
29 Query query;
31 QueryExecType execType = QueryExecType::Default;
33 mt::JobHandle jobHandle = mt::JobNull;
34
35 System_() = default;
36
41 ~System_() {
42 // If the query contains a job handle we can only
43 // destroy the query once the task associated with the handle is finished.
44 if (jobHandle != (mt::JobHandle)mt::JobNull_t{}) {
45 auto& tp = mt::ThreadPool::get();
46 tp.wait(jobHandle);
47 // Job handles created by queries are MANUAL_DELETE so delete it explicitly.
48 tp.del(jobHandle);
49 }
50 }
51
59 void exec(World& world) {
60 [[maybe_unused]] auto& queryInfo = query.fetch();
61
62 #if GAIA_PROFILER_CPU
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);
66 #endif
67
68 auto* pRuntime = world.systems().data_try(entity);
69 GAIA_ASSERT(pRuntime != nullptr);
70 if (pRuntime == nullptr || !pRuntime->on_each_func)
71 return;
72
73 static_cast<void>(pRuntime->on_each_func(query, execType, SystemRuntimeData::RunMode::Immediate));
74 }
75
83 GAIA_NODISCARD mt::JobHandle job_handle(World& world) {
84 if (jobHandle == (mt::JobHandle)mt::JobNull_t{}) {
85 auto& tp = mt::ThreadPool::get();
86 mt::Job syncJob;
87 syncJob.func = [this, &world]() {
88 exec(world);
89 };
90 syncJob.flags = mt::JobCreationFlags::ManualDelete;
91 jobHandle = tp.add(GAIA_MOV(syncJob));
92 }
93 return jobHandle;
94 }
95
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)
109 return {};
110
111 return pRuntime->on_each_func(query, execType, SystemRuntimeData::RunMode::DeferredJob);
112 }
113
117 template <typename Serializer>
118 void save(Serializer& s) const {
119 (void)s;
120 }
124 template <typename Serializer>
125 void load(Serializer& s) {
126 (void)s;
127 }
128 };
129
137 class SystemBuilder {
138 World& m_world;
139 Entity m_entity;
140
144 void validate() const {
145 GAIA_ASSERT(m_world.valid(m_entity));
146 }
147
150 System_& data() {
151 auto ss = m_world.acc_mut(m_entity);
152 auto& sys = ss.smut<System_>();
153 return sys;
154 }
155
158 const System_& data() const {
159 auto ss = m_world.acc(m_entity);
160 const auto& sys = ss.get<System_>();
161 return sys;
162 }
163
166 SystemRuntimeData& runtime_data() {
167 return m_world.systems().data(m_entity);
168 }
169
172 const SystemRuntimeData& runtime_data() const {
173 return m_world.systems().data(m_entity);
174 }
175
176 public:
180 SystemBuilder(World& world, Entity entity): m_world(world), m_entity(entity) {}
181
182 //------------------------------------------------
183
186
191 SystemBuilder& kind(QueryCacheKind kind) {
192 validate();
193 data().query.kind(kind);
194 return *this;
195 }
196
201 SystemBuilder& scope(QueryCacheScope scope) {
202 validate();
203 data().query.scope(scope);
204 return *this;
205 }
207
208 //------------------------------------------------
209
212
217 SystemBuilder& add(QueryInput item) {
218 validate();
219 data().query.add(item);
220 return *this;
221 }
222
223 //------------------------------------------------
224
229 SystemBuilder& is(Entity entity, const QueryTermOptions& options = {}) {
230 return all(Pair(Is, entity), options);
231 }
232
233 //------------------------------------------------
234
239 SystemBuilder& in(Entity entity, QueryTermOptions options = {}) {
240 options.in();
241 return all(Pair(Is, entity), options);
242 }
243
244 //------------------------------------------------
245
250 SystemBuilder& all(Entity entity, const QueryTermOptions& options = {}) {
251 validate();
252 data().query.all(entity, options);
253 return *this;
254 }
255
260 SystemBuilder& any(Entity entity, const QueryTermOptions& options = {}) {
261 validate();
262 data().query.any(entity, options);
263 return *this;
264 }
265
270 SystemBuilder& or_(Entity entity, const QueryTermOptions& options = {}) {
271 validate();
272 data().query.or_(entity, options);
273 return *this;
274 }
275
280 SystemBuilder& no(Entity entity, const QueryTermOptions& options = {}) {
281 validate();
282 data().query.no(entity, options);
283 return *this;
284 }
285
288 SystemBuilder& match_prefab() {
289 validate();
290 data().query.match_prefab();
291 return *this;
292 }
293
297 SystemBuilder& changed(Entity entity) {
298 validate();
299 data().query.changed(entity);
300 return *this;
301 }
302
307 template <typename T>
308 SystemBuilder& all(const QueryTermOptions& options);
309
314 template <typename T>
315 SystemBuilder& any(const QueryTermOptions& options);
316
321 template <typename T>
322 SystemBuilder& or_(const QueryTermOptions& options);
323
328 template <typename T>
329 SystemBuilder& no(const QueryTermOptions& options);
330
331 //------------------------------------------------
332
336 template <typename T>
337 SystemBuilder& all();
338
342 template <typename T>
343 SystemBuilder& any();
344
348 template <typename T>
349 SystemBuilder& or_();
350
354 template <typename T>
355 SystemBuilder& no();
356
360 template <typename T>
361 SystemBuilder& changed();
363
364 //------------------------------------------------
365
368
373 SystemBuilder& depth_order(Entity relation = ChildOf) {
374 data().query.depth_order(relation);
375 return *this;
376 }
377
381 template <typename Rel>
382 SystemBuilder& depth_order();
383
384 //------------------------------------------------
385
391 SystemBuilder& group_by(Entity entity, TGroupByFunc func = group_by_func_default) {
392 data().query.group_by(entity, func);
393 return *this;
394 }
395
400 template <typename T>
401 SystemBuilder& group_by(TGroupByFunc func = group_by_func_default);
402
408 template <typename Rel, typename Tgt>
409 SystemBuilder& group_by(TGroupByFunc func = group_by_func_default);
410
411 //------------------------------------------------
412
417 SystemBuilder& group_dep(Entity relation) {
418 data().query.group_dep(relation);
419 return *this;
420 }
421
426 template <typename Rel>
427 SystemBuilder& group_dep();
428
429 //------------------------------------------------
430
434 SystemBuilder& group_id(GroupId groupId) {
435 data().query.group_id(groupId);
436 return *this;
437 }
438
442 SystemBuilder& group_id(Entity entity) {
443 GAIA_ASSERT(!entity.pair());
444 data().query.group_id(entity.id());
445 return *this;
446 }
447
451 template <typename T>
452 SystemBuilder& group_id();
454
455 //------------------------------------------------
456
459
464 SystemBuilder& name(const char* name, uint32_t len = 0) {
465 m_world.name(m_entity, name, len);
466 return *this;
467 }
468
473 SystemBuilder& name_raw(const char* name, uint32_t len = 0) {
474 m_world.name_raw(m_entity, name, len);
475 return *this;
476 }
477
492 SystemBuilder& phase(Entity phaseEntity) {
493 validate();
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});
498 return *this;
499 }
501
502 //------------------------------------------------
503
506
510 SystemBuilder& mode(QueryExecType type) {
511 auto& ctx = data();
512 ctx.execType = type;
513 return *this;
514 }
515
521
529 SystemBuilder& ctx(void* pCtx) {
530 validate();
531 data().query.ctx(pCtx);
532 return *this;
533 }
534
537 GAIA_NODISCARD void* ctx() const {
538 validate();
539 return data().query.ctx();
540 }
542
549 SystemBuilder& main_thread(bool required = true) {
550 validate();
551 data().query.main_thread(required);
552 return *this;
553 }
555
562 SystemBuilder& reads(Entity entity) {
563 validate();
564 data().query.reads(entity);
565 return *this;
566 }
567
572 template <typename T>
573 SystemBuilder& reads() {
574 validate();
575 data().query.template reads<T>();
576 return *this;
577 }
578
583 SystemBuilder& writes(Entity entity) {
584 validate();
585 data().query.writes(entity);
586 return *this;
587 }
588
593 template <typename T>
594 SystemBuilder& writes() {
595 validate();
596 data().query.template writes<T>();
597 return *this;
598 }
600
606 template <typename Func, std::enable_if_t<detail::is_query_iter_callback_v<Func>, int> = 0>
607 SystemBuilder& on_each(Func func) {
608 validate();
609
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);
614
615 query.each_runtime_erased(
616 execType, static_cast<void*>(&func), &detail::QueryImpl::template invoke_runtime_iter<Func, Iter>,
617 Constraints::EnabledOnly);
618 return SchedJob{};
619 };
620
621 return (SystemBuilder&)*this;
622 }
623
630 template <typename Func, std::enable_if_t<!detail::is_query_iter_callback_v<Func>, int> = 0>
631 SystemBuilder& on_each(Func func);
632
635 GAIA_NODISCARD Entity entity() const {
636 return m_entity;
637 }
638
642 void exec() {
643 auto& ctx = data();
644 ctx.exec(m_world);
645 }
646
655 GAIA_NODISCARD SchedJob job() {
656 auto& ctx = data();
657 return ctx.job(m_world);
658 }
659
662 GAIA_NODISCARD mt::JobHandle job_handle() {
663 auto& ctx = data();
664 return ctx.job_handle(m_world);
665 }
667 };
668
669 } // namespace ecs
670} // namespace gaia
671
672 #include "gaia/ecs/system_typed.inl"
673#else
674namespace gaia {
675 namespace ecs {
676 struct System_ {};
677 } // namespace ecs
678} // namespace gaia
679#endif
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