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