1use alloc::{borrow::ToOwned, boxed::Box, collections::VecDeque, vec::Vec};
2use bevy_platform::collections::{HashMap, HashSet};
3use bevy_ptr::{Ptr, PtrMut};
4use bumpalo::Bump;
5use core::any::TypeId;
6
7use crate::{
8 bundle::Bundle,
9 component::{Component, ComponentCloneBehavior, ComponentCloneFn, ComponentId, ComponentInfo},
10 entity::{hash_map::EntityHashMap, Entities, Entity, EntityMapper},
11 query::DebugCheckedUnwrap,
12 relationship::RelationshipHookMode,
13 world::World,
14};
15
16pub struct SourceComponent<'a> {
18 ptr: Ptr<'a>,
19 info: &'a ComponentInfo,
20}
21
22impl<'a> SourceComponent<'a> {
23 pub fn read<C: Component>(&self) -> Option<&C> {
27 if self
28 .info
29 .type_id()
30 .is_some_and(|id| id == TypeId::of::<C>())
31 {
32 unsafe { Some(self.ptr.deref::<C>()) }
36 } else {
37 None
38 }
39 }
40
41 pub fn ptr(&self) -> Ptr<'a> {
43 self.ptr
44 }
45
46 #[cfg(feature = "bevy_reflect")]
55 pub fn read_reflect(
56 &self,
57 registry: &bevy_reflect::TypeRegistry,
58 ) -> Option<&dyn bevy_reflect::Reflect> {
59 let type_id = self.info.type_id()?;
60 let reflect_from_ptr = registry.get_type_data::<bevy_reflect::ReflectFromPtr>(type_id)?;
61 if reflect_from_ptr.type_id() != type_id {
62 return None;
63 }
64 unsafe { Some(reflect_from_ptr.as_reflect(self.ptr)) }
66 }
67}
68
69pub struct ComponentCloneCtx<'a, 'b> {
74 component_id: ComponentId,
75 target_component_written: bool,
76 bundle_scratch: &'a mut BundleScratch<'b>,
77 bundle_scratch_allocator: &'b Bump,
78 entities: &'a Entities,
79 source: Entity,
80 target: Entity,
81 component_info: &'a ComponentInfo,
82 entity_cloner: &'a mut EntityCloner,
83 mapper: &'a mut dyn EntityMapper,
84 #[cfg(feature = "bevy_reflect")]
85 type_registry: Option<&'a crate::reflect::AppTypeRegistry>,
86 #[cfg(not(feature = "bevy_reflect"))]
87 #[expect(dead_code)]
88 type_registry: Option<&'a ()>,
89}
90
91impl<'a, 'b> ComponentCloneCtx<'a, 'b> {
92 unsafe fn new(
99 component_id: ComponentId,
100 source: Entity,
101 target: Entity,
102 bundle_scratch_allocator: &'b Bump,
103 bundle_scratch: &'a mut BundleScratch<'b>,
104 entities: &'a Entities,
105 component_info: &'a ComponentInfo,
106 entity_cloner: &'a mut EntityCloner,
107 mapper: &'a mut dyn EntityMapper,
108 #[cfg(feature = "bevy_reflect")] type_registry: Option<&'a crate::reflect::AppTypeRegistry>,
109 #[cfg(not(feature = "bevy_reflect"))] type_registry: Option<&'a ()>,
110 ) -> Self {
111 Self {
112 component_id,
113 source,
114 target,
115 bundle_scratch,
116 target_component_written: false,
117 bundle_scratch_allocator,
118 entities,
119 mapper,
120 component_info,
121 entity_cloner,
122 type_registry,
123 }
124 }
125
126 pub fn target_component_written(&self) -> bool {
128 self.target_component_written
129 }
130
131 pub fn source(&self) -> Entity {
133 self.source
134 }
135
136 pub fn target(&self) -> Entity {
138 self.target
139 }
140
141 pub fn component_id(&self) -> ComponentId {
143 self.component_id
144 }
145
146 pub fn component_info(&self) -> &ComponentInfo {
148 self.component_info
149 }
150
151 #[inline]
155 pub fn linked_cloning(&self) -> bool {
156 self.entity_cloner.linked_cloning
157 }
158
159 pub fn entity_mapper(&mut self) -> &mut dyn EntityMapper {
161 self.mapper
162 }
163
164 pub fn write_target_component<C: Component>(&mut self, mut component: C) {
172 C::map_entities(&mut component, &mut self.mapper);
173 let short_name = disqualified::ShortName::of::<C>();
174 if self.target_component_written {
175 panic!("Trying to write component '{short_name}' multiple times")
176 }
177 if self
178 .component_info
179 .type_id()
180 .is_none_or(|id| id != TypeId::of::<C>())
181 {
182 panic!("TypeId of component '{short_name}' does not match source component TypeId")
183 };
184 unsafe {
186 self.bundle_scratch
187 .push(self.bundle_scratch_allocator, self.component_id, component);
188 };
189 self.target_component_written = true;
190 }
191
192 pub unsafe fn write_target_component_ptr(&mut self, ptr: Ptr) {
201 if self.target_component_written {
202 panic!("Trying to write component multiple times")
203 }
204 let layout = self.component_info.layout();
205 let target_ptr = self.bundle_scratch_allocator.alloc_layout(layout);
206 core::ptr::copy_nonoverlapping(ptr.as_ptr(), target_ptr.as_ptr(), layout.size());
207 self.bundle_scratch
208 .push_ptr(self.component_id, PtrMut::new(target_ptr));
209 self.target_component_written = true;
210 }
211
212 #[cfg(feature = "bevy_reflect")]
222 pub fn write_target_component_reflect(&mut self, component: Box<dyn bevy_reflect::Reflect>) {
223 if self.target_component_written {
224 panic!("Trying to write component multiple times")
225 }
226 let source_type_id = self
227 .component_info
228 .type_id()
229 .expect("Source component must have TypeId");
230 let component_type_id = component.type_id();
231 if source_type_id != component_type_id {
232 panic!("Passed component TypeId does not match source component TypeId")
233 }
234 let component_layout = self.component_info.layout();
235
236 let component_data_ptr = Box::into_raw(component).cast::<u8>();
237 let target_component_data_ptr =
238 self.bundle_scratch_allocator.alloc_layout(component_layout);
239 unsafe {
243 core::ptr::copy_nonoverlapping(
244 component_data_ptr,
245 target_component_data_ptr.as_ptr(),
246 component_layout.size(),
247 );
248 self.bundle_scratch
249 .push_ptr(self.component_id, PtrMut::new(target_component_data_ptr));
250
251 if component_layout.size() > 0 {
252 alloc::alloc::dealloc(component_data_ptr, component_layout);
254 }
255 }
256
257 self.target_component_written = true;
258 }
259
260 #[cfg(feature = "bevy_reflect")]
264 pub fn type_registry(&self) -> Option<&crate::reflect::AppTypeRegistry> {
265 self.type_registry
266 }
267
268 pub fn queue_entity_clone(&mut self, entity: Entity) {
270 let target = self.entities.reserve_entity();
271 self.mapper.set_mapped(entity, target);
272 self.entity_cloner.clone_queue.push_back(entity);
273 }
274
275 pub fn queue_deferred(
278 &mut self,
279 deferred: impl FnOnce(&mut World, &mut dyn EntityMapper) + 'static,
280 ) {
281 self.entity_cloner
282 .deferred_commands
283 .push_back(Box::new(deferred));
284 }
285}
286
287pub struct EntityCloner {
347 filter_allows_components: bool,
348 filter: HashSet<ComponentId>,
349 clone_behavior_overrides: HashMap<ComponentId, ComponentCloneBehavior>,
350 move_components: bool,
351 linked_cloning: bool,
352 default_clone_fn: ComponentCloneFn,
353 clone_queue: VecDeque<Entity>,
354 deferred_commands: VecDeque<Box<dyn FnOnce(&mut World, &mut dyn EntityMapper)>>,
355}
356
357impl Default for EntityCloner {
358 fn default() -> Self {
359 Self {
360 filter_allows_components: false,
361 move_components: false,
362 linked_cloning: false,
363 default_clone_fn: ComponentCloneBehavior::global_default_fn(),
364 filter: Default::default(),
365 clone_behavior_overrides: Default::default(),
366 clone_queue: Default::default(),
367 deferred_commands: Default::default(),
368 }
369 }
370}
371
372struct BundleScratch<'a> {
374 component_ids: Vec<ComponentId>,
375 component_ptrs: Vec<PtrMut<'a>>,
376}
377
378impl<'a> BundleScratch<'a> {
379 pub(crate) fn with_capacity(capacity: usize) -> Self {
380 Self {
381 component_ids: Vec::with_capacity(capacity),
382 component_ptrs: Vec::with_capacity(capacity),
383 }
384 }
385
386 pub(crate) unsafe fn push_ptr(&mut self, id: ComponentId, ptr: PtrMut<'a>) {
393 self.component_ids.push(id);
394 self.component_ptrs.push(ptr);
395 }
396
397 pub(crate) unsafe fn push<C: Component>(
403 &mut self,
404 allocator: &'a Bump,
405 id: ComponentId,
406 component: C,
407 ) {
408 let component_ref = allocator.alloc(component);
409 self.component_ids.push(id);
410 self.component_ptrs.push(PtrMut::from(component_ref));
411 }
412
413 pub(crate) unsafe fn write(
418 self,
419 world: &mut World,
420 entity: Entity,
421 relationship_hook_insert_mode: RelationshipHookMode,
422 ) {
423 unsafe {
427 world.entity_mut(entity).insert_by_ids_internal(
428 &self.component_ids,
429 self.component_ptrs.into_iter().map(|ptr| ptr.promote()),
430 relationship_hook_insert_mode,
431 );
432 }
433 }
434}
435
436impl EntityCloner {
437 pub fn build(world: &mut World) -> EntityClonerBuilder {
439 EntityClonerBuilder {
440 world,
441 attach_required_components: true,
442 entity_cloner: EntityCloner::default(),
443 }
444 }
445
446 #[inline]
449 pub fn linked_cloning(&self) -> bool {
450 self.linked_cloning
451 }
452
453 fn clone_entity_internal(
455 &mut self,
456 world: &mut World,
457 source: Entity,
458 mapper: &mut dyn EntityMapper,
459 relationship_hook_insert_mode: RelationshipHookMode,
460 ) -> Entity {
461 let target = mapper.get_mapped(source);
462 let bundle_scratch_allocator = Bump::new();
464 let mut bundle_scratch: BundleScratch;
465 {
466 let world = world.as_unsafe_world_cell();
467 let source_entity = world.get_entity(source).expect("Source entity must exist");
468
469 #[cfg(feature = "bevy_reflect")]
470 let app_registry = unsafe {
473 world
474 .get_resource::<crate::reflect::AppTypeRegistry>()
475 .cloned()
476 };
477 #[cfg(not(feature = "bevy_reflect"))]
478 let app_registry = Option::<()>::None;
479
480 let archetype = source_entity.archetype();
481 bundle_scratch = BundleScratch::with_capacity(archetype.component_count());
482
483 for component in archetype.components() {
484 if !self.is_cloning_allowed(&component) {
485 continue;
486 }
487
488 let handler = match self.clone_behavior_overrides.get(&component) {
489 Some(clone_behavior) => clone_behavior.resolve(self.default_clone_fn),
490 None => world
491 .components()
492 .get_info(component)
493 .map(|info| info.clone_behavior().resolve(self.default_clone_fn))
494 .unwrap_or(self.default_clone_fn),
495 };
496
497 let info = unsafe { world.components().get_info_unchecked(component) };
499
500 let source_component_ptr =
504 unsafe { source_entity.get_by_id(component).debug_checked_unwrap() };
505
506 let source_component = SourceComponent {
507 info,
508 ptr: source_component_ptr,
509 };
510
511 let mut ctx = unsafe {
515 ComponentCloneCtx::new(
516 component,
517 source,
518 target,
519 &bundle_scratch_allocator,
520 &mut bundle_scratch,
521 world.entities(),
522 info,
523 self,
524 mapper,
525 app_registry.as_ref(),
526 )
527 };
528
529 (handler)(&source_component, &mut ctx);
530 }
531 }
532
533 world.flush();
534
535 for deferred in self.deferred_commands.drain(..) {
536 (deferred)(world, mapper);
537 }
538
539 if !world.entities.contains(target) {
540 panic!("Target entity does not exist");
541 }
542
543 if self.move_components {
544 world
545 .entity_mut(source)
546 .remove_by_ids(&bundle_scratch.component_ids);
547 }
548
549 unsafe { bundle_scratch.write(world, target, relationship_hook_insert_mode) };
553 target
554 }
555
556 #[track_caller]
561 pub fn clone_entity(&mut self, world: &mut World, source: Entity, target: Entity) {
562 let mut map = EntityHashMap::<Entity>::new();
563 map.set_mapped(source, target);
564 self.clone_entity_mapped(world, source, &mut map);
565 }
566
567 #[track_caller]
572 pub fn spawn_clone(&mut self, world: &mut World, source: Entity) -> Entity {
573 let target = world.spawn_empty().id();
574 self.clone_entity(world, source, target);
575 target
576 }
577
578 #[track_caller]
580 pub fn clone_entity_mapped(
581 &mut self,
582 world: &mut World,
583 source: Entity,
584 mapper: &mut dyn EntityMapper,
585 ) -> Entity {
586 let target = self.clone_entity_internal(world, source, mapper, RelationshipHookMode::Run);
588 let child_hook_insert_mode = if self.linked_cloning {
589 RelationshipHookMode::RunIfNotLinked
592 } else {
593 RelationshipHookMode::Run
596 };
597 loop {
598 let queued = self.clone_queue.pop_front();
599 if let Some(queued) = queued {
600 self.clone_entity_internal(world, queued, mapper, child_hook_insert_mode);
601 } else {
602 break;
603 }
604 }
605 target
606 }
607
608 fn is_cloning_allowed(&self, component: &ComponentId) -> bool {
609 (self.filter_allows_components && self.filter.contains(component))
610 || (!self.filter_allows_components && !self.filter.contains(component))
611 }
612}
613
614pub struct EntityClonerBuilder<'w> {
616 world: &'w mut World,
617 entity_cloner: EntityCloner,
618 attach_required_components: bool,
619}
620
621impl<'w> EntityClonerBuilder<'w> {
622 pub fn clone_entity(&mut self, source: Entity, target: Entity) -> &mut Self {
624 self.entity_cloner.clone_entity(self.world, source, target);
625 self
626 }
627 pub fn finish(self) -> EntityCloner {
629 self.entity_cloner
630 }
631
632 pub fn without_required_components(
638 &mut self,
639 builder: impl FnOnce(&mut EntityClonerBuilder),
640 ) -> &mut Self {
641 self.attach_required_components = false;
642 builder(self);
643 self.attach_required_components = true;
644 self
645 }
646
647 pub fn with_default_clone_fn(&mut self, clone_fn: ComponentCloneFn) -> &mut Self {
649 self.entity_cloner.default_clone_fn = clone_fn;
650 self
651 }
652
653 pub fn move_components(&mut self, enable: bool) -> &mut Self {
661 self.entity_cloner.move_components = enable;
662 self
663 }
664
665 pub fn allow<T: Bundle>(&mut self) -> &mut Self {
670 let bundle = self.world.register_bundle::<T>();
671 let ids = bundle.explicit_components().to_owned();
672 for id in ids {
673 self.filter_allow(id);
674 }
675 self
676 }
677
678 pub fn allow_by_ids(&mut self, ids: impl IntoIterator<Item = ComponentId>) -> &mut Self {
683 for id in ids {
684 self.filter_allow(id);
685 }
686 self
687 }
688
689 pub fn allow_by_type_ids(&mut self, ids: impl IntoIterator<Item = TypeId>) -> &mut Self {
694 for type_id in ids {
695 if let Some(id) = self.world.components().get_id(type_id) {
696 self.filter_allow(id);
697 }
698 }
699 self
700 }
701
702 pub fn allow_all(&mut self) -> &mut Self {
704 self.entity_cloner.filter_allows_components = false;
705 self.entity_cloner.filter.clear();
706 self
707 }
708
709 pub fn deny<T: Bundle>(&mut self) -> &mut Self {
711 let bundle = self.world.register_bundle::<T>();
712 let ids = bundle.explicit_components().to_owned();
713 for id in ids {
714 self.filter_deny(id);
715 }
716 self
717 }
718
719 pub fn deny_by_ids(&mut self, ids: impl IntoIterator<Item = ComponentId>) -> &mut Self {
721 for id in ids {
722 self.filter_deny(id);
723 }
724 self
725 }
726
727 pub fn deny_by_type_ids(&mut self, ids: impl IntoIterator<Item = TypeId>) -> &mut Self {
729 for type_id in ids {
730 if let Some(id) = self.world.components().get_id(type_id) {
731 self.filter_deny(id);
732 }
733 }
734 self
735 }
736
737 pub fn deny_all(&mut self) -> &mut Self {
739 self.entity_cloner.filter_allows_components = true;
740 self.entity_cloner.filter.clear();
741 self
742 }
743
744 pub fn override_clone_behavior<T: Component>(
749 &mut self,
750 clone_behavior: ComponentCloneBehavior,
751 ) -> &mut Self {
752 if let Some(id) = self.world.components().component_id::<T>() {
753 self.entity_cloner
754 .clone_behavior_overrides
755 .insert(id, clone_behavior);
756 }
757 self
758 }
759
760 pub fn override_clone_behavior_with_id(
765 &mut self,
766 component_id: ComponentId,
767 clone_behavior: ComponentCloneBehavior,
768 ) -> &mut Self {
769 self.entity_cloner
770 .clone_behavior_overrides
771 .insert(component_id, clone_behavior);
772 self
773 }
774
775 pub fn remove_clone_behavior_override<T: Component>(&mut self) -> &mut Self {
777 if let Some(id) = self.world.components().component_id::<T>() {
778 self.entity_cloner.clone_behavior_overrides.remove(&id);
779 }
780 self
781 }
782
783 pub fn remove_clone_behavior_override_with_id(
785 &mut self,
786 component_id: ComponentId,
787 ) -> &mut Self {
788 self.entity_cloner
789 .clone_behavior_overrides
790 .remove(&component_id);
791 self
792 }
793
794 pub fn linked_cloning(&mut self, linked_cloning: bool) -> &mut Self {
797 self.entity_cloner.linked_cloning = linked_cloning;
798 self
799 }
800
801 fn filter_allow(&mut self, id: ComponentId) {
803 if self.entity_cloner.filter_allows_components {
804 self.entity_cloner.filter.insert(id);
805 } else {
806 self.entity_cloner.filter.remove(&id);
807 }
808 if self.attach_required_components {
809 if let Some(info) = self.world.components().get_info(id) {
810 for required_id in info.required_components().iter_ids() {
811 if self.entity_cloner.filter_allows_components {
812 self.entity_cloner.filter.insert(required_id);
813 } else {
814 self.entity_cloner.filter.remove(&required_id);
815 }
816 }
817 }
818 }
819 }
820
821 fn filter_deny(&mut self, id: ComponentId) {
823 if self.entity_cloner.filter_allows_components {
824 self.entity_cloner.filter.remove(&id);
825 } else {
826 self.entity_cloner.filter.insert(id);
827 }
828 if self.attach_required_components {
829 if let Some(info) = self.world.components().get_info(id) {
830 for required_id in info.required_components().iter_ids() {
831 if self.entity_cloner.filter_allows_components {
832 self.entity_cloner.filter.remove(&required_id);
833 } else {
834 self.entity_cloner.filter.insert(required_id);
835 }
836 }
837 }
838 }
839 }
840}
841
842#[cfg(test)]
843mod tests {
844 use super::ComponentCloneCtx;
845 use crate::{
846 component::{Component, ComponentCloneBehavior, ComponentDescriptor, StorageType},
847 entity::{Entity, EntityCloner, EntityHashMap, SourceComponent},
848 prelude::{ChildOf, Children, Resource},
849 reflect::{AppTypeRegistry, ReflectComponent, ReflectFromWorld},
850 world::{FromWorld, World},
851 };
852 use alloc::vec::Vec;
853 use bevy_ptr::OwningPtr;
854 use bevy_reflect::Reflect;
855 use core::marker::PhantomData;
856 use core::{alloc::Layout, ops::Deref};
857
858 #[cfg(feature = "bevy_reflect")]
859 mod reflect {
860 use super::*;
861 use crate::{
862 component::{Component, ComponentCloneBehavior},
863 entity::{EntityCloner, SourceComponent},
864 reflect::{AppTypeRegistry, ReflectComponent, ReflectFromWorld},
865 };
866 use alloc::vec;
867 use bevy_reflect::{std_traits::ReflectDefault, FromType, Reflect, ReflectFromPtr};
868
869 #[test]
870 fn clone_entity_using_reflect() {
871 #[derive(Component, Reflect, Clone, PartialEq, Eq)]
872 #[reflect(Component)]
873 struct A {
874 field: usize,
875 }
876
877 let mut world = World::default();
878 world.init_resource::<AppTypeRegistry>();
879 let registry = world.get_resource::<AppTypeRegistry>().unwrap();
880 registry.write().register::<A>();
881
882 world.register_component::<A>();
883 let component = A { field: 5 };
884
885 let e = world.spawn(component.clone()).id();
886 let e_clone = world.spawn_empty().id();
887
888 EntityCloner::build(&mut world)
889 .override_clone_behavior::<A>(ComponentCloneBehavior::reflect())
890 .clone_entity(e, e_clone);
891
892 assert!(world.get::<A>(e_clone).is_some_and(|c| *c == component));
893 }
894
895 #[test]
896 fn clone_entity_using_reflect_all_paths() {
897 #[derive(PartialEq, Eq, Default, Debug)]
898 struct NotClone;
899
900 #[derive(Component, Reflect, PartialEq, Eq, Default, Debug)]
902 #[reflect(from_reflect = false)]
903 struct A {
904 field: usize,
905 field2: Vec<usize>,
906 }
907
908 #[derive(Component, Reflect, PartialEq, Eq, Default, Debug)]
910 #[reflect(Default)]
911 #[reflect(from_reflect = false)]
912 struct B {
913 field: usize,
914 field2: Vec<usize>,
915 #[reflect(ignore)]
916 ignored: NotClone,
917 }
918
919 #[derive(Component, Reflect, PartialEq, Eq, Default, Debug)]
921 struct C {
922 field: usize,
923 field2: Vec<usize>,
924 #[reflect(ignore)]
925 ignored: NotClone,
926 }
927
928 #[derive(Component, Reflect, PartialEq, Eq, Default, Debug)]
930 #[reflect(FromWorld)]
931 #[reflect(from_reflect = false)]
932 struct D {
933 field: usize,
934 field2: Vec<usize>,
935 #[reflect(ignore)]
936 ignored: NotClone,
937 }
938
939 let mut world = World::default();
940 world.init_resource::<AppTypeRegistry>();
941 let registry = world.get_resource::<AppTypeRegistry>().unwrap();
942 registry.write().register::<(A, B, C, D)>();
943
944 let a_id = world.register_component::<A>();
945 let b_id = world.register_component::<B>();
946 let c_id = world.register_component::<C>();
947 let d_id = world.register_component::<D>();
948 let component_a = A {
949 field: 5,
950 field2: vec![1, 2, 3, 4, 5],
951 };
952 let component_b = B {
953 field: 5,
954 field2: vec![1, 2, 3, 4, 5],
955 ignored: NotClone,
956 };
957 let component_c = C {
958 field: 6,
959 field2: vec![1, 2, 3, 4, 5],
960 ignored: NotClone,
961 };
962 let component_d = D {
963 field: 7,
964 field2: vec![1, 2, 3, 4, 5],
965 ignored: NotClone,
966 };
967
968 let e = world
969 .spawn((component_a, component_b, component_c, component_d))
970 .id();
971 let e_clone = world.spawn_empty().id();
972
973 EntityCloner::build(&mut world)
974 .override_clone_behavior_with_id(a_id, ComponentCloneBehavior::reflect())
975 .override_clone_behavior_with_id(b_id, ComponentCloneBehavior::reflect())
976 .override_clone_behavior_with_id(c_id, ComponentCloneBehavior::reflect())
977 .override_clone_behavior_with_id(d_id, ComponentCloneBehavior::reflect())
978 .clone_entity(e, e_clone);
979
980 assert_eq!(world.get::<A>(e_clone), Some(world.get::<A>(e).unwrap()));
981 assert_eq!(world.get::<B>(e_clone), Some(world.get::<B>(e).unwrap()));
982 assert_eq!(world.get::<C>(e_clone), Some(world.get::<C>(e).unwrap()));
983 assert_eq!(world.get::<D>(e_clone), Some(world.get::<D>(e).unwrap()));
984 }
985
986 #[test]
987 fn read_source_component_reflect_should_return_none_on_invalid_reflect_from_ptr() {
988 #[derive(Component, Reflect)]
989 struct A;
990
991 #[derive(Component, Reflect)]
992 struct B;
993
994 fn test_handler(source: &SourceComponent, ctx: &mut ComponentCloneCtx) {
995 let registry = ctx.type_registry().unwrap();
996 assert!(source.read_reflect(®istry.read()).is_none());
997 }
998
999 let mut world = World::default();
1000 world.init_resource::<AppTypeRegistry>();
1001 let registry = world.get_resource::<AppTypeRegistry>().unwrap();
1002 {
1003 let mut registry = registry.write();
1004 registry.register::<A>();
1005 registry
1006 .get_mut(core::any::TypeId::of::<A>())
1007 .unwrap()
1008 .insert(<ReflectFromPtr as FromType<B>>::from_type());
1009 }
1010
1011 let e = world.spawn(A).id();
1012 let e_clone = world.spawn_empty().id();
1013
1014 EntityCloner::build(&mut world)
1015 .override_clone_behavior::<A>(ComponentCloneBehavior::Custom(test_handler))
1016 .clone_entity(e, e_clone);
1017 }
1018
1019 #[test]
1020 fn clone_entity_specialization() {
1021 #[derive(Component, Reflect, PartialEq, Eq)]
1022 #[reflect(Component)]
1023 struct A {
1024 field: usize,
1025 }
1026
1027 impl Clone for A {
1028 fn clone(&self) -> Self {
1029 Self { field: 10 }
1030 }
1031 }
1032
1033 let mut world = World::default();
1034 world.init_resource::<AppTypeRegistry>();
1035 let registry = world.get_resource::<AppTypeRegistry>().unwrap();
1036 registry.write().register::<A>();
1037
1038 let component = A { field: 5 };
1039
1040 let e = world.spawn(component.clone()).id();
1041 let e_clone = world.spawn_empty().id();
1042
1043 EntityCloner::build(&mut world).clone_entity(e, e_clone);
1044
1045 assert!(world
1046 .get::<A>(e_clone)
1047 .is_some_and(|comp| *comp == A { field: 10 }));
1048 }
1049
1050 #[test]
1051 fn clone_entity_using_reflect_should_skip_without_panic() {
1052 #[derive(Component, PartialEq, Eq, Default, Debug)]
1054 struct A;
1055
1056 #[derive(Component, Reflect, PartialEq, Eq, Default, Debug)]
1058 #[reflect(Component)]
1059 #[reflect(from_reflect = false)]
1060 struct B(#[reflect(ignore)] PhantomData<()>);
1061
1062 let mut world = World::default();
1063
1064 let e = world.spawn((A, B(Default::default()))).id();
1066 let e_clone = world.spawn_empty().id();
1067 EntityCloner::build(&mut world)
1068 .override_clone_behavior::<A>(ComponentCloneBehavior::reflect())
1069 .override_clone_behavior::<B>(ComponentCloneBehavior::reflect())
1070 .clone_entity(e, e_clone);
1071 assert_eq!(world.get::<A>(e_clone), None);
1072 assert_eq!(world.get::<B>(e_clone), None);
1073
1074 world.init_resource::<AppTypeRegistry>();
1076 let registry = world.get_resource::<AppTypeRegistry>().unwrap();
1077 registry.write().register::<B>();
1078
1079 let e = world.spawn((A, B(Default::default()))).id();
1080 let e_clone = world.spawn_empty().id();
1081 EntityCloner::build(&mut world).clone_entity(e, e_clone);
1082 assert_eq!(world.get::<A>(e_clone), None);
1083 assert_eq!(world.get::<B>(e_clone), None);
1084 }
1085 }
1086
1087 #[test]
1088 fn clone_entity_using_clone() {
1089 #[derive(Component, Clone, PartialEq, Eq)]
1090 struct A {
1091 field: usize,
1092 }
1093
1094 let mut world = World::default();
1095
1096 let component = A { field: 5 };
1097
1098 let e = world.spawn(component.clone()).id();
1099 let e_clone = world.spawn_empty().id();
1100
1101 EntityCloner::build(&mut world).clone_entity(e, e_clone);
1102
1103 assert!(world.get::<A>(e_clone).is_some_and(|c| *c == component));
1104 }
1105
1106 #[test]
1107 fn clone_entity_with_allow_filter() {
1108 #[derive(Component, Clone, PartialEq, Eq)]
1109 struct A {
1110 field: usize,
1111 }
1112
1113 #[derive(Component, Clone)]
1114 struct B;
1115
1116 let mut world = World::default();
1117
1118 let component = A { field: 5 };
1119
1120 let e = world.spawn((component.clone(), B)).id();
1121 let e_clone = world.spawn_empty().id();
1122
1123 EntityCloner::build(&mut world)
1124 .deny_all()
1125 .allow::<A>()
1126 .clone_entity(e, e_clone);
1127
1128 assert!(world.get::<A>(e_clone).is_some_and(|c| *c == component));
1129 assert!(world.get::<B>(e_clone).is_none());
1130 }
1131
1132 #[test]
1133 fn clone_entity_with_deny_filter() {
1134 #[derive(Component, Clone, PartialEq, Eq)]
1135 struct A {
1136 field: usize,
1137 }
1138
1139 #[derive(Component, Clone)]
1140 struct B;
1141
1142 #[derive(Component, Clone)]
1143 struct C;
1144
1145 let mut world = World::default();
1146
1147 let component = A { field: 5 };
1148
1149 let e = world.spawn((component.clone(), B, C)).id();
1150 let e_clone = world.spawn_empty().id();
1151
1152 EntityCloner::build(&mut world)
1153 .deny::<B>()
1154 .clone_entity(e, e_clone);
1155
1156 assert!(world.get::<A>(e_clone).is_some_and(|c| *c == component));
1157 assert!(world.get::<B>(e_clone).is_none());
1158 assert!(world.get::<C>(e_clone).is_some());
1159 }
1160
1161 #[test]
1162 fn clone_entity_with_override_allow_filter() {
1163 #[derive(Component, Clone, PartialEq, Eq)]
1164 struct A {
1165 field: usize,
1166 }
1167
1168 #[derive(Component, Clone)]
1169 struct B;
1170
1171 #[derive(Component, Clone)]
1172 struct C;
1173
1174 let mut world = World::default();
1175
1176 let component = A { field: 5 };
1177
1178 let e = world.spawn((component.clone(), B, C)).id();
1179 let e_clone = world.spawn_empty().id();
1180
1181 EntityCloner::build(&mut world)
1182 .deny_all()
1183 .allow::<A>()
1184 .allow::<B>()
1185 .allow::<C>()
1186 .deny::<B>()
1187 .clone_entity(e, e_clone);
1188
1189 assert!(world.get::<A>(e_clone).is_some_and(|c| *c == component));
1190 assert!(world.get::<B>(e_clone).is_none());
1191 assert!(world.get::<C>(e_clone).is_some());
1192 }
1193
1194 #[test]
1195 fn clone_entity_with_override_bundle() {
1196 #[derive(Component, Clone, PartialEq, Eq)]
1197 struct A {
1198 field: usize,
1199 }
1200
1201 #[derive(Component, Clone)]
1202 struct B;
1203
1204 #[derive(Component, Clone)]
1205 struct C;
1206
1207 let mut world = World::default();
1208
1209 let component = A { field: 5 };
1210
1211 let e = world.spawn((component.clone(), B, C)).id();
1212 let e_clone = world.spawn_empty().id();
1213
1214 EntityCloner::build(&mut world)
1215 .deny_all()
1216 .allow::<(A, B, C)>()
1217 .deny::<(B, C)>()
1218 .clone_entity(e, e_clone);
1219
1220 assert!(world.get::<A>(e_clone).is_some_and(|c| *c == component));
1221 assert!(world.get::<B>(e_clone).is_none());
1222 assert!(world.get::<C>(e_clone).is_none());
1223 }
1224
1225 #[test]
1226 fn clone_entity_with_required_components() {
1227 #[derive(Component, Clone, PartialEq, Debug)]
1228 #[require(B)]
1229 struct A;
1230
1231 #[derive(Component, Clone, PartialEq, Debug, Default)]
1232 #[require(C(5))]
1233 struct B;
1234
1235 #[derive(Component, Clone, PartialEq, Debug)]
1236 struct C(u32);
1237
1238 let mut world = World::default();
1239
1240 let e = world.spawn(A).id();
1241 let e_clone = world.spawn_empty().id();
1242
1243 EntityCloner::build(&mut world)
1244 .deny_all()
1245 .allow::<B>()
1246 .clone_entity(e, e_clone);
1247
1248 assert_eq!(world.entity(e_clone).get::<A>(), None);
1249 assert_eq!(world.entity(e_clone).get::<B>(), Some(&B));
1250 assert_eq!(world.entity(e_clone).get::<C>(), Some(&C(5)));
1251 }
1252
1253 #[test]
1254 fn clone_entity_with_default_required_components() {
1255 #[derive(Component, Clone, PartialEq, Debug)]
1256 #[require(B)]
1257 struct A;
1258
1259 #[derive(Component, Clone, PartialEq, Debug, Default)]
1260 #[require(C(5))]
1261 struct B;
1262
1263 #[derive(Component, Clone, PartialEq, Debug)]
1264 struct C(u32);
1265
1266 let mut world = World::default();
1267
1268 let e = world.spawn((A, C(0))).id();
1269 let e_clone = world.spawn_empty().id();
1270
1271 EntityCloner::build(&mut world)
1272 .deny_all()
1273 .without_required_components(|builder| {
1274 builder.allow::<A>();
1275 })
1276 .clone_entity(e, e_clone);
1277
1278 assert_eq!(world.entity(e_clone).get::<A>(), Some(&A));
1279 assert_eq!(world.entity(e_clone).get::<B>(), Some(&B));
1280 assert_eq!(world.entity(e_clone).get::<C>(), Some(&C(5)));
1281 }
1282
1283 #[test]
1284 fn clone_entity_with_dynamic_components() {
1285 const COMPONENT_SIZE: usize = 10;
1286 fn test_handler(source: &SourceComponent, ctx: &mut ComponentCloneCtx) {
1287 unsafe {
1289 ctx.write_target_component_ptr(source.ptr());
1290 }
1291 }
1292
1293 let mut world = World::default();
1294
1295 let layout = Layout::array::<u8>(COMPONENT_SIZE).unwrap();
1296 let descriptor = unsafe {
1300 ComponentDescriptor::new_with_layout(
1301 "DynamicComp",
1302 StorageType::Table,
1303 layout,
1304 None,
1305 true,
1306 ComponentCloneBehavior::Custom(test_handler),
1307 )
1308 };
1309 let component_id = world.register_component_with_descriptor(descriptor);
1310
1311 let mut entity = world.spawn_empty();
1312 let data = [5u8; COMPONENT_SIZE];
1313
1314 OwningPtr::make(data, |ptr| unsafe {
1318 entity.insert_by_id(component_id, ptr);
1319 });
1320 let entity = entity.id();
1321
1322 let entity_clone = world.spawn_empty().id();
1323 EntityCloner::build(&mut world).clone_entity(entity, entity_clone);
1324
1325 let ptr = world.get_by_id(entity, component_id).unwrap();
1326 let clone_ptr = world.get_by_id(entity_clone, component_id).unwrap();
1327 unsafe {
1329 assert_eq!(
1330 core::slice::from_raw_parts(ptr.as_ptr(), COMPONENT_SIZE),
1331 core::slice::from_raw_parts(clone_ptr.as_ptr(), COMPONENT_SIZE),
1332 );
1333 }
1334 }
1335
1336 #[test]
1337 fn recursive_clone() {
1338 let mut world = World::new();
1339 let root = world.spawn_empty().id();
1340 let child1 = world.spawn(ChildOf(root)).id();
1341 let grandchild = world.spawn(ChildOf(child1)).id();
1342 let child2 = world.spawn(ChildOf(root)).id();
1343
1344 let clone_root = world.spawn_empty().id();
1345 EntityCloner::build(&mut world)
1346 .linked_cloning(true)
1347 .clone_entity(root, clone_root);
1348
1349 let root_children = world
1350 .entity(clone_root)
1351 .get::<Children>()
1352 .unwrap()
1353 .iter()
1354 .cloned()
1355 .collect::<Vec<_>>();
1356
1357 assert!(root_children.iter().all(|e| *e != child1 && *e != child2));
1358 assert_eq!(root_children.len(), 2);
1359 let child1_children = world.entity(root_children[0]).get::<Children>().unwrap();
1360 assert_eq!(child1_children.len(), 1);
1361 assert_ne!(child1_children[0], grandchild);
1362 assert!(world.entity(root_children[1]).get::<Children>().is_none());
1363
1364 assert_eq!(
1365 world.entity(root).get::<Children>().unwrap().deref(),
1366 &[child1, child2]
1367 );
1368 }
1369
1370 #[test]
1371 fn clone_with_reflect_from_world() {
1372 #[derive(Component, Reflect, PartialEq, Eq, Debug)]
1373 #[reflect(Component, FromWorld, from_reflect = false)]
1374 struct SomeRef(
1375 #[entities] Entity,
1376 #[reflect(ignore)] PhantomData<()>,
1378 );
1379
1380 #[derive(Resource)]
1381 struct FromWorldCalled(bool);
1382
1383 impl FromWorld for SomeRef {
1384 fn from_world(world: &mut World) -> Self {
1385 world.insert_resource(FromWorldCalled(true));
1386 SomeRef(Entity::PLACEHOLDER, Default::default())
1387 }
1388 }
1389 let mut world = World::new();
1390 let registry = AppTypeRegistry::default();
1391 registry.write().register::<SomeRef>();
1392 world.insert_resource(registry);
1393
1394 let a = world.spawn_empty().id();
1395 let b = world.spawn_empty().id();
1396 let c = world.spawn(SomeRef(a, Default::default())).id();
1397 let d = world.spawn_empty().id();
1398 let mut map = EntityHashMap::<Entity>::new();
1399 map.insert(a, b);
1400 map.insert(c, d);
1401
1402 let cloned = EntityCloner::default().clone_entity_mapped(&mut world, c, &mut map);
1403 assert_eq!(
1404 *world.entity(cloned).get::<SomeRef>().unwrap(),
1405 SomeRef(b, Default::default())
1406 );
1407 assert!(world.resource::<FromWorldCalled>().0);
1408 }
1409}