bevy_ecs/component/
clone.rs1use core::marker::PhantomData;
2
3use crate::component::Component;
4use crate::entity::{ComponentCloneCtx, SourceComponent};
5
6pub type ComponentCloneFn = fn(&SourceComponent, &mut ComponentCloneCtx);
8
9#[derive(Clone, Debug, Default)]
11pub enum ComponentCloneBehavior {
12 #[default]
14 Default,
15 Ignore,
17 Custom(ComponentCloneFn),
19}
20
21impl ComponentCloneBehavior {
22 pub fn clone<C: Component + Clone>() -> Self {
26 Self::Custom(component_clone_via_clone::<C>)
27 }
28
29 #[cfg(feature = "bevy_reflect")]
31 pub fn reflect() -> Self {
32 Self::Custom(component_clone_via_reflect)
33 }
34
35 pub fn global_default_fn() -> ComponentCloneFn {
37 #[cfg(feature = "bevy_reflect")]
38 return component_clone_via_reflect;
39 #[cfg(not(feature = "bevy_reflect"))]
40 return component_clone_ignore;
41 }
42
43 pub fn resolve(&self, default: ComponentCloneFn) -> ComponentCloneFn {
46 match self {
47 ComponentCloneBehavior::Default => default,
48 ComponentCloneBehavior::Ignore => component_clone_ignore,
49 ComponentCloneBehavior::Custom(custom) => *custom,
50 }
51 }
52}
53
54pub fn component_clone_via_clone<C: Clone + Component>(
59 source: &SourceComponent,
60 ctx: &mut ComponentCloneCtx,
61) {
62 if let Some(component) = source.read::<C>() {
63 ctx.write_target_component(component.clone());
64 }
65}
66
67#[cfg(feature = "bevy_reflect")]
85pub fn component_clone_via_reflect(source: &SourceComponent, ctx: &mut ComponentCloneCtx) {
86 let Some(app_registry) = ctx.type_registry().cloned() else {
87 return;
88 };
89 let registry = app_registry.read();
90 let Some(source_component_reflect) = source.read_reflect(®istry) else {
91 return;
92 };
93 let component_info = ctx.component_info();
94 let type_id = component_info.type_id().unwrap();
96
97 if let Ok(mut component) = source_component_reflect.reflect_clone() {
99 if let Some(reflect_component) =
100 registry.get_type_data::<crate::reflect::ReflectComponent>(type_id)
101 {
102 reflect_component.map_entities(&mut *component, ctx.entity_mapper());
103 }
104 drop(registry);
105
106 ctx.write_target_component_reflect(component);
107 return;
108 }
109
110 if let Some(reflect_from_reflect) =
112 registry.get_type_data::<bevy_reflect::ReflectFromReflect>(type_id)
113 && let Some(mut component) =
114 reflect_from_reflect.from_reflect(source_component_reflect.as_partial_reflect())
115 {
116 if let Some(reflect_component) =
117 registry.get_type_data::<crate::reflect::ReflectComponent>(type_id)
118 {
119 reflect_component.map_entities(&mut *component, ctx.entity_mapper());
120 }
121 drop(registry);
122
123 ctx.write_target_component_reflect(component);
124 return;
125 }
126 if let Some(reflect_default) =
128 registry.get_type_data::<bevy_reflect::std_traits::ReflectDefault>(type_id)
129 {
130 let mut component = reflect_default.default();
131 component.apply(source_component_reflect.as_partial_reflect());
132 drop(registry);
133 ctx.write_target_component_reflect(component);
134 return;
135 }
136 if let Some(reflect_from_world) =
138 registry.get_type_data::<crate::reflect::ReflectFromWorld>(type_id)
139 {
140 use crate::{entity::EntityMapper, world::World};
141
142 let reflect_from_world = reflect_from_world.clone();
143 let Ok(source_component_cloned) = source_component_reflect.to_dynamic() else {
144 let component_info = ctx.component_info();
145
146 log::error!(
147 "Failed to clone source component ({}) because to_dynamic call failed. Does your component contain an opaque type that does not implement Reflect?",
148 component_info.name()
149 );
150 return;
151 };
152 let component_layout = component_info.layout();
153 let target = ctx.target();
154 let component_id = ctx.component_id();
155 drop(registry);
156 ctx.queue_deferred(move |world: &mut World, mapper: &mut dyn EntityMapper| {
157 let mut component = reflect_from_world.from_world(world);
158 assert_eq!(type_id, (*component).type_id());
159 component.apply(source_component_cloned.as_partial_reflect());
160 if let Some(reflect_component) = app_registry
161 .read()
162 .get_type_data::<crate::reflect::ReflectComponent>(type_id)
163 {
164 reflect_component.map_entities(&mut *component, mapper);
165 }
166 unsafe {
170 use alloc::boxed::Box;
171 use bevy_ptr::OwningPtr;
172
173 let raw_component_ptr =
174 core::ptr::NonNull::new_unchecked(Box::into_raw(component).cast::<u8>());
175 world
176 .entity_mut(target)
177 .insert_by_id(component_id, OwningPtr::new(raw_component_ptr));
178
179 if component_layout.size() > 0 {
180 alloc::alloc::dealloc(raw_component_ptr.as_ptr(), component_layout);
182 }
183 }
184 });
185 }
186}
187
188pub fn component_clone_ignore(_source: &SourceComponent, _ctx: &mut ComponentCloneCtx) {}
192
193#[doc(hidden)]
195pub struct DefaultCloneBehaviorSpecialization<T>(PhantomData<T>);
196
197impl<T> Default for DefaultCloneBehaviorSpecialization<T> {
198 fn default() -> Self {
199 Self(PhantomData)
200 }
201}
202
203#[doc(hidden)]
205pub trait DefaultCloneBehaviorBase {
206 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
207}
208
209impl<C> DefaultCloneBehaviorBase for DefaultCloneBehaviorSpecialization<C> {
210 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
211 ComponentCloneBehavior::Default
212 }
213}
214
215#[doc(hidden)]
217pub trait DefaultCloneBehaviorViaClone {
218 fn default_clone_behavior(&self) -> ComponentCloneBehavior;
219}
220
221impl<C: Clone + Component> DefaultCloneBehaviorViaClone for &DefaultCloneBehaviorSpecialization<C> {
222 fn default_clone_behavior(&self) -> ComponentCloneBehavior {
223 ComponentCloneBehavior::clone::<C>()
224 }
225}