1pub use bevy_ecs_macros::MapEntities;
2use indexmap::{IndexMap, IndexSet};
3
4use crate::{
5 entity::{hash_map::EntityHashMap, Entity},
6 world::World,
7};
8
9use alloc::{
10 collections::{BTreeMap, BTreeSet, VecDeque},
11 vec::Vec,
12};
13use bevy_platform::collections::{HashMap, HashSet};
14use core::{
15 hash::{BuildHasher, Hash},
16 mem,
17};
18use smallvec::SmallVec;
19
20use super::EntityIndexSet;
21
22pub trait MapEntities {
55 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E);
60}
61
62impl MapEntities for Entity {
63 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
64 *self = entity_mapper.get_mapped(*self);
65 }
66}
67
68impl<T: MapEntities> MapEntities for Option<T> {
69 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
70 if let Some(entities) = self {
71 entities.map_entities(entity_mapper);
72 }
73 }
74}
75
76impl<K: MapEntities + Eq + Hash, V: MapEntities, S: BuildHasher + Default> MapEntities
77 for HashMap<K, V, S>
78{
79 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
80 *self = self
81 .drain()
82 .map(|(mut key_entities, mut value_entities)| {
83 key_entities.map_entities(entity_mapper);
84 value_entities.map_entities(entity_mapper);
85 (key_entities, value_entities)
86 })
87 .collect();
88 }
89}
90
91impl<T: MapEntities + Eq + Hash, S: BuildHasher + Default> MapEntities for HashSet<T, S> {
92 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
93 *self = self
94 .drain()
95 .map(|mut entities| {
96 entities.map_entities(entity_mapper);
97 entities
98 })
99 .collect();
100 }
101}
102
103impl<K: MapEntities + Eq + Hash, V: MapEntities, S: BuildHasher + Default> MapEntities
104 for IndexMap<K, V, S>
105{
106 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
107 *self = self
108 .drain(..)
109 .map(|(mut key_entities, mut value_entities)| {
110 key_entities.map_entities(entity_mapper);
111 value_entities.map_entities(entity_mapper);
112 (key_entities, value_entities)
113 })
114 .collect();
115 }
116}
117
118impl<T: MapEntities + Eq + Hash, S: BuildHasher + Default> MapEntities for IndexSet<T, S> {
119 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
120 *self = self
121 .drain(..)
122 .map(|mut entities| {
123 entities.map_entities(entity_mapper);
124 entities
125 })
126 .collect();
127 }
128}
129
130impl MapEntities for EntityIndexSet {
131 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
132 *self = self
133 .drain(..)
134 .map(|e| entity_mapper.get_mapped(e))
135 .collect();
136 }
137}
138
139impl<K: MapEntities + Ord, V: MapEntities> MapEntities for BTreeMap<K, V> {
140 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
141 *self = mem::take(self)
142 .into_iter()
143 .map(|(mut key_entities, mut value_entities)| {
144 key_entities.map_entities(entity_mapper);
145 value_entities.map_entities(entity_mapper);
146 (key_entities, value_entities)
147 })
148 .collect();
149 }
150}
151
152impl<T: MapEntities + Ord> MapEntities for BTreeSet<T> {
153 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
154 *self = mem::take(self)
155 .into_iter()
156 .map(|mut entities| {
157 entities.map_entities(entity_mapper);
158 entities
159 })
160 .collect();
161 }
162}
163
164impl<T: MapEntities, const N: usize> MapEntities for [T; N] {
165 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
166 for entities in self.iter_mut() {
167 entities.map_entities(entity_mapper);
168 }
169 }
170}
171
172impl<T: MapEntities> MapEntities for Vec<T> {
173 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
174 for entities in self.iter_mut() {
175 entities.map_entities(entity_mapper);
176 }
177 }
178}
179
180impl<T: MapEntities> MapEntities for VecDeque<T> {
181 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
182 for entities in self.iter_mut() {
183 entities.map_entities(entity_mapper);
184 }
185 }
186}
187
188impl<T: MapEntities, A: smallvec::Array<Item = T>> MapEntities for SmallVec<A> {
189 fn map_entities<E: EntityMapper>(&mut self, entity_mapper: &mut E) {
190 for entities in self.iter_mut() {
191 entities.map_entities(entity_mapper);
192 }
193 }
194}
195
196impl MapEntities for () {
197 fn map_entities<E: EntityMapper>(&mut self, _entity_mapper: &mut E) {}
198}
199
200pub trait EntityMapper {
232 fn get_mapped(&mut self, source: Entity) -> Entity;
234
235 fn set_mapped(&mut self, source: Entity, target: Entity);
238}
239
240impl EntityMapper for () {
241 #[inline]
242 fn get_mapped(&mut self, source: Entity) -> Entity {
243 source
244 }
245
246 #[inline]
247 fn set_mapped(&mut self, _source: Entity, _target: Entity) {}
248}
249
250impl EntityMapper for (Entity, Entity) {
251 #[inline]
252 fn get_mapped(&mut self, source: Entity) -> Entity {
253 if source == self.0 {
254 self.1
255 } else {
256 source
257 }
258 }
259
260 fn set_mapped(&mut self, _source: Entity, _target: Entity) {}
261}
262
263impl EntityMapper for &mut dyn EntityMapper {
264 fn get_mapped(&mut self, source: Entity) -> Entity {
265 (*self).get_mapped(source)
266 }
267
268 fn set_mapped(&mut self, source: Entity, target: Entity) {
269 (*self).set_mapped(source, target);
270 }
271}
272
273impl EntityMapper for SceneEntityMapper<'_> {
274 fn get_mapped(&mut self, source: Entity) -> Entity {
276 if let Some(&mapped) = self.map.get(&source) {
277 return mapped;
278 }
279
280 let new = Entity::from_index_and_generation(
282 self.dead_start.index(),
283 self.dead_start.generation.after_versions(self.generations),
284 );
285 self.generations = self.generations.wrapping_add(1);
286
287 self.map.insert(source, new);
288
289 new
290 }
291
292 fn set_mapped(&mut self, source: Entity, target: Entity) {
293 self.map.insert(source, target);
294 }
295}
296
297impl EntityMapper for EntityHashMap<Entity> {
298 fn get_mapped(&mut self, source: Entity) -> Entity {
300 self.get(&source).cloned().unwrap_or(source)
301 }
302
303 fn set_mapped(&mut self, source: Entity, target: Entity) {
304 self.insert(source, target);
305 }
306}
307
308pub struct SceneEntityMapper<'m> {
314 map: &'m mut EntityHashMap<Entity>,
323 dead_start: Entity,
325 generations: u32,
327}
328
329impl<'m> SceneEntityMapper<'m> {
330 pub fn get_map(&'m self) -> &'m EntityHashMap<Entity> {
332 self.map
333 }
334
335 pub fn get_map_mut(&'m mut self) -> &'m mut EntityHashMap<Entity> {
337 self.map
338 }
339
340 pub fn new(map: &'m mut EntityHashMap<Entity>, world: &World) -> Self {
342 Self {
343 map,
344 dead_start: world.entity_allocator.alloc(),
345 generations: 0,
346 }
347 }
348
349 pub fn finish(self, world: &mut World) {
353 let reuse_row = unsafe {
355 world
356 .entities
357 .mark_free(self.dead_start.index(), self.generations)
358 };
359 world.entity_allocator.free(reuse_row);
360 }
361
362 pub fn world_scope<R>(
369 entity_map: &'m mut EntityHashMap<Entity>,
370 world: &mut World,
371 f: impl FnOnce(&mut World, &mut Self) -> R,
372 ) -> R {
373 let mut mapper = Self::new(entity_map, world);
374 let result = f(world, &mut mapper);
375 mapper.finish(world);
376 result
377 }
378}
379
380#[cfg(test)]
381mod tests {
382
383 use crate::{
384 entity::{Entity, EntityHashMap, EntityMapper, SceneEntityMapper},
385 world::World,
386 };
387
388 #[test]
389 fn entity_mapper() {
390 let mut map = EntityHashMap::default();
391 let mut world = World::new();
392 let mut mapper = SceneEntityMapper::new(&mut map, &world);
393
394 let mapped_ent = Entity::from_raw_u32(1).unwrap();
395 let dead_ref = mapper.get_mapped(mapped_ent);
396
397 assert_eq!(
398 dead_ref,
399 mapper.get_mapped(mapped_ent),
400 "should persist the allocated mapping from the previous line"
401 );
402 assert_eq!(
403 mapper.get_mapped(Entity::from_raw_u32(2).unwrap()).index(),
404 dead_ref.index(),
405 "should re-use the same index for further dead refs"
406 );
407
408 mapper.finish(&mut world);
409 let freed_dead_ref = world.entities().resolve_from_index(dead_ref.index());
410 assert!(freed_dead_ref
411 .generation()
412 .cmp_approx(&dead_ref.generation())
413 .is_gt());
414 assert!(world.entities().check_can_spawn_at(freed_dead_ref).is_ok());
415 }
416
417 #[test]
418 fn world_scope_reserves_generations() {
419 let mut map = EntityHashMap::default();
420 let mut world = World::new();
421
422 let dead_ref = SceneEntityMapper::world_scope(&mut map, &mut world, |_, mapper| {
423 mapper.get_mapped(Entity::from_raw_u32(0).unwrap())
424 });
425
426 let freed_dead_ref = world.entities().resolve_from_index(dead_ref.index());
427 assert!(freed_dead_ref
428 .generation()
429 .cmp_approx(&dead_ref.generation())
430 .is_gt());
431 assert!(world.entities().check_can_spawn_at(freed_dead_ref).is_ok());
432 }
433}