@@ -18,6 +18,7 @@ pub struct EntityCloner {
1818 filter_allows_components : bool ,
1919 filter : Arc < HashSet < ComponentId > > ,
2020 clone_handlers_overrides : Arc < HashMap < ComponentId , ComponentCloneHandler > > ,
21+ move_components : bool ,
2122}
2223
2324impl EntityCloner {
@@ -35,17 +36,21 @@ impl EntityCloner {
3536 . filter ( |id| self . is_cloning_allowed ( id) ) ,
3637 ) ;
3738
38- for component in components {
39+ for component in & components {
3940 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) ,
4243 Some ( ComponentCloneHandler :: Default ) => global_handlers. get_default_handler ( ) ,
4344 Some ( ComponentCloneHandler :: Ignore ) => component_clone_ignore,
4445 Some ( ComponentCloneHandler :: Custom ( handler) ) => * handler,
4546 } ;
46- self . component_id = Some ( component) ;
47+ self . component_id = Some ( * component) ;
4748 ( handler) ( & mut world. into ( ) , self ) ;
4849 }
50+
51+ if self . move_components {
52+ world. entity_mut ( self . source ) . remove_by_ids ( & components) ;
53+ }
4954 }
5055
5156 fn is_cloning_allowed ( & self , component : & ComponentId ) -> bool {
@@ -145,6 +150,8 @@ pub struct EntityCloneBuilder<'w> {
145150 filter_allows_components : bool ,
146151 filter : HashSet < ComponentId > ,
147152 clone_handlers_overrides : HashMap < ComponentId , ComponentCloneHandler > ,
153+ attach_required_components : bool ,
154+ move_components : bool ,
148155}
149156
150157impl < ' w > EntityCloneBuilder < ' w > {
@@ -155,6 +162,8 @@ impl<'w> EntityCloneBuilder<'w> {
155162 filter_allows_components : false ,
156163 filter : Default :: default ( ) ,
157164 clone_handlers_overrides : Default :: default ( ) ,
165+ attach_required_components : true ,
166+ move_components : false ,
158167 }
159168 }
160169
@@ -165,6 +174,7 @@ impl<'w> EntityCloneBuilder<'w> {
165174 filter_allows_components,
166175 filter,
167176 clone_handlers_overrides,
177+ move_components,
168178 ..
169179 } = self ;
170180
@@ -175,29 +185,49 @@ impl<'w> EntityCloneBuilder<'w> {
175185 filter_allows_components,
176186 filter : Arc :: new ( filter) ,
177187 clone_handlers_overrides : Arc :: new ( clone_handlers_overrides) ,
188+ move_components,
178189 }
179190 . clone_entity ( world) ;
180191
181192 world. flush_commands ( ) ;
182193 }
183194
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+
184222 /// Adds all components of the bundle to the list of components to clone.
185223 ///
186224 /// Note that all components are allowed by default, to clone only explicitly allowed components make sure to call
187225 /// [`deny_all`](`Self::deny_all`) before calling any of the `allow` methods.
188226 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) ;
201231 }
202232 self
203233 }
@@ -207,12 +237,8 @@ impl<'w> EntityCloneBuilder<'w> {
207237 /// Note that all components are allowed by default, to clone only explicitly allowed components make sure to call
208238 /// [`deny_all`](`Self::deny_all`) before calling any of the `allow` methods.
209239 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) ;
216242 }
217243 self
218244 }
@@ -222,15 +248,10 @@ impl<'w> EntityCloneBuilder<'w> {
222248 /// Note that all components are allowed by default, to clone only explicitly allowed components make sure to call
223249 /// [`deny_all`](`Self::deny_all`) before calling any of the `allow` methods.
224250 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+ }
234255 }
235256 self
236257 }
@@ -244,45 +265,28 @@ impl<'w> EntityCloneBuilder<'w> {
244265
245266 /// Disallows all components of the bundle from being cloned.
246267 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) ;
259272 }
260273 self
261274 }
262275
263276 /// Extends the list of components that shouldn't be cloned.
264277 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) ;
271280 }
272281 self
273282 }
274283
275284 /// Extends the list of components that shouldn't be cloned by type ids.
276285 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+ }
286290 }
287291 self
288292 }
@@ -315,11 +319,52 @@ impl<'w> EntityCloneBuilder<'w> {
315319 }
316320 self
317321 }
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+ }
318362}
319363
320364#[ cfg( test) ]
321365mod tests {
322366 use crate :: { self as bevy_ecs, component:: Component , entity:: EntityCloneBuilder , world:: World } ;
367+ use bevy_ecs_macros:: require;
323368
324369 #[ cfg( feature = "bevy_reflect" ) ]
325370 #[ test]
@@ -520,4 +565,34 @@ mod tests {
520565 assert ! ( world. get:: <B >( e_clone) . is_none( ) ) ;
521566 assert ! ( world. get:: <C >( e_clone) . is_none( ) ) ;
522567 }
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+ }
523598}
0 commit comments