1use std::any::TypeId;
8
9use crate::{
10 prelude::Bundle,
11 world::{EntityMut, EntityWorldMut},
12};
13use bevy_reflect::{FromReflect, FromType, Reflect, ReflectRef, TypeRegistry};
14
15use super::{from_reflect_with_fallback, ReflectComponent};
16
17#[derive(Clone)]
22pub struct ReflectBundle(ReflectBundleFns);
23
24#[derive(Clone)]
28pub struct ReflectBundleFns {
29 pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
31 pub apply: fn(EntityMut, &dyn Reflect, &TypeRegistry),
33 pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
35 pub remove: fn(&mut EntityWorldMut),
37}
38
39impl ReflectBundleFns {
40 pub fn new<T: Bundle + Reflect + FromReflect>() -> Self {
46 <ReflectBundle as FromType<T>>::from_type().0
47 }
48}
49
50impl ReflectBundle {
51 pub fn insert(
53 &self,
54 entity: &mut EntityWorldMut,
55 bundle: &dyn Reflect,
56 registry: &TypeRegistry,
57 ) {
58 (self.0.insert)(entity, bundle, registry);
59 }
60
61 pub fn apply<'a>(
67 &self,
68 entity: impl Into<EntityMut<'a>>,
69 bundle: &dyn Reflect,
70 registry: &TypeRegistry,
71 ) {
72 (self.0.apply)(entity.into(), bundle, registry);
73 }
74
75 pub fn apply_or_insert(
77 &self,
78 entity: &mut EntityWorldMut,
79 bundle: &dyn Reflect,
80 registry: &TypeRegistry,
81 ) {
82 (self.0.apply_or_insert)(entity, bundle, registry);
83 }
84
85 pub fn remove(&self, entity: &mut EntityWorldMut) {
87 (self.0.remove)(entity);
88 }
89
90 pub fn new(fns: ReflectBundleFns) -> Self {
102 Self(fns)
103 }
104
105 pub fn fn_pointers(&self) -> &ReflectBundleFns {
121 &self.0
122 }
123}
124
125impl<B: Bundle + Reflect> FromType<B> for ReflectBundle {
126 fn from_type() -> Self {
127 ReflectBundle(ReflectBundleFns {
128 insert: |entity, reflected_bundle, registry| {
129 let bundle = entity.world_scope(|world| {
130 from_reflect_with_fallback::<B>(reflected_bundle, world, registry)
131 });
132 entity.insert(bundle);
133 },
134 apply: |mut entity, reflected_bundle, registry| {
135 if let Some(reflect_component) =
136 registry.get_type_data::<ReflectComponent>(TypeId::of::<B>())
137 {
138 reflect_component.apply(entity, reflected_bundle);
139 } else {
140 match reflected_bundle.reflect_ref() {
141 ReflectRef::Struct(bundle) => bundle
142 .iter_fields()
143 .for_each(|field| apply_field(&mut entity, field, registry)),
144 ReflectRef::Tuple(bundle) => bundle
145 .iter_fields()
146 .for_each(|field| apply_field(&mut entity, field, registry)),
147 _ => panic!(
148 "expected bundle `{}` to be named struct or tuple",
149 std::any::type_name::<B>(),
151 ),
152 }
153 }
154 },
155 apply_or_insert: |entity, reflected_bundle, registry| {
156 if let Some(reflect_component) =
157 registry.get_type_data::<ReflectComponent>(TypeId::of::<B>())
158 {
159 reflect_component.apply_or_insert(entity, reflected_bundle, registry);
160 } else {
161 match reflected_bundle.reflect_ref() {
162 ReflectRef::Struct(bundle) => bundle
163 .iter_fields()
164 .for_each(|field| apply_or_insert_field(entity, field, registry)),
165 ReflectRef::Tuple(bundle) => bundle
166 .iter_fields()
167 .for_each(|field| apply_or_insert_field(entity, field, registry)),
168 _ => panic!(
169 "expected bundle `{}` to be named struct or tuple",
170 std::any::type_name::<B>(),
172 ),
173 }
174 }
175 },
176 remove: |entity| {
177 entity.remove::<B>();
178 },
179 })
180 }
181}
182
183fn apply_field(entity: &mut EntityMut, field: &dyn Reflect, registry: &TypeRegistry) {
184 if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(field.type_id()) {
185 reflect_component.apply(entity.reborrow(), field);
186 } else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(field.type_id()) {
187 reflect_bundle.apply(entity.reborrow(), field, registry);
188 } else {
189 panic!(
190 "no `ReflectComponent` nor `ReflectBundle` registration found for `{}`",
191 field.reflect_type_path()
192 );
193 }
194}
195
196fn apply_or_insert_field(
197 entity: &mut EntityWorldMut,
198 field: &dyn Reflect,
199 registry: &TypeRegistry,
200) {
201 if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(field.type_id()) {
202 reflect_component.apply_or_insert(entity, field, registry);
203 } else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(field.type_id()) {
204 reflect_bundle.apply_or_insert(entity, field, registry);
205 } else {
206 let is_component = entity
207 .world()
208 .components()
209 .get_id(field.type_id())
210 .is_some();
211
212 if is_component {
213 panic!(
214 "no `ReflectComponent` registration found for `{}`",
215 field.reflect_type_path(),
216 );
217 } else {
218 panic!(
219 "no `ReflectBundle` registration found for `{}`",
220 field.reflect_type_path(),
221 )
222 }
223 }
224}