RelationshipTarget

Trait RelationshipTarget 

Source
pub trait RelationshipTarget: Sized + Component<Mutability = Mutable> {
    type Relationship: Relationship<RelationshipTarget = Self>;
    type Collection: RelationshipSourceCollection;

    const LINKED_SPAWN: bool;

    // Required methods
    fn collection(&self) -> &Self::Collection;
    fn collection_mut_risky(&mut self) -> &mut Self::Collection;
    fn from_collection_risky(collection: Self::Collection) -> Self;

    // Provided methods
    fn on_replace(world: DeferredWorld<'_>, _: HookContext) { ... }
    fn on_despawn(world: DeferredWorld<'_>, _: HookContext) { ... }
    fn with_capacity(capacity: usize) -> Self { ... }
    fn iter(
        &self,
    ) -> <Self::Collection as RelationshipSourceCollection>::SourceIter<'_> { ... }
    fn len(&self) -> usize { ... }
    fn is_empty(&self) -> bool { ... }
}
Expand description

A Component containing the collection of entities that relate to this Entity via the associated Relationship type. See the Relationship documentation for more information.

Required Associated Constants§

Source

const LINKED_SPAWN: bool

If this is true, when despawning or cloning (when linked cloning is enabled), the related entities targeting this entity will also be despawned or cloned.

For example, this is set to true for Bevy’s built-in parent-child relation, defined by ChildOf and Children. This means that when a parent is despawned, any children targeting that parent are also despawned (and the same applies to cloning).

To get around this behavior, you can first break the relationship between entities, and then despawn or clone. This defaults to false when derived.

Required Associated Types§

Source

type Relationship: Relationship<RelationshipTarget = Self>

The Relationship that populates this RelationshipTarget collection.

Source

type Collection: RelationshipSourceCollection

The collection type that stores the “source” entities for this RelationshipTarget component.

Check the list of types which implement RelationshipSourceCollection for the data structures that can be used inside of your component. If you need a new collection type, you can implement the RelationshipSourceCollection trait for a type you own which wraps the collection you want to use (to avoid the orphan rule), or open an issue on the Bevy repository to request first-party support for your collection type.

Required Methods§

Source

fn collection(&self) -> &Self::Collection

Returns a reference to the stored RelationshipTarget::Collection.

Source

fn collection_mut_risky(&mut self) -> &mut Self::Collection

Returns a mutable reference to the stored RelationshipTarget::Collection.

§Warning

This should generally not be called by user code, as modifying the internal collection could invalidate the relationship. The collection should not contain duplicates.

Source

fn from_collection_risky(collection: Self::Collection) -> Self

Creates a new RelationshipTarget from the given RelationshipTarget::Collection.

§Warning

This should generally not be called by user code, as constructing the internal collection could invalidate the relationship. The collection should not contain duplicates.

Provided Methods§

Source

fn on_replace(world: DeferredWorld<'_>, _: HookContext)

The on_replace component hook that maintains the Relationship / RelationshipTarget connection.

Source

fn on_despawn(world: DeferredWorld<'_>, _: HookContext)

The on_despawn component hook that despawns entities stored in an entity’s RelationshipTarget when that entity is despawned.

Source

fn with_capacity(capacity: usize) -> Self

Creates this RelationshipTarget with the given pre-allocated entity capacity.

Source

fn iter( &self, ) -> <Self::Collection as RelationshipSourceCollection>::SourceIter<'_>

Iterates the entities stored in this collection.

Examples found in repository?
examples/ui/text_background_colors.rs (line 74)
66fn cycle_text_background_colors(
67    time: Res<Time>,
68    children_query: Query<&Children, With<Text>>,
69    mut text_background_colors_query: Query<&mut TextBackgroundColor>,
70) {
71    let n = time.elapsed_secs() as usize;
72    let children = children_query.single().unwrap();
73
74    for (i, child) in children.iter().enumerate() {
75        text_background_colors_query.get_mut(child).unwrap().0 = PALETTE[(i + n) % PALETTE.len()];
76    }
77}
More examples
Hide additional examples
examples/usage/context_menu.rs (line 52)
40fn text_color_on_hover<T: Debug + Clone + Reflect>(
41    color: Color,
42) -> impl FnMut(On<Pointer<T>>, Query<&mut TextColor>, Query<&Children>) {
43    move |mut event: On<Pointer<T>>,
44          mut text_color: Query<&mut TextColor>,
45          children: Query<&Children>| {
46        let Ok(children) = children.get(event.original_event_target()) else {
47            return;
48        };
49        event.propagate(false);
50
51        // find the text among children and change its color
52        for child in children.iter() {
53            if let Ok(mut col) = text_color.get_mut(child) {
54                col.0 = color;
55            }
56        }
57    }
58}
examples/3d/motion_blur.rs (line 318)
300fn move_cars(
301    time: Res<Time>,
302    mut movables: Query<(&mut Transform, &Moves, &Children)>,
303    mut spins: Query<&mut Transform, (Without<Moves>, With<Rotates>)>,
304) {
305    for (mut transform, moves, children) in &mut movables {
306        let time = time.elapsed_secs() * 0.25;
307        let t = time + 0.5 * moves.0;
308        let dx = ops::cos(t);
309        let dz = -ops::sin(3.0 * t);
310        let speed_variation = (dx * dx + dz * dz).sqrt() * 0.15;
311        let t = t + speed_variation;
312        let prev = transform.translation;
313        transform.translation.x = race_track_pos(0.0, t).x;
314        transform.translation.z = race_track_pos(0.0, t).y;
315        transform.translation.y = -0.59;
316        let delta = transform.translation - prev;
317        transform.look_to(delta, Vec3::Y);
318        for child in children.iter() {
319            let Ok(mut wheel) = spins.get_mut(child) else {
320                continue;
321            };
322            let radius = wheel.scale.x;
323            let circumference = 2.0 * std::f32::consts::PI * radius;
324            let angle = delta.length() / circumference * std::f32::consts::PI * 2.0;
325            wheel.rotate_local_y(angle);
326        }
327    }
328}
examples/ecs/relationships.rs (line 90)
78    fn debug_relationships(
79        // Not all of our entities are targeted by something, so we use `Option` in our query to handle this case.
80        relations_query: Query<(&Name, &Targeting, Option<&TargetedBy>)>,
81        name_query: Query<&Name>,
82    ) {
83        let mut relationships = String::new();
84
85        for (name, targeting, maybe_targeted_by) in relations_query.iter() {
86            let targeting_name = name_query.get(targeting.0).unwrap();
87            let targeted_by_string = if let Some(targeted_by) = maybe_targeted_by {
88                let mut vec_of_names = Vec::<&Name>::new();
89
90                for entity in targeted_by.iter() {
91                    let name = name_query.get(entity).unwrap();
92                    vec_of_names.push(name);
93                }
94
95                // Convert this to a nice string for printing.
96                let vec_of_str: Vec<&str> = vec_of_names.iter().map(|name| name.as_str()).collect();
97                vec_of_str.join(", ")
98            } else {
99                "nobody".to_string()
100            };
101
102            relationships.push_str(&format!(
103                "{name} is targeting {targeting_name}, and is targeted by {targeted_by_string}\n",
104            ));
105        }
106
107        println!("{relationships}");
108    }
Source

fn len(&self) -> usize

Returns the number of entities in this collection.

Examples found in repository?
examples/ecs/hierarchy.rs (line 82)
62fn rotate(
63    mut commands: Commands,
64    time: Res<Time>,
65    mut parents_query: Query<(Entity, &Children), With<Sprite>>,
66    mut transform_query: Query<&mut Transform, With<Sprite>>,
67) {
68    for (parent, children) in &mut parents_query {
69        if let Ok(mut transform) = transform_query.get_mut(parent) {
70            transform.rotate_z(-PI / 2. * time.delta_secs());
71        }
72
73        // To iterate through the entities children, just treat the Children component as a Vec
74        // Alternatively, you could query entities that have a ChildOf component
75        for child in children {
76            if let Ok(mut transform) = transform_query.get_mut(*child) {
77                transform.rotate_z(PI * time.delta_secs());
78            }
79        }
80
81        // To demonstrate removing children, we'll remove a child after a couple of seconds.
82        if time.elapsed_secs() >= 2.0 && children.len() == 2 {
83            let child = children.last().unwrap();
84            commands.entity(*child).despawn();
85        }
86
87        if time.elapsed_secs() >= 4.0 {
88            // This will remove the entity from its parent's list of children, as well as despawn
89            // any children the entity has.
90            commands.entity(parent).despawn();
91        }
92    }
93}
Source

fn is_empty(&self) -> bool

Returns true if this entity collection is empty.

Examples found in repository?
examples/ui/standard_widgets_observers.rs (line 179)
161fn button_on_interaction<E: EntityEvent, C: Component>(
162    event: On<E, C>,
163    mut buttons: Query<
164        (
165            &Hovered,
166            Has<InteractionDisabled>,
167            Has<Pressed>,
168            &mut BackgroundColor,
169            &mut BorderColor,
170            &Children,
171        ),
172        With<DemoButton>,
173    >,
174    mut text_query: Query<&mut Text>,
175) {
176    if let Ok((hovered, disabled, pressed, mut color, mut border_color, children)) =
177        buttons.get_mut(event.event_target())
178    {
179        if children.is_empty() {
180            return;
181        }
182        let Ok(mut text) = text_query.get_mut(children[0]) else {
183            return;
184        };
185        let hovered = hovered.get();
186        // These "removal event checks" exist because the `Remove` event is triggered _before_ the component is actually
187        // removed, meaning it still shows up in the query. We're investigating the best way to improve this scenario.
188        let pressed = pressed && !(E::is::<Remove>() && C::is::<Pressed>());
189        let disabled = disabled && !(E::is::<Remove>() && C::is::<InteractionDisabled>());
190        match (disabled, hovered, pressed) {
191            // Disabled button
192            (true, _, _) => {
193                **text = "Disabled".to_string();
194                *color = NORMAL_BUTTON.into();
195                border_color.set_all(GRAY);
196            }
197
198            // Pressed and hovered button
199            (false, true, true) => {
200                **text = "Press".to_string();
201                *color = PRESSED_BUTTON.into();
202                border_color.set_all(RED);
203            }
204
205            // Hovered, unpressed button
206            (false, true, false) => {
207                **text = "Hover".to_string();
208                *color = HOVERED_BUTTON.into();
209                border_color.set_all(WHITE);
210            }
211
212            // Unhovered button (either pressed or not).
213            (false, false, _) => {
214                **text = "Button".to_string();
215                *color = NORMAL_BUTTON.into();
216                border_color.set_all(BLACK);
217            }
218        }
219    }
220}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§