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);