Skip to content
Flecs v4.1
flecs_c.h
Go to the documentation of this file.
1/**
2 * @file addons/flecs_c.h
3 * @brief Extends the core API with convenience macros for C applications.
4 */
5
6#ifndef FLECS_C_
7#define FLECS_C_
8
9/**
10 * @defgroup flecs_c Macro API
11 * @ingroup c
12 * Convenience macros for C API.
13 *
14 * @{
15 */
16
17/**
18 * @defgroup flecs_c_creation Creation macros
19 * Convenience macros for creating entities, components, and observers.
20 *
21 * @{
22 */
23
24/** Forward declare an entity, tag, prefab, or any other entity identifier. */
25#define ECS_DECLARE(id)\
26 ecs_entity_t id, ecs_id(id)
27
28/** Forward declare a tag. */
29#define ECS_TAG_DECLARE ECS_DECLARE
30
31/** Define a forward-declared tag.
32 *
33 * Example:
34 *
35 * @code
36 * ECS_TAG_DEFINE(world, MyTag);
37 * @endcode
38 */
39#define ECS_TAG_DEFINE(world, id_) \
40 { \
41 ecs_entity_desc_t desc = {0}; \
42 desc.id = id_; \
43 desc.name = #id_; \
44 id_ = ecs_entity_init(world, &desc); \
45 ecs_id(id_) = id_; \
46 ecs_assert(id_ != 0, ECS_INVALID_PARAMETER, "failed to create tag %s", #id_); \
47 } \
48 (void)id_; \
49 (void)ecs_id(id_)
50
51/** Declare and define a tag.
52 *
53 * Example:
54 *
55 * @code
56 * ECS_TAG(world, MyTag);
57 * @endcode
58 */
59#define ECS_TAG(world, id) \
60 ecs_entity_t ecs_id(id); \
61 ecs_entity_t id = 0; \
62 ECS_TAG_DEFINE(world, id)
63
64/** Forward declare a component. */
65#define ECS_COMPONENT_DECLARE(id) ecs_entity_t ecs_id(id)
66
67/** Define a forward-declared component.
68 *
69 * Example:
70 *
71 * @code
72 * ECS_COMPONENT_DEFINE(world, Position);
73 * @endcode
74 */
75#define ECS_COMPONENT_DEFINE(world, id_) \
76 {\
77 ecs_component_desc_t desc = {0}; \
78 ecs_entity_desc_t edesc = {0}; \
79 edesc.id = ecs_id(id_); \
80 edesc.use_low_id = true; \
81 edesc.name = #id_; \
82 edesc.symbol = #id_; \
83 desc.entity = ecs_entity_init(world, &edesc); \
84 desc.type.size = ECS_SIZEOF(id_); \
85 desc.type.alignment = ECS_ALIGNOF(id_); \
86 ecs_id(id_) = ecs_component_init(world, &desc);\
87 ecs_assert(ecs_id(id_) != 0, ECS_INVALID_PARAMETER, "failed to create component %s", #id_);\
88 }\
89 (void)ecs_id(id_)
90
91/** Declare and define a component.
92 *
93 * Example:
94 *
95 * @code
96 * ECS_COMPONENT(world, Position);
97 * @endcode
98 */
99#define ECS_COMPONENT(world, id)\
100 ecs_entity_t ecs_id(id) = 0;\
101 ECS_COMPONENT_DEFINE(world, id);\
102 (void)ecs_id(id)
103
104/** Forward declare an observer. */
105#define ECS_OBSERVER_DECLARE(id) ecs_entity_t ecs_id(id)
106
107/** Define a forward-declared observer.
108 *
109 * Example:
110 *
111 * @code
112 * ECS_OBSERVER_DEFINE(world, AddPosition, EcsOnAdd, Position);
113 * @endcode
114 */
115#define ECS_OBSERVER_DEFINE(world, id_, kind, ...)\
116 {\
117 ecs_observer_desc_t desc = {0};\
118 ecs_entity_desc_t edesc = {0}; \
119 edesc.id = ecs_id(id_); \
120 edesc.name = #id_; \
121 desc.entity = ecs_entity_init(world, &edesc); \
122 desc.callback = id_;\
123 desc.query.expr = #__VA_ARGS__;\
124 desc.events[0] = kind;\
125 ecs_id(id_) = ecs_observer_init(world, &desc);\
126 ecs_assert(ecs_id(id_) != 0, ECS_INVALID_PARAMETER, "failed to create observer %s", #id_);\
127 }\
128 (void)ecs_id(id_)
129
130/** Declare and define an observer.
131 *
132 * Example:
133 *
134 * @code
135 * ECS_OBSERVER(world, AddPosition, EcsOnAdd, Position);
136 * @endcode
137 */
138#define ECS_OBSERVER(world, id, kind, ...)\
139 ecs_entity_t ecs_id(id) = 0; \
140 ECS_OBSERVER_DEFINE(world, id, kind, __VA_ARGS__);\
141 ecs_entity_t id = ecs_id(id);\
142 (void)ecs_id(id);\
143 (void)id
144
145/** Forward declare a query. */
146#define ECS_QUERY_DECLARE(name) ecs_query_t* name
147
148/** Define a forward-declared query.
149 *
150 * Example:
151 *
152 * @code
153 * ECS_QUERY_DEFINE(world, Move, Position, [in] Velocity);
154 * @endcode
155 */
156#define ECS_QUERY_DEFINE(world, name_, ...)\
157 {\
158 ecs_query_desc_t desc = {0};\
159 ecs_entity_desc_t edesc = {0}; \
160 edesc.name = #name_; \
161 desc.entity = ecs_entity_init(world, &edesc); \
162 desc.expr = #__VA_ARGS__;\
163 name_ = ecs_query_init(world, &desc);\
164 ecs_assert(name_ != NULL, ECS_INVALID_PARAMETER, "failed to create query %s", #name_);\
165 }\
166 (void)name_
167
168/** Declare and define a query.
169 *
170 * Example:
171 *
172 * @code
173 * ECS_QUERY(world, Move, Position, [in] Velocity);
174 * @endcode
175 */
176#define ECS_QUERY(world, name, ...)\
177 ecs_query_t* name = NULL; \
178 ECS_QUERY_DEFINE(world, name, __VA_ARGS__);\
179 (void)name
180
181/** Shorthand for creating an entity with ecs_entity_init().
182 *
183 * Example:
184 *
185 * @code
186 * ecs_entity(world, {
187 * .name = "MyEntity"
188 * });
189 * @endcode
190 */
191#define ecs_entity(world, ...)\
192 ecs_entity_init(world, &(ecs_entity_desc_t) __VA_ARGS__ )
193
194/** Shorthand for creating a component with ecs_component_init().
195 *
196 * Example:
197 *
198 * @code
199 * ecs_component(world, {
200 * .type.size = 4,
201 * .type.alignment = 4
202 * });
203 * @endcode
204 */
205#define ecs_component(world, ...)\
206 ecs_component_init(world, &(ecs_component_desc_t) __VA_ARGS__ )
207
208/** Shorthand for creating a query with ecs_query_init().
209 *
210 * Example:
211 *
212 * @code
213 * ecs_query(world, {
214 * .terms = {{ ecs_id(Position) }}
215 * });
216 * @endcode
217 */
218#define ecs_query(world, ...)\
219 ecs_query_init(world, &(ecs_query_desc_t) __VA_ARGS__ )
220
221/** Shorthand for creating an observer with ecs_observer_init().
222 *
223 * Example:
224 *
225 * @code
226 * ecs_observer(world, {
227 * .terms = {{ ecs_id(Position) }},
228 * .events = { EcsOnAdd },
229 * .callback = AddPosition
230 * });
231 * @endcode
232 */
233#define ecs_observer(world, ...)\
234 ecs_observer_init(world, &(ecs_observer_desc_t) __VA_ARGS__ )
235
236/** @} */
237
238/**
239 * @defgroup flecs_c_type_safe Type-Safe API
240 * Macros that wrap around core functions to provide a "type-safe" API in C.
241 *
242 * @{
243 */
244
245/**
246 * @defgroup flecs_c_entities Entity API
247 * @{
248 */
249
250/**
251 * @defgroup flecs_c_creation_deletion Creation & Deletion
252 * @{
253 */
254
255/** Create a new entity with a component. */
256#define ecs_new_w(world, T) ecs_new_w_id(world, ecs_id(T))
257
258/** Create a new entity with a pair. */
259#define ecs_new_w_pair(world, first, second)\
260 ecs_new_w_id(world, ecs_pair(first, second))
261
262/** Bulk create entities with a component. */
263#define ecs_bulk_new(world, component, count)\
264 ecs_bulk_new_w_id(world, ecs_id(component), count)
265
266/** @} */
267
268/**
269 * @defgroup flecs_c_adding_removing Adding & Removing
270 * @{
271 */
272
273/** Add a component to an entity. */
274#define ecs_add(world, entity, T)\
275 ecs_add_id(world, entity, ecs_id(T))
276
277/** Add a pair to an entity. */
278#define ecs_add_pair(world, subject, first, second)\
279 ecs_add_id(world, subject, ecs_pair(first, second))
280
281/** Remove a component from an entity. */
282#define ecs_remove(world, entity, T)\
283 ecs_remove_id(world, entity, ecs_id(T))
284
285/** Remove a pair from an entity. */
286#define ecs_remove_pair(world, subject, first, second)\
287 ecs_remove_id(world, subject, ecs_pair(first, second))
288
289/** Auto-override a component on an entity. */
290#define ecs_auto_override(world, entity, T)\
291 ecs_auto_override_id(world, entity, ecs_id(T))
292
293/** Auto-override a pair on an entity. */
294#define ecs_auto_override_pair(world, subject, first, second)\
295 ecs_auto_override_id(world, subject, ecs_pair(first, second))
296
297/** @} */
298
299/**
300 * @defgroup flecs_c_getting_setting Getting & Setting
301 * @{
302 */
303
304/** Insert a new entity with a list of component values. */
305#define ecs_insert(world, ...)\
306 ecs_insert_w_values(world, ecs_values(__VA_ARGS__))
307
308/** Set a component using a pointer. */
309#define ecs_set_ptr(world, entity, component, ptr)\
310 ecs_set_id(world, entity, ecs_id(component), sizeof(component), ptr)
311
312/** Set a component value. */
313#define ecs_set(world, entity, component, ...)\
314 ecs_set_id(world, entity, ecs_id(component), sizeof(component), &(component)__VA_ARGS__)
315
316/** Set the first element of a pair. */
317#define ecs_set_pair(world, subject, First, second, ...)\
318 ecs_set_id(world, subject,\
319 ecs_pair(ecs_id(First), second),\
320 sizeof(First), &(First)__VA_ARGS__)
321
322/** Set the second element of a pair. */
323#define ecs_set_pair_second(world, subject, first, Second, ...)\
324 ecs_set_id(world, subject,\
325 ecs_pair(first, ecs_id(Second)),\
326 sizeof(Second), &(Second)__VA_ARGS__)
327
328/** Set a component with auto-override. */
329#define ecs_set_override(world, entity, T, ...)\
330 ecs_add_id(world, entity, ECS_AUTO_OVERRIDE | ecs_id(T));\
331 ecs_set(world, entity, T, __VA_ARGS__)
332
333/** Emplace a component. */
334#define ecs_emplace(world, entity, T, is_new)\
335 (ECS_CAST(T*, ecs_emplace_id(world, entity, ecs_id(T), sizeof(T), is_new)))
336
337/** Emplace the first element of a pair. */
338#define ecs_emplace_pair(world, entity, First, second, is_new)\
339 (ECS_CAST(First*, ecs_emplace_id(world, entity, ecs_pair_t(First, second), sizeof(First), is_new)))
340
341/** Get a component. */
342#define ecs_get(world, entity, T)\
343 (ECS_CAST(const T*, ecs_get_id(world, entity, ecs_id(T))))
344
345/** Get the first element of a pair. */
346#define ecs_get_pair(world, subject, First, second)\
347 (ECS_CAST(const First*, ecs_get_id(world, subject,\
348 ecs_pair(ecs_id(First), second))))
349
350/** Get the second element of a pair. */
351#define ecs_get_pair_second(world, subject, first, Second)\
352 (ECS_CAST(const Second*, ecs_get_id(world, subject,\
353 ecs_pair(first, ecs_id(Second)))))
354
355/** Get a mutable pointer to a component. */
356#define ecs_get_mut(world, entity, T)\
357 (ECS_CAST(T*, ecs_get_mut_id(world, entity, ecs_id(T))))
358
359/** Get a mutable pointer to the first element of a pair. */
360#define ecs_get_mut_pair(world, subject, First, second)\
361 (ECS_CAST(First*, ecs_get_mut_id(world, subject,\
362 ecs_pair(ecs_id(First), second))))
363
364/** Get a mutable pointer to the second element of a pair. */
365#define ecs_get_mut_pair_second(world, subject, first, Second)\
366 (ECS_CAST(Second*, ecs_get_mut_id(world, subject,\
367 ecs_pair(first, ecs_id(Second)))))
368
369/** Get a mutable pointer to a component. */
370#define ecs_get_mut(world, entity, T)\
371 (ECS_CAST(T*, ecs_get_mut_id(world, entity, ecs_id(T))))
372
373/** Ensure entity has a component, return mutable pointer. */
374#define ecs_ensure(world, entity, T)\
375 (ECS_CAST(T*, ecs_ensure_id(world, entity, ecs_id(T), sizeof(T))))
376
377/** Ensure entity has the first element of a pair, return mutable pointer. */
378#define ecs_ensure_pair(world, subject, First, second)\
379 (ECS_CAST(First*, ecs_ensure_id(world, subject,\
380 ecs_pair(ecs_id(First), second), sizeof(First))))
381
382/** Ensure entity has the second element of a pair, return mutable pointer. */
383#define ecs_ensure_pair_second(world, subject, first, Second)\
384 (ECS_CAST(Second*, ecs_ensure_id(world, subject,\
385 ecs_pair(first, ecs_id(Second)), sizeof(Second))))
386
387/** Signal that a component has been modified. */
388#define ecs_modified(world, entity, component)\
389 ecs_modified_id(world, entity, ecs_id(component))
390
391/** Signal that a pair has been modified. */
392#define ecs_modified_pair(world, subject, first, second)\
393 ecs_modified_id(world, subject, ecs_pair(first, second))
394
395/** Initialize a ref for a component. */
396#define ecs_ref_init(world, entity, T)\
397 ecs_ref_init_id(world, entity, ecs_id(T))
398
399/** Get a component from a ref. */
400#define ecs_ref_get(world, ref, T)\
401 (ECS_CAST(T*, ecs_ref_get_id(world, ref, ecs_id(T))))
402
403/** @} */
404
405/**
406 * @defgroup flecs_c_singletons Singletons
407 * @{
408 */
409
410/** Add a singleton component. */
411#define ecs_singleton_add(world, comp)\
412 ecs_add(world, ecs_id(comp), comp)
413
414/** Remove a singleton component. */
415#define ecs_singleton_remove(world, comp)\
416 ecs_remove(world, ecs_id(comp), comp)
417
418/** Get a singleton component. */
419#define ecs_singleton_get(world, comp)\
420 ecs_get(world, ecs_id(comp), comp)
421
422/** Get a mutable pointer to a singleton component. */
423#define ecs_singleton_get_mut(world, comp)\
424 ecs_get_mut(world, ecs_id(comp), comp)
425
426/** Set a singleton component using a pointer. */
427#define ecs_singleton_set_ptr(world, comp, ptr)\
428 ecs_set_ptr(world, ecs_id(comp), comp, ptr)
429
430/** Set a singleton component value. */
431#define ecs_singleton_set(world, comp, ...)\
432 ecs_set(world, ecs_id(comp), comp, __VA_ARGS__)
433
434/** Ensure a singleton component, return mutable pointer. */
435#define ecs_singleton_ensure(world, comp)\
436 ecs_ensure(world, ecs_id(comp), comp)
437
438/** Emplace a singleton component. */
439#define ecs_singleton_emplace(world, comp, is_new)\
440 ecs_emplace(world, ecs_id(comp), comp, is_new)
441
442/** Signal that a singleton component has been modified. */
443#define ecs_singleton_modified(world, comp)\
444 ecs_modified(world, ecs_id(comp), comp)
445
446/** Test if world has a singleton component. */
447#define ecs_singleton_has(world, comp)\
448 ecs_has(world, ecs_id(comp), comp)
449
450/** Add a singleton pair component. */
451#define ecs_singleton_add_pair(world, rel, tgt)\
452 ecs_add_id(world, ecs_id(rel), ecs_pair_t(rel, tgt))
453
454/** Remove a singleton pair component. */
455#define ecs_singleton_remove_pair(world, rel, tgt)\
456 ecs_remove_id(world, ecs_id(rel), ecs_pair_t(rel, tgt))
457
458/** Get a singleton pair component. */
459#define ecs_singleton_get_pair(world, rel, tgt)\
460 ecs_get_pair(world, ecs_id(rel), rel, tgt)
461
462/** Get a mutable pointer to a singleton pair component. */
463#define ecs_singleton_get_mut_pair(world, rel, tgt)\
464 ecs_get_mut_pair(world, ecs_id(rel), rel, tgt)
465
466/** Set a singleton pair component value. */
467#define ecs_singleton_set_pair(world, rel, tgt, ...)\
468 ecs_set_pair(world, ecs_id(rel), rel, tgt, __VA_ARGS__)
469
470/** Ensure a singleton pair component, return mutable pointer. */
471#define ecs_singleton_ensure_pair(world, rel, tgt)\
472 ecs_ensure_pair(world, ecs_id(rel), rel, tgt)
473
474/** Emplace a singleton pair component. */
475#define ecs_singleton_emplace_pair(world, rel, tgt, is_new)\
476 ecs_emplace_pair(world, ecs_id(rel), rel, tgt, is_new)
477
478/** Signal that a singleton pair component has been modified. */
479#define ecs_singleton_modified_pair(world, rel, tgt)\
480 ecs_modified_id(world, ecs_id(rel), ecs_pair_t(rel, tgt))
481
482/** Test if world has a singleton pair component. */
483#define ecs_singleton_has_pair(world, rel, tgt)\
484 ecs_has_id(world, ecs_id(rel), ecs_pair_t(rel, tgt))
485
486/** @} */
487
488/**
489 * @defgroup flecs_c_has Has, Owns, Shares
490 * @{
491 */
492
493/** Test if an entity has a component. */
494#define ecs_has(world, entity, T)\
495 ecs_has_id(world, entity, ecs_id(T))
496
497/** Test if an entity has a pair. */
498#define ecs_has_pair(world, entity, first, second)\
499 ecs_has_id(world, entity, ecs_pair(first, second))
500
501/** Test if an entity owns a pair. */
502#define ecs_owns_pair(world, entity, first, second)\
503 ecs_owns_id(world, entity, ecs_pair(first, second))
504
505/** Test if an entity owns a component. */
506#define ecs_owns(world, entity, T)\
507 ecs_owns_id(world, entity, ecs_id(T))
508
509/** Test if an entity shares a component. */
510#define ecs_shares_id(world, entity, id)\
511 (ecs_search_relation(world, ecs_get_table(world, entity), 0, ecs_id(id), \
512 EcsIsA, 1, 0, 0, 0, 0) != -1)
513
514/** Test if an entity shares a pair. */
515#define ecs_shares_pair(world, entity, first, second)\
516 (ecs_shares_id(world, entity, ecs_pair(first, second)))
517
518/** Test if an entity shares a component. */
519#define ecs_shares(world, entity, T)\
520 (ecs_shares_id(world, entity, ecs_id(T)))
521
522/** Get the target for a relationship. */
523#define ecs_get_target_for(world, entity, rel, T)\
524 ecs_get_target_for_id(world, entity, rel, ecs_id(T))
525
526/** @} */
527
528/**
529 * @defgroup flecs_c_enable_disable Enabling & Disabling
530 * @{
531 */
532
533/** Enable or disable a component. */
534#define ecs_enable_component(world, entity, T, enable)\
535 ecs_enable_id(world, entity, ecs_id(T), enable)
536
537/** Test if a component is enabled. */
538#define ecs_is_enabled(world, entity, T)\
539 ecs_is_enabled_id(world, entity, ecs_id(T))
540
541/** Enable or disable a pair. */
542#define ecs_enable_pair(world, entity, First, second, enable)\
543 ecs_enable_id(world, entity, ecs_pair(ecs_id(First), second), enable)
544
545/** Test if a pair is enabled. */
546#define ecs_is_enabled_pair(world, entity, First, second)\
547 ecs_is_enabled_id(world, entity, ecs_pair(ecs_id(First), second))
548
549/** @} */
550
551/**
552 * @defgroup flecs_c_entity_names Entity Names
553 * @{
554 */
555
556/** Lookup an entity from a parent. */
557#define ecs_lookup_from(world, parent, path)\
558 ecs_lookup_path_w_sep(world, parent, path, ".", NULL, true)
559
560/** Get path from a parent. */
561#define ecs_get_path_from(world, parent, child)\
562 ecs_get_path_w_sep(world, parent, child, ".", NULL)
563
564/** Get path from root. */
565#define ecs_get_path(world, child)\
566 ecs_get_path_w_sep(world, 0, child, ".", NULL)
567
568/** Get path from root, write to buffer. */
569#define ecs_get_path_buf(world, child, buf)\
570 ecs_get_path_w_sep_buf(world, 0, child, ".", NULL, buf, false)
571
572/** Create a new entity from a path. */
573#define ecs_new_from_path(world, parent, path)\
574 ecs_new_from_path_w_sep(world, parent, path, ".", NULL)
575
576/** Add a path to an entity. */
577#define ecs_add_path(world, entity, parent, path)\
578 ecs_add_path_w_sep(world, entity, parent, path, ".", NULL)
579
580/** Add a full path to an entity. */
581#define ecs_add_fullpath(world, entity, path)\
582 ecs_add_path_w_sep(world, entity, 0, path, ".", NULL)
583
584/** @} */
585
586/** @} */
587
588/**
589 * @defgroup flecs_c_components Component API
590 * @{
591 */
592
593/** Set component hooks. */
594#define ecs_set_hooks(world, T, ...)\
595 ecs_set_hooks_id(world, ecs_id(T), &(ecs_type_hooks_t)__VA_ARGS__)
596
597/** Get component hooks. */
598#define ecs_get_hooks(world, T)\
599 ecs_get_hooks_id(world, ecs_id(T));
600
601/** Declare a constructor.
602 * Example:
603 *
604 * @code
605 * ECS_CTOR(MyType, ptr, { ptr->value = NULL; });
606 * @endcode
607 */
608#define ECS_CTOR(type, var, ...)\
609 ECS_XTOR_IMPL(type, ctor, var, __VA_ARGS__)
610
611/** Declare a destructor.
612 * Example:
613 *
614 * @code
615 * ECS_DTOR(MyType, ptr, { free(ptr->value); });
616 * @endcode
617 */
618#define ECS_DTOR(type, var, ...)\
619 ECS_XTOR_IMPL(type, dtor, var, __VA_ARGS__)
620
621/** Declare a copy action.
622 * Example:
623 *
624 * @code
625 * ECS_COPY(MyType, dst, src, { dst->value = strdup(src->value); });
626 * @endcode
627 */
628#define ECS_COPY(type, dst_var, src_var, ...)\
629 ECS_COPY_IMPL(type, dst_var, src_var, __VA_ARGS__)
630
631/** Declare a move action.
632 * Example:
633 *
634 * @code
635 * ECS_MOVE(MyType, dst, src, { dst->value = src->value; src->value = 0; });
636 * @endcode
637 */
638#define ECS_MOVE(type, dst_var, src_var, ...)\
639 ECS_MOVE_IMPL(type, dst_var, src_var, __VA_ARGS__)
640
641/** Declare an on_add hook.
642 * Example:
643 *
644 * @code
645 * ECS_ON_ADD(MyType, ptr, { printf("added\n"); });
646 * @endcode
647 */
648#define ECS_ON_ADD(type, ptr, ...)\
649 ECS_HOOK_IMPL(type, ecs_on_add(type), ptr, __VA_ARGS__)
650/** Declare an on_remove hook. */
651#define ECS_ON_REMOVE(type, ptr, ...)\
652 ECS_HOOK_IMPL(type, ecs_on_remove(type), ptr, __VA_ARGS__)
653/** Declare an on_set hook. */
654#define ECS_ON_SET(type, ptr, ...)\
655 ECS_HOOK_IMPL(type, ecs_on_set(type), ptr, __VA_ARGS__)
656
657/** Map from typename to constructor function name. */
658#define ecs_ctor(type) type##_ctor
659/** Map from typename to destructor function name. */
660#define ecs_dtor(type) type##_dtor
661/** Map from typename to copy function name. */
662#define ecs_copy(type) type##_copy
663/** Map from typename to move function name. */
664#define ecs_move(type) type##_move
665/** Map from typename to on_set function name. */
666#define ecs_on_set(type) type##_on_set
667/** Map from typename to on_add function name. */
668#define ecs_on_add(type) type##_on_add
669/** Map from typename to on_remove function name. */
670#define ecs_on_remove(type) type##_on_remove
671
672/** @} */
673
674/**
675 * @defgroup flecs_c_ids ID API
676 * @{
677 */
678
679/** Count entities with a component. */
680#define ecs_count(world, type)\
681 ecs_count_id(world, ecs_id(type))
682
683/** @} */
684
685/**
686 * @defgroup flecs_c_iterators Iterator API
687 * @{
688 */
689
690/** Get field data for a component. */
691#define ecs_field(it, T, index)\
692 (ECS_CAST(T*, ecs_field_w_size(it, sizeof(T), index)))
693
694/** Get field data for a component matched through component inheritance.
695 * Use this instead of ecs_field() when a field is matched on a component that
696 * is derived from the queried (base) type. The data must be iterated with the
697 * stride returned by ecs_field_stride(). */
698#define ecs_base_field(it, T, index)\
699 (ECS_CAST(T*, ecs_base_field_w_size(it, sizeof(T), index)))
700
701/** Get field data for a self-owned component. */
702#define ecs_field_self(it, T, index)\
703 (ECS_CAST(T*, ecs_field_self_w_size(it, sizeof(T), index)))
704
705/** Get field data at a specific row. */
706#define ecs_field_at(it, T, index, row)\
707 (ECS_CAST(T*, ecs_field_at_w_size(it, sizeof(T), index, row)))
708
709/** @} */
710
711/**
712 * @defgroup flecs_c_tables Table API
713 * @{
714 */
715
716/** Get a component from a table at an offset. */
717#define ecs_table_get(world, table, T, offset)\
718 (ECS_CAST(T*, ecs_table_get_id(world, table, ecs_id(T), offset)))
719
720/** Get the first element of a pair from a table at an offset. */
721#define ecs_table_get_pair(world, table, First, second, offset)\
722 (ECS_CAST(First*, ecs_table_get_id(world, table, ecs_pair(ecs_id(First), second), offset)))
723
724/** Get the second element of a pair from a table at an offset. */
725#define ecs_table_get_pair_second(world, table, first, Second, offset)\
726 (ECS_CAST(Second*, ecs_table_get_id(world, table, ecs_pair(first, ecs_id(Second)), offset)))
727
728/** @} */
729
730/**
731 * @defgroup flecs_c_values Value API
732 * @{
733 */
734
735/** Convenience macro for creating a compound literal ID array. */
736#define ecs_ids(...) (ecs_id_t[]){ __VA_ARGS__, 0 }
737
738/** Convenience macro for creating a compound literal values array. */
739#define ecs_values(...) (ecs_value_t[]){ __VA_ARGS__, {0, 0}}
740
741/** Convenience macro for creating a compound literal value. */
742#define ecs_value_ptr(T, ptr) ((ecs_value_t){ecs_id(T), ptr})
743
744/** Convenience macro for creating a compound literal pair value. */
745#define ecs_pair_value(R, t, ...) ((ecs_value_t){ecs_pair_t(R, t), &(R)__VA_ARGS__})
746
747/** Convenience macro for creating a compound literal pair value. */
748#define ecs_pair_value_2nd(r, T, ...) ((ecs_value_t){ecs_pair(r, ecs_id(T)), &(T)__VA_ARGS__})
749
750/** Convenience macro for creating a heap-allocated value. */
751#define ecs_ptr_new_t(world, T) ecs_ptr_new(world, ecs_id(T))
752
753/** Convenience macro for creating a compound literal value literal. */
754#define ecs_value(T, ...) ((ecs_value_t){ecs_id(T), &(T)__VA_ARGS__})
755
756/** @} */
757
758/** @} */
759
760/**
761 * @defgroup flecs_c_table_sorting Table sorting
762 * Convenience macros for sorting tables.
763 *
764 * @{
765 */
766/** Declare a table sort function. */
767#define ecs_sort_table(id) ecs_id(id##_sort_table)
768
769/** Declare a comparison function. */
770#define ecs_compare(id) ecs_id(id##_compare_fn)
771
772/** Declare an efficient table sorting operation that uses the provided compare function.
773 * For best results, use LTO or make the function body visible in the same compilation unit.
774 * Variadic arguments are prepended before generated functions; use them to declare static
775 * or exported functions.
776 * Parameters of the comparison function:
777 * ecs_entity_t e1, const void* ptr1,
778 * ecs_entity_t e2, const void* ptr2
779 * Parameters of the sort functions:
780 * ecs_world_t *world
781 * ecs_table_t *table
782 * ecs_entity_t *entities
783 * void *ptr
784 * int32_t elem_size
785 * int32_t lo
786 * int32_t hi
787 * ecs_order_by_action_t order_by - Pointer to the original comparison function. You are not supposed to use it.
788 * Example:
789 *
790 * @code
791 * 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; }
792 * ECS_SORT_TABLE_WITH_COMPARE(MyType, MyCustomCompare, CompareMyType)
793 * @endcode
794 */
795#define ECS_SORT_TABLE_WITH_COMPARE(id, op_name, compare_fn, ...) \
796 static int32_t ECS_CONCAT(op_name, _partition)( \
797 ecs_world_t *world, \
798 ecs_table_t *table, \
799 ecs_entity_t *entities, \
800 void *ptr, \
801 int32_t elem_size, \
802 int32_t lo, \
803 int32_t hi, \
804 ecs_order_by_action_t order_by) \
805 { \
806 (void)(order_by); \
807 int32_t p = (hi + lo) / 2; \
808 void *pivot = ECS_ELEM(ptr, elem_size, p); \
809 ecs_entity_t pivot_e = entities[p]; \
810 int32_t i = lo - 1, j = hi + 1; \
811 void *el; \
812 repeat: \
813 { \
814 do { \
815 i ++; \
816 el = ECS_ELEM(ptr, elem_size, i); \
817 } while ( compare_fn(entities[i], el, pivot_e, pivot) < 0); \
818 do { \
819 j --; \
820 el = ECS_ELEM(ptr, elem_size, j); \
821 } while ( compare_fn(entities[j], el, pivot_e, pivot) > 0); \
822 if (i >= j) { \
823 return j; \
824 } \
825 ecs_table_swap_rows(world, table, i, j); \
826 if (p == i) { \
827 pivot = ECS_ELEM(ptr, elem_size, j); \
828 pivot_e = entities[j]; \
829 } else if (p == j) { \
830 pivot = ECS_ELEM(ptr, elem_size, i); \
831 pivot_e = entities[i]; \
832 } \
833 goto repeat; \
834 } \
835 } \
836 __VA_ARGS__ void op_name( \
837 ecs_world_t *world, \
838 ecs_table_t *table, \
839 ecs_entity_t *entities, \
840 void *ptr, \
841 int32_t size, \
842 int32_t lo, \
843 int32_t hi, \
844 ecs_order_by_action_t order_by) \
845 { \
846 if ((hi - lo) < 1) { \
847 return; \
848 } \
849 int32_t p = ECS_CONCAT(op_name, _partition)(world, table, entities, ptr, size, lo, hi, order_by); \
850 op_name(world, table, entities, ptr, size, lo, p, order_by); \
851 op_name(world, table, entities, ptr, size, p + 1, hi, order_by); \
852 }
853
854/** Declare an efficient table sorting operation that uses the default component comparison operator.
855 * For best results, use LTO or make the comparison operator visible in the same compilation unit.
856 * Variadic arguments are prepended before generated functions; use them to declare static
857 * or exported functions.
858 * Example:
859 *
860 * @code
861 * ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
862 * ECS_SORT_TABLE(MyType)
863 * @endcode
864 */
865#define ECS_SORT_TABLE(id, ...) \
866 ECS_SORT_TABLE_WITH_COMPARE(id, ecs_sort_table(id), ecs_compare(id), __VA_ARGS__)
867
868/** Declare component comparison operations.
869 * Parameters:
870 * ecs_entity_t e1, const void* ptr1,
871 * ecs_entity_t e2, const void* ptr2
872 * Example:
873 *
874 * @code
875 * ECS_COMPARE(MyType, { const MyType* p1 = ptr1; const MyType* p2 = ptr2; return p1->value - p2->value; });
876 * @endcode
877 */
878#define ECS_COMPARE(id, ...) \
879 int ecs_compare(id)(ecs_entity_t e1, const void* ptr1, ecs_entity_t e2, const void* ptr2) { \
880 __VA_ARGS__ \
881 }
882
883/** @} */
884
885/**
886 * @defgroup flecs_c_misc Misc
887 * Misc convenience macros.
888 *
889 * @{
890 */
891
892/** Construct an IsA pair. */
893#define ecs_isa(e) ecs_pair(EcsIsA, e)
894/** Construct a ChildOf pair. */
895#define ecs_childof(e) ecs_pair(EcsChildOf, e)
896/** Construct a DependsOn pair. */
897#define ecs_dependson(e) ecs_pair(EcsDependsOn, e)
898/** Construct a With pair. */
899#define ecs_with(e) ecs_pair(EcsWith, e)
900
901/** Iterate entities with a component. */
902#define ecs_each(world, id) ecs_each_id(world, ecs_id(id))
903/** Iterate entities with a pair. */
904#define ecs_each_pair(world, r, t) ecs_each_id(world, ecs_pair(r, t))
905/** Iterate entities with a pair (type-safe first element). */
906#define ecs_each_pair_t(world, R, t) ecs_each_id(world, ecs_pair(ecs_id(R), t))
907
908/** @} */
909
910/** @} */
911
912#endif // FLECS_C_