1use core::any::{Any, TypeId};
8
9use crate::{
10 prelude::Bundle,
11 world::{EntityMut, EntityWorldMut},
12};
13use bevy_reflect::{
14 FromReflect, FromType, PartialReflect, Reflect, ReflectRef, TypePath, TypeRegistry,
15};
16
17use super::{from_reflect_with_fallback, ReflectComponent};
18
19#[derive(Clone)]
24pub struct ReflectBundle(ReflectBundleFns);
25
26#[derive(Clone)]
30pub struct ReflectBundleFns {
31 pub insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry),
33 pub apply: fn(EntityMut, &dyn PartialReflect, &TypeRegistry),
35 pub apply_or_insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry),
37 pub remove: fn(&mut EntityWorldMut),
39 pub take: fn(&mut EntityWorldMut) -> Option<Box<dyn Reflect>>,
41}
42
43impl ReflectBundleFns {
44 pub fn new<T: Bundle + FromReflect + TypePath>() -> Self {
50 <ReflectBundle as FromType<T>>::from_type().0
51 }
52}
53
54impl ReflectBundle {
55 pub fn insert(
57 &self,
58 entity: &mut EntityWorldMut,
59 bundle: &dyn PartialReflect,
60 registry: &TypeRegistry,
61 ) {
62 (self.0.insert)(entity, bundle, registry);
63 }
64
65 pub fn apply<'a>(
71 &self,
72 entity: impl Into<EntityMut<'a>>,
73 bundle: &dyn PartialReflect,
74 registry: &TypeRegistry,
75 ) {
76 (self.0.apply)(entity.into(), bundle, registry);
77 }
78
79 pub fn apply_or_insert(
81 &self,
82 entity: &mut EntityWorldMut,
83 bundle: &dyn PartialReflect,
84 registry: &TypeRegistry,
85 ) {
86 (self.0.apply_or_insert)(entity, bundle, registry);
87 }
88
89 pub fn remove(&self, entity: &mut EntityWorldMut) -> &ReflectBundle {
91 (self.0.remove)(entity);
92 self
93 }
94
95 #[must_use]
99 pub fn take(&self, entity: &mut EntityWorldMut) -> Option<Box<dyn Reflect>> {
100 (self.0.take)(entity)
101 }
102
103 pub fn new(fns: ReflectBundleFns) -> Self {
115 Self(fns)
116 }
117
118 pub fn fn_pointers(&self) -> &ReflectBundleFns {
134 &self.0
135 }
136}
137
138impl<B: Bundle + Reflect + TypePath> FromType<B> for ReflectBundle {
139 fn from_type() -> Self {
140 ReflectBundle(ReflectBundleFns {
141 insert: |entity, reflected_bundle, registry| {
142 let bundle = entity.world_scope(|world| {
143 from_reflect_with_fallback::<B>(reflected_bundle, world, registry)
144 });
145 entity.insert(bundle);
146 },
147 apply: |mut entity, reflected_bundle, registry| {
148 if let Some(reflect_component) =
149 registry.get_type_data::<ReflectComponent>(TypeId::of::<B>())
150 {
151 reflect_component.apply(entity, reflected_bundle);
152 } else {
153 match reflected_bundle.reflect_ref() {
154 ReflectRef::Struct(bundle) => bundle
155 .iter_fields()
156 .for_each(|field| apply_field(&mut entity, field, registry)),
157 ReflectRef::Tuple(bundle) => bundle
158 .iter_fields()
159 .for_each(|field| apply_field(&mut entity, field, registry)),
160 _ => panic!(
161 "expected bundle `{}` to be named struct or tuple",
162 core::any::type_name::<B>(),
164 ),
165 }
166 }
167 },
168 apply_or_insert: |entity, reflected_bundle, registry| {
169 if let Some(reflect_component) =
170 registry.get_type_data::<ReflectComponent>(TypeId::of::<B>())
171 {
172 reflect_component.apply_or_insert(entity, reflected_bundle, registry);
173 } else {
174 match reflected_bundle.reflect_ref() {
175 ReflectRef::Struct(bundle) => bundle
176 .iter_fields()
177 .for_each(|field| apply_or_insert_field(entity, field, registry)),
178 ReflectRef::Tuple(bundle) => bundle
179 .iter_fields()
180 .for_each(|field| apply_or_insert_field(entity, field, registry)),
181 _ => panic!(
182 "expected bundle `{}` to be a named struct or tuple",
183 core::any::type_name::<B>(),
185 ),
186 }
187 }
188 },
189 remove: |entity| {
190 entity.remove::<B>();
191 },
192 take: |entity| {
193 entity
194 .take::<B>()
195 .map(|bundle| Box::new(bundle).into_reflect())
196 },
197 })
198 }
199}
200
201fn apply_field(entity: &mut EntityMut, field: &dyn PartialReflect, registry: &TypeRegistry) {
202 let Some(type_id) = field.try_as_reflect().map(Any::type_id) else {
203 panic!(
204 "`{}` did not implement `Reflect`",
205 field.reflect_type_path()
206 );
207 };
208 if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(type_id) {
209 reflect_component.apply(entity.reborrow(), field);
210 } else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(type_id) {
211 reflect_bundle.apply(entity.reborrow(), field, registry);
212 } else {
213 panic!(
214 "no `ReflectComponent` nor `ReflectBundle` registration found for `{}`",
215 field.reflect_type_path()
216 );
217 }
218}
219
220fn apply_or_insert_field(
221 entity: &mut EntityWorldMut,
222 field: &dyn PartialReflect,
223 registry: &TypeRegistry,
224) {
225 let Some(type_id) = field.try_as_reflect().map(Any::type_id) else {
226 panic!(
227 "`{}` did not implement `Reflect`",
228 field.reflect_type_path()
229 );
230 };
231
232 if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(type_id) {
233 reflect_component.apply_or_insert(entity, field, registry);
234 } else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(type_id) {
235 reflect_bundle.apply_or_insert(entity, field, registry);
236 } else {
237 let is_component = entity.world().components().get_id(type_id).is_some();
238
239 if is_component {
240 panic!(
241 "no `ReflectComponent` registration found for `{}`",
242 field.reflect_type_path(),
243 );
244 } else {
245 panic!(
246 "no `ReflectBundle` registration found for `{}`",
247 field.reflect_type_path(),
248 )
249 }
250 }
251}