Skip to main content

flecs_ecs/core/flecs/
component_traits.rs

1//! Component traits are tags and pairs that can be added to components to modify their behavior.
2
3use super::*;
4
5/// Marker trait for Flecs component traits.
6pub trait FlecsComponentTrait {}
7
8// Component traits
9
10/// A relationship can be marked with the `Acyclic` trait to indicate that it cannot contain cycles.
11/// Both the builtin `ChildOf` and `IsA` relationships are marked acyclic. Knowing whether a relationship
12/// is acyclic allows the storage to detect and throw errors when a cyclic relationship is introduced by accident.
13///
14/// Note that because cycle detection requires expensive algorithms, adding `Acyclic` to a relationship does not
15/// guarantee that an error will be thrown when a cycle is accidentally introduced. While detection may improve
16/// over time, an application that runs without errors is no guarantee that it does not contain acyclic
17/// relationships with cycles.
18#[derive(Debug, Default, Clone)]
19pub struct Acyclic;
20
21impl_component_trait!(Acyclic, ECS_ACYCLIC);
22
23/// The `CanToggle` trait allows a component to be toggled. Component toggling can (temporarily) disable a
24/// component, which excludes it from queries. Component toggling can be used as a cheaper alternative to
25/// adding/removing as toggling relies on setting a bitset, and doesn't require the entity to be moved between
26/// tables. Component toggling can also be used to restore a component with its old value.
27///
28/// Queries treat a disabled component as if the entity doesn't have it. `CanToggle` components add a small
29/// amount of overhead to query evaluation, even for entities that did not toggle their component.
30///
31/// # Example
32/// ```rust
33/// # use flecs_ecs::prelude::*;
34///
35/// # #[derive(Component)]
36/// # struct Position {
37/// #     x: f32,
38/// #     y: f32,
39/// # }
40///
41/// # let world = World::new();
42///
43/// world
44///     .component::<Position>()
45///     .add_trait::<flecs::CanToggle>();
46///
47/// let e = world.entity().set(Position { x: 10.0, y: 20.0 });
48///
49/// e.disable(Position::id()); // Disable component
50/// assert!(!e.is_enabled(Position::id()));
51///
52/// e.enable(Position::id()); // Enable component
53/// assert!(e.is_enabled(Position::id()));
54/// ```
55#[derive(Debug, Default, Clone)]
56pub struct CanToggle;
57
58impl_component_trait!(CanToggle, ECS_CAN_TOGGLE);
59
60/// Cleanup traits ensure that the store does not contain any dangling references when entities are deleted.
61///
62/// When entities that are used as tags, components, relationships or relationship targets are deleted,
63/// cleanup traits ensure that the store does not contain any dangling references. Any cleanup policy
64/// provides this guarantee, so while they are configurable, applications cannot configure traits that
65/// allow for dangling references.
66///
67/// **Note**: this only applies to entities (like tags, components, relationships) that are added _to_
68/// other entities. It does not apply to components that store an entity value, so:
69///
70/// ```no_run
71/// # use flecs_ecs::prelude::*;
72/// # let world = World::new();
73/// # let parent = world.entity();
74/// # let e = world.entity();
75/// #[derive(Component)]
76/// struct MyComponent {
77///     e: Entity, // Not covered by cleanup traits
78/// }
79///
80/// e.child_of(parent); // Covered by cleanup traits
81/// ```
82///
83/// The default policy is that any references to the entity will be **removed**. For example, when the
84/// tag `Archer` is deleted, it will be removed from all entities that have it. Which is similar to invoking
85/// the [`World::remove_all()`](flecs_ecs::core::World::remove_all) method.
86///
87/// Since entities can be used in relationship pairs, just calling `remove_all` on just the entity itself
88/// does not guarantee that no dangling references are left. A more comprehensive description of what happens is:
89///
90/// ```
91/// # use flecs_ecs::prelude::*;
92/// # let world = World::new();
93/// # let archer = world.entity();
94/// world.remove_all(archer);
95/// world.remove_all((archer, flecs::Wildcard));
96/// world.remove_all((flecs::Wildcard, archer));
97/// ```
98///
99/// This succeeds in removing all possible references to `Archer`. Sometimes this behavior is not what we want however.
100/// Consider a parent-child hierarchy, where we want to delete the child entities when the parent is deleted.
101/// Instead of removing `(ChildOf, parent)` from all children, we need to *delete* the children.
102///
103/// We also want to specify this per relationship. If an entity has `(Likes, parent)` we may not want to delete that entity,
104/// meaning the cleanup we want to perform for `Likes` and `ChildOf` may not be the same.
105///
106/// This is what cleanup traits are for: to specify which action needs to be executed under which condition.
107/// They are applied *to* entities that have a reference to the entity being deleted:
108/// if I delete the `Archer` tag I remove the tag *from* all entities that have it.
109///
110/// To configure a cleanup policy for an entity, a `(Condition, Action)` pair can be added to it.
111/// If no policy is specified, the default cleanup action (`Remove`) is performed.
112///
113/// There are three cleanup actions:
114/// - [`Remove`]: as if doing `remove_all(entity)` (default)
115/// - [`Delete`]: as if doing `delete_with(entity)`
116/// - [`Panic`]: throw a fatal error (default for components)
117///
118/// There are two cleanup conditions:
119/// - [`OnDelete`]: the component, tag or relationship is deleted
120/// - [`OnDeleteTarget`]: a target used with the relationship is deleted
121///
122/// Policies apply to both regular and pair instances, so to all entities with `T` as well as `(T, *)`.
123///
124/// # Cleanup order
125///
126/// While cleanup actions allow for specifying what needs to happen when a particular entity is deleted,
127/// or when an entity used with a particular relationship is deleted, they do not enforce a strict cleanup *order*.
128/// The reason for this is that there can be many orderings that satisfy the cleanup traits.
129///
130/// This is important to consider especially when writing `OnRemove` triggers or hooks,
131/// as the order in which they are invoked highly depends on the order in which entities are cleaned up.
132///
133/// Take an example with a parent and a child that both have the `Node` tag:
134///
135/// ```rust
136/// # use flecs_ecs::prelude::*;
137/// # #[derive(Component)]
138/// # struct Node;
139/// # let world = World::new();
140/// world
141///     .observer::<flecs::OnRemove, ()>()
142///     .with(Node)
143///     .each_entity(|e, _| {
144///         // This observer will be invoked when a Node is removed
145///     });
146///
147/// let p = world.entity().add(Node);
148/// let c = world.entity().add(Node).child_of(p);
149/// ```
150///
151/// In this example, when calling `p.destruct()` the observer is first invoked for the child, and then for the parent,
152/// which is to be expected as the child is deleted before the parent.
153/// Cleanup traits do not however guarantee that this is always the case.
154///
155/// An application could also call `world.component::<Node>().destruct()` which would delete the `Node` component and
156/// all of its instances. In this scenario the cleanup traits for the `flecs::ChildOf` relationship are not considered,
157/// and therefore the ordering is undefined. Another typical scenario in which ordering is undefined is when an application
158/// has cyclical relationships with a `Delete` cleanup action.
159///
160/// #### Cleanup order during world teardown
161/// Cleanup issues often show up during world teardown as the ordering in which entities are deleted is controlled by the application.
162/// While world teardown respects cleanup traits, there can be many entity delete orderings that are valid according to the cleanup traits,
163/// but not all of them are equally useful. There are ways to organize entities that helps world cleanup to do the right thing. These are:
164///
165/// **Organize components, triggers, observers and systems in modules.**
166/// Storing these entities in modules ensures that they stay alive for as long as possible.
167/// This leads to more predictable cleanup ordering as components will be deleted as their entities are,
168/// vs. when the component is deleted. It also ensures that triggers and observers are not deleted while matching events are still being generated.
169///
170/// **Avoid organizing components, triggers, observers and systems under entities that are not modules**.
171/// If a non-module entity with children is stored in the root, it will get cleaned up along with other regular entities.
172/// If you have entities such as these organized in a non-module scope, consider adding the `flecs::Module` tag to the root of that scope.
173///
174/// The next section goes into more detail on why this improves cleanup behavior and what happens during world teardown.
175///
176/// #### World teardown sequence
177/// To understand why some ways to organize entities work better than others, having an overview of what happens during world teardown is useful.
178/// Here is a list of the steps that happen when a world is deleted:
179///
180/// 1. **Find all root entities**
181///    World teardown starts by finding all root entities, which are entities that do not have the builtin `ChildOf` relationship.
182///    Note that empty entities (entities without any components) are not found during this step.
183///
184/// 2. **Query out modules, components, observers and systems**
185///    This ensures that components are not cleaned up before the entities that use them, and triggers,
186///    observers and systems are not cleaned up while there are still conditions under which they could be invoked.
187///
188/// 3. **Query out entities that have no children**
189///    If entities have no children they cannot cause complex cleanup logic. This also decreases the likelihood of initiating cleanup actions that could impact other entities.
190///
191/// 4. **Delete root entities**
192///    The root entities that were not filtered out will be deleted.
193///
194/// 5. **Delete everything else**
195///    The last step will delete all remaining entities. At this point cleanup traits are no longer considered and cleanup order is undefined.
196pub mod cleanup {
197    use super::*;
198
199    /// Cleanup action. Remove any references to the entity being deleted. This is the default cleanup action.
200    /// see [`cleanup`] for general information on cleanup traits.
201    ///
202    /// # Example
203    /// ```
204    /// # use flecs_ecs::prelude::*;
205    /// # #[derive(Component)]
206    /// # struct Archer;
207    /// # let world = World::new();
208    ///
209    /// // Remove Archer from entities when Archer is deleted
210    /// world
211    ///     .component::<Archer>()
212    ///     .add_trait::<(flecs::OnDelete, flecs::Remove)>();
213    ///
214    /// let e = world.entity().add(Archer::id());
215    ///
216    /// // This will remove Archer from e
217    /// world.component::<Archer>().destruct();
218    /// ```
219    #[derive(Debug, Default, Clone)]
220    pub struct Remove;
221
222    impl_component_trait!(Remove, ECS_REMOVE);
223
224    /// Cleanup action. Delete any entities that have a reference to the entity being deleted.
225    /// see [`cleanup`] for general information on cleanup traits.
226    ///
227    /// # Example
228    ///
229    /// ```rust
230    /// # use flecs_ecs::prelude::*;
231    /// # #[derive(Component)]
232    /// # struct Archer;
233    /// # let world = World::new();
234    ///
235    /// // Delete entities with Archer when Archer is deleted
236    /// world
237    ///     .component::<Archer>()
238    ///     .add_trait::<(flecs::OnDelete, flecs::Delete)>();
239    ///
240    /// let e = world.entity().add(Archer::id());
241    ///
242    /// // This will delete e
243    /// world.component::<Archer>().destruct();
244    /// ```
245    ///
246    /// ```rust
247    /// # use flecs_ecs::prelude::*;
248    /// # let world = World::new();
249    /// world
250    ///     .component::<flecs::ChildOf>()
251    ///     .add_trait::<(flecs::OnDeleteTarget, flecs::Delete)>();
252    /// let p = world.entity();
253    /// let e = world.entity().child_of(p);
254    ///
255    /// // This will delete both p and e
256    /// p.destruct();
257    /// ```
258    #[derive(Debug, Default, Clone)]
259    pub struct Delete;
260
261    impl_component_trait!(Delete, ECS_DELETE);
262
263    /// Cleanup action. Throw a fatal error. This is the default for components.
264    /// see [`cleanup`] for general information on cleanup traits.
265    ///
266    /// # Example
267    ///
268    /// ```rust,no_run
269    /// # //TODO this doesn't panic in release mode, texted Sander 22 october 2025
270    /// # use flecs_ecs::prelude::*;
271    /// # #[derive(Component)]
272    /// # struct Archer;
273    /// # let world = World::new();
274    ///
275    /// // Panic when Archer is deleted
276    /// world
277    ///     .component::<Archer>()
278    ///     .add_trait::<(flecs::OnDelete, flecs::Panic)>();
279    ///
280    /// let e = world.entity().add(Archer::id());
281    ///
282    /// // This will panic
283    /// world.component::<Archer>().destruct();
284    /// ```
285    #[derive(Debug, Default, Clone)]
286    pub struct Panic;
287
288    impl_component_trait!(Panic, ECS_PANIC);
289
290    /// Cleanup condition. Specifies what action to take when the component, tag or relationship is deleted.
291    ///
292    /// Used as a pair with one of [`Remove`], [`Delete`], or [`Panic`].
293    ///
294    /// see [`cleanup`] for general information on cleanup traits.
295    ///
296    /// # Example
297    ///
298    /// ```rust
299    /// # use flecs_ecs::prelude::*;
300    /// # #[derive(Component)]
301    /// # struct Archer;
302    /// # let world = World::new();
303    ///
304    /// // Delete entities with Archer when Archer is deleted
305    /// world
306    ///     .component::<Archer>()
307    ///     .add_trait::<(flecs::OnDelete, flecs::Delete)>();
308    ///
309    /// let e = world.entity().add(Archer::id());
310    ///
311    /// // This will delete e
312    /// world.component::<Archer>().destruct();
313    /// ```
314    ///
315    /// # See also
316    /// * [`OnDeleteTarget`]
317    #[derive(Debug, Default, Clone)]
318    pub struct OnDelete;
319
320    impl_component_trait!(OnDelete, ECS_ON_DELETE);
321
322    /// Cleanup condition. Specifies what action to take when a target used with the relationship is deleted.
323    ///
324    /// Used as a pair with one of [`Remove`], [`Delete`], or [`Panic`].
325    ///
326    /// see [`cleanup`] for general information on cleanup traits.
327    ///
328    /// # Example
329    ///
330    /// ```rust
331    /// # use flecs_ecs::prelude::*;
332    /// # let world = World::new();
333    /// world
334    ///     .component::<flecs::ChildOf>()
335    ///     .add_trait::<(flecs::OnDeleteTarget, flecs::Delete)>();
336    /// let p = world.entity();
337    /// let e = world.entity().child_of(p);
338    ///
339    /// // This will delete both p and e
340    /// p.destruct();
341    /// ```
342    ///
343    /// # See also
344    /// * [`OnDelete`]
345    #[derive(Debug, Default, Clone)]
346    pub struct OnDeleteTarget;
347
348    impl_component_trait!(OnDeleteTarget, ECS_ON_DELETE_TARGET);
349}
350
351pub use cleanup::*;
352
353/// The `DontFragment` trait uses the same sparse storage as the `Sparse` trait, but does not fragment tables.
354/// This can be desirable especially if a component or relationship is very sparse (e.g. it is only added to a
355/// few entities) as this would otherwise result in many tables that only contain a small number of entities.
356///
357/// The following code example shows how to mark a component as `DontFragment`:
358///
359/// # Example
360/// ```no_run
361/// # use flecs_ecs::prelude::*;
362/// #[derive(Component)]
363/// #[flecs(traits(DontFragment))]
364/// struct Position {
365///     x: f32,
366///     y: f32,
367/// }
368/// # let world = World::new();
369///
370/// // or
371/// world
372///     .component::<Position>()
373///     .add_trait::<flecs::DontFragment>();
374/// ```
375///
376/// Components with the `DontFragment` trait have the following limitations:
377/// - They don't show up in types [`Archetype`](flecs_ecs::core::Archetype)
378/// - Monitors don't trigger on `DontFragment` components. The reason for this is that monitors compare the
379///   previous table with the current table of an entity to determine if an entity started matching, and
380///   `DontFragment` components aren't part of the table.
381///
382/// Support for `DontFragment` has a number of (temporary) limitations:
383/// - `target_for` does not yet work for `DontFragment` components.
384/// - `DontFragment` components are not serialized yet to JSON (and don't show up in the explorer).
385/// - `Or`, `Optional`, `AndFrom` and `NotFrom` operators are not yet supported.
386/// - Component inheritance and transitivity are not yet supported.
387/// - Queries for `DontFragment` components may run slower than expected.
388///
389/// What does work:
390/// - ECS operations (`add`, `remove`, `get`, `get_mut`, `ensure`, `emplace`, `set`, `delete`).
391/// - Relationships (including `Exclusive` relationships).
392/// - Simple component queries.
393/// - Wildcard queries.
394/// - Queries with variables.
395#[derive(Debug, Default, Clone)]
396pub struct DontFragment;
397
398impl_component_trait!(DontFragment, ECS_DONT_FRAGMENT);
399
400/// The `Exclusive` trait enforces that an entity can have only a single instance of a relationship. When a
401/// second instance is added, it replaces the first instance. An example of a relationship with the `Exclusive`
402/// trait is the builtin `ChildOf` relationship.
403///
404/// # Usage Example
405/// ```no_run
406/// # use flecs_ecs::prelude::*;
407/// # let world = World::new();
408/// # let e = world.entity();
409/// # let parent_a = world.entity();
410/// # let parent_b = world.entity();
411/// e.child_of(parent_a);
412/// e.child_of(parent_b); // replaces (ChildOf, parent_a)
413/// ```
414///
415/// to create a custom exclusive relationship, add the `Exclusive` trait to it:
416/// ```
417/// # use flecs_ecs::prelude::*;
418/// # let world = World::new();
419/// let married_to = world.entity().add_trait::<flecs::Exclusive>();
420/// ```
421#[derive(Debug, Default, Clone)]
422pub struct Exclusive;
423
424impl_component_trait!(Exclusive, ECS_EXCLUSIVE);
425
426/// Entities can be annotated with the `Final` trait, which prevents using them with `IsA` relationship.
427/// This is similar to the concept of a final class as something that cannot be extended.
428///
429/// # Example
430/// ```
431/// # use flecs_ecs::prelude::*;
432/// # let world = World::new();
433/// let e = world.entity().add_trait::<flecs::Final>();
434///
435/// // not allowed
436/// // let i = world.entity().is_a(e);
437/// ```
438///
439/// Queries may use the final trait to optimize, as they do not have to explore subsets of a final entity.
440#[derive(Debug, Default, Clone)]
441pub struct Final;
442
443impl_component_trait!(Final, ECS_FINAL);
444
445/// The `Inheritable` trait indicates that a component can be inherited from (it can be used as target of an
446/// `IsA` relationship). It is not required to add this trait to components before using them as target of an
447/// `IsA` pair, but it can be used to ensure that queries for the component take into account component inheritance.
448///
449/// # Example
450/// ```
451/// # use flecs_ecs::prelude::*;
452/// # #[derive(Component)]
453/// # struct Unit;
454/// # #[derive(Component)]
455/// # struct Warrior;
456/// # let world = World::new();
457/// world.component::<Unit>().add_trait::<flecs::Inheritable>();
458///
459/// let q = world.query::<()>().with(Unit).build();
460///
461/// world.component::<Warrior>().is_a(Unit::id());
462///
463/// q.each_entity(|e, _| {
464///     // ...
465/// });
466/// ```
467///
468/// Queries must be aware of (potential) inheritance relationships when they are created. A query will be
469/// created with support for inheritance under the following conditions:
470///  - If the component has the `Inheritable` trait
471///  - If the component inherits from another component and is not `Final`
472///
473/// If a query was not aware of inheritance relationships at creation time and one or more of the components
474/// in the query were inherited from, query iteration will fail in debug mode.
475#[derive(Debug, Default, Clone)]
476pub struct Inheritable;
477
478impl_component_trait!(Inheritable, ECS_INHERITABLE);
479
480/// The `OneOf` trait enforces that the target of the relationship is a child of a specified entity. `OneOf`
481/// can be used to indicate that the target needs to be either a child of the relationship (common for enum
482/// relationships), or of another entity.
483///
484/// # Example - Constrain target to child of relationship
485/// ```
486/// # use flecs_ecs::prelude::*;
487/// # let world = World::new();
488///
489/// // Enforce that target of relationship is child of Food
490/// let food = world.entity().add_trait::<flecs::OneOf>();
491/// let apples = world.entity().child_of(food);
492/// let fork = world.entity();
493///
494/// // This is ok, Apples is a child of Food
495/// let a = world.entity().add((food, apples));
496///
497/// // not allowed - Fork is not a child of Food
498/// // let b = world.entity().add((food, fork));
499/// ```
500///
501/// # Example - Constrain target to child of another entity
502/// The following example shows how `OneOf` can be used to enforce that the relationship
503/// target is the child of an entity other than the relationship:
504/// ```
505/// # use flecs_ecs::prelude::*;
506/// # let world = World::new();
507///
508/// // Enforce that target of relationship is child of Food
509/// let food = world.entity();
510/// let eats = world.entity().add((flecs::OneOf::id(), food));
511/// let apples = world.entity().child_of(food);
512/// let fork = world.entity();
513///
514/// // This is ok, Apples is a child of Food
515/// let a = world.entity().add((eats, apples));
516///
517/// // not allowed - Fork is not a child of Food
518/// // let b = world.entity().add((eats, fork));
519/// ```
520#[derive(Debug, Default, Clone)]
521pub struct OneOf;
522
523impl_component_trait!(OneOf, ECS_ONE_OF);
524
525/// `OnInstantiate` traits configure component behavior during entity instantiation.
526///
527/// The `OnInstantiate` trait configures the behavior of components when an entity is instantiated from
528/// another entity (usually a prefab). Instantiation happens when an `IsA` pair is added to an entity.
529///
530/// By default, when an entity is instantiated, the components from the base entity (the `IsA` target)
531/// are copied to the instance. This behavior can be modified with the `OnInstantiate` trait, which can
532/// be used as a pair in combination with three targets:
533///
534/// | Target | Description |
535/// |--------|-------------|
536/// | [`Override`] | Copy component from base to instance (default) |
537/// | [`Inherit`] | Inherit component from base |
538/// | [`DontInherit`] | Don't inherit (and don't copy) component from base |
539pub mod on_instantiate {
540    use super::*;
541
542    /// The `OnInstantiate` trait configures the behavior of components when an entity is instantiated from another
543    /// entity (usually a prefab). Instantiation happens when an `IsA` pair is added to an entity.
544    ///
545    /// By default, when an entity is instantiated, the components from the base entity (the `IsA` target) are copied
546    /// to the instance. This behavior can be modified with the `OnInstantiate` trait, which can be used as pair in
547    /// combination with three targets: [`Override`], [`Inherit`], or [`DontInherit`].
548    #[derive(Debug, Default, Clone)]
549    pub struct OnInstantiate;
550
551    impl_component_trait!(OnInstantiate, ECS_ON_INSTANTIATE);
552
553    /// The default behavior for `OnInstantiate` is `Override`, which means that the component is copied to the
554    /// instance. This means that after instantiation, the instance has an owned copy for the component that masks
555    /// the base component (the "override").
556    ///
557    /// Note that for an override to work correctly, a component has to be clone-able.
558    ///
559    /// # Example
560    /// ```
561    /// # use flecs_ecs::prelude::*;
562    ///
563    /// #[derive(Component, Clone, PartialEq)]
564    /// struct Mass {
565    ///     value: f32,
566    /// }
567    /// # let world = World::new();
568    ///
569    /// // Register component with trait. Optional, since this is the default behavior.
570    /// world
571    ///     .component::<Mass>()
572    ///     .add_trait::<(flecs::OnInstantiate, flecs::Override)>();
573    ///
574    /// let base = world.entity().set(Mass { value: 100.0 });
575    /// let inst = world.entity().is_a(base); // Mass is copied to inst
576    ///
577    /// assert!(inst.owns(Mass::id()));
578    /// assert!(base.cloned::<&Mass>() == inst.cloned::<&Mass>());
579    /// ```
580    #[derive(Debug, Default, Clone)]
581    pub struct Override;
582
583    impl_component_trait!(Override, ECS_OVERRIDE);
584
585    /// Components with the `Inherit` trait are inherited from a base entity (the `IsA` target) on instantiation.
586    /// Inherited components are not copied to the instance, and are only stored once in memory. Operations such as
587    /// `get` and `has`, and queries will automatically lookup inheritable components by following the `IsA` relationship.
588    ///
589    /// Inheritable components can be overridden manually by adding the component to the instance. This results in
590    /// the same behavior as the `Override` trait, where the component is copied from the base entity.
591    ///
592    /// # Example
593    /// ```
594    /// # use flecs_ecs::prelude::*;
595    /// #[derive(Component, Clone, PartialEq)]
596    /// struct Mass {
597    ///     value: f32,
598    /// }
599    /// # let world = World::new();
600    ///
601    /// // Register component with trait
602    /// world
603    ///     .component::<Mass>()
604    ///     .add_trait::<(flecs::OnInstantiate, flecs::Inherit)>();
605    ///
606    /// let base = world.entity().set(Mass { value: 100.0 });
607    /// let inst = world.entity().is_a(base);
608    ///
609    /// assert!(inst.has(Mass::id()));
610    /// assert!(!inst.owns(Mass::id()));
611    /// // Inherited component points to the same data
612    /// assert!(base.cloned::<&Mass>() == inst.cloned::<&Mass>());
613    /// ```
614    #[derive(Debug, Default, Clone)]
615    pub struct Inherit;
616
617    impl_component_trait!(Inherit, ECS_INHERIT);
618
619    /// Components with the `DontInherit` trait are not inherited from a base entity (the `IsA` target) on instantiation,
620    /// and are not copied to the instance. Operations such as `has` and `get` will not find the component,
621    /// and queries will not match it.
622    ///
623    /// Components with the `DontInherit` cannot be overridden manually.
624    /// When a component is added to an instance and the base also has the component,
625    /// the base component is ignored and its value is not copied to the instance.
626    ///
627    /// # Example
628    /// ```
629    /// # use flecs_ecs::prelude::*;
630    /// # let world = World::new();
631    /// # #[derive(Component, Clone, PartialEq)]
632    /// # struct Mass {
633    /// #     value: f32,
634    /// # }
635    /// // Register component with trait
636    /// world
637    ///     .component::<Mass>()
638    ///     .add_trait::<(flecs::OnInstantiate, flecs::DontInherit)>();
639    ///
640    /// let base = world.entity().set(Mass { value: 100.0 });
641    /// let inst = world.entity().is_a(base);
642    ///
643    /// assert!(!inst.has(Mass::id()));
644    /// assert!(!inst.owns(Mass::id()));
645    /// assert!(inst.try_get::<&Mass>(|mass| {}).is_none());
646    /// ```
647    #[derive(Debug, Default, Clone)]
648    pub struct DontInherit;
649
650    impl_component_trait!(DontInherit, ECS_DONT_INHERIT);
651}
652
653pub use on_instantiate::*;
654
655/// The `OrderedChildren` trait can be added to entities to indicate that creation order or a custom order should be preserved.
656///
657/// When this trait is added to a parent, the entity ids returned by the [`EntityView::each_child`](flecs_ecs::core::EntityView::each_child) operations will be in creation or custom order.
658/// Children of a parent with the `OrderedChildren` trait are guaranteed to be returned in a single result.
659///
660/// The trait does not affect the order in which entities are returned by queries.
661///
662/// The stored order can be modified by an application with the [`EntityView::set_child_order`](flecs_ecs::core::EntityView::set_child_order) operation.
663///
664/// # Example
665/// ```rust
666/// # use flecs_ecs::prelude::*;
667/// # let world = World::new();
668/// # #[derive(Component)]
669/// # struct Position { x: f32, y: f32 }
670/// let parent = world.entity().add_trait::<flecs::OrderedChildren>();
671///
672/// let child_1 = world.entity().child_of(parent);
673/// let child_2 = world.entity().child_of(parent);
674/// let child_3 = world.entity().child_of(parent);
675///
676/// // Adding/removing components usually changes the order in which children are
677/// // iterated, but with the OrderedChildren trait order is preserved.
678/// child_2.set(Position { x: 10.0, y: 20.0 });
679///
680/// parent.each_child(|child| {
681///     // 1st result: child_1
682///     // 2nd result: child_2
683///     // 3rd result: child_3
684/// });
685/// ```
686#[derive(Debug, Default, Clone)]
687pub struct OrderedChildren;
688
689impl_component_trait!(OrderedChildren, ECS_ORDERED_CHILDREN);
690
691/// A relationship can be marked with `PairIsTag` in which case a pair with the relationship will never contain data.
692/// By default the data associated with a pair is determined by whether either the relationship or target are components.
693/// For some relationships however, even if the target is a component, no data should be added to the relationship.
694///
695/// # Example
696/// TODO
697#[derive(Debug, Default, Clone)]
698pub struct PairIsTag;
699
700impl_component_trait!(PairIsTag, ECS_PAIR_IS_TAG);
701
702/// Component trait. Enforces that an entity can only be used as a relationship.
703///
704/// # Example
705///
706/// ```rust, no_run
707/// # use flecs_ecs::prelude::*;
708/// # let world = World::new();
709/// #[derive(Component)]
710/// struct Likes;
711///
712/// #[derive(Component)]
713/// struct Apples;
714///
715/// world
716///     .component::<Likes>()
717///     .add_trait::<flecs::Relationship>();
718///
719/// let e = world
720///     .entity()
721///     // .add(Likes::id()) // Panic, 'Likes' is not used as relationship
722///     // .add((Apples::id(), Likes::id())) // Panic, 'Likes' is not used as relationship, but as target
723///     .add((Likes::id(), Apples::id())); // OK
724/// ```
725///
726/// Entities marked with `Relationship` may still be used as target if the relationship part of the pair has the `Trait` trait.
727/// This ensures the relationship can still be used to configure the behavior of other entities.
728///
729/// # Example
730///
731/// ```rust
732/// # use flecs_ecs::prelude::*;
733/// # let world = World::new();
734/// #[derive(Component)]
735/// struct Likes;
736///
737/// #[derive(Component)]
738/// struct Loves;
739///
740/// world
741///     .component::<Likes>()
742///     .add_trait::<flecs::Relationship>();
743///
744/// // Even though Likes is marked as relationship and used as target here, this
745/// // won't panic as With is marked as trait.
746/// world
747///     .component::<Loves>()
748///     .add_trait::<(flecs::With, Likes)>();
749/// ```
750#[derive(Debug, Default, Clone)]
751pub struct Relationship;
752
753impl_component_trait!(Relationship, ECS_RELATIONSHIP);
754
755/// A relationship can be marked reflexive which means that a query like `Relationship(Entity, Entity)` should evaluate to true.
756/// The utility of `Reflexive` becomes more obvious with an example:
757///
758/// Given this dataset:
759/// ```ignore
760/// IsA(Oak, Tree)
761/// ```
762///
763/// we can ask whether an oak is a tree:
764/// ```ignore
765/// IsA(Oak, Tree)
766/// - Yes, an Oak is a tree (Oak has (IsA, Tree))
767/// ```
768///
769/// We can also ask whether a tree is a tree, which it obviously is:
770/// ```ignore
771/// IsA(Tree, Tree)
772/// - Yes, even though Tree does not have (IsA, Tree)
773/// ```
774///
775/// However, this does not apply to all relationships. Consider a dataset with a `LocatedIn` relationship:
776///
777/// ```ignore
778/// LocatedIn(SanFrancisco, UnitedStates)
779/// ```
780///
781/// we can now ask whether `SanFrancisco` is located in `SanFrancisco`, which it is not:
782/// ```ignore
783/// LocatedIn(SanFrancisco, SanFrancisco)
784/// - No
785/// ```
786///
787/// In these examples, `IsA` is a reflexive relationship, whereas `LocatedIn` is not.
788#[derive(Debug, Default, Clone)]
789pub struct Reflexive;
790
791impl_component_trait!(Reflexive, ECS_REFLEXIVE);
792
793/// The `Singleton` trait enforces that a component can only be instantiated once in the world.
794/// A singleton component can only be added to the entity that is associated with the component.
795/// This happens automatically when using the singleton APIs:
796///
797/// # Example
798///
799/// ```rust
800/// # use flecs_ecs::prelude::*;
801/// # let world = World::new();
802/// # #[derive(Component)]
803/// # struct TimeOfDay(f32);
804/// world
805///     .component::<TimeOfDay>()
806///     .add_trait::<flecs::Singleton>();
807///
808/// world.set(TimeOfDay(0.0));
809/// ```
810///
811/// Attempting to add the component to other entities beside itself will panic.
812///
813/// When a query is created for a component with the `Singleton` trait,
814/// the query will automatically match the singleton component on the component entity.
815/// This is the same as specifying the component itself as source for the term:
816///
817/// ```rust
818/// # use flecs_ecs::prelude::*;
819/// # let world = World::new();
820/// # #[derive(Component)]
821/// # struct Position { x: f32, y: f32 }
822/// # #[derive(Component)]
823/// # struct Velocity { x: f32, y: f32 }
824/// # #[derive(Component)]
825/// # struct TimeOfDay(f32);
826/// // Automatically matches TimeOfDay as singleton
827/// let q = world.new_query::<(&Position, &Velocity, &TimeOfDay)>();
828///
829/// // Is the same as
830/// let q = world
831///     .query::<(&Position, &Velocity, &TimeOfDay)>()
832///     .term_at(2)
833///     .set_src(TimeOfDay::id())
834///     .build();
835/// ```
836#[derive(Debug, Default, Clone)]
837pub struct Singleton;
838
839impl_component_trait!(Singleton, ECS_SINGLETON);
840
841/// The `Sparse` trait configures a component to use sparse storage.
842/// Sparse components are stored outside of tables, which means they do not have to be moved.
843/// Sparse components are also guaranteed to have stable pointers, which means that a component pointer
844/// is not invalidated when an entity moves to a new table. ECS operations and queries work as expected with sparse components.
845///
846/// Sparse components trade in query speed for component add/remove speed.
847/// Adding and removing sparse components still requires an archetype change.
848///
849/// They also enable storage of non-movable components.
850///
851/// # Example
852/// adding the trait
853/// ```rust
854/// # use flecs_ecs::prelude::*;
855/// # #[derive(Component)]
856/// # struct Position { x: f32, y: f32 }
857/// # let world = World::new();
858/// world.component::<Position>().add_trait::<flecs::Sparse>();
859/// ```
860#[derive(Debug, Default, Clone)]
861pub struct Sparse;
862
863impl_component_trait!(Sparse, ECS_SPARSE);
864
865/// The `Symmetric` trait enforces that when a relationship `(R, Y)` is added to entity `X`, the relationship
866/// `(R, X)` will be added to entity `Y`. The reverse is also true, if relationship `(R, Y)` is removed from `X`,
867/// relationship `(R, X)` will be removed from `Y`.
868///
869/// The symmetric trait is useful for relationships that do not make sense unless they are bidirectional.
870/// Examples of such relationships are `AlliesWith`, `MarriedTo`, `TradingWith` and so on.
871///
872/// # Example
873/// ```
874/// # use flecs_ecs::prelude::*;
875/// # let world = World::new();
876/// let married_to = world.entity().add_trait::<flecs::Symmetric>();
877/// let bob = world.entity();
878/// let alice = world.entity();
879/// bob.add((married_to, alice)); // Also adds (MarriedTo, Bob) to Alice
880/// ```
881#[derive(Debug, Default, Clone)]
882pub struct Symmetric;
883
884impl_component_trait!(Symmetric, ECS_SYMMETRIC);
885
886/// The target trait enforces that an entity can only be used as relationship target.
887///
888/// # Example
889/// ```
890/// # use flecs_ecs::prelude::*;
891/// # let world = World::new();
892/// #[derive(Component)]
893/// struct Likes;
894///
895/// #[derive(Component)]
896/// struct Apples;
897///
898/// world.component::<Apples>().add_trait::<flecs::Target>();
899///
900/// let e = world
901///     .entity()
902///     // .add(Apples::id()) // Panic, 'Apples' is not used as target
903///     // .add((Apples::id(), Likes::id())) // Panic, 'Apples' is not used as target, but as relationship
904///     .add((Likes::id(), Apples::id())); // OK
905/// ```
906#[derive(Debug, Default, Clone)]
907pub struct Target;
908
909impl_component_trait!(Target, ECS_TARGET);
910
911/// The trait trait marks an entity as a trait, which is any tag that is added to another tag/component/relationship
912/// to modify its behavior. All traits in this manual are marked as trait. It is not required to mark a trait as
913/// a trait before adding it to another tag/component/relationship. The main reason for the trait trait is to ease
914/// some of the constraints on relationships (see the [`Relationship`] trait).
915///
916/// # Example
917/// ```
918/// # use flecs_ecs::prelude::*;
919/// # let world = World::new();
920/// #[derive(Component)]
921/// struct Serializable;
922///
923/// world
924///     .component::<Serializable>()
925///     .add_trait::<flecs::Trait>();
926/// ```
927#[derive(Debug, Default, Clone)]
928pub struct Trait;
929
930impl_component_trait!(Trait, ECS_TRAIT);
931
932/// Relationships can be marked as transitive. A formal-ish definition of transitivity in the context of
933/// relationships is:
934///
935/// ```text
936/// If   Relationship(EntityA, EntityB)
937/// And  Relationship(EntityB, EntityC)
938/// Then Relationship(EntityA, EntityC)
939/// ```
940///
941/// What this means becomes more obvious when translated to a real-life example:
942///
943/// > If Manhattan is located in New York, and New York is located in the USA, then Manhattan is located in the USA.
944///
945/// In this example, `LocatedIn` is the relationship and `Manhattan`, `New York` and `USA` are entities `A`, `B` and `C`.
946/// Another common example of transitivity is found in OOP inheritance:
947///
948/// > If a Square is a Rectangle and a Rectangle is a Shape, then a Square is a Shape.
949///
950/// In this example `IsA` is the relationship and `Square`, `Rectangle` and `Shape` are the entities.
951///
952/// When relationships in Flecs are marked as transitive, queries can follow the transitive relationship to see
953/// if an entity matches.
954///
955/// # Example
956/// ```
957/// # use flecs_ecs::prelude::*;
958/// # let world = World::new();
959/// let locatedin = world.entity();
960/// let manhattan = world.entity();
961/// let newyork = world.entity();
962/// let usa = world.entity();
963///
964/// // Make the LocatedIn relationship transitive
965/// locatedin.add_trait::<flecs::Transitive>();
966///
967/// manhattan.add((locatedin, newyork));
968/// newyork.add((locatedin, usa));
969///
970/// // Now querying for (LocatedIn, USA) will match both NewYork and Manhattan
971/// ```
972///
973/// If we were to query for `(LocatedIn, USA)` without making it transitive, we would only match `NewYork`,
974/// because we never added `(LocatedIn, USA)` to `Manhattan`. By adding the transitive trait to the relationship
975/// entity, queries will follow the `LocatedIn` relationship and return both `NewYork` and `Manhattan`.
976#[derive(Debug, Default, Clone)]
977pub struct Transitive;
978
979impl_component_trait!(Transitive, ECS_TRANSITIVE);
980
981/// Traversable relationships are allowed to be traversed automatically by queries, for example using the
982/// `up` traversal (upwards traversal). Traversable relationships are also marked as [`Acyclic`], which ensures
983/// a query won't accidentally attempt to traverse a relationship that contains cycles.
984///
985/// Events are propagated along the edges of traversable relationships. A typical example of this is when a
986/// component value is changed on a prefab. The event of this change will be propagated by traversing the `IsA`
987/// relationship downwards, for all instances of the prefab. Event propagation does not happen for relationships
988/// that are not marked with `Traversable`.
989#[derive(Debug, Default, Clone)]
990pub struct Traversable;
991
992impl_component_trait!(Traversable, ECS_TRAVERSABLE);
993
994/// The `With` relationship can be added to components to indicate that it must always come together with
995/// another component.
996///
997/// # Example - With regular components/tags
998/// ```rust
999/// # use flecs_ecs::prelude::*;
1000/// # let world = World::new();
1001/// let responsibility = world.entity();
1002/// let power = world.entity().add((flecs::With, responsibility));
1003///
1004/// // Create new entity that has both Power and Responsibility
1005/// let e = world.entity().add(power);
1006/// ```
1007///
1008/// When the `With` relationship is added to a relationship, the additional id added to the entity will be
1009/// a relationship pair as well, with the same target as the original relationship:
1010///
1011/// # Example - With relationships
1012/// ```rust
1013/// # use flecs_ecs::prelude::*;
1014/// # let world = World::new();
1015/// let likes = world.entity();
1016/// let loves = world.entity().add((flecs::With::id(), likes));
1017/// let pears = world.entity();
1018///
1019/// // Create new entity with both (Loves, Pears) and (Likes, Pears)
1020/// let e = world.entity().add((loves, pears));
1021/// ```
1022#[derive(Debug, Default, Clone)]
1023pub struct With;
1024
1025impl_component_trait!(With, ECS_WITH);