1
1
use crate :: { entity:: Entity , world:: World } ;
2
- use bevy_utils:: { Entry , HashMap } ;
2
+ use bevy_utils:: HashMap ;
3
3
4
4
/// Operation to map all contained [`Entity`] fields in a type to new values.
5
5
///
6
6
/// As entity IDs are valid only for the [`World`] they're sourced from, using [`Entity`]
7
7
/// as references in components copied from another world will be invalid. This trait
8
- /// allows defining custom mappings for these references via [`EntityMap`].
8
+ /// allows defining custom mappings for these references via [`HashMap<Entity, Entity>`]
9
9
///
10
10
/// Implementing this trait correctly is required for properly loading components
11
11
/// with entity references from scenes.
@@ -32,112 +32,29 @@ use bevy_utils::{Entry, HashMap};
32
32
///
33
33
/// [`World`]: crate::world::World
34
34
pub trait MapEntities {
35
- /// Updates all [`Entity`] references stored inside using `entity_map `.
35
+ /// Updates all [`Entity`] references stored inside using `entity_mapper `.
36
36
///
37
37
/// Implementors should look up any and all [`Entity`] values stored within and
38
38
/// update them to the mapped values via `entity_mapper`.
39
39
fn map_entities ( & mut self , entity_mapper : & mut EntityMapper ) ;
40
40
}
41
41
42
- /// A mapping from one set of entities to another.
43
- ///
44
- /// The API generally follows [`HashMap`], but each [`Entity`] is returned by value, as they are [`Copy`].
45
- ///
46
- /// This is typically used to coordinate data transfer between sets of entities, such as between a scene and the world
47
- /// or over the network. This is required as [`Entity`] identifiers are opaque; you cannot and do not want to reuse
48
- /// identifiers directly.
49
- ///
50
- /// On its own, an `EntityMap` is not capable of allocating new entity identifiers, which is needed to map references
51
- /// to entities that lie outside the source entity set. To do this, an `EntityMap` can be wrapped in an
52
- /// [`EntityMapper`] which scopes it to a particular destination [`World`] and allows new identifiers to be allocated.
53
- /// This functionality can be accessed through [`Self::world_scope()`].
54
- #[ derive( Default , Debug ) ]
55
- pub struct EntityMap {
56
- map : HashMap < Entity , Entity > ,
57
- }
58
-
59
- impl EntityMap {
60
- /// Inserts an entities pair into the map.
61
- ///
62
- /// If the map did not have `from` present, [`None`] is returned.
63
- ///
64
- /// If the map did have `from` present, the value is updated, and the old value is returned.
65
- pub fn insert ( & mut self , from : Entity , to : Entity ) -> Option < Entity > {
66
- self . map . insert ( from, to)
67
- }
68
-
69
- /// Removes an `entity` from the map, returning the mapped value of it if the `entity` was previously in the map.
70
- pub fn remove ( & mut self , entity : Entity ) -> Option < Entity > {
71
- self . map . remove ( & entity)
72
- }
73
-
74
- /// Gets the given entity's corresponding entry in the map for in-place manipulation.
75
- pub fn entry ( & mut self , entity : Entity ) -> Entry < ' _ , Entity , Entity > {
76
- self . map . entry ( entity)
77
- }
78
-
79
- /// Returns the corresponding mapped entity.
80
- pub fn get ( & self , entity : Entity ) -> Option < Entity > {
81
- self . map . get ( & entity) . copied ( )
82
- }
83
-
84
- /// An iterator visiting all keys in arbitrary order.
85
- pub fn keys ( & self ) -> impl Iterator < Item = Entity > + ' _ {
86
- self . map . keys ( ) . cloned ( )
87
- }
88
-
89
- /// An iterator visiting all values in arbitrary order.
90
- pub fn values ( & self ) -> impl Iterator < Item = Entity > + ' _ {
91
- self . map . values ( ) . cloned ( )
92
- }
93
-
94
- /// Returns the number of elements in the map.
95
- pub fn len ( & self ) -> usize {
96
- self . map . len ( )
97
- }
98
-
99
- /// Returns true if the map contains no elements.
100
- pub fn is_empty ( & self ) -> bool {
101
- self . map . is_empty ( )
102
- }
103
-
104
- /// An iterator visiting all (key, value) pairs in arbitrary order.
105
- pub fn iter ( & self ) -> impl Iterator < Item = ( Entity , Entity ) > + ' _ {
106
- self . map . iter ( ) . map ( |( from, to) | ( * from, * to) )
107
- }
108
-
109
- /// Clears the map, removing all entity pairs. Keeps the allocated memory for reuse.
110
- pub fn clear ( & mut self ) {
111
- self . map . clear ( ) ;
112
- }
113
-
114
- /// Creates an [`EntityMapper`] from this [`EntityMap`] and scoped to the provided [`World`], then calls the
115
- /// provided function with it. This allows one to allocate new entity references in the provided `World` that are
116
- /// guaranteed to never point at a living entity now or in the future. This functionality is useful for safely
117
- /// mapping entity identifiers that point at entities outside the source world. The passed function, `f`, is called
118
- /// within the scope of the passed world. Its return value is then returned from `world_scope` as the generic type
119
- /// parameter `R`.
120
- pub fn world_scope < R > (
121
- & mut self ,
122
- world : & mut World ,
123
- f : impl FnOnce ( & mut World , & mut EntityMapper ) -> R ,
124
- ) -> R {
125
- let mut mapper = EntityMapper :: new ( self , world) ;
126
- let result = f ( world, & mut mapper) ;
127
- mapper. finish ( world) ;
128
- result
129
- }
130
- }
131
-
132
- /// A wrapper for [`EntityMap`], augmenting it with the ability to allocate new [`Entity`] references in a destination
42
+ /// A wrapper for [`HashMap<Entity, Entity>`], augmenting it with the ability to allocate new [`Entity`] references in a destination
133
43
/// world. These newly allocated references are guaranteed to never point to any living entity in that world.
134
44
///
135
45
/// References are allocated by returning increasing generations starting from an internally initialized base
136
46
/// [`Entity`]. After it is finished being used by [`MapEntities`] implementations, this entity is despawned and the
137
47
/// requisite number of generations reserved.
138
48
pub struct EntityMapper < ' m > {
139
- /// The wrapped [`EntityMap`].
140
- map : & ' m mut EntityMap ,
49
+ /// A mapping from one set of entities to another.
50
+ ///
51
+ /// This is typically used to coordinate data transfer between sets of entities, such as between a scene and the world
52
+ /// or over the network. This is required as [`Entity`] identifiers are opaque; you cannot and do not want to reuse
53
+ /// identifiers directly.
54
+ ///
55
+ /// On its own, a [`HashMap<Entity, Entity>`] is not capable of allocating new entity identifiers, which is needed to map references
56
+ /// to entities that lie outside the source entity set. This functionality can be accessed through [`EntityMapper::world_scope()`].
57
+ map : & ' m mut HashMap < Entity , Entity > ,
141
58
/// A base [`Entity`] used to allocate new references.
142
59
dead_start : Entity ,
143
60
/// The number of generations this mapper has allocated thus far.
@@ -147,7 +64,7 @@ pub struct EntityMapper<'m> {
147
64
impl < ' m > EntityMapper < ' m > {
148
65
/// Returns the corresponding mapped entity or reserves a new dead entity ID if it is absent.
149
66
pub fn get_or_reserve ( & mut self , entity : Entity ) -> Entity {
150
- if let Some ( mapped) = self . map . get ( entity) {
67
+ if let Some ( & mapped) = self . map . get ( & entity) {
151
68
return mapped;
152
69
}
153
70
@@ -163,21 +80,21 @@ impl<'m> EntityMapper<'m> {
163
80
new
164
81
}
165
82
166
- /// Gets a reference to the underlying [`EntityMap `].
167
- pub fn get_map ( & ' m self ) -> & ' m EntityMap {
83
+ /// Gets a reference to the underlying [`HashMap<Entity, Entity> `].
84
+ pub fn get_map ( & ' m self ) -> & ' m HashMap < Entity , Entity > {
168
85
self . map
169
86
}
170
87
171
- /// Gets a mutable reference to the underlying [`EntityMap`]
172
- pub fn get_map_mut ( & ' m mut self ) -> & ' m mut EntityMap {
88
+ /// Gets a mutable reference to the underlying [`HashMap<Entity, Entity>`].
89
+ pub fn get_map_mut ( & ' m mut self ) -> & ' m mut HashMap < Entity , Entity > {
173
90
self . map
174
91
}
175
92
176
93
/// Creates a new [`EntityMapper`], spawning a temporary base [`Entity`] in the provided [`World`]
177
- fn new ( map : & ' m mut EntityMap , world : & mut World ) -> Self {
94
+ fn new ( map : & ' m mut HashMap < Entity , Entity > , world : & mut World ) -> Self {
178
95
Self {
179
96
map,
180
- // SAFETY: Entities data is kept in a valid state via `EntityMap ::world_scope`
97
+ // SAFETY: Entities data is kept in a valid state via `EntityMapper ::world_scope`
181
98
dead_start : unsafe { world. entities_mut ( ) . alloc ( ) } ,
182
99
generations : 0 ,
183
100
}
@@ -193,19 +110,40 @@ impl<'m> EntityMapper<'m> {
193
110
assert ! ( entities. free( self . dead_start) . is_some( ) ) ;
194
111
assert ! ( entities. reserve_generations( self . dead_start. index, self . generations) ) ;
195
112
}
113
+
114
+ /// Creates an [`EntityMapper`] from a provided [`World`] and [`HashMap<Entity, Entity>`], then calls the
115
+ /// provided function with it. This allows one to allocate new entity references in this [`World`] that are
116
+ /// guaranteed to never point at a living entity now or in the future. This functionality is useful for safely
117
+ /// mapping entity identifiers that point at entities outside the source world. The passed function, `f`, is called
118
+ /// within the scope of this world. Its return value is then returned from `world_scope` as the generic type
119
+ /// parameter `R`.
120
+ pub fn world_scope < R > (
121
+ entity_map : & ' m mut HashMap < Entity , Entity > ,
122
+ world : & mut World ,
123
+ f : impl FnOnce ( & mut World , & mut Self ) -> R ,
124
+ ) -> R {
125
+ let mut mapper = Self :: new ( entity_map, world) ;
126
+ let result = f ( world, & mut mapper) ;
127
+ mapper. finish ( world) ;
128
+ result
129
+ }
196
130
}
197
131
198
132
#[ cfg( test) ]
199
133
mod tests {
200
- use super :: { EntityMap , EntityMapper } ;
201
- use crate :: { entity:: Entity , world:: World } ;
134
+ use bevy_utils:: HashMap ;
135
+
136
+ use crate :: {
137
+ entity:: { Entity , EntityMapper } ,
138
+ world:: World ,
139
+ } ;
202
140
203
141
#[ test]
204
142
fn entity_mapper ( ) {
205
143
const FIRST_IDX : u32 = 1 ;
206
144
const SECOND_IDX : u32 = 2 ;
207
145
208
- let mut map = EntityMap :: default ( ) ;
146
+ let mut map = HashMap :: default ( ) ;
209
147
let mut world = World :: new ( ) ;
210
148
let mut mapper = EntityMapper :: new ( & mut map, & mut world) ;
211
149
@@ -232,10 +170,10 @@ mod tests {
232
170
233
171
#[ test]
234
172
fn world_scope_reserves_generations ( ) {
235
- let mut map = EntityMap :: default ( ) ;
173
+ let mut map = HashMap :: default ( ) ;
236
174
let mut world = World :: new ( ) ;
237
175
238
- let dead_ref = map . world_scope ( & mut world, |_, mapper| {
176
+ let dead_ref = EntityMapper :: world_scope ( & mut map , & mut world, |_, mapper| {
239
177
mapper. get_or_reserve ( Entity :: new ( 0 , 0 ) )
240
178
} ) ;
241
179
0 commit comments