1use crate::{
2bundle::Bundle,
3 entity::{Entity, EntityIndexSet},
4prelude::Children,
5 relationship::{
6Relationship, RelationshipHookMode, RelationshipSourceCollection, RelationshipTarget,
7 },
8 system::{Commands, EntityCommands},
9 world::{DeferredWorld, EntityWorldMut, World},
10};
11use bevy_platform::prelude::{Box, Vec};
12use core::{marker::PhantomData, mem};
1314use super::OrderedRelationshipSourceCollection;
1516impl<'w> EntityWorldMut<'w> {
17/// Spawns an entity related to this entity (with the `R` relationship) by taking a bundle
18pub fn with_related<R: Relationship>(&mut self, bundle: impl Bundle) -> &mut Self {
19let parent = self.id();
20self.world_scope(|world| {
21world.spawn((bundle, R::from(parent)));
22 });
23self24 }
2526/// Spawns entities related to this entity (with the `R` relationship) by taking a function that operates on a [`RelatedSpawner`].
27pub fn with_related_entities<R: Relationship>(
28&mut self,
29 func: impl FnOnce(&mut RelatedSpawner<R>),
30 ) -> &mut Self {
31let parent = self.id();
32self.world_scope(|world| {
33func(&mut RelatedSpawner::new(world, parent));
34 });
35self36 }
3738/// Relates the given entities to this entity with the relation `R`.
39 ///
40 /// See [`add_one_related`](Self::add_one_related) if you want relate only one entity.
41pub fn add_related<R: Relationship>(&mut self, related: &[Entity]) -> &mut Self {
42let id = self.id();
43self.world_scope(|world| {
44for related in related {
45 world
46 .entity_mut(*related)
47 .modify_or_insert_relation_with_relationship_hook_mode::<R>(
48 id,
49 RelationshipHookMode::Run,
50 );
51 }
52 });
53self54 }
5556/// Removes the relation `R` between this entity and all its related entities.
57pub fn detach_all_related<R: Relationship>(&mut self) -> &mut Self {
58self.remove::<R::RelationshipTarget>()
59 }
6061/// Relates the given entities to this entity with the relation `R`, starting at this particular index.
62 ///
63 /// If the `related` has duplicates, a related entity will take the index of its last occurrence in `related`.
64 /// If the indices go out of bounds, they will be clamped into bounds.
65 /// This will not re-order existing related entities unless they are in `related`.
66 ///
67 /// # Example
68 ///
69 /// ```
70 /// use bevy_ecs::prelude::*;
71 ///
72 /// let mut world = World::new();
73 /// let e0 = world.spawn_empty().id();
74 /// let e1 = world.spawn_empty().id();
75 /// let e2 = world.spawn_empty().id();
76 /// let e3 = world.spawn_empty().id();
77 /// let e4 = world.spawn_empty().id();
78 ///
79 /// let mut main_entity = world.spawn_empty();
80 /// main_entity.add_related::<ChildOf>(&[e0, e1, e2, e2]);
81 /// main_entity.insert_related::<ChildOf>(1, &[e0, e3, e4, e4]);
82 /// let main_id = main_entity.id();
83 ///
84 /// let relationship_source = main_entity.get::<Children>().unwrap().collection();
85 /// assert_eq!(relationship_source, &[e1, e0, e3, e2, e4]);
86 /// ```
87pub fn insert_related<R: Relationship>(&mut self, index: usize, related: &[Entity]) -> &mut Self
88where
89<R::RelationshipTarget as RelationshipTarget>::Collection:
90OrderedRelationshipSourceCollection,
91 {
92let id = self.id();
93self.world_scope(|world| {
94for (offset, related) in related.iter().enumerate() {
95let index = index.saturating_add(offset);
96if world
97 .get::<R>(*related)
98 .is_some_and(|relationship| relationship.get() == id)
99 {
100 world
101 .get_mut::<R::RelationshipTarget>(id)
102 .expect("hooks should have added relationship target")
103 .collection_mut_risky()
104 .place(*related, index);
105 } else {
106 world
107 .entity_mut(*related)
108 .modify_or_insert_relation_with_relationship_hook_mode::<R>(
109 id,
110 RelationshipHookMode::Run,
111 );
112 world
113 .get_mut::<R::RelationshipTarget>(id)
114 .expect("hooks should have added relationship target")
115 .collection_mut_risky()
116 .place_most_recent(index);
117 }
118 }
119 });
120121self122 }
123124/// Removes the relation `R` between this entity and the given entities.
125pub fn remove_related<R: Relationship>(&mut self, related: &[Entity]) -> &mut Self {
126let id = self.id();
127self.world_scope(|world| {
128for related in related {
129if world
130 .get::<R>(*related)
131 .is_some_and(|relationship| relationship.get() == id)
132 {
133 world.entity_mut(*related).remove::<R>();
134 }
135 }
136 });
137138self139 }
140141/// Replaces all the related entities with a new set of entities.
142 ///
143 /// Duplicated entities are removed, leaving only their first occurrence.
144pub fn replace_related<R: Relationship>(&mut self, related: &[Entity]) -> &mut Self {
145type Collection<R> =
146 <<R as Relationship>::RelationshipTargetas RelationshipTarget>::Collection;
147148if related.is_empty() {
149self.remove::<R::RelationshipTarget>();
150151return self;
152 }
153154let Some(existing_relations) = self.get_mut::<R::RelationshipTarget>() else {
155return self.add_related::<R>(related);
156 };
157158// We replace the component here with a dummy value so we can modify it without taking it (this would create archetype move).
159 // SAFETY: We eventually return the correctly initialized collection into the target.
160let mut relations = mem::replace(
161existing_relations.into_inner(),
162 <R as Relationship>::RelationshipTarget::from_collection_risky(
163Collection::<R>::with_capacity(0),
164 ),
165 );
166167let collection = relations.collection_mut_risky();
168169let existing_relations = EntityIndexSet::from_iter(collection.iter());
170let final_relations = EntityIndexSet::from_iter(related.iter().copied());
171172let id = self.id();
173self.world_scope(|world| {
174// Remove the existing relations that we won't keep
175for &related in existing_relations.difference(&final_relations) {
176 world.entity_mut(related).remove::<R>();
177 }
178179// Add the final relations that don't exist yet.
180for &related in final_relations.difference(&existing_relations) {
181// SAFETY: We'll manually be adjusting the contents of the `RelationshipTarget` to fit the final state.
182world
183 .entity_mut(related)
184 .modify_or_insert_relation_with_relationship_hook_mode::<R>(
185 id,
186 RelationshipHookMode::Skip,
187 );
188 }
189 });
190191// SAFETY: The entities we're inserting will be the entities that were either already there or entities that we've just inserted.
192collection.clear();
193collection.extend_from_iter(final_relations);
194self.insert(relations);
195196self197 }
198199/// Replaces all the related entities with a new set of entities.
200 ///
201 /// This is a more efficient of [`Self::replace_related`] which doesn't allocate.
202 /// The passed in arguments must adhere to these invariants:
203 /// - `entities_to_unrelate`: A slice of entities to remove from the relationship source.
204 /// Entities need not be related to this entity, but must not appear in `entities_to_relate`
205 /// - `entities_to_relate`: A slice of entities to relate to this entity.
206 /// This must contain all entities that will remain related (i.e. not those in `entities_to_unrelate`) plus the newly related entities.
207 /// - `newly_related_entities`: A subset of `entities_to_relate` containing only entities not already related to this entity.
208 /// - Slices **must not** contain any duplicates
209 ///
210 /// # Warning
211 ///
212 /// Violating these invariants may lead to panics, crashes or unpredictable engine behavior.
213 ///
214 /// # Panics
215 ///
216 /// Panics when debug assertions are enabled and any invariants are broken.
217 ///
218// TODO: Consider making these iterators so users aren't required to allocate a separate buffers for the different slices.
219pub fn replace_related_with_difference<R: Relationship>(
220&mut self,
221 entities_to_unrelate: &[Entity],
222 entities_to_relate: &[Entity],
223 newly_related_entities: &[Entity],
224 ) -> &mut Self {
225#[cfg(debug_assertions)]
226{
227use crate::entity::hash_set::EntityHashSet;
228let entities_to_relate = EntityHashSet::from_iter(entities_to_relate.iter().copied());
229let entities_to_unrelate =
230EntityHashSet::from_iter(entities_to_unrelate.iter().copied());
231let mut newly_related_entities =
232EntityHashSet::from_iter(newly_related_entities.iter().copied());
233if !entities_to_relate.is_disjoint(&entities_to_unrelate) {
{
::core::panicking::panic_fmt(format_args!("`entities_to_relate` ({0:?}) shared entities with `entities_to_unrelate` ({1:?})",
entities_to_relate, entities_to_unrelate));
}
};assert!(
234 entities_to_relate.is_disjoint(&entities_to_unrelate),
235"`entities_to_relate` ({entities_to_relate:?}) shared entities with `entities_to_unrelate` ({entities_to_unrelate:?})"
236);
237if !newly_related_entities.is_disjoint(&entities_to_unrelate) {
{
::core::panicking::panic_fmt(format_args!("`newly_related_entities` ({0:?}) shared entities with `entities_to_unrelate ({1:?})`",
newly_related_entities, entities_to_unrelate));
}
};assert!(
238 newly_related_entities.is_disjoint(&entities_to_unrelate),
239"`newly_related_entities` ({newly_related_entities:?}) shared entities with `entities_to_unrelate ({entities_to_unrelate:?})`"
240);
241if !newly_related_entities.is_subset(&entities_to_relate) {
{
::core::panicking::panic_fmt(format_args!("`newly_related_entities` ({0:?}) wasn\'t a subset of `entities_to_relate` ({1:?})",
newly_related_entities, entities_to_relate));
}
};assert!(
242 newly_related_entities.is_subset(&entities_to_relate),
243"`newly_related_entities` ({newly_related_entities:?}) wasn't a subset of `entities_to_relate` ({entities_to_relate:?})"
244);
245246if let Some(target) = self.get::<R::RelationshipTarget>() {
247let existing_relationships: EntityHashSet = target.collection().iter().collect();
248249if !existing_relationships.is_disjoint(&newly_related_entities) {
{
::core::panicking::panic_fmt(format_args!("`newly_related_entities` contains an entity that wouldn\'t be newly related"));
}
};assert!(
250 existing_relationships.is_disjoint(&newly_related_entities),
251"`newly_related_entities` contains an entity that wouldn't be newly related"
252);
253254newly_related_entities.extend(existing_relationships);
255newly_related_entities -= &entities_to_unrelate;
256 }
257258{
match (&newly_related_entities, &entities_to_relate) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("`entities_to_relate` ({0:?}) didn\'t contain all entities that would end up related",
entities_to_relate)));
}
}
}
};assert_eq!(newly_related_entities, entities_to_relate, "`entities_to_relate` ({entities_to_relate:?}) didn't contain all entities that would end up related");
259 };
260261match self.get_mut::<R::RelationshipTarget>() {
262None => {
263self.add_related::<R>(entities_to_relate);
264265return self;
266 }
267Some(mut target) => {
268// SAFETY: The invariants expected by this function mean we'll only be inserting entities that are already related.
269let collection = target.collection_mut_risky();
270collection.clear();
271272collection.extend_from_iter(entities_to_relate.iter().copied());
273 }
274 }
275276let this = self.id();
277self.world_scope(|world| {
278for unrelate in entities_to_unrelate {
279 world.entity_mut(*unrelate).remove::<R>();
280 }
281282for new_relation in newly_related_entities {
283// We changed the target collection manually so don't run the insert hook
284world
285 .entity_mut(*new_relation)
286 .modify_or_insert_relation_with_relationship_hook_mode::<R>(
287 this,
288 RelationshipHookMode::Skip,
289 );
290 }
291 });
292293self294 }
295296/// Relates the given entity to this with the relation `R`.
297 ///
298 /// See [`add_related`](Self::add_related) if you want to relate more than one entity.
299pub fn add_one_related<R: Relationship>(&mut self, entity: Entity) -> &mut Self {
300self.add_related::<R>(&[entity])
301 }
302303/// Despawns entities that relate to this one via the given [`RelationshipTarget`].
304 /// This entity will not be despawned.
305pub fn despawn_related<S: RelationshipTarget>(&mut self) -> &mut Self {
306if let Some(sources) = self.get::<S>() {
307// We have to collect here to defer removal, allowing observers and hooks to see this data
308 // before it is finally removed.
309let sources = sources.iter().collect::<Vec<_>>();
310self.world_scope(|world| {
311for entity in sources {
312if let Ok(entity_mut) = world.get_entity_mut(entity) {
313 entity_mut.despawn();
314 };
315 }
316 });
317 }
318self319 }
320321/// Despawns the children of this entity.
322 /// This entity will not be despawned.
323 ///
324 /// This is a specialization of [`despawn_related`](EntityWorldMut::despawn_related), a more general method for despawning via relationships.
325pub fn despawn_children(&mut self) -> &mut Self {
326self.despawn_related::<Children>();
327self328 }
329330/// Inserts a component or bundle of components into the entity and all related entities,
331 /// traversing the relationship tracked in `S` in a breadth-first manner.
332 ///
333 /// # Warning
334 ///
335 /// This method should only be called on relationships that form a tree-like structure.
336 /// Any cycles will cause this method to loop infinitely.
337// We could keep track of a list of visited entities and track cycles,
338 // but this is not a very well-defined operation (or hard to write) for arbitrary relationships.
339pub fn insert_recursive<S: RelationshipTarget>(
340&mut self,
341 bundle: impl Bundle + Clone,
342 ) -> &mut Self {
343self.insert(bundle.clone());
344if let Some(relationship_target) = self.get::<S>() {
345let related_vec: Vec<Entity> = relationship_target.iter().collect();
346for related in related_vec {
347self.world_scope(|world| {
348 world
349 .entity_mut(related)
350 .insert_recursive::<S>(bundle.clone());
351 });
352 }
353 }
354355self356 }
357358/// Removes a component or bundle of components of type `B` from the entity and all related entities,
359 /// traversing the relationship tracked in `S` in a breadth-first manner.
360 ///
361 /// # Warning
362 ///
363 /// This method should only be called on relationships that form a tree-like structure.
364 /// Any cycles will cause this method to loop infinitely.
365pub fn remove_recursive<S: RelationshipTarget, B: Bundle>(&mut self) -> &mut Self {
366self.remove::<B>();
367if let Some(relationship_target) = self.get::<S>() {
368let related_vec: Vec<Entity> = relationship_target.iter().collect();
369for related in related_vec {
370self.world_scope(|world| {
371 world.entity_mut(related).remove_recursive::<S, B>();
372 });
373 }
374 }
375376self377 }
378379fn modify_or_insert_relation_with_relationship_hook_mode<R: Relationship>(
380&mut self,
381 entity: Entity,
382 relationship_hook_mode: RelationshipHookMode,
383 ) {
384// Check if the relation edge holds additional data
385if size_of::<R>() > size_of::<Entity>() {
386self.assert_not_despawned();
387388let this = self.id();
389390let modified = self.world_scope(|world| {
391let modified = DeferredWorld::from(&mut *world)
392 .modify_component_with_relationship_hook_mode::<R, _>(
393this,
394relationship_hook_mode,
395 |r| r.set_risky(entity),
396 )
397 .expect("entity access must be valid")
398 .is_some();
399400world.flush();
401402modified403 });
404405if modified {
406return;
407 }
408 }
409410self.insert_with_relationship_hook_mode(R::from(entity), relationship_hook_mode);
411 }
412}
413414impl<'a> EntityCommands<'a> {
415/// Spawns an entity related to this entity (with the `R` relationship) by taking a bundle
416pub fn with_related<R: Relationship>(&mut self, bundle: impl Bundle) -> &mut Self {
417let parent = self.id();
418self.commands.spawn((bundle, R::from(parent)));
419self420 }
421422/// Spawns entities related to this entity (with the `R` relationship) by taking a function that operates on a [`RelatedSpawner`].
423pub fn with_related_entities<R: Relationship>(
424&mut self,
425 func: impl FnOnce(&mut RelatedSpawnerCommands<R>),
426 ) -> &mut Self {
427let id = self.id();
428func(&mut RelatedSpawnerCommands::new(self.commands(), id));
429self430 }
431432/// Relates the given entities to this entity with the relation `R`.
433 ///
434 /// See [`add_one_related`](Self::add_one_related) if you want relate only one entity.
435pub fn add_related<R: Relationship>(&mut self, related: &[Entity]) -> &mut Self {
436let related: Box<[Entity]> = related.into();
437438self.queue(move |mut entity: EntityWorldMut| {
439entity.add_related::<R>(&related);
440 })
441 }
442443/// Removes the relation `R` between this entity and all its related entities.
444pub fn detach_all_related<R: Relationship>(&mut self) -> &mut Self {
445self.queue(|mut entity: EntityWorldMut| {
446entity.detach_all_related::<R>();
447 })
448 }
449450/// Relates the given entities to this entity with the relation `R`, starting at this particular index.
451 ///
452 /// If the `related` has duplicates, a related entity will take the index of its last occurrence in `related`.
453 /// If the indices go out of bounds, they will be clamped into bounds.
454 /// This will not re-order existing related entities unless they are in `related`.
455pub fn insert_related<R: Relationship>(&mut self, index: usize, related: &[Entity]) -> &mut Self
456where
457<R::RelationshipTarget as RelationshipTarget>::Collection:
458OrderedRelationshipSourceCollection,
459 {
460let related: Box<[Entity]> = related.into();
461462self.queue(move |mut entity: EntityWorldMut| {
463entity.insert_related::<R>(index, &related);
464 })
465 }
466467/// Relates the given entity to this with the relation `R`.
468 ///
469 /// See [`add_related`](Self::add_related) if you want to relate more than one entity.
470pub fn add_one_related<R: Relationship>(&mut self, entity: Entity) -> &mut Self {
471self.add_related::<R>(&[entity])
472 }
473474/// Removes the relation `R` between this entity and the given entities.
475pub fn remove_related<R: Relationship>(&mut self, related: &[Entity]) -> &mut Self {
476let related: Box<[Entity]> = related.into();
477478self.queue(move |mut entity: EntityWorldMut| {
479entity.remove_related::<R>(&related);
480 })
481 }
482483/// Replaces all the related entities with the given set of new related entities.
484 ///
485 /// Duplicated entities are removed, leaving only their first occurrence.
486pub fn replace_related<R: Relationship>(&mut self, related: &[Entity]) -> &mut Self {
487let related: Box<[Entity]> = related.into();
488489self.queue(move |mut entity: EntityWorldMut| {
490entity.replace_related::<R>(&related);
491 })
492 }
493494/// Replaces all the related entities with a new set of entities.
495 ///
496 /// # Warning
497 ///
498 /// Failing to maintain the functions invariants may lead to erratic engine behavior including random crashes.
499 /// Refer to [`EntityWorldMut::replace_related_with_difference`] for a list of these invariants.
500 ///
501 /// # Panics
502 ///
503 /// Panics when debug assertions are enable, an invariant is are broken and the command is executed.
504pub fn replace_related_with_difference<R: Relationship>(
505&mut self,
506 entities_to_unrelate: &[Entity],
507 entities_to_relate: &[Entity],
508 newly_related_entities: &[Entity],
509 ) -> &mut Self {
510let entities_to_unrelate: Box<[Entity]> = entities_to_unrelate.into();
511let entities_to_relate: Box<[Entity]> = entities_to_relate.into();
512let newly_related_entities: Box<[Entity]> = newly_related_entities.into();
513514self.queue(move |mut entity: EntityWorldMut| {
515entity.replace_related_with_difference::<R>(
516&entities_to_unrelate,
517&entities_to_relate,
518&newly_related_entities,
519 );
520 })
521 }
522523/// Despawns entities that relate to this one via the given [`RelationshipTarget`].
524 /// This entity will not be despawned.
525pub fn despawn_related<S: RelationshipTarget>(&mut self) -> &mut Self {
526self.queue(move |mut entity: EntityWorldMut| {
527entity.despawn_related::<S>();
528 })
529 }
530531/// Despawns the children of this entity.
532 /// This entity will not be despawned.
533 ///
534 /// This is a specialization of [`despawn_related`](EntityCommands::despawn_related), a more general method for despawning via relationships.
535pub fn despawn_children(&mut self) -> &mut Self {
536self.despawn_related::<Children>()
537 }
538539/// Inserts a component or bundle of components into the entity and all related entities,
540 /// traversing the relationship tracked in `S` in a breadth-first manner.
541 ///
542 /// # Warning
543 ///
544 /// This method should only be called on relationships that form a tree-like structure.
545 /// Any cycles will cause this method to loop infinitely.
546pub fn insert_recursive<S: RelationshipTarget>(
547&mut self,
548 bundle: impl Bundle + Clone,
549 ) -> &mut Self {
550self.queue(move |mut entity: EntityWorldMut| {
551entity.insert_recursive::<S>(bundle);
552 })
553 }
554555/// Removes a component or bundle of components of type `B` from the entity and all related entities,
556 /// traversing the relationship tracked in `S` in a breadth-first manner.
557 ///
558 /// # Warning
559 ///
560 /// This method should only be called on relationships that form a tree-like structure.
561 /// Any cycles will cause this method to loop infinitely.
562pub fn remove_recursive<S: RelationshipTarget, B: Bundle>(&mut self) -> &mut Self {
563self.queue(move |mut entity: EntityWorldMut| {
564entity.remove_recursive::<S, B>();
565 })
566 }
567}
568569/// Directly spawns related "source" entities with the given [`Relationship`], targeting
570/// a specific entity.
571pub struct RelatedSpawner<'w, R: Relationship> {
572 target: Entity,
573 world: &'w mut World,
574 _marker: PhantomData<R>,
575}
576577impl<'w, R: Relationship> RelatedSpawner<'w, R> {
578/// Creates a new instance that will spawn entities targeting the `target` entity.
579pub fn new(world: &'w mut World, target: Entity) -> Self {
580Self {
581world,
582target,
583 _marker: PhantomData,
584 }
585 }
586587/// Spawns an entity with the given `bundle` and an `R` relationship targeting the `target`
588 /// entity this spawner was initialized with.
589pub fn spawn(&mut self, bundle: impl Bundle) -> EntityWorldMut<'_> {
590self.world.spawn((R::from(self.target), bundle))
591 }
592593/// Spawns an entity with an `R` relationship targeting the `target`
594 /// entity this spawner was initialized with.
595pub fn spawn_empty(&mut self) -> EntityWorldMut<'_> {
596self.world.spawn(R::from(self.target))
597 }
598599/// Returns the "target entity" used when spawning entities with an `R` [`Relationship`].
600pub fn target_entity(&self) -> Entity {
601self.target
602 }
603604/// Returns a reference to the underlying [`World`].
605pub fn world(&self) -> &World {
606self.world
607 }
608609/// Returns a mutable reference to the underlying [`World`].
610pub fn world_mut(&mut self) -> &mut World {
611self.world
612 }
613}
614615/// Uses commands to spawn related "source" entities with the given [`Relationship`], targeting
616/// a specific entity.
617pub struct RelatedSpawnerCommands<'w, R: Relationship> {
618 target: Entity,
619 commands: Commands<'w, 'w>,
620 _marker: PhantomData<R>,
621}
622623impl<'w, R: Relationship> RelatedSpawnerCommands<'w, R> {
624/// Creates a new instance that will spawn entities targeting the `target` entity.
625pub fn new(commands: Commands<'w, 'w>, target: Entity) -> Self {
626Self {
627commands,
628target,
629 _marker: PhantomData,
630 }
631 }
632633/// Returns a [`RelatedSpawnerCommands`] with a smaller lifetime.
634 ///
635 /// This is useful if you have `&mut RelatedSpawnerCommands` but need `RelatedSpawnerCommands`.
636pub fn reborrow(&mut self) -> RelatedSpawnerCommands<'_, R> {
637RelatedSpawnerCommands {
638 target: self.target,
639 commands: self.commands.reborrow(),
640 _marker: PhantomData,
641 }
642 }
643644/// Spawns an entity with the given `bundle` and an `R` relationship targeting the `target`
645 /// entity this spawner was initialized with.
646pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands<'_> {
647self.commands.spawn((R::from(self.target), bundle))
648 }
649650/// Spawns an entity with an `R` relationship targeting the `target`
651 /// entity this spawner was initialized with.
652pub fn spawn_empty(&mut self) -> EntityCommands<'_> {
653self.commands.spawn(R::from(self.target))
654 }
655656/// Returns the "target entity" used when spawning entities with an `R` [`Relationship`].
657pub fn target_entity(&self) -> Entity {
658self.target
659 }
660661/// Returns the underlying [`Commands`].
662pub fn commands(&mut self) -> Commands<'_, '_> {
663self.commands.reborrow()
664 }
665666/// Returns a mutable reference to the underlying [`Commands`].
667pub fn commands_mut(&mut self) -> &mut Commands<'w, 'w> {
668&mut self.commands
669 }
670}
671672#[cfg(test)]
673mod tests {
674use super::*;
675use crate::prelude::{ChildOf, Children, Component};
676677#[derive(Component, Clone, Copy)]
678struct TestComponent;
679680#[test]
681fn insert_and_remove_recursive() {
682let mut world = World::new();
683684let a = world.spawn_empty().id();
685let b = world.spawn(ChildOf(a)).id();
686let c = world.spawn(ChildOf(a)).id();
687let d = world.spawn(ChildOf(b)).id();
688689 world
690 .entity_mut(a)
691 .insert_recursive::<Children>(TestComponent);
692693for entity in [a, b, c, d] {
694assert!(world.entity(entity).contains::<TestComponent>());
695 }
696697 world
698 .entity_mut(b)
699 .remove_recursive::<Children, TestComponent>();
700701// Parent
702assert!(world.entity(a).contains::<TestComponent>());
703// Target
704assert!(!world.entity(b).contains::<TestComponent>());
705// Sibling
706assert!(world.entity(c).contains::<TestComponent>());
707// Child
708assert!(!world.entity(d).contains::<TestComponent>());
709710 world
711 .entity_mut(a)
712 .remove_recursive::<Children, TestComponent>();
713714for entity in [a, b, c, d] {
715assert!(!world.entity(entity).contains::<TestComponent>());
716 }
717 }
718719#[test]
720fn remove_all_related() {
721let mut world = World::new();
722723let a = world.spawn_empty().id();
724let b = world.spawn(ChildOf(a)).id();
725let c = world.spawn(ChildOf(a)).id();
726727 world.entity_mut(a).detach_all_related::<ChildOf>();
728729assert_eq!(world.entity(a).get::<Children>(), None);
730assert_eq!(world.entity(b).get::<ChildOf>(), None);
731assert_eq!(world.entity(c).get::<ChildOf>(), None);
732 }
733734#[test]
735fn replace_related_works() {
736let mut world = World::new();
737let child1 = world.spawn_empty().id();
738let child2 = world.spawn_empty().id();
739let child3 = world.spawn_empty().id();
740741let mut parent = world.spawn_empty();
742 parent.add_children(&[child1, child2]);
743let child_value = ChildOf(parent.id());
744let some_child = Some(&child_value);
745746 parent.replace_children(&[child2, child3]);
747let children = parent.get::<Children>().unwrap().collection();
748assert_eq!(children, &[child2, child3]);
749assert_eq!(parent.world().get::<ChildOf>(child1), None);
750assert_eq!(parent.world().get::<ChildOf>(child2), some_child);
751assert_eq!(parent.world().get::<ChildOf>(child3), some_child);
752753 parent.replace_children_with_difference(&[child3], &[child1, child2], &[child1]);
754let children = parent.get::<Children>().unwrap().collection();
755assert_eq!(children, &[child1, child2]);
756assert_eq!(parent.world().get::<ChildOf>(child1), some_child);
757assert_eq!(parent.world().get::<ChildOf>(child2), some_child);
758assert_eq!(parent.world().get::<ChildOf>(child3), None);
759 }
760761#[test]
762fn add_related_keeps_relationship_data() {
763#[derive(Component, PartialEq, Debug)]
764 #[relationship(relationship_target = Parent)]
765struct Child {
766#[relationship]
767parent: Entity,
768 data: u8,
769 }
770771#[derive(Component)]
772 #[relationship_target(relationship = Child)]
773struct Parent(Vec<Entity>);
774775let mut world = World::new();
776let parent1 = world.spawn_empty().id();
777let parent2 = world.spawn_empty().id();
778let child = world
779 .spawn(Child {
780 parent: parent1,
781 data: 42,
782 })
783 .id();
784785 world.entity_mut(parent2).add_related::<Child>(&[child]);
786assert_eq!(
787 world.get::<Child>(child),
788Some(&Child {
789 parent: parent2,
790 data: 42
791})
792 );
793 }
794795#[test]
796fn insert_related_keeps_relationship_data() {
797#[derive(Component, PartialEq, Debug)]
798 #[relationship(relationship_target = Parent)]
799struct Child {
800#[relationship]
801parent: Entity,
802 data: u8,
803 }
804805#[derive(Component)]
806 #[relationship_target(relationship = Child)]
807struct Parent(Vec<Entity>);
808809let mut world = World::new();
810let parent1 = world.spawn_empty().id();
811let parent2 = world.spawn_empty().id();
812let child = world
813 .spawn(Child {
814 parent: parent1,
815 data: 42,
816 })
817 .id();
818819 world
820 .entity_mut(parent2)
821 .insert_related::<Child>(0, &[child]);
822assert_eq!(
823 world.get::<Child>(child),
824Some(&Child {
825 parent: parent2,
826 data: 42
827})
828 );
829 }
830831#[test]
832fn replace_related_keeps_relationship_data() {
833#[derive(Component, PartialEq, Debug)]
834 #[relationship(relationship_target = Parent)]
835struct Child {
836#[relationship]
837parent: Entity,
838 data: u8,
839 }
840841#[derive(Component)]
842 #[relationship_target(relationship = Child)]
843struct Parent(Vec<Entity>);
844845let mut world = World::new();
846let parent1 = world.spawn_empty().id();
847let parent2 = world.spawn_empty().id();
848let child = world
849 .spawn(Child {
850 parent: parent1,
851 data: 42,
852 })
853 .id();
854855 world
856 .entity_mut(parent2)
857 .replace_related_with_difference::<Child>(&[], &[child], &[child]);
858assert_eq!(
859 world.get::<Child>(child),
860Some(&Child {
861 parent: parent2,
862 data: 42
863})
864 );
865866 world.entity_mut(parent1).replace_related::<Child>(&[child]);
867assert_eq!(
868 world.get::<Child>(child),
869Some(&Child {
870 parent: parent1,
871 data: 42
872})
873 );
874 }
875876#[test]
877fn replace_related_keeps_relationship_target_data() {
878#[derive(Component)]
879 #[relationship(relationship_target = Parent)]
880struct Child(Entity);
881882#[derive(Component)]
883 #[relationship_target(relationship = Child)]
884struct Parent {
885#[relationship]
886children: Vec<Entity>,
887 data: u8,
888 }
889890let mut world = World::new();
891let child1 = world.spawn_empty().id();
892let child2 = world.spawn_empty().id();
893let mut parent = world.spawn_empty();
894 parent.add_related::<Child>(&[child1]);
895 parent.get_mut::<Parent>().unwrap().data = 42;
896897 parent.replace_related_with_difference::<Child>(&[child1], &[child2], &[child2]);
898let data = parent.get::<Parent>().unwrap().data;
899assert_eq!(data, 42);
900901 parent.replace_related::<Child>(&[child1]);
902let data = parent.get::<Parent>().unwrap().data;
903assert_eq!(data, 42);
904 }
905906#[test]
907fn despawn_related_observers_can_access_relationship_data() {
908use crate::lifecycle::Discard;
909use crate::observer::On;
910use crate::prelude::Has;
911use crate::system::Query;
912913#[derive(Component)]
914struct MyComponent;
915916#[derive(Component, Default)]
917struct ObserverResult {
918 success: bool,
919 }
920921let mut world = World::new();
922let result_entity = world.spawn(ObserverResult::default()).id();
923924 world.add_observer(
925move |replace: On<Discard<MyComponent>>,
926 has_relationship: Query<Has<ChildOf>>,
927mut results: Query<&mut ObserverResult>| {
928if has_relationship.get(replace.entity).unwrap_or(false) {
929 results.get_mut(result_entity).unwrap().success = true;
930 }
931 },
932 );
933934let parent = world.spawn_empty().id();
935let _child = world.spawn((MyComponent, ChildOf(parent))).id();
936937 world.entity_mut(parent).despawn_related::<Children>();
938939assert!(world.get::<ObserverResult>(result_entity).unwrap().success);
940 }
941}