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