Flecs
v3.1
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
ecs_assert(ecs_id(id_) != 0, ECS_INVALID_PARAMETER, NULL);\
113
}
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_get(world, entity, T)\
328
(ECS_CAST(const T*, ecs_get_id(world, entity, ecs_id(T))))
329
330
#define ecs_get_pair(world, subject, First, second)\
331
(ECS_CAST(const First*, ecs_get_id(world, subject,\
332
ecs_pair(ecs_id(First), second))))
333
334
#define ecs_get_pair_second(world, subject, first, Second)\
335
(ECS_CAST(const Second*, ecs_get_id(world, subject,\
336
ecs_pair(first, ecs_id(Second)))))
337
338
#define ecs_get_pair_object ecs_get_pair_second
339
340
#define ecs_record_get(world, record, T)\
341
(ECS_CAST(const T*, ecs_record_get_id(world, record, ecs_id(T))))
342
343
#define ecs_record_get_pair(world, record, First, second)\
344
(ECS_CAST(const First*, ecs_record_get_id(world, record, \
345
ecs_pair(ecs_id(First), second))))
346
347
#define ecs_record_get_pair_second(world, record, first, Second)\
348
(ECS_CAST(const Second*, ecs_record_get_id(world, record,\
349
ecs_pair(first, ecs_id(Second)))))
350
351
#define ecs_record_get_mut(world, record, T)\
352
(ECS_CAST(T*, ecs_record_get_mut_id(world, record, ecs_id(T))))
353
354
#define ecs_record_get_mut_pair(world, record, First, second)\
355
(ECS_CAST(First*, ecs_record_get_mut_id(world, record, \
356
ecs_pair(ecs_id(First), second))))
357
358
#define ecs_record_get_mut_pair_second(world, record, first, Second)\
359
(ECS_CAST(Second*, ecs_record_get_mut_id(world, record,\
360
ecs_pair(first, ecs_id(Second)))))
361
362
#define ecs_record_get_mut_pair_object ecs_record_get_mut_pair_second
363
364
#define ecs_ref_init(world, entity, T)\
365
ecs_ref_init_id(world, entity, ecs_id(T))
366
367
#define ecs_ref_get(world, ref, T)\
368
(ECS_CAST(const T*, ecs_ref_get_id(world, ref, ecs_id(T))))
369
370
#define ecs_get_mut(world, entity, T)\
371
(ECS_CAST(T*, ecs_get_mut_id(world, entity, ecs_id(T))))
372
373
#define ecs_get_mut_pair(world, subject, First, second)\
374
(ECS_CAST(First*, ecs_get_mut_id(world, subject,\
375
ecs_pair(ecs_id(First), second))))
376
377
#define ecs_get_mut_pair_second(world, subject, first, Second)\
378
(ECS_CAST(Second*, ecs_get_mut_id(world, subject,\
379
ecs_pair(first, ecs_id(Second)))))
380
381
#define ecs_get_mut_pair_object ecs_get_mut_pair_second
382
383
#define ecs_modified(world, entity, component)\
384
ecs_modified_id(world, entity, ecs_id(component))
385
386
#define ecs_modified_pair(world, subject, first, second)\
387
ecs_modified_id(world, subject, ecs_pair(first, second))
388
396
#define ecs_singleton_add(world, comp)\
397
ecs_add(world, ecs_id(comp), comp)
398
399
#define ecs_singleton_remove(world, comp)\
400
ecs_remove(world, ecs_id(comp), comp)
401
402
#define ecs_singleton_get(world, comp)\
403
ecs_get(world, ecs_id(comp), comp)
404
405
#define ecs_singleton_set(world, comp, ...)\
406
ecs_set(world, ecs_id(comp), comp, __VA_ARGS__)
407
408
#define ecs_singleton_get_mut(world, comp)\
409
ecs_get_mut(world, ecs_id(comp), comp)
410
411
#define ecs_singleton_modified(world, comp)\
412
ecs_modified(world, ecs_id(comp), comp)
413
421
#define ecs_has(world, entity, T)\
422
ecs_has_id(world, entity, ecs_id(T))
423
424
#define ecs_has_pair(world, entity, first, second)\
425
ecs_has_id(world, entity, ecs_pair(first, second))
426
427
#define ecs_owns_id(world, entity, id)\
428
(ecs_search(world, ecs_get_table(world, entity), id, 0) != -1)
429
430
#define ecs_owns_pair(world, entity, first, second)\
431
ecs_owns_id(world, entity, ecs_pair(first, second))
432
433
#define ecs_owns(world, entity, T)\
434
ecs_owns_id(world, entity, ecs_id(T))
435
436
#define ecs_shares_id(world, entity, id)\
437
(ecs_search_relation(world, ecs_get_table(world, entity), 0, ecs_id(id), \
438
EcsIsA, 1, 0, 0, 0, 0) != -1)
439
440
#define ecs_shares_pair(world, entity, first, second)\
441
(ecs_shares_id(world, entity, ecs_pair(first, second)))
442
443
#define ecs_shares(world, entity, T)\
444
(ecs_shares_id(world, entity, ecs_id(T)))
445
453
#define ecs_enable_component(world, entity, T, enable)\
454
ecs_enable_id(world, entity, ecs_id(T), enable)
455
456
#define ecs_is_enabled_component(world, entity, T)\
457
ecs_is_enabled_id(world, entity, ecs_id(T))
458
459
#define ecs_enable_pair(world, entity, First, second, enable)\
460
ecs_enable_id(world, entity, ecs_pair(ecs_id(First), second), enable)
461
462
#define ecs_is_enabled_pair(world, entity, First, second)\
463
ecs_is_enabled_id(world, entity, ecs_pair(ecs_id(First), second))
464
472
#define ecs_lookup_path(world, parent, path)\
473
ecs_lookup_path_w_sep(world, parent, path, "."
, NULL, true)
474
475
#define ecs_lookup_fullpath(world, path)\
476
ecs_lookup_path_w_sep(world, 0, path, "."
, NULL, true)
477
478
#define ecs_get_path(world, parent, child)\
479
ecs_get_path_w_sep(world, parent, child, "."
, NULL)
480
481
#define ecs_get_fullpath(world, child)\
482
ecs_get_path_w_sep(world, 0, child, "."
, NULL)
483
484
#define ecs_get_fullpath_buf(world, child, buf)\
485
ecs_get_path_w_sep_buf(world, 0, child, "."
, NULL, buf)
486
487
#define ecs_new_from_path(world, parent, path)\
488
ecs_new_from_path_w_sep(world, parent, path, "."
, NULL)
489
490
#define ecs_new_from_fullpath(world, path)\
491
ecs_new_from_path_w_sep(world, 0, path, "."
, NULL)
492
493
#define ecs_add_path(world, entity, parent, path)\
494
ecs_add_path_w_sep(world, entity, parent, path, "."
, NULL)
495
496
#define ecs_add_fullpath(world, entity, path)\
497
ecs_add_path_w_sep(world, entity, 0, path, "."
, NULL)
498
508
#define ecs_set_hooks(world, T, ...)\
509
ecs_set_hooks_id(world, ecs_id(T), &(ecs_type_hooks_t)__VA_ARGS__)
510
511
#define ecs_get_hooks(world, T)\
512
ecs_get_hooks_id(world, ecs_id(T));
513
518
#define ECS_CTOR(type, var, ...)\
519
ECS_XTOR_IMPL(type, ctor, var, __VA_ARGS__)
520
525
#define ECS_DTOR(type, var, ...)\
526
ECS_XTOR_IMPL(type, dtor, var, __VA_ARGS__)
527
532
#define ECS_COPY(type, dst_var, src_var, ...)\
533
ECS_COPY_IMPL(type, dst_var, src_var, __VA_ARGS__)
534
539
#define ECS_MOVE(type, dst_var, src_var, ...)\
540
ECS_MOVE_IMPL(type, dst_var, src_var, __VA_ARGS__)
541
546
#define ECS_ON_ADD(type, ptr, ...)\
547
ECS_HOOK_IMPL(type, ecs_on_add(type), ptr, __VA_ARGS__)
548
#define ECS_ON_REMOVE(type, ptr, ...)\
549
ECS_HOOK_IMPL(type, ecs_on_remove(type), ptr, __VA_ARGS__)
550
#define ECS_ON_SET(type, ptr, ...)\
551
ECS_HOOK_IMPL(type, ecs_on_set(type), ptr, __VA_ARGS__)
552
553
/* Map from typename to function name of component lifecycle action */
554
#define ecs_ctor(type) type##_ctor
555
#define ecs_dtor(type) type##_dtor
556
#define ecs_copy(type) type##_copy
557
#define ecs_move(type) type##_move
558
#define ecs_on_set(type) type##_on_set
559
#define ecs_on_add(type) type##_on_add
560
#define ecs_on_remove(type) type##_on_remove
561
569
#define ecs_count(world, type)\
570
ecs_count_id(world, ecs_id(type))
571
579
#define ecs_field(it, T, index)\
580
(ECS_CAST(T*, ecs_field_w_size(it, sizeof(T), index)))
581
589
#define ecs_table_get(world, table, T, offset)\
590
(ECS_CAST(T*, ecs_table_get_id(world, table, ecs_id(T), offset)))
591
592
#define ecs_table_get_pair(world, table, First, second, offset)\
593
(ECS_CAST(First*, ecs_table_get_id(world, table, ecs_pair(ecs_id(First), second), offset)))
594
595
#define ecs_table_get_pair_second(world, table, first, Second, offset)\
596
(ECS_CAST(Second*, ecs_table_get_id(world, table, ecs_pair(first, ecs_id(Second)), offset)))
597
605
#define ecs_value(T, ptr) ((ecs_value_t){ecs_id(T), ptr})
606
#define ecs_value_new_t(world, T) ecs_value_new(world, ecs_id(T))
607
618
#define ecs_sort_table(id) ecs_id(id##_sort_table)
619
620
#define ecs_compare(id) ecs_id(id##_compare_fn)
621
622
/* Declare efficient table sorting operation that uses provided compare function.
623
* For best results use LTO or make the function body visible in the same compilation unit.
624
* Variadic arguments are prepended before generated functions, use it to declare static
625
* or exported functions.
626
* Parameters of the comparison function:
627
* ecs_entity_t e1, const void* ptr1,
628
* ecs_entity_t e2, const void* ptr2
629
* Parameters of the sort functions:
630
* ecs_world_t *world
631
* ecs_table_t *table
632
* ecs_entity_t *entities
633
* void *ptr
634
* int32_t elem_size
635
* int32_t lo
636
* int32_t hi
637
* ecs_order_by_action_t order_by - Pointer to the original comparison function. You are not supposed to use it.
638
* Example:
639
* 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; }
640
* ECS_SORT_TABLE_WITH_COMPARE(MyType, MyCustomCompare, CompareMyType)
641
*/
642
#define ECS_SORT_TABLE_WITH_COMPARE(id, op_name, compare_fn, ...) \
643
static int32_t ECS_CONCAT(op_name, _partition)( \
644
ecs_world_t *world, \
645
ecs_table_t *table, \
646
ecs_entity_t *entities, \
647
void *ptr, \
648
int32_t elem_size, \
649
int32_t lo, \
650
int32_t hi, \
651
ecs_order_by_action_t order_by) \
652
{ \
653
(void)(order_by); \
654
int32_t p = (hi + lo) / 2; \
655
void *pivot = ECS_ELEM(ptr, elem_size, p); \
656
ecs_entity_t pivot_e = entities[p]; \
657
int32_t i = lo - 1, j = hi + 1; \
658
void *el; \
659
repeat: \
660
{ \
661
do { \
662
i ++; \
663
el = ECS_ELEM(ptr, elem_size, i); \
664
} while ( compare_fn(entities[i], el, pivot_e, pivot) < 0); \
665
do { \
666
j --; \
667
el = ECS_ELEM(ptr, elem_size, j); \
668
} while ( compare_fn(entities[j], el, pivot_e, pivot) > 0); \
669
if (i >= j) { \
670
return j; \
671
} \
672
ecs_table_swap_rows(world, table, i, j); \
673
if (p == i) { \
674
pivot = ECS_ELEM(ptr, elem_size, j); \
675
pivot_e = entities[j]; \
676
} else if (p == j) { \
677
pivot = ECS_ELEM(ptr, elem_size, i); \
678
pivot_e = entities[i]; \
679
} \
680
goto repeat; \
681
} \
682
} \
683
__VA_ARGS__ void op_name( \
684
ecs_world_t *world, \
685
ecs_table_t *table, \
686
ecs_entity_t *entities, \
687
void *ptr, \
688
int32_t size, \
689
int32_t lo, \
690
int32_t hi, \
691
ecs_order_by_action_t order_by) \
692
{ \
693
if ((hi - lo) < 1) { \
694
return; \
695
} \
696
int32_t p = ECS_CONCAT(op_name, _partition)(world, table, entities, ptr, size, lo, hi, order_by); \
697
op_name(world, table, entities, ptr, size, lo, p, order_by); \
698
op_name(world, table, entities, ptr, size, p + 1, hi, order_by); \
699
}
700
701
/* Declare efficient table sorting operation that uses default component comparison operator.
702
* For best results use LTO or make the comparison operator visible in the same compilation unit.
703
* Variadic arguments are prepended before generated functions, use it to declare static
704
* or exported functions.
705
* Example:
706
* ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
707
* ECS_SORT_TABLE(MyType)
708
*/
709
#define ECS_SORT_TABLE(id, ...) \
710
ECS_SORT_TABLE_WITH_COMPARE(id, ecs_sort_table(id), ecs_compare(id), __VA_ARGS__)
711
712
/* Declare component comparison operations.
713
* Parameters:
714
* ecs_entity_t e1, const void* ptr1,
715
* ecs_entity_t e2, const void* ptr2
716
* Example:
717
* ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
718
*/
719
#define ECS_COMPARE(id, ...) \
720
int ecs_compare(id)(ecs_entity_t e1, const void* ptr1, ecs_entity_t e2, const void* ptr2) { \
721
__VA_ARGS__ \
722
}
723
733
#define ecs_isa(e) ecs_pair(EcsIsA, e)
734
#define ecs_childof(e) ecs_pair(EcsChildOf, e)
735
#define ecs_dependson(e) ecs_pair(EcsDependsOn, e)
736
737
#define ecs_query_new(world, q_expr)\
738
ecs_query_init(world, &(ecs_query_desc_t){\
739
.filter.expr = q_expr\
740
})
741
742
#define ecs_rule_new(world, q_expr)\
743
ecs_rule_init(world, &(ecs_filter_desc_t){\
744
.expr = q_expr\
745
})
746
751
#endif
// FLECS_C_