bevy_ecs/traversal.rs
1//! A trait for components that let you traverse the ECS.
2
3use crate::{
4 entity::Entity,
5 query::{ReadOnlyQueryData, ReleaseStateQueryData},
6 relationship::Relationship,
7};
8
9/// A component that can point to another entity, and which can be used to define a path through the ECS.
10///
11/// Traversals are used to [specify the direction] of [event propagation] in [`EntityEvent`] [observers].
12/// The default query is `()`.
13///
14/// Infinite loops are possible, and are not checked for. While looping can be desirable in some contexts
15/// (for example, an observer that triggers itself multiple times before stopping), following an infinite
16/// traversal loop without an eventual exit will cause your application to hang. Each implementer of `Traversal`
17/// is responsible for documenting possible looping behavior, and consumers of those implementations are responsible for
18/// avoiding infinite loops in their code.
19///
20/// Traversals may be parameterized with additional data. For example, in observer event propagation, the
21/// parameter `D` is the event type given in `On<E>`. This allows traversal to differ depending on event
22/// data.
23///
24/// [specify the direction]: crate::event::PropagateEntityTrigger
25/// [event propagation]: crate::observer::On::propagate
26/// [observers]: crate::observer::Observer
27/// [`EntityEvent`]: crate::event::EntityEvent
28pub trait Traversal<D: ?Sized>: ReadOnlyQueryData + ReleaseStateQueryData {
29 /// Returns the next entity to visit.
30 fn traverse(item: Self::Item<'_, '_>, data: &D) -> Option<Entity>;
31}
32
33impl<D> Traversal<D> for () {
34 fn traverse(_: Self::Item<'_, '_>, _data: &D) -> Option<Entity> {
35 None
36 }
37}
38
39/// This provides generalized hierarchy traversal for use in [event propagation].
40///
41/// # Warning
42///
43/// Traversing in a loop could result in infinite loops for relationship graphs with loops.
44///
45/// [event propagation]: crate::observer::On::propagate
46impl<R: Relationship, D> Traversal<D> for &R {
47 fn traverse(item: Self::Item<'_, '_>, _data: &D) -> Option<Entity> {
48 Some(item.get())
49 }
50}