Flecs v3.2
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
flecs_c.h
Go to the documentation of this file.
1
6#ifndef FLECS_C_
7#define FLECS_C_
8
24/* Use for declaring entity, tag, prefab / any other entity identifier */
25#define ECS_DECLARE(id)\
26 ecs_entity_t id, ecs_id(id)
27
29#define ECS_ENTITY_DECLARE ECS_DECLARE
30
39#define ECS_ENTITY_DEFINE(world, id_, ...) \
40 { \
41 ecs_entity_desc_t desc = {0}; \
42 desc.id = id_; \
43 desc.name = #id_; \
44 desc.add_expr = #__VA_ARGS__; \
45 id_ = ecs_entity_init(world, &desc); \
46 ecs_id(id_) = id_; \
47 ecs_assert(id_ != 0, ECS_INVALID_PARAMETER, NULL); \
48 } \
49 (void)id_; \
50 (void)ecs_id(id_)
51
60#define ECS_ENTITY(world, id, ...) \
61 ecs_entity_t ecs_id(id); \
62 ecs_entity_t id = 0; \
63 ECS_ENTITY_DEFINE(world, id, __VA_ARGS__)
64
66#define ECS_TAG_DECLARE ECS_DECLARE
67
76#define ECS_TAG_DEFINE(world, id) ECS_ENTITY_DEFINE(world, id, 0)
77
86#define ECS_TAG(world, id) ECS_ENTITY(world, id, 0)
87
89#define ECS_PREFAB_DECLARE ECS_DECLARE
90
99#define ECS_PREFAB_DEFINE(world, id, ...) ECS_ENTITY_DEFINE(world, id, Prefab, __VA_ARGS__)
100
109#define ECS_PREFAB(world, id, ...) ECS_ENTITY(world, id, Prefab, __VA_ARGS__)
110
112#define ECS_COMPONENT_DECLARE(id) ecs_entity_t ecs_id(id)
113
122#define ECS_COMPONENT_DEFINE(world, id_) \
123 {\
124 ecs_component_desc_t desc = {0}; \
125 ecs_entity_desc_t edesc = {0}; \
126 edesc.id = ecs_id(id_); \
127 edesc.use_low_id = true; \
128 edesc.name = #id_; \
129 edesc.symbol = #id_; \
130 desc.entity = ecs_entity_init(world, &edesc); \
131 desc.type.size = ECS_SIZEOF(id_); \
132 desc.type.alignment = ECS_ALIGNOF(id_); \
133 ecs_id(id_) = ecs_component_init(world, &desc);\
134 }\
135 ecs_assert(ecs_id(id_) != 0, ECS_INVALID_PARAMETER, NULL)
136
145#define ECS_COMPONENT(world, id)\
146 ecs_entity_t ecs_id(id) = 0;\
147 ECS_COMPONENT_DEFINE(world, id);\
148 (void)ecs_id(id)
149
150/* Forward declare an observer. */
151#define ECS_OBSERVER_DECLARE(id) ecs_entity_t ecs_id(id)
152
161#define ECS_OBSERVER_DEFINE(world, id_, kind, ...)\
162 {\
163 ecs_observer_desc_t desc = {0};\
164 ecs_entity_desc_t edesc = {0}; \
165 edesc.id = ecs_id(id_); \
166 edesc.name = #id_; \
167 desc.entity = ecs_entity_init(world, &edesc); \
168 desc.callback = id_;\
169 desc.filter.expr = #__VA_ARGS__;\
170 desc.events[0] = kind;\
171 ecs_id(id_) = ecs_observer_init(world, &desc);\
172 ecs_assert(ecs_id(id_) != 0, ECS_INVALID_PARAMETER, NULL);\
173 }
174
183#define ECS_OBSERVER(world, id, kind, ...)\
184 ecs_entity_t ecs_id(id) = 0; \
185 ECS_OBSERVER_DEFINE(world, id, kind, __VA_ARGS__);\
186 ecs_entity_t id = ecs_id(id);\
187 (void)ecs_id(id);\
188 (void)id
189
200#define ecs_entity(world, ...)\
201 ecs_entity_init(world, &(ecs_entity_desc_t) __VA_ARGS__ )
202
214#define ecs_component(world, ...)\
215 ecs_component_init(world, &(ecs_component_desc_t) __VA_ARGS__ )
216
225#define ecs_component_t(world, T)\
226 ecs_component_init(world, &(ecs_component_desc_t) { \
227 .entity = ecs_entity(world, { \
228 .name = #T, \
229 .symbol = #T, \
230 .use_low_id = true \
231 }), \
232 .type.size = ECS_SIZEOF(T), \
233 .type.alignment = ECS_ALIGNOF(T) \
234 })
235
246#define ecs_filter(world, ...)\
247 ecs_filter_init(world, &(ecs_filter_desc_t) __VA_ARGS__ )
248
259#define ecs_query(world, ...)\
260 ecs_query_init(world, &(ecs_query_desc_t) __VA_ARGS__ )
261
274#define ecs_observer(world, ...)\
275 ecs_observer_init(world, &(ecs_observer_desc_t) __VA_ARGS__ )
276
296#define ecs_new(world, T) ecs_new_w_id(world, ecs_id(T))
297
298#define ecs_new_w_pair(world, first, second)\
299 ecs_new_w_id(world, ecs_pair(first, second))
300
301#define ecs_bulk_new(world, component, count)\
302 ecs_bulk_new_w_id(world, ecs_id(component), count)
303
304#define ecs_new_entity(world, n)\
305 ecs_entity_init(world, &(ecs_entity_desc_t){\
306 .name = n,\
307 })
308
309#define ecs_new_prefab(world, n)\
310 ecs_entity_init(world, &(ecs_entity_desc_t){\
311 .name = n,\
312 .add = {EcsPrefab}\
313 })
314
315#define ecs_delete_children(world, parent)\
316 ecs_delete_with(world, ecs_pair(EcsChildOf, parent))
317
325#define ecs_add(world, entity, T)\
326 ecs_add_id(world, entity, ecs_id(T))
327
328#define ecs_add_pair(world, subject, first, second)\
329 ecs_add_id(world, subject, ecs_pair(first, second))
330
331
332#define ecs_remove(world, entity, T)\
333 ecs_remove_id(world, entity, ecs_id(T))
334
335#define ecs_remove_pair(world, subject, first, second)\
336 ecs_remove_id(world, subject, ecs_pair(first, second))
337
338
339#define ecs_override(world, entity, T)\
340 ecs_override_id(world, entity, ecs_id(T))
341
342#define ecs_override_pair(world, subject, first, second)\
343 ecs_override_id(world, subject, ecs_pair(first, second))
344
352#define ecs_set_ptr(world, entity, component, ptr)\
353 ecs_set_id(world, entity, ecs_id(component), sizeof(component), ptr)
354
355#define ecs_set(world, entity, component, ...)\
356 ecs_set_id(world, entity, ecs_id(component), sizeof(component), &(component)__VA_ARGS__)
357
358#define ecs_set_pair(world, subject, First, second, ...)\
359 ecs_set_id(world, subject,\
360 ecs_pair(ecs_id(First), second),\
361 sizeof(First), &(First)__VA_ARGS__)
362
363#define ecs_set_pair_second(world, subject, first, Second, ...)\
364 ecs_set_id(world, subject,\
365 ecs_pair(first, ecs_id(Second)),\
366 sizeof(Second), &(Second)__VA_ARGS__)
367
368#define ecs_set_pair_object ecs_set_pair_second
369
370#define ecs_set_override(world, entity, T, ...)\
371 ecs_add_id(world, entity, ECS_OVERRIDE | ecs_id(T));\
372 ecs_set(world, entity, T, __VA_ARGS__)
373
374#define ecs_emplace(world, entity, T)\
375 (ECS_CAST(T*, ecs_emplace_id(world, entity, ecs_id(T))))
376
377#define ecs_emplace_pair(world, entity, First, second)\
378 (ECS_CAST(First*, ecs_emplace_id(world, entity, ecs_pair_t(First, second))))
379
380#define ecs_get(world, entity, T)\
381 (ECS_CAST(const T*, ecs_get_id(world, entity, ecs_id(T))))
382
383#define ecs_get_pair(world, subject, First, second)\
384 (ECS_CAST(const First*, ecs_get_id(world, subject,\
385 ecs_pair(ecs_id(First), second))))
386
387#define ecs_get_pair_second(world, subject, first, Second)\
388 (ECS_CAST(const Second*, ecs_get_id(world, subject,\
389 ecs_pair(first, ecs_id(Second)))))
390
391#define ecs_get_pair_object ecs_get_pair_second
392
393#define ecs_record_get(world, record, T)\
394 (ECS_CAST(const T*, ecs_record_get_id(world, record, ecs_id(T))))
395
396#define ecs_record_has(world, record, T)\
397 (ecs_record_has_id(world, record, ecs_id(T)))
398
399#define ecs_record_get_pair(world, record, First, second)\
400 (ECS_CAST(const First*, ecs_record_get_id(world, record, \
401 ecs_pair(ecs_id(First), second))))
402
403#define ecs_record_get_pair_second(world, record, first, Second)\
404 (ECS_CAST(const Second*, ecs_record_get_id(world, record,\
405 ecs_pair(first, ecs_id(Second)))))
406
407#define ecs_record_get_mut(world, record, T)\
408 (ECS_CAST(T*, ecs_record_get_mut_id(world, record, ecs_id(T))))
409
410#define ecs_record_get_mut_pair(world, record, First, second)\
411 (ECS_CAST(First*, ecs_record_get_mut_id(world, record, \
412 ecs_pair(ecs_id(First), second))))
413
414#define ecs_record_get_mut_pair_second(world, record, first, Second)\
415 (ECS_CAST(Second*, ecs_record_get_mut_id(world, record,\
416 ecs_pair(first, ecs_id(Second)))))
417
418#define ecs_record_get_mut_pair_object ecs_record_get_mut_pair_second
419
420#define ecs_ref_init(world, entity, T)\
421 ecs_ref_init_id(world, entity, ecs_id(T))
422
423#define ecs_ref_get(world, ref, T)\
424 (ECS_CAST(const T*, ecs_ref_get_id(world, ref, ecs_id(T))))
425
426#define ecs_get_mut(world, entity, T)\
427 (ECS_CAST(T*, ecs_get_mut_id(world, entity, ecs_id(T))))
428
429#define ecs_get_mut_pair(world, subject, First, second)\
430 (ECS_CAST(First*, ecs_get_mut_id(world, subject,\
431 ecs_pair(ecs_id(First), second))))
432
433#define ecs_get_mut_pair_second(world, subject, first, Second)\
434 (ECS_CAST(Second*, ecs_get_mut_id(world, subject,\
435 ecs_pair(first, ecs_id(Second)))))
436
437#define ecs_get_mut_pair_object ecs_get_mut_pair_second
438
439#define ecs_modified(world, entity, component)\
440 ecs_modified_id(world, entity, ecs_id(component))
441
442#define ecs_modified_pair(world, subject, first, second)\
443 ecs_modified_id(world, subject, ecs_pair(first, second))
444
452#define ecs_singleton_add(world, comp)\
453 ecs_add(world, ecs_id(comp), comp)
454
455#define ecs_singleton_remove(world, comp)\
456 ecs_remove(world, ecs_id(comp), comp)
457
458#define ecs_singleton_get(world, comp)\
459 ecs_get(world, ecs_id(comp), comp)
460
461#define ecs_singleton_set_ptr(world, comp, ptr)\
462 ecs_set_ptr(world, ecs_id(comp), comp, ptr)
463
464#define ecs_singleton_set(world, comp, ...)\
465 ecs_set(world, ecs_id(comp), comp, __VA_ARGS__)
466
467#define ecs_singleton_get_mut(world, comp)\
468 ecs_get_mut(world, ecs_id(comp), comp)
469
470#define ecs_singleton_modified(world, comp)\
471 ecs_modified(world, ecs_id(comp), comp)
472
480#define ecs_has(world, entity, T)\
481 ecs_has_id(world, entity, ecs_id(T))
482
483#define ecs_has_pair(world, entity, first, second)\
484 ecs_has_id(world, entity, ecs_pair(first, second))
485
486#define ecs_owns_pair(world, entity, first, second)\
487 ecs_owns_id(world, entity, ecs_pair(first, second))
488
489#define ecs_owns(world, entity, T)\
490 ecs_owns_id(world, entity, ecs_id(T))
491
492#define ecs_shares_id(world, entity, id)\
493 (ecs_search_relation(world, ecs_get_table(world, entity), 0, ecs_id(id), \
494 EcsIsA, 1, 0, 0, 0, 0) != -1)
495
496#define ecs_shares_pair(world, entity, first, second)\
497 (ecs_shares_id(world, entity, ecs_pair(first, second)))
498
499#define ecs_shares(world, entity, T)\
500 (ecs_shares_id(world, entity, ecs_id(T)))
501
509#define ecs_enable_component(world, entity, T, enable)\
510 ecs_enable_id(world, entity, ecs_id(T), enable)
511
512#define ecs_is_enabled_component(world, entity, T)\
513 ecs_is_enabled_id(world, entity, ecs_id(T))
514
515#define ecs_enable_pair(world, entity, First, second, enable)\
516 ecs_enable_id(world, entity, ecs_pair(ecs_id(First), second), enable)
517
518#define ecs_is_enabled_pair(world, entity, First, second)\
519 ecs_is_enabled_id(world, entity, ecs_pair(ecs_id(First), second))
520
528#define ecs_lookup_path(world, parent, path)\
529 ecs_lookup_path_w_sep(world, parent, path, ".", NULL, true)
530
531#define ecs_lookup_fullpath(world, path)\
532 ecs_lookup_path_w_sep(world, 0, path, ".", NULL, true)
533
534#define ecs_get_path(world, parent, child)\
535 ecs_get_path_w_sep(world, parent, child, ".", NULL)
536
537#define ecs_get_fullpath(world, child)\
538 ecs_get_path_w_sep(world, 0, child, ".", NULL)
539
540#define ecs_get_fullpath_buf(world, child, buf)\
541 ecs_get_path_w_sep_buf(world, 0, child, ".", NULL, buf)
542
543#define ecs_new_from_path(world, parent, path)\
544 ecs_new_from_path_w_sep(world, parent, path, ".", NULL)
545
546#define ecs_new_from_fullpath(world, path)\
547 ecs_new_from_path_w_sep(world, 0, path, ".", NULL)
548
549#define ecs_add_path(world, entity, parent, path)\
550 ecs_add_path_w_sep(world, entity, parent, path, ".", NULL)
551
552#define ecs_add_fullpath(world, entity, path)\
553 ecs_add_path_w_sep(world, entity, 0, path, ".", NULL)
554
564#define ecs_set_hooks(world, T, ...)\
565 ecs_set_hooks_id(world, ecs_id(T), &(ecs_type_hooks_t)__VA_ARGS__)
566
567#define ecs_get_hooks(world, T)\
568 ecs_get_hooks_id(world, ecs_id(T));
569
577#define ECS_CTOR(type, var, ...)\
578 ECS_XTOR_IMPL(type, ctor, var, __VA_ARGS__)
579
587#define ECS_DTOR(type, var, ...)\
588 ECS_XTOR_IMPL(type, dtor, var, __VA_ARGS__)
589
597#define ECS_COPY(type, dst_var, src_var, ...)\
598 ECS_COPY_IMPL(type, dst_var, src_var, __VA_ARGS__)
599
607#define ECS_MOVE(type, dst_var, src_var, ...)\
608 ECS_MOVE_IMPL(type, dst_var, src_var, __VA_ARGS__)
609
617#define ECS_ON_ADD(type, ptr, ...)\
618 ECS_HOOK_IMPL(type, ecs_on_add(type), ptr, __VA_ARGS__)
619#define ECS_ON_REMOVE(type, ptr, ...)\
620 ECS_HOOK_IMPL(type, ecs_on_remove(type), ptr, __VA_ARGS__)
621#define ECS_ON_SET(type, ptr, ...)\
622 ECS_HOOK_IMPL(type, ecs_on_set(type), ptr, __VA_ARGS__)
623
624/* Map from typename to function name of component lifecycle action */
625#define ecs_ctor(type) type##_ctor
626#define ecs_dtor(type) type##_dtor
627#define ecs_copy(type) type##_copy
628#define ecs_move(type) type##_move
629#define ecs_on_set(type) type##_on_set
630#define ecs_on_add(type) type##_on_add
631#define ecs_on_remove(type) type##_on_remove
632
640#define ecs_count(world, type)\
641 ecs_count_id(world, ecs_id(type))
642
650#define ecs_field(it, T, index)\
651 (ECS_CAST(T*, ecs_field_w_size(it, sizeof(T), index)))
652
660#define ecs_table_get(world, table, T, offset)\
661 (ECS_CAST(T*, ecs_table_get_id(world, table, ecs_id(T), offset)))
662
663#define ecs_table_get_pair(world, table, First, second, offset)\
664 (ECS_CAST(First*, ecs_table_get_id(world, table, ecs_pair(ecs_id(First), second), offset)))
665
666#define ecs_table_get_pair_second(world, table, first, Second, offset)\
667 (ECS_CAST(Second*, ecs_table_get_id(world, table, ecs_pair(first, ecs_id(Second)), offset)))
668
676#define ecs_value(T, ptr) ((ecs_value_t){ecs_id(T), ptr})
677#define ecs_value_new_t(world, T) ecs_value_new(world, ecs_id(T))
678
689#define ecs_sort_table(id) ecs_id(id##_sort_table)
690
691#define ecs_compare(id) ecs_id(id##_compare_fn)
692
693/* Declare efficient table sorting operation that uses provided compare function.
694 * For best results use LTO or make the function body visible in the same compilation unit.
695 * Variadic arguments are prepended before generated functions, use it to declare static
696 * or exported functions.
697 * Parameters of the comparison function:
698 * ecs_entity_t e1, const void* ptr1,
699 * ecs_entity_t e2, const void* ptr2
700 * Parameters of the sort functions:
701 * ecs_world_t *world
702 * ecs_table_t *table
703 * ecs_entity_t *entities
704 * void *ptr
705 * int32_t elem_size
706 * int32_t lo
707 * int32_t hi
708 * ecs_order_by_action_t order_by - Pointer to the original comparison function. You are not supposed to use it.
709 * Example:
710 *
711 * @code
712 * int CompareMyType(ecs_entity_t e1, const void* ptr1, ecs_entity_t e2, const void* ptr2) { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; }
713 * ECS_SORT_TABLE_WITH_COMPARE(MyType, MyCustomCompare, CompareMyType)
714 * @endcode
715 */
716#define ECS_SORT_TABLE_WITH_COMPARE(id, op_name, compare_fn, ...) \
717 static int32_t ECS_CONCAT(op_name, _partition)( \
718 ecs_world_t *world, \
719 ecs_table_t *table, \
720 ecs_entity_t *entities, \
721 void *ptr, \
722 int32_t elem_size, \
723 int32_t lo, \
724 int32_t hi, \
725 ecs_order_by_action_t order_by) \
726 { \
727 (void)(order_by); \
728 int32_t p = (hi + lo) / 2; \
729 void *pivot = ECS_ELEM(ptr, elem_size, p); \
730 ecs_entity_t pivot_e = entities[p]; \
731 int32_t i = lo - 1, j = hi + 1; \
732 void *el; \
733 repeat: \
734 { \
735 do { \
736 i ++; \
737 el = ECS_ELEM(ptr, elem_size, i); \
738 } while ( compare_fn(entities[i], el, pivot_e, pivot) < 0); \
739 do { \
740 j --; \
741 el = ECS_ELEM(ptr, elem_size, j); \
742 } while ( compare_fn(entities[j], el, pivot_e, pivot) > 0); \
743 if (i >= j) { \
744 return j; \
745 } \
746 ecs_table_swap_rows(world, table, i, j); \
747 if (p == i) { \
748 pivot = ECS_ELEM(ptr, elem_size, j); \
749 pivot_e = entities[j]; \
750 } else if (p == j) { \
751 pivot = ECS_ELEM(ptr, elem_size, i); \
752 pivot_e = entities[i]; \
753 } \
754 goto repeat; \
755 } \
756 } \
757 __VA_ARGS__ void op_name( \
758 ecs_world_t *world, \
759 ecs_table_t *table, \
760 ecs_entity_t *entities, \
761 void *ptr, \
762 int32_t size, \
763 int32_t lo, \
764 int32_t hi, \
765 ecs_order_by_action_t order_by) \
766 { \
767 if ((hi - lo) < 1) { \
768 return; \
769 } \
770 int32_t p = ECS_CONCAT(op_name, _partition)(world, table, entities, ptr, size, lo, hi, order_by); \
771 op_name(world, table, entities, ptr, size, lo, p, order_by); \
772 op_name(world, table, entities, ptr, size, p + 1, hi, order_by); \
773 }
774
775/* Declare efficient table sorting operation that uses default component comparison operator.
776 * For best results use LTO or make the comparison operator visible in the same compilation unit.
777 * Variadic arguments are prepended before generated functions, use it to declare static
778 * or exported functions.
779 * Example:
780 *
781 * @code
782 * ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
783 * ECS_SORT_TABLE(MyType)
784 * @endcode
785 */
786#define ECS_SORT_TABLE(id, ...) \
787 ECS_SORT_TABLE_WITH_COMPARE(id, ecs_sort_table(id), ecs_compare(id), __VA_ARGS__)
788
789/* Declare component comparison operations.
790 * Parameters:
791 * ecs_entity_t e1, const void* ptr1,
792 * ecs_entity_t e2, const void* ptr2
793 * Example:
794 *
795 * @code
796 * ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
797 * @endcode
798 */
799#define ECS_COMPARE(id, ...) \
800 int ecs_compare(id)(ecs_entity_t e1, const void* ptr1, ecs_entity_t e2, const void* ptr2) { \
801 __VA_ARGS__ \
802 }
803
813#define ecs_isa(e) ecs_pair(EcsIsA, e)
814#define ecs_childof(e) ecs_pair(EcsChildOf, e)
815#define ecs_dependson(e) ecs_pair(EcsDependsOn, e)
816
817#define ecs_query_new(world, q_expr)\
818 ecs_query_init(world, &(ecs_query_desc_t){\
819 .filter.expr = q_expr\
820 })
821
822#define ecs_rule_new(world, q_expr)\
823 ecs_rule_init(world, &(ecs_filter_desc_t){\
824 .expr = q_expr\
825 })
826
831#endif // FLECS_C_