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
/* set */
353
354
#define ecs_set_ptr(world, entity, component, ptr)\
355
ecs_set_id(world, entity, ecs_id(component), sizeof(component), ptr)
356
357
#define ecs_set(world, entity, component, ...)\
358
ecs_set_id(world, entity, ecs_id(component), sizeof(component), &(component)__VA_ARGS__)
359
360
#define ecs_set_pair(world, subject, First, second, ...)\
361
ecs_set_id(world, subject,\
362
ecs_pair(ecs_id(First), second),\
363
sizeof(First), &(First)__VA_ARGS__)
364
365
#define ecs_set_pair_second(world, subject, first, Second, ...)\
366
ecs_set_id(world, subject,\
367
ecs_pair(first, ecs_id(Second)),\
368
sizeof(Second), &(Second)__VA_ARGS__)
369
370
#define ecs_set_pair_object ecs_set_pair_second
371
372
#define ecs_set_override(world, entity, T, ...)\
373
ecs_add_id(world, entity, ECS_OVERRIDE | ecs_id(T));\
374
ecs_set(world, entity, T, __VA_ARGS__)
375
376
/* emplace */
377
378
#define ecs_emplace(world, entity, T)\
379
(ECS_CAST(T*, ecs_emplace_id(world, entity, ecs_id(T))))
380
381
#define ecs_emplace_pair(world, entity, First, second)\
382
(ECS_CAST(First*, ecs_emplace_id(world, entity, ecs_pair_t(First, second))))
383
384
/* get */
385
386
#define ecs_get(world, entity, T)\
387
(ECS_CAST(const T*, ecs_get_id(world, entity, ecs_id(T))))
388
389
#define ecs_get_pair(world, subject, First, second)\
390
(ECS_CAST(const First*, ecs_get_id(world, subject,\
391
ecs_pair(ecs_id(First), second))))
392
393
#define ecs_get_pair_second(world, subject, first, Second)\
394
(ECS_CAST(const Second*, ecs_get_id(world, subject,\
395
ecs_pair(first, ecs_id(Second)))))
396
397
#define ecs_get_pair_object ecs_get_pair_second
398
399
/* get_mut */
400
401
#define ecs_get_mut(world, entity, T)\
402
(ECS_CAST(T*, ecs_get_mut_id(world, entity, ecs_id(T))))
403
404
#define ecs_get_mut_pair(world, subject, First, second)\
405
(ECS_CAST(First*, ecs_get_mut_id(world, subject,\
406
ecs_pair(ecs_id(First), second))))
407
408
#define ecs_get_mut_pair_second(world, subject, first, Second)\
409
(ECS_CAST(Second*, ecs_get_mut_id(world, subject,\
410
ecs_pair(first, ecs_id(Second)))))
411
412
#define ecs_get_mut_pair_object ecs_get_mut_pair_second
413
414
#define ecs_get_mut(world, entity, T)\
415
(ECS_CAST(T*, ecs_get_mut_id(world, entity, ecs_id(T))))
416
417
/* ensure */
418
419
#define ecs_ensure(world, entity, T)\
420
(ECS_CAST(T*, ecs_ensure_id(world, entity, ecs_id(T))))
421
422
#define ecs_ensure_pair(world, subject, First, second)\
423
(ECS_CAST(First*, ecs_ensure_id(world, subject,\
424
ecs_pair(ecs_id(First), second))))
425
426
#define ecs_ensure_pair_second(world, subject, first, Second)\
427
(ECS_CAST(Second*, ecs_ensure_id(world, subject,\
428
ecs_pair(first, ecs_id(Second)))))
429
430
#define ecs_ensure_pair_object ecs_ensure_pair_second
431
432
#define ecs_ensure(world, entity, T)\
433
(ECS_CAST(T*, ecs_ensure_id(world, entity, ecs_id(T))))
434
435
#define ecs_ensure_pair(world, subject, First, second)\
436
(ECS_CAST(First*, ecs_ensure_id(world, subject,\
437
ecs_pair(ecs_id(First), second))))
438
439
#define ecs_ensure_pair_second(world, subject, first, Second)\
440
(ECS_CAST(Second*, ecs_ensure_id(world, subject,\
441
ecs_pair(first, ecs_id(Second)))))
442
443
#define ecs_ensure_pair_object ecs_ensure_pair_second
444
445
/* modified */
446
447
#define ecs_modified(world, entity, component)\
448
ecs_modified_id(world, entity, ecs_id(component))
449
450
#define ecs_modified_pair(world, subject, first, second)\
451
ecs_modified_id(world, subject, ecs_pair(first, second))
452
453
/* record */
454
455
#define ecs_record_get(world, record, T)\
456
(ECS_CAST(const T*, ecs_record_get_id(world, record, ecs_id(T))))
457
458
#define ecs_record_has(world, record, T)\
459
(ecs_record_has_id(world, record, ecs_id(T)))
460
461
#define ecs_record_get_pair(world, record, First, second)\
462
(ECS_CAST(const First*, ecs_record_get_id(world, record, \
463
ecs_pair(ecs_id(First), second))))
464
465
#define ecs_record_get_pair_second(world, record, first, Second)\
466
(ECS_CAST(const Second*, ecs_record_get_id(world, record,\
467
ecs_pair(first, ecs_id(Second)))))
468
469
#define ecs_record_ensure(world, record, T)\
470
(ECS_CAST(T*, ecs_record_ensure_id(world, record, ecs_id(T))))
471
472
#define ecs_record_ensure_pair(world, record, First, second)\
473
(ECS_CAST(First*, ecs_record_ensure_id(world, record, \
474
ecs_pair(ecs_id(First), second))))
475
476
#define ecs_record_ensure_pair_second(world, record, first, Second)\
477
(ECS_CAST(Second*, ecs_record_ensure_id(world, record,\
478
ecs_pair(first, ecs_id(Second)))))
479
480
#define ecs_record_ensure_pair_object ecs_record_ensure_pair_second
481
482
#define ecs_ref_init(world, entity, T)\
483
ecs_ref_init_id(world, entity, ecs_id(T))
484
485
#define ecs_ref_get(world, ref, T)\
486
(ECS_CAST(const T*, ecs_ref_get_id(world, ref, ecs_id(T))))
487
495
#define ecs_singleton_add(world, comp)\
496
ecs_add(world, ecs_id(comp), comp)
497
498
#define ecs_singleton_remove(world, comp)\
499
ecs_remove(world, ecs_id(comp), comp)
500
501
#define ecs_singleton_get(world, comp)\
502
ecs_get(world, ecs_id(comp), comp)
503
504
#define ecs_singleton_set_ptr(world, comp, ptr)\
505
ecs_set_ptr(world, ecs_id(comp), comp, ptr)
506
507
#define ecs_singleton_set(world, comp, ...)\
508
ecs_set(world, ecs_id(comp), comp, __VA_ARGS__)
509
510
#define ecs_singleton_ensure(world, comp)\
511
ecs_ensure(world, ecs_id(comp), comp)
512
513
#define ecs_singleton_modified(world, comp)\
514
ecs_modified(world, ecs_id(comp), comp)
515
523
#define ecs_has(world, entity, T)\
524
ecs_has_id(world, entity, ecs_id(T))
525
526
#define ecs_has_pair(world, entity, first, second)\
527
ecs_has_id(world, entity, ecs_pair(first, second))
528
529
#define ecs_owns_pair(world, entity, first, second)\
530
ecs_owns_id(world, entity, ecs_pair(first, second))
531
532
#define ecs_owns(world, entity, T)\
533
ecs_owns_id(world, entity, ecs_id(T))
534
535
#define ecs_shares_id(world, entity, id)\
536
(ecs_search_relation(world, ecs_get_table(world, entity), 0, ecs_id(id), \
537
EcsIsA, 1, 0, 0, 0, 0) != -1)
538
539
#define ecs_shares_pair(world, entity, first, second)\
540
(ecs_shares_id(world, entity, ecs_pair(first, second)))
541
542
#define ecs_shares(world, entity, T)\
543
(ecs_shares_id(world, entity, ecs_id(T)))
544
552
#define ecs_enable_component(world, entity, T, enable)\
553
ecs_enable_id(world, entity, ecs_id(T), enable)
554
555
#define ecs_is_enabled_component(world, entity, T)\
556
ecs_is_enabled_id(world, entity, ecs_id(T))
557
558
#define ecs_enable_pair(world, entity, First, second, enable)\
559
ecs_enable_id(world, entity, ecs_pair(ecs_id(First), second), enable)
560
561
#define ecs_is_enabled_pair(world, entity, First, second)\
562
ecs_is_enabled_id(world, entity, ecs_pair(ecs_id(First), second))
563
571
#define ecs_lookup_path(world, parent, path)\
572
ecs_lookup_path_w_sep(world, parent, path, ".", NULL, true)
573
574
/* Deprecated: use ecs_lookup instead */
575
#define ecs_lookup_fullpath(world, path)\
576
ecs_lookup(world, path)
577
578
#define ecs_get_path(world, parent, child)\
579
ecs_get_path_w_sep(world, parent, child, ".", NULL)
580
581
#define ecs_get_fullpath(world, child)\
582
ecs_get_path_w_sep(world, 0, child, ".", NULL)
583
584
#define ecs_get_fullpath_buf(world, child, buf)\
585
ecs_get_path_w_sep_buf(world, 0, child, ".", NULL, buf)
586
587
#define ecs_new_from_path(world, parent, path)\
588
ecs_new_from_path_w_sep(world, parent, path, ".", NULL)
589
590
#define ecs_new_from_fullpath(world, path)\
591
ecs_new_from_path_w_sep(world, 0, path, ".", NULL)
592
593
#define ecs_add_path(world, entity, parent, path)\
594
ecs_add_path_w_sep(world, entity, parent, path, ".", NULL)
595
596
#define ecs_add_fullpath(world, entity, path)\
597
ecs_add_path_w_sep(world, entity, 0, path, ".", NULL)
598
608
#define ecs_set_hooks(world, T, ...)\
609
ecs_set_hooks_id(world, ecs_id(T), &(ecs_type_hooks_t)__VA_ARGS__)
610
611
#define ecs_get_hooks(world, T)\
612
ecs_get_hooks_id(world, ecs_id(T));
613
621
#define ECS_CTOR(type, var, ...)\
622
ECS_XTOR_IMPL(type, ctor, var, __VA_ARGS__)
623
631
#define ECS_DTOR(type, var, ...)\
632
ECS_XTOR_IMPL(type, dtor, var, __VA_ARGS__)
633
641
#define ECS_COPY(type, dst_var, src_var, ...)\
642
ECS_COPY_IMPL(type, dst_var, src_var, __VA_ARGS__)
643
651
#define ECS_MOVE(type, dst_var, src_var, ...)\
652
ECS_MOVE_IMPL(type, dst_var, src_var, __VA_ARGS__)
653
661
#define ECS_ON_ADD(type, ptr, ...)\
662
ECS_HOOK_IMPL(type, ecs_on_add(type), ptr, __VA_ARGS__)
663
#define ECS_ON_REMOVE(type, ptr, ...)\
664
ECS_HOOK_IMPL(type, ecs_on_remove(type), ptr, __VA_ARGS__)
665
#define ECS_ON_SET(type, ptr, ...)\
666
ECS_HOOK_IMPL(type, ecs_on_set(type), ptr, __VA_ARGS__)
667
668
/* Map from typename to function name of component lifecycle action */
669
#define ecs_ctor(type) type##_ctor
670
#define ecs_dtor(type) type##_dtor
671
#define ecs_copy(type) type##_copy
672
#define ecs_move(type) type##_move
673
#define ecs_on_set(type) type##_on_set
674
#define ecs_on_add(type) type##_on_add
675
#define ecs_on_remove(type) type##_on_remove
676
684
#define ecs_count(world, type)\
685
ecs_count_id(world, ecs_id(type))
686
694
#define ecs_field(it, T, index)\
695
(ECS_CAST(T*, ecs_field_w_size(it, sizeof(T), index)))
696
704
#define ecs_table_get(world, table, T, offset)\
705
(ECS_CAST(T*, ecs_table_get_id(world, table, ecs_id(T), offset)))
706
707
#define ecs_table_get_pair(world, table, First, second, offset)\
708
(ECS_CAST(First*, ecs_table_get_id(world, table, ecs_pair(ecs_id(First), second), offset)))
709
710
#define ecs_table_get_pair_second(world, table, first, Second, offset)\
711
(ECS_CAST(Second*, ecs_table_get_id(world, table, ecs_pair(first, ecs_id(Second)), offset)))
712
720
#define ecs_value(T, ptr) ((ecs_value_t){ecs_id(T), ptr})
721
#define ecs_value_new_t(world, T) ecs_value_new(world, ecs_id(T))
722
733
#define ecs_sort_table(id) ecs_id(id##_sort_table)
734
735
#define ecs_compare(id) ecs_id(id##_compare_fn)
736
737
/* Declare efficient table sorting operation that uses provided compare function.
738
* For best results use LTO or make the function body visible in the same compilation unit.
739
* Variadic arguments are prepended before generated functions, use it to declare static
740
* or exported functions.
741
* Parameters of the comparison function:
742
* ecs_entity_t e1, const void* ptr1,
743
* ecs_entity_t e2, const void* ptr2
744
* Parameters of the sort functions:
745
* ecs_world_t *world
746
* ecs_table_t *table
747
* ecs_entity_t *entities
748
* void *ptr
749
* int32_t elem_size
750
* int32_t lo
751
* int32_t hi
752
* ecs_order_by_action_t order_by - Pointer to the original comparison function. You are not supposed to use it.
753
* Example:
754
*
755
* @code
756
* 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; }
757
* ECS_SORT_TABLE_WITH_COMPARE(MyType, MyCustomCompare, CompareMyType)
758
* @endcode
759
*/
760
#define ECS_SORT_TABLE_WITH_COMPARE(id, op_name, compare_fn, ...) \
761
static int32_t ECS_CONCAT(op_name, _partition)( \
762
ecs_world_t *world, \
763
ecs_table_t *table, \
764
ecs_entity_t *entities, \
765
void *ptr, \
766
int32_t elem_size, \
767
int32_t lo, \
768
int32_t hi, \
769
ecs_order_by_action_t order_by) \
770
{ \
771
(void)(order_by); \
772
int32_t p = (hi + lo) / 2; \
773
void *pivot = ECS_ELEM(ptr, elem_size, p); \
774
ecs_entity_t pivot_e = entities[p]; \
775
int32_t i = lo - 1, j = hi + 1; \
776
void *el; \
777
repeat: \
778
{ \
779
do { \
780
i ++; \
781
el = ECS_ELEM(ptr, elem_size, i); \
782
} while ( compare_fn(entities[i], el, pivot_e, pivot) < 0); \
783
do { \
784
j --; \
785
el = ECS_ELEM(ptr, elem_size, j); \
786
} while ( compare_fn(entities[j], el, pivot_e, pivot) > 0); \
787
if (i >= j) { \
788
return j; \
789
} \
790
ecs_table_swap_rows(world, table, i, j); \
791
if (p == i) { \
792
pivot = ECS_ELEM(ptr, elem_size, j); \
793
pivot_e = entities[j]; \
794
} else if (p == j) { \
795
pivot = ECS_ELEM(ptr, elem_size, i); \
796
pivot_e = entities[i]; \
797
} \
798
goto repeat; \
799
} \
800
} \
801
__VA_ARGS__ void op_name( \
802
ecs_world_t *world, \
803
ecs_table_t *table, \
804
ecs_entity_t *entities, \
805
void *ptr, \
806
int32_t size, \
807
int32_t lo, \
808
int32_t hi, \
809
ecs_order_by_action_t order_by) \
810
{ \
811
if ((hi - lo) < 1) { \
812
return; \
813
} \
814
int32_t p = ECS_CONCAT(op_name, _partition)(world, table, entities, ptr, size, lo, hi, order_by); \
815
op_name(world, table, entities, ptr, size, lo, p, order_by); \
816
op_name(world, table, entities, ptr, size, p + 1, hi, order_by); \
817
}
818
819
/* Declare efficient table sorting operation that uses default component comparison operator.
820
* For best results use LTO or make the comparison operator visible in the same compilation unit.
821
* Variadic arguments are prepended before generated functions, use it to declare static
822
* or exported functions.
823
* Example:
824
*
825
* @code
826
* ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
827
* ECS_SORT_TABLE(MyType)
828
* @endcode
829
*/
830
#define ECS_SORT_TABLE(id, ...) \
831
ECS_SORT_TABLE_WITH_COMPARE(id, ecs_sort_table(id), ecs_compare(id), __VA_ARGS__)
832
833
/* Declare component comparison operations.
834
* Parameters:
835
* ecs_entity_t e1, const void* ptr1,
836
* ecs_entity_t e2, const void* ptr2
837
* Example:
838
*
839
* @code
840
* ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
841
* @endcode
842
*/
843
#define ECS_COMPARE(id, ...) \
844
int ecs_compare(id)(ecs_entity_t e1, const void* ptr1, ecs_entity_t e2, const void* ptr2) { \
845
__VA_ARGS__ \
846
}
847
857
#define ecs_isa(e) ecs_pair(EcsIsA, e)
858
#define ecs_childof(e) ecs_pair(EcsChildOf, e)
859
#define ecs_dependson(e) ecs_pair(EcsDependsOn, e)
860
861
#define ecs_query_new(world, q_expr)\
862
ecs_query_init(world, &(ecs_query_desc_t){\
863
.filter.expr = q_expr\
864
})
865
866
#define ecs_rule_new(world, q_expr)\
867
ecs_rule_init(world, &(ecs_filter_desc_t){\
868
.expr = q_expr\
869
})
870
875
#endif
// FLECS_C_