@@ -2,6 +2,7 @@ use crate::storage::SparseSetIndex;
22use  bevy_utils:: HashSet ; 
33use  core:: fmt; 
44use  fixedbitset:: FixedBitSet ; 
5+ use  smallvec:: SmallVec ; 
56use  std:: marker:: PhantomData ; 
67
78/// A wrapper struct to make Debug representations of [`FixedBitSet`] easier 
@@ -25,6 +26,7 @@ struct FormattedBitSet<'a, T: SparseSetIndex> {
2526    bit_set :  & ' a  FixedBitSet , 
2627    _marker :  PhantomData < T > , 
2728} 
29+ 
2830impl < ' a ,  T :  SparseSetIndex >  FormattedBitSet < ' a ,  T >  { 
2931    fn  new ( bit_set :  & ' a  FixedBitSet )  -> Self  { 
3032        Self  { 
@@ -33,6 +35,7 @@ impl<'a, T: SparseSetIndex> FormattedBitSet<'a, T> {
3335        } 
3436    } 
3537} 
38+ 
3639impl < ' a ,  T :  SparseSetIndex  + fmt:: Debug >  fmt:: Debug  for  FormattedBitSet < ' a ,  T >  { 
3740    fn  fmt ( & self ,  f :  & mut  fmt:: Formatter < ' _ > )  -> fmt:: Result  { 
3841        f. debug_list ( ) 
@@ -41,6 +44,28 @@ impl<'a, T: SparseSetIndex + fmt::Debug> fmt::Debug for FormattedBitSet<'a, T> {
4144    } 
4245} 
4346
47+ struct  FormattedExpandedOrWithAccesses < ' a ,  T :  SparseSetIndex >  { 
48+     with :  & ' a  ExpandedOrWithAccesses , 
49+     _marker :  PhantomData < T > , 
50+ } 
51+ 
52+ impl < ' a ,  T :  SparseSetIndex >  FormattedExpandedOrWithAccesses < ' a ,  T >  { 
53+     fn  new ( with :  & ' a  ExpandedOrWithAccesses )  -> Self  { 
54+         Self  { 
55+             with, 
56+             _marker :  PhantomData , 
57+         } 
58+     } 
59+ } 
60+ 
61+ impl < ' a ,  T :  SparseSetIndex  + fmt:: Debug >  fmt:: Debug  for  FormattedExpandedOrWithAccesses < ' a ,  T >  { 
62+     fn  fmt ( & self ,  f :  & mut  fmt:: Formatter < ' _ > )  -> fmt:: Result  { 
63+         f. debug_list ( ) 
64+             . entries ( self . with . arr . iter ( ) . map ( FormattedBitSet :: < T > :: new) ) 
65+             . finish ( ) 
66+     } 
67+ } 
68+ 
4469/// Tracks read and write access to specific elements in a collection. 
4570/// 
4671/// Used internally to ensure soundness during system initialization and execution. 
@@ -69,6 +94,7 @@ impl<T: SparseSetIndex + fmt::Debug> fmt::Debug for Access<T> {
6994            . finish ( ) 
7095    } 
7196} 
97+ 
7298impl < T :  SparseSetIndex >  Default  for  Access < T >  { 
7399    fn  default ( )  -> Self  { 
74100        Self :: new ( ) 
@@ -213,20 +239,24 @@ impl<T: SparseSetIndex> Access<T> {
213239/// is read/write `T`, read `U`. It must still have a read `U` access otherwise the following 
214240/// queries would be incorrectly considered disjoint: 
215241/// - `Query<&mut T>`  read/write `T` 
216- /// - `Query<Option<&T>` accesses nothing 
242+ /// - `Query<Option<&T>> ` accesses nothing 
217243/// 
218244/// See comments the `WorldQuery` impls of `AnyOf`/`Option`/`Or` for more information. 
219245#[ derive( Clone ,  Eq ,  PartialEq ) ]  
220246pub  struct  FilteredAccess < T :  SparseSetIndex >  { 
221247    access :  Access < T > , 
222-     with :  FixedBitSet , 
248+     with :  ExpandedOrWithAccesses , 
223249    without :  FixedBitSet , 
224250} 
251+ 
225252impl < T :  SparseSetIndex  + fmt:: Debug >  fmt:: Debug  for  FilteredAccess < T >  { 
226253    fn  fmt ( & self ,  f :  & mut  fmt:: Formatter < ' _ > )  -> fmt:: Result  { 
227254        f. debug_struct ( "FilteredAccess" ) 
228255            . field ( "access" ,  & self . access ) 
229-             . field ( "with" ,  & FormattedBitSet :: < T > :: new ( & self . with ) ) 
256+             . field ( 
257+                 "with" , 
258+                 & FormattedExpandedOrWithAccesses :: < T > :: new ( & self . with ) , 
259+             ) 
230260            . field ( "without" ,  & FormattedBitSet :: < T > :: new ( & self . without ) ) 
231261            . finish ( ) 
232262    } 
@@ -277,8 +307,7 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
277307
278308    /// Retains only combinations where the element given by `index` is also present. 
279309     pub  fn  add_with ( & mut  self ,  index :  T )  { 
280-         self . with . grow ( index. sparse_set_index ( )  + 1 ) ; 
281-         self . with . insert ( index. sparse_set_index ( ) ) ; 
310+         self . with . add ( index. sparse_set_index ( ) ) ; 
282311    } 
283312
284313    /// Retains only combinations where the element given by `index` is not present. 
@@ -289,7 +318,7 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
289318
290319    pub  fn  extend_intersect_filter ( & mut  self ,  other :  & FilteredAccess < T > )  { 
291320        self . without . intersect_with ( & other. without ) ; 
292-         self . with . intersect_with ( & other. with ) ; 
321+         self . with . extend_with_or ( & other. with ) ; 
293322    } 
294323
295324    pub  fn  extend_access ( & mut  self ,  other :  & FilteredAccess < T > )  { 
@@ -325,6 +354,57 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
325354    } 
326355} 
327356
357+ // A struct to express something like `Or<(With<A>, With<B>)>`. 
358+ // Filters like `(With<A>, Or<(With<B>, With<C>)>` are expanded into `Or<(With<(A, B)>, With<(B, C)>)>`. 
359+ #[ derive( Clone ,  Eq ,  PartialEq ) ]  
360+ struct  ExpandedOrWithAccesses  { 
361+     arr :  SmallVec < [ FixedBitSet ;  8 ] > , 
362+ } 
363+ 
364+ impl  Default  for  ExpandedOrWithAccesses  { 
365+     fn  default ( )  -> Self  { 
366+         Self  { 
367+             arr :  smallvec:: smallvec![ FixedBitSet :: default ( ) ] , 
368+         } 
369+     } 
370+ } 
371+ 
372+ impl  ExpandedOrWithAccesses  { 
373+     fn  add ( & mut  self ,  index :  usize )  { 
374+         for  with in  & mut  self . arr  { 
375+             with. grow ( index + 1 ) ; 
376+             with. insert ( index) ; 
377+         } 
378+     } 
379+ 
380+     fn  extend_with_or ( & mut  self ,  other :  & ExpandedOrWithAccesses )  { 
381+         self . arr . append ( & mut  other. arr . clone ( ) ) ; 
382+     } 
383+ 
384+     fn  is_disjoint ( & self ,  without :  & FixedBitSet )  -> bool  { 
385+         self . arr . iter ( ) . any ( |with| with. is_disjoint ( without) ) 
386+     } 
387+ 
388+     fn  union_with ( & mut  self ,  other :  & Self )  { 
389+         if  other. arr . len ( )  == 1  { 
390+             for  with in  & mut  self . arr  { 
391+                 with. union_with ( & other. arr [ 0 ] ) ; 
392+             } 
393+             return ; 
394+         } 
395+ 
396+         let  mut  new_with = SmallVec :: with_capacity ( self . arr . len ( )  *  other. arr . len ( ) ) ; 
397+         for  with in  & self . arr  { 
398+             for  other_with in  & other. arr  { 
399+                 let  mut  w = with. clone ( ) ; 
400+                 w. union_with ( other_with) ; 
401+                 new_with. push ( w) ; 
402+             } 
403+         } 
404+         self . arr  = new_with; 
405+     } 
406+ } 
407+ 
328408/// A collection of [`FilteredAccess`] instances. 
329409/// 
330410/// Used internally to statically check if systems have conflicting access. 
0 commit comments