@@ -18,6 +18,7 @@ pub struct EntityCloner {
18
18
filter_allows_components : bool ,
19
19
filter : Arc < HashSet < ComponentId > > ,
20
20
clone_handlers_overrides : Arc < HashMap < ComponentId , ComponentCloneHandler > > ,
21
+ move_components : bool ,
21
22
}
22
23
23
24
impl EntityCloner {
@@ -35,17 +36,21 @@ impl EntityCloner {
35
36
. filter ( |id| self . is_cloning_allowed ( id) ) ,
36
37
) ;
37
38
38
- for component in components {
39
+ for component in & components {
39
40
let global_handlers = world. components ( ) . get_component_clone_handlers ( ) ;
40
- let handler = match self . clone_handlers_overrides . get ( & component) {
41
- None => global_handlers. get_handler ( component) ,
41
+ let handler = match self . clone_handlers_overrides . get ( component) {
42
+ None => global_handlers. get_handler ( * component) ,
42
43
Some ( ComponentCloneHandler :: Default ) => global_handlers. get_default_handler ( ) ,
43
44
Some ( ComponentCloneHandler :: Ignore ) => component_clone_ignore,
44
45
Some ( ComponentCloneHandler :: Custom ( handler) ) => * handler,
45
46
} ;
46
- self . component_id = Some ( component) ;
47
+ self . component_id = Some ( * component) ;
47
48
( handler) ( & mut world. into ( ) , self ) ;
48
49
}
50
+
51
+ if self . move_components {
52
+ world. entity_mut ( self . source ) . remove_by_ids ( & components) ;
53
+ }
49
54
}
50
55
51
56
fn is_cloning_allowed ( & self , component : & ComponentId ) -> bool {
@@ -145,6 +150,8 @@ pub struct EntityCloneBuilder<'w> {
145
150
filter_allows_components : bool ,
146
151
filter : HashSet < ComponentId > ,
147
152
clone_handlers_overrides : HashMap < ComponentId , ComponentCloneHandler > ,
153
+ attach_required_components : bool ,
154
+ move_components : bool ,
148
155
}
149
156
150
157
impl < ' w > EntityCloneBuilder < ' w > {
@@ -155,6 +162,8 @@ impl<'w> EntityCloneBuilder<'w> {
155
162
filter_allows_components : false ,
156
163
filter : Default :: default ( ) ,
157
164
clone_handlers_overrides : Default :: default ( ) ,
165
+ attach_required_components : true ,
166
+ move_components : false ,
158
167
}
159
168
}
160
169
@@ -165,6 +174,7 @@ impl<'w> EntityCloneBuilder<'w> {
165
174
filter_allows_components,
166
175
filter,
167
176
clone_handlers_overrides,
177
+ move_components,
168
178
..
169
179
} = self ;
170
180
@@ -175,29 +185,49 @@ impl<'w> EntityCloneBuilder<'w> {
175
185
filter_allows_components,
176
186
filter : Arc :: new ( filter) ,
177
187
clone_handlers_overrides : Arc :: new ( clone_handlers_overrides) ,
188
+ move_components,
178
189
}
179
190
. clone_entity ( world) ;
180
191
181
192
world. flush_commands ( ) ;
182
193
}
183
194
195
+ /// By default, any components allowed/denied through the filter will automatically
196
+ /// allow/deny all of their required components.
197
+ ///
198
+ /// This method allows for a scoped mode where any changes to the filter
199
+ /// will not involve required components.
200
+ pub fn without_required_components (
201
+ & mut self ,
202
+ builder : impl FnOnce ( & mut EntityCloneBuilder ) + Send + Sync + ' static ,
203
+ ) -> & mut Self {
204
+ self . attach_required_components = false ;
205
+ builder ( self ) ;
206
+ self . attach_required_components = true ;
207
+ self
208
+ }
209
+
210
+ /// Sets whether the cloner should remove any components that were cloned,
211
+ /// effectively moving them from the source entity to the target.
212
+ ///
213
+ /// This is disabled by default.
214
+ ///
215
+ /// The setting only applies to components that are allowed through the filter
216
+ /// at the time [`EntityCloneBuilder::clone_entity`] is called.
217
+ pub fn move_components ( & mut self , enable : bool ) -> & mut Self {
218
+ self . move_components = enable;
219
+ self
220
+ }
221
+
184
222
/// Adds all components of the bundle to the list of components to clone.
185
223
///
186
224
/// Note that all components are allowed by default, to clone only explicitly allowed components make sure to call
187
225
/// [`deny_all`](`Self::deny_all`) before calling any of the `allow` methods.
188
226
pub fn allow < T : Bundle > ( & mut self ) -> & mut Self {
189
- if self . filter_allows_components {
190
- T :: get_component_ids ( self . world . components ( ) , & mut |id| {
191
- if let Some ( id) = id {
192
- self . filter . insert ( id) ;
193
- }
194
- } ) ;
195
- } else {
196
- T :: get_component_ids ( self . world . components ( ) , & mut |id| {
197
- if let Some ( id) = id {
198
- self . filter . remove ( & id) ;
199
- }
200
- } ) ;
227
+ let bundle = self . world . register_bundle :: < T > ( ) ;
228
+ let ids = bundle. explicit_components ( ) . to_owned ( ) ;
229
+ for id in ids {
230
+ self . filter_allow ( id) ;
201
231
}
202
232
self
203
233
}
@@ -207,12 +237,8 @@ impl<'w> EntityCloneBuilder<'w> {
207
237
/// Note that all components are allowed by default, to clone only explicitly allowed components make sure to call
208
238
/// [`deny_all`](`Self::deny_all`) before calling any of the `allow` methods.
209
239
pub fn allow_by_ids ( & mut self , ids : impl IntoIterator < Item = ComponentId > ) -> & mut Self {
210
- if self . filter_allows_components {
211
- self . filter . extend ( ids) ;
212
- } else {
213
- ids. into_iter ( ) . for_each ( |id| {
214
- self . filter . remove ( & id) ;
215
- } ) ;
240
+ for id in ids {
241
+ self . filter_allow ( id) ;
216
242
}
217
243
self
218
244
}
@@ -222,15 +248,10 @@ impl<'w> EntityCloneBuilder<'w> {
222
248
/// Note that all components are allowed by default, to clone only explicitly allowed components make sure to call
223
249
/// [`deny_all`](`Self::deny_all`) before calling any of the `allow` methods.
224
250
pub fn allow_by_type_ids ( & mut self , ids : impl IntoIterator < Item = TypeId > ) -> & mut Self {
225
- let ids = ids
226
- . into_iter ( )
227
- . filter_map ( |id| self . world . components ( ) . get_id ( id) ) ;
228
- if self . filter_allows_components {
229
- self . filter . extend ( ids) ;
230
- } else {
231
- ids. into_iter ( ) . for_each ( |id| {
232
- self . filter . remove ( & id) ;
233
- } ) ;
251
+ for type_id in ids {
252
+ if let Some ( id) = self . world . components ( ) . get_id ( type_id) {
253
+ self . filter_allow ( id) ;
254
+ }
234
255
}
235
256
self
236
257
}
@@ -244,45 +265,28 @@ impl<'w> EntityCloneBuilder<'w> {
244
265
245
266
/// Disallows all components of the bundle from being cloned.
246
267
pub fn deny < T : Bundle > ( & mut self ) -> & mut Self {
247
- if self . filter_allows_components {
248
- T :: get_component_ids ( self . world . components ( ) , & mut |id| {
249
- if let Some ( id) = id {
250
- self . filter . remove ( & id) ;
251
- }
252
- } ) ;
253
- } else {
254
- T :: get_component_ids ( self . world . components ( ) , & mut |id| {
255
- if let Some ( id) = id {
256
- self . filter . insert ( id) ;
257
- }
258
- } ) ;
268
+ let bundle = self . world . register_bundle :: < T > ( ) ;
269
+ let ids = bundle. explicit_components ( ) . to_owned ( ) ;
270
+ for id in ids {
271
+ self . filter_deny ( id) ;
259
272
}
260
273
self
261
274
}
262
275
263
276
/// Extends the list of components that shouldn't be cloned.
264
277
pub fn deny_by_ids ( & mut self , ids : impl IntoIterator < Item = ComponentId > ) -> & mut Self {
265
- if self . filter_allows_components {
266
- ids. into_iter ( ) . for_each ( |id| {
267
- self . filter . remove ( & id) ;
268
- } ) ;
269
- } else {
270
- self . filter . extend ( ids) ;
278
+ for id in ids {
279
+ self . filter_deny ( id) ;
271
280
}
272
281
self
273
282
}
274
283
275
284
/// Extends the list of components that shouldn't be cloned by type ids.
276
285
pub fn deny_by_type_ids ( & mut self , ids : impl IntoIterator < Item = TypeId > ) -> & mut Self {
277
- let ids = ids
278
- . into_iter ( )
279
- . filter_map ( |id| self . world . components ( ) . get_id ( id) ) ;
280
- if self . filter_allows_components {
281
- ids. into_iter ( ) . for_each ( |id| {
282
- self . filter . remove ( & id) ;
283
- } ) ;
284
- } else {
285
- self . filter . extend ( ids) ;
286
+ for type_id in ids {
287
+ if let Some ( id) = self . world . components ( ) . get_id ( type_id) {
288
+ self . filter_deny ( id) ;
289
+ }
286
290
}
287
291
self
288
292
}
@@ -315,11 +319,52 @@ impl<'w> EntityCloneBuilder<'w> {
315
319
}
316
320
self
317
321
}
322
+
323
+ /// Helper function that allows a component through the filter.
324
+ fn filter_allow ( & mut self , id : ComponentId ) {
325
+ if self . filter_allows_components {
326
+ self . filter . insert ( id) ;
327
+ } else {
328
+ self . filter . remove ( & id) ;
329
+ }
330
+ if self . attach_required_components {
331
+ if let Some ( info) = self . world . components ( ) . get_info ( id) {
332
+ for required_id in info. required_components ( ) . iter_ids ( ) {
333
+ if self . filter_allows_components {
334
+ self . filter . insert ( required_id) ;
335
+ } else {
336
+ self . filter . remove ( & required_id) ;
337
+ }
338
+ }
339
+ }
340
+ }
341
+ }
342
+
343
+ /// Helper function that disallows a component through the filter.
344
+ fn filter_deny ( & mut self , id : ComponentId ) {
345
+ if self . filter_allows_components {
346
+ self . filter . remove ( & id) ;
347
+ } else {
348
+ self . filter . insert ( id) ;
349
+ }
350
+ if self . attach_required_components {
351
+ if let Some ( info) = self . world . components ( ) . get_info ( id) {
352
+ for required_id in info. required_components ( ) . iter_ids ( ) {
353
+ if self . filter_allows_components {
354
+ self . filter . remove ( & required_id) ;
355
+ } else {
356
+ self . filter . insert ( required_id) ;
357
+ }
358
+ }
359
+ }
360
+ }
361
+ }
318
362
}
319
363
320
364
#[ cfg( test) ]
321
365
mod tests {
322
366
use crate :: { self as bevy_ecs, component:: Component , entity:: EntityCloneBuilder , world:: World } ;
367
+ use bevy_ecs_macros:: require;
323
368
324
369
#[ cfg( feature = "bevy_reflect" ) ]
325
370
#[ test]
@@ -520,4 +565,34 @@ mod tests {
520
565
assert ! ( world. get:: <B >( e_clone) . is_none( ) ) ;
521
566
assert ! ( world. get:: <C >( e_clone) . is_none( ) ) ;
522
567
}
568
+
569
+ #[ test]
570
+ fn clone_entity_with_required_components ( ) {
571
+ #[ derive( Component , Clone , PartialEq , Debug ) ]
572
+ #[ require( B ) ]
573
+ struct A ;
574
+
575
+ #[ derive( Component , Clone , PartialEq , Debug , Default ) ]
576
+ #[ require( C ( || C ( 5 ) ) ) ]
577
+ struct B ;
578
+
579
+ #[ derive( Component , Clone , PartialEq , Debug ) ]
580
+ struct C ( u32 ) ;
581
+
582
+ let mut world = World :: default ( ) ;
583
+
584
+ let e = world. spawn ( A ) . id ( ) ;
585
+ let e_clone = world. spawn_empty ( ) . id ( ) ;
586
+
587
+ let mut builder = EntityCloneBuilder :: new ( & mut world) ;
588
+ builder. deny_all ( ) ;
589
+ builder. without_required_components ( |builder| {
590
+ builder. allow :: < B > ( ) ;
591
+ } ) ;
592
+ builder. clone_entity ( e, e_clone) ;
593
+
594
+ assert_eq ! ( world. entity( e_clone) . get:: <A >( ) , None ) ;
595
+ assert_eq ! ( world. entity( e_clone) . get:: <B >( ) , Some ( & B ) ) ;
596
+ assert_eq ! ( world. entity( e_clone) . get:: <C >( ) , Some ( & C ( 5 ) ) ) ;
597
+ }
523
598
}
0 commit comments