@@ -9,7 +9,10 @@ use bevy_utils::EntityHashMap;
99///
1010/// As entity IDs are valid only for the [`World`] they're sourced from, using [`Entity`]
1111/// as references in components copied from another world will be invalid. This trait
12- /// allows defining custom mappings for these references via [`EntityHashMap<Entity, Entity>`]
12+ /// allows defining custom mappings for these references via [`EntityMappers`](EntityMapper), which
13+ /// inject the entity mapping strategy between your `MapEntities` type and the current world
14+ /// (usually by using an [`EntityHashMap<Entity, Entity>`] between source entities and entities in the
15+ /// current world).
1316///
1417/// Implementing this trait correctly is required for properly loading components
1518/// with entity references from scenes.
@@ -18,7 +21,7 @@ use bevy_utils::EntityHashMap;
1821///
1922/// ```
2023/// use bevy_ecs::prelude::*;
21- /// use bevy_ecs::entity::{EntityMapper, MapEntities} ;
24+ /// use bevy_ecs::entity::MapEntities;
2225///
2326/// #[derive(Component)]
2427/// struct Spring {
@@ -27,19 +30,52 @@ use bevy_utils::EntityHashMap;
2730/// }
2831///
2932/// impl MapEntities for Spring {
30- /// fn map_entities(&mut self, entity_mapper: &mut EntityMapper ) {
31- /// self.a = entity_mapper.get_or_reserve (self.a);
32- /// self.b = entity_mapper.get_or_reserve (self.b);
33+ /// fn map_entities<M: EntityMapper> (&mut self, entity_mapper: &mut M ) {
34+ /// self.a = entity_mapper.map_entity (self.a);
35+ /// self.b = entity_mapper.map_entity (self.b);
3336/// }
3437/// }
3538/// ```
3639///
3740pub trait MapEntities {
3841 /// Updates all [`Entity`] references stored inside using `entity_mapper`.
3942 ///
40- /// Implementors should look up any and all [`Entity`] values stored within and
43+ /// Implementors should look up any and all [`Entity`] values stored within `self` and
4144 /// update them to the mapped values via `entity_mapper`.
42- fn map_entities ( & mut self , entity_mapper : & mut EntityMapper ) ;
45+ fn map_entities < M : EntityMapper > ( & mut self , entity_mapper : & mut M ) ;
46+ }
47+
48+ /// An implementor of this trait knows how to map an [`Entity`] into another [`Entity`].
49+ ///
50+ /// Usually this is done by using an [`EntityHashMap<Entity, Entity>`] to map source entities
51+ /// (mapper inputs) to the current world's entities (mapper outputs).
52+ ///
53+ /// More generally, this can be used to map [`Entity`] references between any two [`Worlds`](World).
54+ pub trait EntityMapper {
55+ /// Map an entity to another entity
56+ fn map_entity ( & mut self , entity : Entity ) -> Entity ;
57+ }
58+
59+ impl EntityMapper for SceneEntityMapper < ' _ > {
60+ /// Returns the corresponding mapped entity or reserves a new dead entity ID in the current world if it is absent.
61+ fn map_entity ( & mut self , entity : Entity ) -> Entity {
62+ if let Some ( & mapped) = self . map . get ( & entity) {
63+ return mapped;
64+ }
65+
66+ // this new entity reference is specifically designed to never represent any living entity
67+ let new = Entity :: from_raw_and_generation (
68+ self . dead_start . index ( ) ,
69+ IdentifierMask :: inc_masked_high_by ( self . dead_start . generation , self . generations ) ,
70+ ) ;
71+
72+ // Prevent generations counter from being a greater value than HIGH_MASK.
73+ self . generations = ( self . generations + 1 ) & HIGH_MASK ;
74+
75+ self . map . insert ( entity, new) ;
76+
77+ new
78+ }
4379}
4480
4581/// A wrapper for [`EntityHashMap<Entity, Entity>`], augmenting it with the ability to allocate new [`Entity`] references in a destination
@@ -48,41 +84,30 @@ pub trait MapEntities {
4884/// References are allocated by returning increasing generations starting from an internally initialized base
4985/// [`Entity`]. After it is finished being used by [`MapEntities`] implementations, this entity is despawned and the
5086/// requisite number of generations reserved.
51- pub struct EntityMapper < ' m > {
87+ pub struct SceneEntityMapper < ' m > {
5288 /// A mapping from one set of entities to another.
5389 ///
5490 /// This is typically used to coordinate data transfer between sets of entities, such as between a scene and the world
5591 /// or over the network. This is required as [`Entity`] identifiers are opaque; you cannot and do not want to reuse
5692 /// identifiers directly.
5793 ///
5894 /// On its own, a [`EntityHashMap<Entity, Entity>`] is not capable of allocating new entity identifiers, which is needed to map references
59- /// to entities that lie outside the source entity set. This functionality can be accessed through [`EntityMapper ::world_scope()`].
95+ /// to entities that lie outside the source entity set. This functionality can be accessed through [`SceneEntityMapper ::world_scope()`].
6096 map : & ' m mut EntityHashMap < Entity , Entity > ,
6197 /// A base [`Entity`] used to allocate new references.
6298 dead_start : Entity ,
6399 /// The number of generations this mapper has allocated thus far.
64100 generations : u32 ,
65101}
66102
67- impl < ' m > EntityMapper < ' m > {
68- /// Returns the corresponding mapped entity or reserves a new dead entity ID if it is absent.
103+ impl < ' m > SceneEntityMapper < ' m > {
104+ #[ deprecated(
105+ since = "0.13.0" ,
106+ note = "please use `EntityMapper::map_entity` instead"
107+ ) ]
108+ /// Returns the corresponding mapped entity or reserves a new dead entity ID in the current world if it is absent.
69109 pub fn get_or_reserve ( & mut self , entity : Entity ) -> Entity {
70- if let Some ( & mapped) = self . map . get ( & entity) {
71- return mapped;
72- }
73-
74- // this new entity reference is specifically designed to never represent any living entity
75- let new = Entity :: from_raw_and_generation (
76- self . dead_start . index ( ) ,
77- IdentifierMask :: inc_masked_high_by ( self . dead_start . generation , self . generations ) ,
78- ) ;
79-
80- // Prevent generations counter from being a greater value than HIGH_MASK.
81- self . generations = ( self . generations + 1 ) & HIGH_MASK ;
82-
83- self . map . insert ( entity, new) ;
84-
85- new
110+ self . map_entity ( entity)
86111 }
87112
88113 /// Gets a reference to the underlying [`EntityHashMap<Entity, Entity>`].
@@ -95,7 +120,7 @@ impl<'m> EntityMapper<'m> {
95120 self . map
96121 }
97122
98- /// Creates a new [`EntityMapper `], spawning a temporary base [`Entity`] in the provided [`World`]
123+ /// Creates a new [`SceneEntityMapper `], spawning a temporary base [`Entity`] in the provided [`World`]
99124 fn new ( map : & ' m mut EntityHashMap < Entity , Entity > , world : & mut World ) -> Self {
100125 Self {
101126 map,
@@ -107,7 +132,7 @@ impl<'m> EntityMapper<'m> {
107132
108133 /// Reserves the allocated references to dead entities within the world. This frees the temporary base
109134 /// [`Entity`] while reserving extra generations via [`crate::entity::Entities::reserve_generations`]. Because this
110- /// renders the [`EntityMapper `] unable to safely allocate any more references, this method takes ownership of
135+ /// renders the [`SceneEntityMapper `] unable to safely allocate any more references, this method takes ownership of
111136 /// `self` in order to render it unusable.
112137 fn finish ( self , world : & mut World ) {
113138 // SAFETY: Entities data is kept in a valid state via `EntityMap::world_scope`
@@ -116,7 +141,7 @@ impl<'m> EntityMapper<'m> {
116141 assert ! ( entities. reserve_generations( self . dead_start. index( ) , self . generations) ) ;
117142 }
118143
119- /// Creates an [`EntityMapper `] from a provided [`World`] and [`EntityHashMap<Entity, Entity>`], then calls the
144+ /// Creates an [`SceneEntityMapper `] from a provided [`World`] and [`EntityHashMap<Entity, Entity>`], then calls the
120145 /// provided function with it. This allows one to allocate new entity references in this [`World`] that are
121146 /// guaranteed to never point at a living entity now or in the future. This functionality is useful for safely
122147 /// mapping entity identifiers that point at entities outside the source world. The passed function, `f`, is called
@@ -139,7 +164,7 @@ mod tests {
139164 use bevy_utils:: EntityHashMap ;
140165
141166 use crate :: {
142- entity:: { Entity , EntityMapper } ,
167+ entity:: { Entity , EntityMapper , SceneEntityMapper } ,
143168 world:: World ,
144169 } ;
145170
@@ -150,18 +175,18 @@ mod tests {
150175
151176 let mut map = EntityHashMap :: default ( ) ;
152177 let mut world = World :: new ( ) ;
153- let mut mapper = EntityMapper :: new ( & mut map, & mut world) ;
178+ let mut mapper = SceneEntityMapper :: new ( & mut map, & mut world) ;
154179
155180 let mapped_ent = Entity :: from_raw ( FIRST_IDX ) ;
156- let dead_ref = mapper. get_or_reserve ( mapped_ent) ;
181+ let dead_ref = mapper. map_entity ( mapped_ent) ;
157182
158183 assert_eq ! (
159184 dead_ref,
160- mapper. get_or_reserve ( mapped_ent) ,
185+ mapper. map_entity ( mapped_ent) ,
161186 "should persist the allocated mapping from the previous line"
162187 ) ;
163188 assert_eq ! (
164- mapper. get_or_reserve ( Entity :: from_raw( SECOND_IDX ) ) . index( ) ,
189+ mapper. map_entity ( Entity :: from_raw( SECOND_IDX ) ) . index( ) ,
165190 dead_ref. index( ) ,
166191 "should re-use the same index for further dead refs"
167192 ) ;
@@ -178,8 +203,8 @@ mod tests {
178203 let mut map = EntityHashMap :: default ( ) ;
179204 let mut world = World :: new ( ) ;
180205
181- let dead_ref = EntityMapper :: world_scope ( & mut map, & mut world, |_, mapper| {
182- mapper. get_or_reserve ( Entity :: from_raw ( 0 ) )
206+ let dead_ref = SceneEntityMapper :: world_scope ( & mut map, & mut world, |_, mapper| {
207+ mapper. map_entity ( Entity :: from_raw ( 0 ) )
183208 } ) ;
184209
185210 // Next allocated entity should be a further generation on the same index
0 commit comments