bevy_ecs/reflect/
map_entities.rs

1use crate::{
2    component::Component,
3    entity::{Entity, EntityHashMap, MapEntities, SceneEntityMapper},
4    world::World,
5};
6use bevy_reflect::FromType;
7
8/// For a specific type of component, this maps any fields with values of type [`Entity`] to a new world.
9/// Since a given `Entity` ID is only valid for the world it came from, when performing deserialization
10/// any stored IDs need to be re-allocated in the destination world.
11///
12/// See [`SceneEntityMapper`] and [`MapEntities`] for more information.
13#[derive(Clone)]
14pub struct ReflectMapEntities {
15    map_all_entities: fn(&mut World, &mut SceneEntityMapper),
16    map_entities: fn(&mut World, &mut SceneEntityMapper, &[Entity]),
17}
18
19impl ReflectMapEntities {
20    /// A general method for applying [`MapEntities`] behavior to all elements in an [`EntityHashMap<Entity>`].
21    ///
22    /// Be mindful in its usage: Works best in situations where the entities in the [`EntityHashMap<Entity>`] are newly
23    /// created, before systems have a chance to add new components. If some of the entities referred to
24    /// by the [`EntityHashMap<Entity>`] might already contain valid entity references, you should use [`map_entities`](Self::map_entities).
25    ///
26    /// An example of this: A scene can be loaded with `Parent` components, but then a `Parent` component can be added
27    /// to these entities after they have been loaded. If you reload the scene using [`map_all_entities`](Self::map_all_entities), those `Parent`
28    /// components with already valid entity references could be updated to point at something else entirely.
29    pub fn map_all_entities(&self, world: &mut World, entity_map: &mut EntityHashMap<Entity>) {
30        SceneEntityMapper::world_scope(entity_map, world, self.map_all_entities);
31    }
32
33    /// A general method for applying [`MapEntities`] behavior to elements in an [`EntityHashMap<Entity>`]. Unlike
34    /// [`map_all_entities`](Self::map_all_entities), this is applied to specific entities, not all values
35    /// in the [`EntityHashMap<Entity>`].
36    ///
37    /// This is useful mostly for when you need to be careful not to update components that already contain valid entity
38    /// values. See [`map_all_entities`](Self::map_all_entities) for more details.
39    pub fn map_entities(
40        &self,
41        world: &mut World,
42        entity_map: &mut EntityHashMap<Entity>,
43        entities: &[Entity],
44    ) {
45        SceneEntityMapper::world_scope(entity_map, world, |world, mapper| {
46            (self.map_entities)(world, mapper, entities);
47        });
48    }
49}
50
51impl<C: Component + MapEntities> FromType<C> for ReflectMapEntities {
52    fn from_type() -> Self {
53        ReflectMapEntities {
54            map_entities: |world, entity_mapper, entities| {
55                for &entity in entities {
56                    if let Some(mut component) = world.get_mut::<C>(entity) {
57                        component.map_entities(entity_mapper);
58                    }
59                }
60            },
61            map_all_entities: |world, entity_mapper| {
62                let entities = entity_mapper
63                    .get_map()
64                    .values()
65                    .copied()
66                    .collect::<Vec<Entity>>();
67                for entity in &entities {
68                    if let Some(mut component) = world.get_mut::<C>(*entity) {
69                        component.map_entities(entity_mapper);
70                    }
71                }
72            },
73        }
74    }
75}
76
77/// For a specific type of resource, this maps any fields with values of type [`Entity`] to a new world.
78/// Since a given `Entity` ID is only valid for the world it came from, when performing deserialization
79/// any stored IDs need to be re-allocated in the destination world.
80///
81/// See [`SceneEntityMapper`] and [`MapEntities`] for more information.
82#[derive(Clone)]
83pub struct ReflectMapEntitiesResource {
84    map_entities: fn(&mut World, &mut SceneEntityMapper),
85}
86
87impl ReflectMapEntitiesResource {
88    /// A method for applying [`MapEntities`] behavior to elements in an [`EntityHashMap<Entity>`].
89    pub fn map_entities(&self, world: &mut World, entity_map: &mut EntityHashMap<Entity>) {
90        SceneEntityMapper::world_scope(entity_map, world, |world, mapper| {
91            (self.map_entities)(world, mapper);
92        });
93    }
94}
95
96impl<R: crate::system::Resource + MapEntities> FromType<R> for ReflectMapEntitiesResource {
97    fn from_type() -> Self {
98        ReflectMapEntitiesResource {
99            map_entities: |world, entity_mapper| {
100                if let Some(mut resource) = world.get_resource_mut::<R>() {
101                    resource.map_entities(entity_mapper);
102                }
103            },
104        }
105    }
106}