1mod related_methods;
4mod relationship_query;
5mod relationship_source_collection;
6
7use alloc::boxed::Box;
8use bevy_ptr::Ptr;
9use core::marker::PhantomData;
10
11use alloc::format;
12
13use bevy_utils::prelude::DebugName;
14pub use related_methods::*;
15pub use relationship_query::*;
16pub use relationship_source_collection::*;
17
18use crate::{
19 component::{Component, ComponentCloneBehavior, Mutable},
20 entity::{ComponentCloneCtx, Entity},
21 error::CommandWithEntity,
22 lifecycle::HookContext,
23 world::{DeferredWorld, EntityWorldMut},
24};
25use log::warn;
26
27pub trait Relationship: Component + Sized {
79 type RelationshipTarget: RelationshipTarget<Relationship = Self>;
82
83 fn get(&self) -> Entity;
85
86 fn from(entity: Entity) -> Self;
88
89 fn set_risky(&mut self, entity: Entity);
102
103 fn on_insert(
105 mut world: DeferredWorld,
106 HookContext {
107 entity,
108 caller,
109 relationship_hook_mode,
110 ..
111 }: HookContext,
112 ) {
113 match relationship_hook_mode {
114 RelationshipHookMode::Run => {}
115 RelationshipHookMode::Skip => return,
116 RelationshipHookMode::RunIfNotLinked => {
117 if <Self::RelationshipTarget as RelationshipTarget>::LINKED_SPAWN {
118 return;
119 }
120 }
121 }
122 let target_entity = world.entity(entity).get::<Self>().unwrap().get();
123 if target_entity == entity {
124 warn!(
125 "{}The {}({target_entity:?}) relationship on entity {entity:?} points to itself. The invalid {} relationship has been removed.",
126 caller.map(|location|format!("{location}: ")).unwrap_or_default(),
127 DebugName::type_name::<Self>(),
128 DebugName::type_name::<Self>()
129 );
130 world.commands().entity(entity).remove::<Self>();
131 return;
132 }
133 let current_source_to_remove = world
135 .get_entity(target_entity)
136 .ok()
137 .and_then(|target_entity_ref| target_entity_ref.get::<Self::RelationshipTarget>())
138 .and_then(|relationship_target| {
139 relationship_target
140 .collection()
141 .source_to_remove_before_add()
142 });
143
144 if let Some(current_source) = current_source_to_remove {
145 world.commands().entity(current_source).try_remove::<Self>();
146 }
147
148 if let Ok(mut entity_commands) = world.commands().get_entity(target_entity) {
149 entity_commands
151 .entry::<Self::RelationshipTarget>()
152 .and_modify(move |mut relationship_target| {
153 relationship_target.collection_mut_risky().add(entity);
154 })
155 .or_insert_with(move || {
156 let mut target = Self::RelationshipTarget::with_capacity(1);
157 target.collection_mut_risky().add(entity);
158 target
159 });
160 } else {
161 warn!(
162 "{}The {}({target_entity:?}) relationship on entity {entity:?} relates to an entity that does not exist. The invalid {} relationship has been removed.",
163 caller.map(|location|format!("{location}: ")).unwrap_or_default(),
164 DebugName::type_name::<Self>(),
165 DebugName::type_name::<Self>()
166 );
167 world.commands().entity(entity).remove::<Self>();
168 }
169 }
170
171 fn on_replace(
174 mut world: DeferredWorld,
175 HookContext {
176 entity,
177 relationship_hook_mode,
178 ..
179 }: HookContext,
180 ) {
181 match relationship_hook_mode {
182 RelationshipHookMode::Run => {}
183 RelationshipHookMode::Skip => return,
184 RelationshipHookMode::RunIfNotLinked => {
185 if <Self::RelationshipTarget as RelationshipTarget>::LINKED_SPAWN {
186 return;
187 }
188 }
189 }
190 let target_entity = world.entity(entity).get::<Self>().unwrap().get();
191 if let Ok(mut target_entity_mut) = world.get_entity_mut(target_entity)
192 && let Some(mut relationship_target) =
193 target_entity_mut.get_mut::<Self::RelationshipTarget>()
194 {
195 relationship_target.collection_mut_risky().remove(entity);
196 if relationship_target.len() == 0 {
197 let command = |mut entity: EntityWorldMut| {
198 if entity
202 .get::<Self::RelationshipTarget>()
203 .is_some_and(RelationshipTarget::is_empty)
204 {
205 entity.remove::<Self::RelationshipTarget>();
206 }
207 };
208
209 world
210 .commands()
211 .queue_silenced(command.with_entity(target_entity));
212 }
213 }
214 }
215}
216
217pub type SourceIter<'w, R> =
220 <<R as RelationshipTarget>::Collection as RelationshipSourceCollection>::SourceIter<'w>;
221
222pub trait RelationshipTarget: Component<Mutability = Mutable> + Sized {
225 const LINKED_SPAWN: bool;
233 type Relationship: Relationship<RelationshipTarget = Self>;
235 type Collection: RelationshipSourceCollection;
242
243 fn collection(&self) -> &Self::Collection;
245 fn collection_mut_risky(&mut self) -> &mut Self::Collection;
251
252 fn from_collection_risky(collection: Self::Collection) -> Self;
258
259 fn on_replace(
262 mut world: DeferredWorld,
263 HookContext {
264 entity,
265 relationship_hook_mode,
266 ..
267 }: HookContext,
268 ) {
269 match relationship_hook_mode {
270 RelationshipHookMode::Run => {}
271 RelationshipHookMode::Skip | RelationshipHookMode::RunIfNotLinked => return,
273 }
274 let (entities, mut commands) = world.entities_and_commands();
275 let relationship_target = entities.get(entity).unwrap().get::<Self>().unwrap();
276 for source_entity in relationship_target.iter() {
277 commands
278 .entity(source_entity)
279 .try_remove::<Self::Relationship>();
280 }
281 }
282
283 fn on_despawn(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
287 let (entities, mut commands) = world.entities_and_commands();
288 let relationship_target = entities.get(entity).unwrap().get::<Self>().unwrap();
289 for source_entity in relationship_target.iter() {
290 commands.entity(source_entity).try_despawn();
291 }
292 }
293
294 fn with_capacity(capacity: usize) -> Self {
296 let collection =
297 <Self::Collection as RelationshipSourceCollection>::with_capacity(capacity);
298 Self::from_collection_risky(collection)
299 }
300
301 #[inline]
303 fn iter(&self) -> SourceIter<'_, Self> {
304 self.collection().iter()
305 }
306
307 #[inline]
309 fn len(&self) -> usize {
310 self.collection().len()
311 }
312
313 #[inline]
315 fn is_empty(&self) -> bool {
316 self.collection().is_empty()
317 }
318}
319
320pub fn clone_relationship_target<T: RelationshipTarget>(
327 component: &T,
328 cloned: &mut T,
329 context: &mut ComponentCloneCtx,
330) {
331 if context.linked_cloning() && T::LINKED_SPAWN {
332 let collection = cloned.collection_mut_risky();
333 for entity in component.iter() {
334 collection.add(entity);
335 context.queue_entity_clone(entity);
336 }
337 } else if context.moving() {
338 let target = context.target();
339 let collection = cloned.collection_mut_risky();
340 for entity in component.iter() {
341 collection.add(entity);
342 context.queue_deferred(move |world, _mapper| {
343 _ = DeferredWorld::from(world)
345 .modify_component_with_relationship_hook_mode::<T::Relationship, ()>(
346 entity,
347 RelationshipHookMode::Skip,
348 |r| r.set_risky(target),
349 );
350 });
351 }
352 }
353}
354
355#[derive(Copy, Clone, Debug)]
357pub enum RelationshipHookMode {
358 Run,
360 RunIfNotLinked,
362 Skip,
364}
365
366#[doc(hidden)]
368pub struct RelationshipCloneBehaviorSpecialization<T>(PhantomData<T>);
369
370impl<T> Default for RelationshipCloneBehaviorSpecialization<T> {
371 fn default() -> Self {
372 Self(PhantomData)
373 }
374}
375
376#[doc(hidden)]
378pub trait RelationshipCloneBehaviorBase {
379 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
380}
381
382impl<C> RelationshipCloneBehaviorBase for RelationshipCloneBehaviorSpecialization<C> {
383 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
384 ComponentCloneBehavior::Ignore
386 }
387}
388
389#[doc(hidden)]
391pub trait RelationshipCloneBehaviorViaReflect {
392 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
393}
394
395#[cfg(feature = "bevy_reflect")]
396impl<C: Relationship + bevy_reflect::Reflect> RelationshipCloneBehaviorViaReflect
397 for &RelationshipCloneBehaviorSpecialization<C>
398{
399 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
400 ComponentCloneBehavior::reflect()
401 }
402}
403
404#[doc(hidden)]
406pub trait RelationshipCloneBehaviorViaClone {
407 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
408}
409
410impl<C: Relationship + Clone> RelationshipCloneBehaviorViaClone
411 for &&RelationshipCloneBehaviorSpecialization<C>
412{
413 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
414 ComponentCloneBehavior::clone::<C>()
415 }
416}
417
418#[doc(hidden)]
420pub trait RelationshipTargetCloneBehaviorViaReflect {
421 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
422}
423
424#[cfg(feature = "bevy_reflect")]
425impl<C: RelationshipTarget + bevy_reflect::Reflect + bevy_reflect::TypePath>
426 RelationshipTargetCloneBehaviorViaReflect for &&&RelationshipCloneBehaviorSpecialization<C>
427{
428 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
429 ComponentCloneBehavior::Custom(|source, context| {
430 if let Some(component) = source.read::<C>()
431 && let Ok(mut cloned) = component.reflect_clone_and_take::<C>()
432 {
433 cloned.collection_mut_risky().clear();
434 clone_relationship_target(component, &mut cloned, context);
435 context.write_target_component(cloned);
436 }
437 })
438 }
439}
440
441#[doc(hidden)]
443pub trait RelationshipTargetCloneBehaviorViaClone {
444 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
445}
446
447impl<C: RelationshipTarget + Clone> RelationshipTargetCloneBehaviorViaClone
448 for &&&&RelationshipCloneBehaviorSpecialization<C>
449{
450 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
451 ComponentCloneBehavior::Custom(|source, context| {
452 if let Some(component) = source.read::<C>() {
453 let mut cloned = component.clone();
454 cloned.collection_mut_risky().clear();
455 clone_relationship_target(component, &mut cloned, context);
456 context.write_target_component(cloned);
457 }
458 })
459 }
460}
461
462#[doc(hidden)]
464pub trait RelationshipTargetCloneBehaviorHierarchy {
465 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
466}
467
468impl RelationshipTargetCloneBehaviorHierarchy
469 for &&&&&RelationshipCloneBehaviorSpecialization<crate::hierarchy::Children>
470{
471 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
472 ComponentCloneBehavior::Custom(|source, context| {
473 if let Some(component) = source.read::<crate::hierarchy::Children>() {
474 let mut cloned = crate::hierarchy::Children::with_capacity(component.len());
475 clone_relationship_target(component, &mut cloned, context);
476 context.write_target_component(cloned);
477 }
478 })
479 }
480}
481
482#[derive(Debug, Clone, Copy)]
485pub enum RelationshipAccessor {
486 Relationship {
488 entity_field_offset: usize,
492 linked_spawn: bool,
494 },
495 RelationshipTarget {
497 iter: for<'a> unsafe fn(Ptr<'a>) -> Box<dyn Iterator<Item = Entity> + 'a>,
503 linked_spawn: bool,
505 },
506}
507
508pub struct ComponentRelationshipAccessor<C: ?Sized> {
510 pub(crate) accessor: RelationshipAccessor,
511 phantom: PhantomData<C>,
512}
513
514impl<C> ComponentRelationshipAccessor<C> {
515 pub unsafe fn relationship(entity_field_offset: usize) -> Self
520 where
521 C: Relationship,
522 {
523 Self {
524 accessor: RelationshipAccessor::Relationship {
525 entity_field_offset,
526 linked_spawn: C::RelationshipTarget::LINKED_SPAWN,
527 },
528 phantom: Default::default(),
529 }
530 }
531
532 pub fn relationship_target() -> Self
534 where
535 C: RelationshipTarget,
536 {
537 Self {
538 accessor: RelationshipAccessor::RelationshipTarget {
539 iter: |ptr| unsafe { Box::new(RelationshipTarget::iter(ptr.deref::<C>())) },
541 linked_spawn: C::LINKED_SPAWN,
542 },
543 phantom: Default::default(),
544 }
545 }
546}
547
548#[cfg(test)]
549mod tests {
550 use core::marker::PhantomData;
551
552 use crate::prelude::{ChildOf, Children};
553 use crate::relationship::RelationshipAccessor;
554 use crate::world::World;
555 use crate::{component::Component, entity::Entity};
556 use alloc::vec::Vec;
557
558 #[test]
559 fn custom_relationship() {
560 #[derive(Component)]
561 #[relationship(relationship_target = LikedBy)]
562 struct Likes(pub Entity);
563
564 #[derive(Component)]
565 #[relationship_target(relationship = Likes)]
566 struct LikedBy(Vec<Entity>);
567
568 let mut world = World::new();
569 let a = world.spawn_empty().id();
570 let b = world.spawn(Likes(a)).id();
571 let c = world.spawn(Likes(a)).id();
572 assert_eq!(world.entity(a).get::<LikedBy>().unwrap().0, &[b, c]);
573 }
574
575 #[test]
576 fn self_relationship_fails() {
577 #[derive(Component)]
578 #[relationship(relationship_target = RelTarget)]
579 struct Rel(Entity);
580
581 #[derive(Component)]
582 #[relationship_target(relationship = Rel)]
583 struct RelTarget(Vec<Entity>);
584
585 let mut world = World::new();
586 let a = world.spawn_empty().id();
587 world.entity_mut(a).insert(Rel(a));
588 assert!(!world.entity(a).contains::<Rel>());
589 assert!(!world.entity(a).contains::<RelTarget>());
590 }
591
592 #[test]
593 fn relationship_with_missing_target_fails() {
594 #[derive(Component)]
595 #[relationship(relationship_target = RelTarget)]
596 struct Rel(Entity);
597
598 #[derive(Component)]
599 #[relationship_target(relationship = Rel)]
600 struct RelTarget(Vec<Entity>);
601
602 let mut world = World::new();
603 let a = world.spawn_empty().id();
604 world.despawn(a);
605 let b = world.spawn(Rel(a)).id();
606 assert!(!world.entity(b).contains::<Rel>());
607 assert!(!world.entity(b).contains::<RelTarget>());
608 }
609
610 #[test]
611 fn relationship_with_multiple_non_target_fields_compiles() {
612 #[expect(
613 dead_code,
614 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
615 )]
616 #[derive(Component)]
617 #[relationship(relationship_target=Target)]
618 struct Source {
619 #[relationship]
620 target: Entity,
621 foo: u8,
622 bar: u8,
623 }
624
625 #[expect(
626 dead_code,
627 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
628 )]
629 #[derive(Component)]
630 #[relationship_target(relationship=Source)]
631 struct Target(Vec<Entity>);
632
633 }
635 #[test]
636 fn relationship_target_with_multiple_non_target_fields_compiles() {
637 #[expect(
638 dead_code,
639 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
640 )]
641 #[derive(Component)]
642 #[relationship(relationship_target=Target)]
643 struct Source(Entity);
644
645 #[expect(
646 dead_code,
647 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
648 )]
649 #[derive(Component)]
650 #[relationship_target(relationship=Source)]
651 struct Target {
652 #[relationship]
653 target: Vec<Entity>,
654 foo: u8,
655 bar: u8,
656 }
657
658 }
660
661 #[test]
662 fn relationship_with_multiple_unnamed_non_target_fields_compiles() {
663 #[expect(
664 dead_code,
665 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
666 )]
667 #[derive(Component)]
668 #[relationship(relationship_target=Target<T>)]
669 struct Source<T: Send + Sync + 'static>(#[relationship] Entity, PhantomData<T>);
670
671 #[expect(
672 dead_code,
673 reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
674 )]
675 #[derive(Component)]
676 #[relationship_target(relationship=Source<T>)]
677 struct Target<T: Send + Sync + 'static>(#[relationship] Vec<Entity>, PhantomData<T>);
678
679 }
681
682 #[test]
683 fn parent_child_relationship_with_custom_relationship() {
684 #[derive(Component)]
685 #[relationship(relationship_target = RelTarget)]
686 struct Rel(Entity);
687
688 #[derive(Component)]
689 #[relationship_target(relationship = Rel)]
690 struct RelTarget(Entity);
691
692 let mut world = World::new();
693
694 let mut commands = world.commands();
697 let child = commands.spawn_empty().id();
698 let parent = commands.spawn(Rel(child)).add_child(child).id();
699 commands.entity(parent).despawn();
700 world.flush();
701
702 assert!(world.get_entity(child).is_err());
703 assert!(world.get_entity(parent).is_err());
704
705 let mut commands = world.commands();
708 let child = commands.spawn_empty().id();
709 let parent = commands.spawn(Rel(child)).add_child(child).id();
710 commands.entity(child).despawn();
711 world.flush();
712
713 assert!(world.get_entity(child).is_err());
714 assert!(!world.entity(parent).contains::<Rel>());
715
716 let mut commands = world.commands();
719 let parent = commands.spawn_empty().id();
720 let child = commands.spawn((ChildOf(parent), Rel(parent))).id();
721 commands.entity(parent).despawn();
722 world.flush();
723
724 assert!(world.get_entity(child).is_err());
725 assert!(world.get_entity(parent).is_err());
726
727 let mut commands = world.commands();
730 let parent = commands.spawn_empty().id();
731 let child = commands.spawn((ChildOf(parent), Rel(parent))).id();
732 commands.entity(child).despawn();
733 world.flush();
734
735 assert!(world.get_entity(child).is_err());
736 assert!(!world.entity(parent).contains::<RelTarget>());
737 }
738
739 #[test]
740 fn spawn_batch_with_relationship() {
741 let mut world = World::new();
742 let parent = world.spawn_empty().id();
743 let children = world
744 .spawn_batch((0..10).map(|_| ChildOf(parent)))
745 .collect::<Vec<_>>();
746
747 for &child in &children {
748 assert!(world
749 .get::<ChildOf>(child)
750 .is_some_and(|child_of| child_of.parent() == parent));
751 }
752 assert!(world
753 .get::<Children>(parent)
754 .is_some_and(|children| children.len() == 10));
755 }
756
757 #[test]
758 fn insert_batch_with_relationship() {
759 let mut world = World::new();
760 let parent = world.spawn_empty().id();
761 let child = world.spawn_empty().id();
762 world.insert_batch([(child, ChildOf(parent))]);
763 world.flush();
764
765 assert!(world.get::<ChildOf>(child).is_some());
766 assert!(world.get::<Children>(parent).is_some());
767 }
768
769 #[test]
770 fn dynamically_traverse_hierarchy() {
771 let mut world = World::new();
772 let child_of_id = world.register_component::<ChildOf>();
773 let children_id = world.register_component::<Children>();
774
775 let parent = world.spawn_empty().id();
776 let child = world.spawn_empty().id();
777 world.entity_mut(child).insert(ChildOf(parent));
778 world.flush();
779
780 let children_ptr = world.get_by_id(parent, children_id).unwrap();
781 let RelationshipAccessor::RelationshipTarget { iter, .. } = world
782 .components()
783 .get_info(children_id)
784 .unwrap()
785 .relationship_accessor()
786 .unwrap()
787 else {
788 unreachable!()
789 };
790 let children: Vec<_> = unsafe { iter(children_ptr).collect() };
792 assert_eq!(children, alloc::vec![child]);
793
794 let child_of_ptr = world.get_by_id(child, child_of_id).unwrap();
795 let RelationshipAccessor::Relationship {
796 entity_field_offset,
797 ..
798 } = world
799 .components()
800 .get_info(child_of_id)
801 .unwrap()
802 .relationship_accessor()
803 .unwrap()
804 else {
805 unreachable!()
806 };
807 let child_of_entity: Entity =
811 unsafe { *child_of_ptr.byte_add(*entity_field_offset).deref() };
812 assert_eq!(child_of_entity, parent);
813 }
814}