1#[cfg(feature = "bevy_reflect")]
10use crate::reflect::{ReflectComponent, ReflectFromWorld};
11use crate::{
12 bundle::Bundle,
13 component::{Component, HookContext},
14 entity::Entity,
15 relationship::{RelatedSpawner, RelatedSpawnerCommands},
16 system::EntityCommands,
17 world::{DeferredWorld, EntityWorldMut, FromWorld, World},
18};
19use alloc::{format, string::String, vec::Vec};
20#[cfg(feature = "bevy_reflect")]
21use bevy_reflect::std_traits::ReflectDefault;
22#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
23use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
24use core::ops::Deref;
25use core::slice;
26use disqualified::ShortName;
27use log::warn;
28
29#[derive(Component, Clone, PartialEq, Eq, Debug)]
96#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
97#[cfg_attr(
98 feature = "bevy_reflect",
99 reflect(Component, PartialEq, Debug, FromWorld, Clone)
100)]
101#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
102#[cfg_attr(
103 all(feature = "serialize", feature = "bevy_reflect"),
104 reflect(Serialize, Deserialize)
105)]
106#[relationship(relationship_target = Children)]
107#[doc(alias = "IsChild", alias = "Parent")]
108pub struct ChildOf(#[entities] pub Entity);
109
110impl ChildOf {
111 #[inline]
113 pub fn parent(&self) -> Entity {
114 self.0
115 }
116
117 #[deprecated(since = "0.16.0", note = "Use child_of.parent() instead")]
119 #[inline]
120 pub fn get(&self) -> Entity {
121 self.0
122 }
123}
124
125impl FromWorld for ChildOf {
130 #[inline(always)]
131 fn from_world(_world: &mut World) -> Self {
132 ChildOf(Entity::PLACEHOLDER)
133 }
134}
135
136#[derive(Component, Default, Debug, PartialEq, Eq)]
156#[relationship_target(relationship = ChildOf, linked_spawn)]
157#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
158#[cfg_attr(feature = "bevy_reflect", reflect(Component, FromWorld, Default))]
159#[doc(alias = "IsParent")]
160pub struct Children(Vec<Entity>);
161
162impl Children {
163 #[inline]
165 pub fn swap(&mut self, a_index: usize, b_index: usize) {
166 self.0.swap(a_index, b_index);
167 }
168
169 #[inline]
178 pub fn sort_by<F>(&mut self, compare: F)
179 where
180 F: FnMut(&Entity, &Entity) -> core::cmp::Ordering,
181 {
182 self.0.sort_by(compare);
183 }
184
185 #[inline]
194 pub fn sort_by_key<K, F>(&mut self, compare: F)
195 where
196 F: FnMut(&Entity) -> K,
197 K: Ord,
198 {
199 self.0.sort_by_key(compare);
200 }
201
202 #[inline]
210 pub fn sort_by_cached_key<K, F>(&mut self, compare: F)
211 where
212 F: FnMut(&Entity) -> K,
213 K: Ord,
214 {
215 self.0.sort_by_cached_key(compare);
216 }
217
218 #[inline]
227 pub fn sort_unstable_by<F>(&mut self, compare: F)
228 where
229 F: FnMut(&Entity, &Entity) -> core::cmp::Ordering,
230 {
231 self.0.sort_unstable_by(compare);
232 }
233
234 #[inline]
243 pub fn sort_unstable_by_key<K, F>(&mut self, compare: F)
244 where
245 F: FnMut(&Entity) -> K,
246 K: Ord,
247 {
248 self.0.sort_unstable_by_key(compare);
249 }
250}
251
252impl<'a> IntoIterator for &'a Children {
253 type Item = <Self::IntoIter as Iterator>::Item;
254
255 type IntoIter = slice::Iter<'a, Entity>;
256
257 #[inline(always)]
258 fn into_iter(self) -> Self::IntoIter {
259 self.0.iter()
260 }
261}
262
263impl Deref for Children {
264 type Target = [Entity];
265
266 fn deref(&self) -> &Self::Target {
267 &self.0
268 }
269}
270
271pub type ChildSpawner<'w> = RelatedSpawner<'w, ChildOf>;
273
274pub type ChildSpawnerCommands<'w> = RelatedSpawnerCommands<'w, ChildOf>;
276
277impl<'w> EntityWorldMut<'w> {
278 pub fn with_children(&mut self, func: impl FnOnce(&mut ChildSpawner)) -> &mut Self {
281 self.with_related_entities(func);
282 self
283 }
284
285 pub fn add_children(&mut self, children: &[Entity]) -> &mut Self {
288 self.add_related::<ChildOf>(children)
289 }
290
291 pub fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
294 self.insert_related::<ChildOf>(index, children)
295 }
296
297 pub fn add_child(&mut self, child: Entity) -> &mut Self {
300 self.add_related::<ChildOf>(&[child])
301 }
302
303 pub fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
305 self.remove_related::<ChildOf>(children)
306 }
307
308 pub fn replace_children(&mut self, children: &[Entity]) -> &mut Self {
310 self.replace_related::<ChildOf>(children)
311 }
312
313 pub fn replace_children_with_difference(
324 &mut self,
325 entities_to_unrelate: &[Entity],
326 entities_to_relate: &[Entity],
327 newly_related_entities: &[Entity],
328 ) -> &mut Self {
329 self.replace_related_with_difference::<ChildOf>(
330 entities_to_unrelate,
331 entities_to_relate,
332 newly_related_entities,
333 )
334 }
335
336 pub fn with_child(&mut self, bundle: impl Bundle) -> &mut Self {
342 let parent = self.id();
343 self.world_scope(|world| {
344 world.spawn((bundle, ChildOf(parent)));
345 });
346 self
347 }
348
349 #[deprecated(since = "0.16.0", note = "Use entity_mut.remove::<ChildOf>()")]
351 pub fn remove_parent(&mut self) -> &mut Self {
352 self.remove::<ChildOf>();
353 self
354 }
355
356 #[deprecated(since = "0.16.0", note = "Use entity_mut.insert(ChildOf(entity))")]
358 pub fn set_parent(&mut self, parent: Entity) -> &mut Self {
359 self.insert(ChildOf(parent));
360 self
361 }
362}
363
364impl<'a> EntityCommands<'a> {
365 pub fn with_children(
367 &mut self,
368 func: impl FnOnce(&mut RelatedSpawnerCommands<ChildOf>),
369 ) -> &mut Self {
370 self.with_related_entities(func);
371 self
372 }
373
374 pub fn add_children(&mut self, children: &[Entity]) -> &mut Self {
376 self.add_related::<ChildOf>(children)
377 }
378
379 pub fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self {
382 self.insert_related::<ChildOf>(index, children)
383 }
384
385 pub fn add_child(&mut self, child: Entity) -> &mut Self {
387 self.add_related::<ChildOf>(&[child])
388 }
389
390 pub fn remove_children(&mut self, children: &[Entity]) -> &mut Self {
392 self.remove_related::<ChildOf>(children)
393 }
394
395 pub fn replace_children(&mut self, children: &[Entity]) -> &mut Self {
397 self.replace_related::<ChildOf>(children)
398 }
399
400 pub fn replace_children_with_difference(
411 &mut self,
412 entities_to_unrelate: &[Entity],
413 entities_to_relate: &[Entity],
414 newly_related_entities: &[Entity],
415 ) -> &mut Self {
416 self.replace_related_with_difference::<ChildOf>(
417 entities_to_unrelate,
418 entities_to_relate,
419 newly_related_entities,
420 )
421 }
422
423 pub fn with_child(&mut self, bundle: impl Bundle) -> &mut Self {
429 self.with_related::<ChildOf>(bundle);
430 self
431 }
432
433 #[deprecated(since = "0.16.0", note = "Use entity_commands.remove::<ChildOf>()")]
435 pub fn remove_parent(&mut self) -> &mut Self {
436 self.remove::<ChildOf>();
437 self
438 }
439
440 #[deprecated(since = "0.16.0", note = "Use entity_commands.insert(ChildOf(entity))")]
442 pub fn set_parent(&mut self, parent: Entity) -> &mut Self {
443 self.insert(ChildOf(parent));
444 self
445 }
446}
447
448pub fn validate_parent_has_component<C: Component>(
451 world: DeferredWorld,
452 HookContext { entity, caller, .. }: HookContext,
453) {
454 let entity_ref = world.entity(entity);
455 let Some(child_of) = entity_ref.get::<ChildOf>() else {
456 return;
457 };
458 if !world
459 .get_entity(child_of.parent())
460 .is_ok_and(|e| e.contains::<C>())
461 {
462 let name: Option<String> = None;
464 warn!(
465 "warning[B0004]: {}{name} with the {ty_name} component has a parent without {ty_name}.\n\
466 This will cause inconsistent behaviors! See: https://bevyengine.org/learn/errors/b0004",
467 caller.map(|c| format!("{c}: ")).unwrap_or_default(),
468 ty_name = ShortName::of::<C>(),
469 name = name.map_or_else(
470 || format!("Entity {}", entity),
471 |s| format!("The {s} entity")
472 ),
473 );
474 }
475}
476
477#[macro_export]
507macro_rules! children {
508 [$($child:expr),*$(,)?] => {
509 $crate::hierarchy::Children::spawn(($($crate::spawn::Spawn($child)),*))
510 };
511}
512
513#[cfg(test)]
514mod tests {
515 use crate::{
516 entity::Entity,
517 hierarchy::{ChildOf, Children},
518 relationship::{RelationshipHookMode, RelationshipTarget},
519 spawn::{Spawn, SpawnRelated},
520 world::World,
521 };
522 use alloc::{vec, vec::Vec};
523
524 #[derive(PartialEq, Eq, Debug)]
525 struct Node {
526 entity: Entity,
527 children: Vec<Node>,
528 }
529
530 impl Node {
531 fn new(entity: Entity) -> Self {
532 Self {
533 entity,
534 children: Vec::new(),
535 }
536 }
537
538 fn new_with(entity: Entity, children: Vec<Node>) -> Self {
539 Self { entity, children }
540 }
541 }
542
543 fn get_hierarchy(world: &World, entity: Entity) -> Node {
544 Node {
545 entity,
546 children: world
547 .entity(entity)
548 .get::<Children>()
549 .map_or_else(Default::default, |c| {
550 c.iter().map(|e| get_hierarchy(world, e)).collect()
551 }),
552 }
553 }
554
555 #[test]
556 fn hierarchy() {
557 let mut world = World::new();
558 let root = world.spawn_empty().id();
559 let child1 = world.spawn(ChildOf(root)).id();
560 let grandchild = world.spawn(ChildOf(child1)).id();
561 let child2 = world.spawn(ChildOf(root)).id();
562
563 let hierarchy = get_hierarchy(&world, root);
565 assert_eq!(
566 hierarchy,
567 Node::new_with(
568 root,
569 vec![
570 Node::new_with(child1, vec![Node::new(grandchild)]),
571 Node::new(child2)
572 ]
573 )
574 );
575
576 world.entity_mut(child1).remove::<ChildOf>();
578 let hierarchy = get_hierarchy(&world, root);
579 assert_eq!(hierarchy, Node::new_with(root, vec![Node::new(child2)]));
580
581 world.entity_mut(child1).insert(ChildOf(root));
583 let hierarchy = get_hierarchy(&world, root);
584 assert_eq!(
585 hierarchy,
586 Node::new_with(
587 root,
588 vec![
589 Node::new(child2),
590 Node::new_with(child1, vec![Node::new(grandchild)])
591 ]
592 )
593 );
594
595 world.entity_mut(root).despawn();
597 assert!(world.get_entity(root).is_err());
598 assert!(world.get_entity(child1).is_err());
599 assert!(world.get_entity(child2).is_err());
600 assert!(world.get_entity(grandchild).is_err());
601 }
602
603 #[test]
604 fn with_children() {
605 let mut world = World::new();
606 let mut child1 = Entity::PLACEHOLDER;
607 let mut child2 = Entity::PLACEHOLDER;
608 let root = world
609 .spawn_empty()
610 .with_children(|p| {
611 child1 = p.spawn_empty().id();
612 child2 = p.spawn_empty().id();
613 })
614 .id();
615
616 let hierarchy = get_hierarchy(&world, root);
617 assert_eq!(
618 hierarchy,
619 Node::new_with(root, vec![Node::new(child1), Node::new(child2)])
620 );
621 }
622
623 #[test]
624 fn add_children() {
625 let mut world = World::new();
626 let child1 = world.spawn_empty().id();
627 let child2 = world.spawn_empty().id();
628 let root = world.spawn_empty().add_children(&[child1, child2]).id();
629
630 let hierarchy = get_hierarchy(&world, root);
631 assert_eq!(
632 hierarchy,
633 Node::new_with(root, vec![Node::new(child1), Node::new(child2)])
634 );
635 }
636
637 #[test]
638 fn insert_children() {
639 let mut world = World::new();
640 let child1 = world.spawn_empty().id();
641 let child2 = world.spawn_empty().id();
642 let child3 = world.spawn_empty().id();
643 let child4 = world.spawn_empty().id();
644
645 let mut entity_world_mut = world.spawn_empty();
646
647 let first_children = entity_world_mut.add_children(&[child1, child2]);
648
649 let root = first_children.insert_children(1, &[child3, child4]).id();
650
651 let hierarchy = get_hierarchy(&world, root);
652 assert_eq!(
653 hierarchy,
654 Node::new_with(
655 root,
656 vec![
657 Node::new(child1),
658 Node::new(child3),
659 Node::new(child4),
660 Node::new(child2)
661 ]
662 )
663 );
664 }
665
666 #[test]
668 fn insert_children_index_bound() {
669 let mut world = World::new();
670 let child1 = world.spawn_empty().id();
671 let child2 = world.spawn_empty().id();
672 let child3 = world.spawn_empty().id();
673 let child4 = world.spawn_empty().id();
674
675 let mut entity_world_mut = world.spawn_empty();
676
677 let first_children = entity_world_mut.add_children(&[child1, child2]).id();
678 let hierarchy = get_hierarchy(&world, first_children);
679 assert_eq!(
680 hierarchy,
681 Node::new_with(first_children, vec![Node::new(child1), Node::new(child2)])
682 );
683
684 let root = world
685 .entity_mut(first_children)
686 .insert_children(usize::MAX, &[child3, child4])
687 .id();
688 let hierarchy = get_hierarchy(&world, root);
689 assert_eq!(
690 hierarchy,
691 Node::new_with(
692 root,
693 vec![
694 Node::new(child1),
695 Node::new(child2),
696 Node::new(child3),
697 Node::new(child4),
698 ]
699 )
700 );
701 }
702
703 #[test]
704 fn remove_children() {
705 let mut world = World::new();
706 let child1 = world.spawn_empty().id();
707 let child2 = world.spawn_empty().id();
708 let child3 = world.spawn_empty().id();
709 let child4 = world.spawn_empty().id();
710
711 let mut root = world.spawn_empty();
712 root.add_children(&[child1, child2, child3, child4]);
713 root.remove_children(&[child2, child3]);
714 let root = root.id();
715
716 let hierarchy = get_hierarchy(&world, root);
717 assert_eq!(
718 hierarchy,
719 Node::new_with(root, vec![Node::new(child1), Node::new(child4)])
720 );
721 }
722
723 #[test]
724 fn self_parenting_invalid() {
725 let mut world = World::new();
726 let id = world.spawn_empty().id();
727 world.entity_mut(id).insert(ChildOf(id));
728 assert!(
729 world.entity(id).get::<ChildOf>().is_none(),
730 "invalid ChildOf relationships should self-remove"
731 );
732 }
733
734 #[test]
735 fn missing_parent_invalid() {
736 let mut world = World::new();
737 let parent = world.spawn_empty().id();
738 world.entity_mut(parent).despawn();
739 let id = world.spawn(ChildOf(parent)).id();
740 assert!(
741 world.entity(id).get::<ChildOf>().is_none(),
742 "invalid ChildOf relationships should self-remove"
743 );
744 }
745
746 #[test]
747 fn reinsert_same_parent() {
748 let mut world = World::new();
749 let parent = world.spawn_empty().id();
750 let id = world.spawn(ChildOf(parent)).id();
751 world.entity_mut(id).insert(ChildOf(parent));
752 assert_eq!(
753 Some(&ChildOf(parent)),
754 world.entity(id).get::<ChildOf>(),
755 "ChildOf should still be there"
756 );
757 }
758
759 #[test]
760 fn spawn_children() {
761 let mut world = World::new();
762 let id = world.spawn(Children::spawn((Spawn(()), Spawn(())))).id();
763 assert_eq!(world.entity(id).get::<Children>().unwrap().len(), 2,);
764 }
765
766 #[test]
767 fn replace_children() {
768 let mut world = World::new();
769 let parent = world.spawn(Children::spawn((Spawn(()), Spawn(())))).id();
770 let &[child_a, child_b] = &world.entity(parent).get::<Children>().unwrap().0[..] else {
771 panic!("Tried to spawn 2 children on an entity and didn't get 2 children");
772 };
773
774 let child_c = world.spawn_empty().id();
775
776 world
777 .entity_mut(parent)
778 .replace_children(&[child_a, child_c]);
779
780 let children = world.entity(parent).get::<Children>().unwrap();
781
782 assert!(children.contains(&child_a));
783 assert!(children.contains(&child_c));
784 assert!(!children.contains(&child_b));
785
786 assert_eq!(
787 world.entity(child_a).get::<ChildOf>().unwrap(),
788 &ChildOf(parent)
789 );
790 assert_eq!(
791 world.entity(child_c).get::<ChildOf>().unwrap(),
792 &ChildOf(parent)
793 );
794 assert!(world.entity(child_b).get::<ChildOf>().is_none());
795 }
796
797 #[test]
798 fn replace_children_with_nothing() {
799 let mut world = World::new();
800 let parent = world.spawn_empty().id();
801 let child_a = world.spawn_empty().id();
802 let child_b = world.spawn_empty().id();
803
804 world.entity_mut(parent).add_children(&[child_a, child_b]);
805
806 assert_eq!(world.entity(parent).get::<Children>().unwrap().len(), 2);
807
808 world.entity_mut(parent).replace_children(&[]);
809
810 assert!(world.entity(child_a).get::<ChildOf>().is_none());
811 assert!(world.entity(child_b).get::<ChildOf>().is_none());
812 }
813
814 #[test]
815 fn insert_same_child_twice() {
816 let mut world = World::new();
817
818 let parent = world.spawn_empty().id();
819 let child = world.spawn_empty().id();
820
821 world.entity_mut(parent).add_child(child);
822 world.entity_mut(parent).add_child(child);
823
824 let children = world.get::<Children>(parent).unwrap();
825 assert_eq!(children.0, [child]);
826 assert_eq!(
827 world.entity(child).get::<ChildOf>().unwrap(),
828 &ChildOf(parent)
829 );
830 }
831
832 #[test]
833 fn replace_with_difference() {
834 let mut world = World::new();
835
836 let parent = world.spawn_empty().id();
837 let child_a = world.spawn_empty().id();
838 let child_b = world.spawn_empty().id();
839 let child_c = world.spawn_empty().id();
840 let child_d = world.spawn_empty().id();
841
842 world.entity_mut(parent).replace_children_with_difference(
844 &[],
845 &[child_a, child_b],
846 &[child_a, child_b],
847 );
848
849 assert_eq!(
850 world.entity(child_a).get::<ChildOf>().unwrap(),
851 &ChildOf(parent)
852 );
853 assert_eq!(
854 world.entity(child_b).get::<ChildOf>().unwrap(),
855 &ChildOf(parent)
856 );
857 assert_eq!(
858 world.entity(parent).get::<Children>().unwrap().0,
859 [child_a, child_b]
860 );
861
862 world.entity_mut(parent).replace_children_with_difference(
864 &[child_b],
865 &[child_d, child_c, child_a],
866 &[child_c, child_d],
867 );
868 assert_eq!(
869 world.entity(child_a).get::<ChildOf>().unwrap(),
870 &ChildOf(parent)
871 );
872 assert_eq!(
873 world.entity(child_c).get::<ChildOf>().unwrap(),
874 &ChildOf(parent)
875 );
876 assert_eq!(
877 world.entity(child_d).get::<ChildOf>().unwrap(),
878 &ChildOf(parent)
879 );
880 assert_eq!(
881 world.entity(parent).get::<Children>().unwrap().0,
882 [child_d, child_c, child_a]
883 );
884 assert!(!world.entity(child_b).contains::<ChildOf>());
885
886 world.entity_mut(parent).replace_children_with_difference(
888 &[child_a, child_d, child_c],
889 &[],
890 &[],
891 );
892 assert!(!world.entity(parent).contains::<Children>());
893 assert!(!world.entity(child_a).contains::<ChildOf>());
894 assert!(!world.entity(child_b).contains::<ChildOf>());
895 assert!(!world.entity(child_c).contains::<ChildOf>());
896 assert!(!world.entity(child_d).contains::<ChildOf>());
897 }
898
899 #[test]
900 fn replace_with_difference_on_empty() {
901 let mut world = World::new();
902
903 let parent = world.spawn_empty().id();
904 let child_a = world.spawn_empty().id();
905
906 world
907 .entity_mut(parent)
908 .replace_children_with_difference(&[child_a], &[], &[]);
909
910 assert!(!world.entity(parent).contains::<Children>());
911 assert!(!world.entity(child_a).contains::<ChildOf>());
912 }
913
914 #[test]
915 fn replace_with_difference_totally_new_children() {
916 let mut world = World::new();
917
918 let parent = world.spawn_empty().id();
919 let child_a = world.spawn_empty().id();
920 let child_b = world.spawn_empty().id();
921 let child_c = world.spawn_empty().id();
922 let child_d = world.spawn_empty().id();
923
924 world.entity_mut(parent).replace_children_with_difference(
926 &[],
927 &[child_a, child_b],
928 &[child_a, child_b],
929 );
930
931 assert_eq!(
932 world.entity(child_a).get::<ChildOf>().unwrap(),
933 &ChildOf(parent)
934 );
935 assert_eq!(
936 world.entity(child_b).get::<ChildOf>().unwrap(),
937 &ChildOf(parent)
938 );
939 assert_eq!(
940 world.entity(parent).get::<Children>().unwrap().0,
941 [child_a, child_b]
942 );
943
944 world.entity_mut(parent).replace_children_with_difference(
946 &[child_b, child_a],
947 &[child_d, child_c],
948 &[child_c, child_d],
949 );
950 assert_eq!(
951 world.entity(child_c).get::<ChildOf>().unwrap(),
952 &ChildOf(parent)
953 );
954 assert_eq!(
955 world.entity(child_d).get::<ChildOf>().unwrap(),
956 &ChildOf(parent)
957 );
958 assert_eq!(
959 world.entity(parent).get::<Children>().unwrap().0,
960 [child_d, child_c]
961 );
962 assert!(!world.entity(child_a).contains::<ChildOf>());
963 assert!(!world.entity(child_b).contains::<ChildOf>());
964 }
965
966 #[test]
967 fn replace_children_order() {
968 let mut world = World::new();
969
970 let parent = world.spawn_empty().id();
971 let child_a = world.spawn_empty().id();
972 let child_b = world.spawn_empty().id();
973 let child_c = world.spawn_empty().id();
974 let child_d = world.spawn_empty().id();
975
976 let initial_order = [child_a, child_b, child_c, child_d];
977 world.entity_mut(parent).add_children(&initial_order);
978
979 assert_eq!(
980 world.entity_mut(parent).get::<Children>().unwrap().0,
981 initial_order
982 );
983
984 let new_order = [child_d, child_b, child_a, child_c];
985 world.entity_mut(parent).replace_children(&new_order);
986
987 assert_eq!(world.entity(parent).get::<Children>().unwrap().0, new_order);
988 }
989
990 #[test]
991 #[should_panic]
992 #[cfg_attr(
993 not(debug_assertions),
994 ignore = "we don't check invariants if debug assertions are off"
995 )]
996 fn replace_diff_invariant_overlapping_unrelate_with_relate() {
997 let mut world = World::new();
998
999 let parent = world.spawn_empty().id();
1000 let child_a = world.spawn_empty().id();
1001
1002 world
1003 .entity_mut(parent)
1004 .replace_children_with_difference(&[], &[child_a], &[child_a]);
1005
1006 world
1008 .entity_mut(parent)
1009 .replace_children_with_difference(&[child_a], &[child_a], &[]);
1010 }
1011
1012 #[test]
1013 #[should_panic]
1014 #[cfg_attr(
1015 not(debug_assertions),
1016 ignore = "we don't check invariants if debug assertions are off"
1017 )]
1018 fn replace_diff_invariant_overlapping_unrelate_with_newly() {
1019 let mut world = World::new();
1020
1021 let parent = world.spawn_empty().id();
1022 let child_a = world.spawn_empty().id();
1023 let child_b = world.spawn_empty().id();
1024
1025 world
1026 .entity_mut(parent)
1027 .replace_children_with_difference(&[], &[child_a], &[child_a]);
1028
1029 world.entity_mut(parent).replace_children_with_difference(
1031 &[child_b],
1032 &[child_a, child_b],
1033 &[child_b],
1034 );
1035 }
1036
1037 #[test]
1038 #[should_panic]
1039 #[cfg_attr(
1040 not(debug_assertions),
1041 ignore = "we don't check invariants if debug assertions are off"
1042 )]
1043 fn replace_diff_invariant_newly_not_subset() {
1044 let mut world = World::new();
1045
1046 let parent = world.spawn_empty().id();
1047 let child_a = world.spawn_empty().id();
1048 let child_b = world.spawn_empty().id();
1049
1050 world.entity_mut(parent).replace_children_with_difference(
1052 &[],
1053 &[child_a, child_b],
1054 &[child_a],
1055 );
1056 }
1057
1058 #[test]
1059 fn child_replace_hook_skip() {
1060 let mut world = World::new();
1061 let parent = world.spawn_empty().id();
1062 let other = world.spawn_empty().id();
1063 let child = world.spawn(ChildOf(parent)).id();
1064 world
1065 .entity_mut(child)
1066 .insert_with_relationship_hook_mode(ChildOf(other), RelationshipHookMode::Skip);
1067 assert_eq!(
1068 &**world.entity(parent).get::<Children>().unwrap(),
1069 &[child],
1070 "Children should still have the old value, as on_insert/on_replace didn't run"
1071 );
1072 }
1073}