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§
Sourceconst LINKED_SPAWN: bool
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§
Sourcetype Relationship: Relationship<RelationshipTarget = Self>
type Relationship: Relationship<RelationshipTarget = Self>
The Relationship that populates this RelationshipTarget collection.
Sourcetype Collection: RelationshipSourceCollection
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§
Sourcefn collection(&self) -> &Self::Collection
fn collection(&self) -> &Self::Collection
Returns a reference to the stored RelationshipTarget::Collection.
Sourcefn collection_mut_risky(&mut self) -> &mut Self::Collection
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.
Sourcefn from_collection_risky(collection: Self::Collection) -> Self
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§
Sourcefn on_replace(world: DeferredWorld<'_>, _: HookContext)
fn on_replace(world: DeferredWorld<'_>, _: HookContext)
The on_replace component hook that maintains the Relationship / RelationshipTarget connection.
Sourcefn on_despawn(world: DeferredWorld<'_>, _: HookContext)
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.
Sourcefn with_capacity(capacity: usize) -> Self
fn with_capacity(capacity: usize) -> Self
Creates this RelationshipTarget with the given pre-allocated entity capacity.
Sourcefn iter(
&self,
) -> <Self::Collection as RelationshipSourceCollection>::SourceIter<'_>
fn iter( &self, ) -> <Self::Collection as RelationshipSourceCollection>::SourceIter<'_>
Iterates the entities stored in this collection.
Examples found in repository?
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
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}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}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 }Sourcefn len(&self) -> usize
fn len(&self) -> usize
Returns the number of entities in this collection.
Examples found in repository?
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}Sourcefn is_empty(&self) -> bool
fn is_empty(&self) -> bool
Returns true if this entity collection is empty.
Examples found in repository?
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.