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
23/* Use for declaring entity, tag, prefab / any other entity identifier */
24#define ECS_DECLARE(id)\
25 ecs_entity_t id, ecs_id(id)
26
28#define ECS_ENTITY_DECLARE ECS_DECLARE
29
35#define ECS_ENTITY_DEFINE(world, id_, ...) \
36 { \
37 ecs_entity_desc_t desc = {0}; \
38 desc.id = id_; \
39 desc.name = #id_; \
40 desc.add_expr = #__VA_ARGS__; \
41 id_ = ecs_entity_init(world, &desc); \
42 ecs_id(id_) = id_; \
43 ecs_assert(id_ != 0, ECS_INVALID_PARAMETER, NULL); \
44 } \
45 (void)id_; \
46 (void)ecs_id(id_)
47
53#define ECS_ENTITY(world, id, ...) \
54 ecs_entity_t ecs_id(id); \
55 ecs_entity_t id = 0; \
56 ECS_ENTITY_DEFINE(world, id, __VA_ARGS__)
57
59#define ECS_TAG_DECLARE ECS_DECLARE
60
66#define ECS_TAG_DEFINE(world, id) ECS_ENTITY_DEFINE(world, id, 0)
67
73#define ECS_TAG(world, id) ECS_ENTITY(world, id, 0)
74
76#define ECS_PREFAB_DECLARE ECS_DECLARE
77
83#define ECS_PREFAB_DEFINE(world, id, ...) ECS_ENTITY_DEFINE(world, id, Prefab, __VA_ARGS__)
84
90#define ECS_PREFAB(world, id, ...) ECS_ENTITY(world, id, Prefab, __VA_ARGS__)
91
93#define ECS_COMPONENT_DECLARE(id) ecs_entity_t ecs_id(id)
94
100#define ECS_COMPONENT_DEFINE(world, id_) \
101 {\
102 ecs_component_desc_t desc = {0}; \
103 ecs_entity_desc_t edesc = {0}; \
104 edesc.id = ecs_id(id_); \
105 edesc.use_low_id = true; \
106 edesc.name = #id_; \
107 edesc.symbol = #id_; \
108 desc.entity = ecs_entity_init(world, &edesc); \
109 desc.type.size = ECS_SIZEOF(id_); \
110 desc.type.alignment = ECS_ALIGNOF(id_); \
111 ecs_id(id_) = ecs_component_init(world, &desc);\
112 }\
113 ecs_assert(ecs_id(id_) != 0, ECS_INVALID_PARAMETER, NULL)
114
120#define ECS_COMPONENT(world, id)\
121 ecs_entity_t ecs_id(id) = 0;\
122 ECS_COMPONENT_DEFINE(world, id);\
123 (void)ecs_id(id)
124
125/* Forward declare an observer. */
126#define ECS_OBSERVER_DECLARE(id) ecs_entity_t ecs_id(id)
127
133#define ECS_OBSERVER_DEFINE(world, id_, kind, ...)\
134 {\
135 ecs_observer_desc_t desc = {0};\
136 ecs_entity_desc_t edesc = {0}; \
137 edesc.id = ecs_id(id_); \
138 edesc.name = #id_; \
139 desc.entity = ecs_entity_init(world, &edesc); \
140 desc.callback = id_;\
141 desc.filter.expr = #__VA_ARGS__;\
142 desc.events[0] = kind;\
143 ecs_id(id_) = ecs_observer_init(world, &desc);\
144 ecs_assert(ecs_id(id_) != 0, ECS_INVALID_PARAMETER, NULL);\
145 }
146
152#define ECS_OBSERVER(world, id, kind, ...)\
153 ecs_entity_t ecs_id(id) = 0; \
154 ECS_OBSERVER_DEFINE(world, id, kind, __VA_ARGS__);\
155 ecs_entity_t id = ecs_id(id);\
156 (void)ecs_id(id);\
157 (void)id
158
166#define ecs_entity(world, ...)\
167 ecs_entity_init(world, &(ecs_entity_desc_t) __VA_ARGS__ )
168
177#define ecs_component(world, ...)\
178 ecs_component_init(world, &(ecs_component_desc_t) __VA_ARGS__ )
179
185#define ecs_component_t(world, T)\
186 ecs_component_init(world, &(ecs_component_desc_t) { \
187 .entity = ecs_entity(world, { \
188 .name = #T, \
189 .symbol = #T, \
190 .use_low_id = true \
191 }), \
192 .type.size = ECS_SIZEOF(T), \
193 .type.alignment = ECS_ALIGNOF(T) \
194 })
195
203#define ecs_filter(world, ...)\
204 ecs_filter_init(world, &(ecs_filter_desc_t) __VA_ARGS__ )
205
213#define ecs_query(world, ...)\
214 ecs_query_init(world, &(ecs_query_desc_t) __VA_ARGS__ )
215
225#define ecs_observer(world, ...)\
226 ecs_observer_init(world, &(ecs_observer_desc_t) __VA_ARGS__ )
227
246#define ecs_new(world, T) ecs_new_w_id(world, ecs_id(T))
247
248#define ecs_new_w_pair(world, first, second)\
249 ecs_new_w_id(world, ecs_pair(first, second))
250
251#define ecs_bulk_new(world, component, count)\
252 ecs_bulk_new_w_id(world, ecs_id(component), count)
253
254#define ecs_new_entity(world, n)\
255 ecs_entity_init(world, &(ecs_entity_desc_t){\
256 .name = n,\
257 })
258
259#define ecs_new_prefab(world, n)\
260 ecs_entity_init(world, &(ecs_entity_desc_t){\
261 .name = n,\
262 .add = {EcsPrefab}\
263 })
264
265#define ecs_delete_children(world, parent)\
266 ecs_delete_with(world, ecs_pair(EcsChildOf, parent))
267
275#define ecs_add(world, entity, T)\
276 ecs_add_id(world, entity, ecs_id(T))
277
278#define ecs_add_pair(world, subject, first, second)\
279 ecs_add_id(world, subject, ecs_pair(first, second))
280
281
282#define ecs_remove(world, entity, T)\
283 ecs_remove_id(world, entity, ecs_id(T))
284
285#define ecs_remove_pair(world, subject, first, second)\
286 ecs_remove_id(world, subject, ecs_pair(first, second))
287
288
289#define ecs_override(world, entity, T)\
290 ecs_override_id(world, entity, ecs_id(T))
291
292#define ecs_override_pair(world, subject, first, second)\
293 ecs_override_id(world, subject, ecs_pair(first, second))
294
302#define ecs_set_ptr(world, entity, component, ptr)\
303 ecs_set_id(world, entity, ecs_id(component), sizeof(component), ptr)
304
305#define ecs_set(world, entity, component, ...)\
306 ecs_set_id(world, entity, ecs_id(component), sizeof(component), &(component)__VA_ARGS__)
307
308#define ecs_set_pair(world, subject, First, second, ...)\
309 ecs_set_id(world, subject,\
310 ecs_pair(ecs_id(First), second),\
311 sizeof(First), &(First)__VA_ARGS__)
312
313#define ecs_set_pair_second(world, subject, first, Second, ...)\
314 ecs_set_id(world, subject,\
315 ecs_pair(first, ecs_id(Second)),\
316 sizeof(Second), &(Second)__VA_ARGS__)
317
318#define ecs_set_pair_object ecs_set_pair_second
319
320#define ecs_set_override(world, entity, T, ...)\
321 ecs_add_id(world, entity, ECS_OVERRIDE | ecs_id(T));\
322 ecs_set(world, entity, T, __VA_ARGS__)
323
324#define ecs_emplace(world, entity, T)\
325 (ECS_CAST(T*, ecs_emplace_id(world, entity, ecs_id(T))))
326
327#define ecs_emplace_pair(world, entity, First, second)\
328 (ECS_CAST(First*, ecs_emplace_id(world, entity, ecs_pair_t(First, second))))
329
330#define ecs_get(world, entity, T)\
331 (ECS_CAST(const T*, ecs_get_id(world, entity, ecs_id(T))))
332
333#define ecs_get_pair(world, subject, First, second)\
334 (ECS_CAST(const First*, ecs_get_id(world, subject,\
335 ecs_pair(ecs_id(First), second))))
336
337#define ecs_get_pair_second(world, subject, first, Second)\
338 (ECS_CAST(const Second*, ecs_get_id(world, subject,\
339 ecs_pair(first, ecs_id(Second)))))
340
341#define ecs_get_pair_object ecs_get_pair_second
342
343#define ecs_record_get(world, record, T)\
344 (ECS_CAST(const T*, ecs_record_get_id(world, record, ecs_id(T))))
345
346#define ecs_record_has(world, record, T)\
347 (ecs_record_has_id(world, record, ecs_id(T)))
348
349#define ecs_record_get_pair(world, record, First, second)\
350 (ECS_CAST(const First*, ecs_record_get_id(world, record, \
351 ecs_pair(ecs_id(First), second))))
352
353#define ecs_record_get_pair_second(world, record, first, Second)\
354 (ECS_CAST(const Second*, ecs_record_get_id(world, record,\
355 ecs_pair(first, ecs_id(Second)))))
356
357#define ecs_record_get_mut(world, record, T)\
358 (ECS_CAST(T*, ecs_record_get_mut_id(world, record, ecs_id(T))))
359
360#define ecs_record_get_mut_pair(world, record, First, second)\
361 (ECS_CAST(First*, ecs_record_get_mut_id(world, record, \
362 ecs_pair(ecs_id(First), second))))
363
364#define ecs_record_get_mut_pair_second(world, record, first, Second)\
365 (ECS_CAST(Second*, ecs_record_get_mut_id(world, record,\
366 ecs_pair(first, ecs_id(Second)))))
367
368#define ecs_record_get_mut_pair_object ecs_record_get_mut_pair_second
369
370#define ecs_ref_init(world, entity, T)\
371 ecs_ref_init_id(world, entity, ecs_id(T))
372
373#define ecs_ref_get(world, ref, T)\
374 (ECS_CAST(const T*, ecs_ref_get_id(world, ref, ecs_id(T))))
375
376#define ecs_get_mut(world, entity, T)\
377 (ECS_CAST(T*, ecs_get_mut_id(world, entity, ecs_id(T))))
378
379#define ecs_get_mut_pair(world, subject, First, second)\
380 (ECS_CAST(First*, ecs_get_mut_id(world, subject,\
381 ecs_pair(ecs_id(First), second))))
382
383#define ecs_get_mut_pair_second(world, subject, first, Second)\
384 (ECS_CAST(Second*, ecs_get_mut_id(world, subject,\
385 ecs_pair(first, ecs_id(Second)))))
386
387#define ecs_get_mut_pair_object ecs_get_mut_pair_second
388
389#define ecs_modified(world, entity, component)\
390 ecs_modified_id(world, entity, ecs_id(component))
391
392#define ecs_modified_pair(world, subject, first, second)\
393 ecs_modified_id(world, subject, ecs_pair(first, second))
394
402#define ecs_singleton_add(world, comp)\
403 ecs_add(world, ecs_id(comp), comp)
404
405#define ecs_singleton_remove(world, comp)\
406 ecs_remove(world, ecs_id(comp), comp)
407
408#define ecs_singleton_get(world, comp)\
409 ecs_get(world, ecs_id(comp), comp)
410
411#define ecs_singleton_set_ptr(world, comp, ptr)\
412 ecs_set_ptr(world, ecs_id(comp), comp, ptr)
413
414#define ecs_singleton_set(world, comp, ...)\
415 ecs_set(world, ecs_id(comp), comp, __VA_ARGS__)
416
417#define ecs_singleton_get_mut(world, comp)\
418 ecs_get_mut(world, ecs_id(comp), comp)
419
420#define ecs_singleton_modified(world, comp)\
421 ecs_modified(world, ecs_id(comp), comp)
422
430#define ecs_has(world, entity, T)\
431 ecs_has_id(world, entity, ecs_id(T))
432
433#define ecs_has_pair(world, entity, first, second)\
434 ecs_has_id(world, entity, ecs_pair(first, second))
435
436#define ecs_owns_pair(world, entity, first, second)\
437 ecs_owns_id(world, entity, ecs_pair(first, second))
438
439#define ecs_owns(world, entity, T)\
440 ecs_owns_id(world, entity, ecs_id(T))
441
442#define ecs_shares_id(world, entity, id)\
443 (ecs_search_relation(world, ecs_get_table(world, entity), 0, ecs_id(id), \
444 EcsIsA, 1, 0, 0, 0, 0) != -1)
445
446#define ecs_shares_pair(world, entity, first, second)\
447 (ecs_shares_id(world, entity, ecs_pair(first, second)))
448
449#define ecs_shares(world, entity, T)\
450 (ecs_shares_id(world, entity, ecs_id(T)))
451
459#define ecs_enable_component(world, entity, T, enable)\
460 ecs_enable_id(world, entity, ecs_id(T), enable)
461
462#define ecs_is_enabled_component(world, entity, T)\
463 ecs_is_enabled_id(world, entity, ecs_id(T))
464
465#define ecs_enable_pair(world, entity, First, second, enable)\
466 ecs_enable_id(world, entity, ecs_pair(ecs_id(First), second), enable)
467
468#define ecs_is_enabled_pair(world, entity, First, second)\
469 ecs_is_enabled_id(world, entity, ecs_pair(ecs_id(First), second))
470
478#define ecs_lookup_path(world, parent, path)\
479 ecs_lookup_path_w_sep(world, parent, path, ".", NULL, true)
480
481#define ecs_lookup_fullpath(world, path)\
482 ecs_lookup_path_w_sep(world, 0, path, ".", NULL, true)
483
484#define ecs_get_path(world, parent, child)\
485 ecs_get_path_w_sep(world, parent, child, ".", NULL)
486
487#define ecs_get_fullpath(world, child)\
488 ecs_get_path_w_sep(world, 0, child, ".", NULL)
489
490#define ecs_get_fullpath_buf(world, child, buf)\
491 ecs_get_path_w_sep_buf(world, 0, child, ".", NULL, buf)
492
493#define ecs_new_from_path(world, parent, path)\
494 ecs_new_from_path_w_sep(world, parent, path, ".", NULL)
495
496#define ecs_new_from_fullpath(world, path)\
497 ecs_new_from_path_w_sep(world, 0, path, ".", NULL)
498
499#define ecs_add_path(world, entity, parent, path)\
500 ecs_add_path_w_sep(world, entity, parent, path, ".", NULL)
501
502#define ecs_add_fullpath(world, entity, path)\
503 ecs_add_path_w_sep(world, entity, 0, path, ".", NULL)
504
514#define ecs_set_hooks(world, T, ...)\
515 ecs_set_hooks_id(world, ecs_id(T), &(ecs_type_hooks_t)__VA_ARGS__)
516
517#define ecs_get_hooks(world, T)\
518 ecs_get_hooks_id(world, ecs_id(T));
519
524#define ECS_CTOR(type, var, ...)\
525 ECS_XTOR_IMPL(type, ctor, var, __VA_ARGS__)
526
531#define ECS_DTOR(type, var, ...)\
532 ECS_XTOR_IMPL(type, dtor, var, __VA_ARGS__)
533
538#define ECS_COPY(type, dst_var, src_var, ...)\
539 ECS_COPY_IMPL(type, dst_var, src_var, __VA_ARGS__)
540
545#define ECS_MOVE(type, dst_var, src_var, ...)\
546 ECS_MOVE_IMPL(type, dst_var, src_var, __VA_ARGS__)
547
552#define ECS_ON_ADD(type, ptr, ...)\
553 ECS_HOOK_IMPL(type, ecs_on_add(type), ptr, __VA_ARGS__)
554#define ECS_ON_REMOVE(type, ptr, ...)\
555 ECS_HOOK_IMPL(type, ecs_on_remove(type), ptr, __VA_ARGS__)
556#define ECS_ON_SET(type, ptr, ...)\
557 ECS_HOOK_IMPL(type, ecs_on_set(type), ptr, __VA_ARGS__)
558
559/* Map from typename to function name of component lifecycle action */
560#define ecs_ctor(type) type##_ctor
561#define ecs_dtor(type) type##_dtor
562#define ecs_copy(type) type##_copy
563#define ecs_move(type) type##_move
564#define ecs_on_set(type) type##_on_set
565#define ecs_on_add(type) type##_on_add
566#define ecs_on_remove(type) type##_on_remove
567
575#define ecs_count(world, type)\
576 ecs_count_id(world, ecs_id(type))
577
585#define ecs_field(it, T, index)\
586 (ECS_CAST(T*, ecs_field_w_size(it, sizeof(T), index)))
587
595#define ecs_table_get(world, table, T, offset)\
596 (ECS_CAST(T*, ecs_table_get_id(world, table, ecs_id(T), offset)))
597
598#define ecs_table_get_pair(world, table, First, second, offset)\
599 (ECS_CAST(First*, ecs_table_get_id(world, table, ecs_pair(ecs_id(First), second), offset)))
600
601#define ecs_table_get_pair_second(world, table, first, Second, offset)\
602 (ECS_CAST(Second*, ecs_table_get_id(world, table, ecs_pair(first, ecs_id(Second)), offset)))
603
611#define ecs_value(T, ptr) ((ecs_value_t){ecs_id(T), ptr})
612#define ecs_value_new_t(world, T) ecs_value_new(world, ecs_id(T))
613
624#define ecs_sort_table(id) ecs_id(id##_sort_table)
625
626#define ecs_compare(id) ecs_id(id##_compare_fn)
627
628/* Declare efficient table sorting operation that uses provided compare function.
629 * For best results use LTO or make the function body visible in the same compilation unit.
630 * Variadic arguments are prepended before generated functions, use it to declare static
631 * or exported functions.
632 * Parameters of the comparison function:
633 * ecs_entity_t e1, const void* ptr1,
634 * ecs_entity_t e2, const void* ptr2
635 * Parameters of the sort functions:
636 * ecs_world_t *world
637 * ecs_table_t *table
638 * ecs_entity_t *entities
639 * void *ptr
640 * int32_t elem_size
641 * int32_t lo
642 * int32_t hi
643 * ecs_order_by_action_t order_by - Pointer to the original comparison function. You are not supposed to use it.
644 * Example:
645 * 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; }
646 * ECS_SORT_TABLE_WITH_COMPARE(MyType, MyCustomCompare, CompareMyType)
647 */
648#define ECS_SORT_TABLE_WITH_COMPARE(id, op_name, compare_fn, ...) \
649 static int32_t ECS_CONCAT(op_name, _partition)( \
650 ecs_world_t *world, \
651 ecs_table_t *table, \
652 ecs_entity_t *entities, \
653 void *ptr, \
654 int32_t elem_size, \
655 int32_t lo, \
656 int32_t hi, \
657 ecs_order_by_action_t order_by) \
658 { \
659 (void)(order_by); \
660 int32_t p = (hi + lo) / 2; \
661 void *pivot = ECS_ELEM(ptr, elem_size, p); \
662 ecs_entity_t pivot_e = entities[p]; \
663 int32_t i = lo - 1, j = hi + 1; \
664 void *el; \
665 repeat: \
666 { \
667 do { \
668 i ++; \
669 el = ECS_ELEM(ptr, elem_size, i); \
670 } while ( compare_fn(entities[i], el, pivot_e, pivot) < 0); \
671 do { \
672 j --; \
673 el = ECS_ELEM(ptr, elem_size, j); \
674 } while ( compare_fn(entities[j], el, pivot_e, pivot) > 0); \
675 if (i >= j) { \
676 return j; \
677 } \
678 ecs_table_swap_rows(world, table, i, j); \
679 if (p == i) { \
680 pivot = ECS_ELEM(ptr, elem_size, j); \
681 pivot_e = entities[j]; \
682 } else if (p == j) { \
683 pivot = ECS_ELEM(ptr, elem_size, i); \
684 pivot_e = entities[i]; \
685 } \
686 goto repeat; \
687 } \
688 } \
689 __VA_ARGS__ void op_name( \
690 ecs_world_t *world, \
691 ecs_table_t *table, \
692 ecs_entity_t *entities, \
693 void *ptr, \
694 int32_t size, \
695 int32_t lo, \
696 int32_t hi, \
697 ecs_order_by_action_t order_by) \
698 { \
699 if ((hi - lo) < 1) { \
700 return; \
701 } \
702 int32_t p = ECS_CONCAT(op_name, _partition)(world, table, entities, ptr, size, lo, hi, order_by); \
703 op_name(world, table, entities, ptr, size, lo, p, order_by); \
704 op_name(world, table, entities, ptr, size, p + 1, hi, order_by); \
705 }
706
707/* Declare efficient table sorting operation that uses default component comparison operator.
708 * For best results use LTO or make the comparison operator visible in the same compilation unit.
709 * Variadic arguments are prepended before generated functions, use it to declare static
710 * or exported functions.
711 * Example:
712 * ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
713 * ECS_SORT_TABLE(MyType)
714 */
715#define ECS_SORT_TABLE(id, ...) \
716 ECS_SORT_TABLE_WITH_COMPARE(id, ecs_sort_table(id), ecs_compare(id), __VA_ARGS__)
717
718/* Declare component comparison operations.
719 * Parameters:
720 * ecs_entity_t e1, const void* ptr1,
721 * ecs_entity_t e2, const void* ptr2
722 * Example:
723 * ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
724 */
725#define ECS_COMPARE(id, ...) \
726 int ecs_compare(id)(ecs_entity_t e1, const void* ptr1, ecs_entity_t e2, const void* ptr2) { \
727 __VA_ARGS__ \
728 }
729
739#define ecs_isa(e) ecs_pair(EcsIsA, e)
740#define ecs_childof(e) ecs_pair(EcsChildOf, e)
741#define ecs_dependson(e) ecs_pair(EcsDependsOn, e)
742
743#define ecs_query_new(world, q_expr)\
744 ecs_query_init(world, &(ecs_query_desc_t){\
745 .filter.expr = q_expr\
746 })
747
748#define ecs_rule_new(world, q_expr)\
749 ecs_rule_init(world, &(ecs_filter_desc_t){\
750 .expr = q_expr\
751 })
752
757#endif // FLECS_C_