11//! QuadTree Plugin
2+ //!
3+
4+ #[ cfg( feature = "multi-quadtree" ) ]
5+ mod multi_plugin;
6+
7+ #[ cfg( feature = "multi-quadtree" ) ]
8+ pub use multi_plugin:: {
9+ AsQuadTreePluginConfig , MultiQuadTreePlugin , QTConfig , QuadTreePluginConfig ,
10+ } ;
211
312use crate :: collision:: AsDynCollision ;
413use crate :: system:: { update_collision, update_quadtree} ;
@@ -9,7 +18,7 @@ use bevy_ecs::prelude::*;
918use bevy_ecs:: schedule:: { IntoSystemConfigs , SystemConfigs } ;
1019#[ cfg( feature = "sprite" ) ]
1120use bevy_sprite:: Sprite ;
12- use bevy_transform:: components :: GlobalTransform ;
21+ use bevy_transform:: prelude :: * ;
1322
1423/// A Bevy plugin for quadtree.
1524/// # Type Parameters
@@ -35,34 +44,37 @@ use bevy_transform::components::GlobalTransform;
3544/// `K`: For `LooseQuadTree`, K / 10 = outlet_boundary / inlet_boundary. Set K to 10 by default and 20 is founded best.
3645/// K should >= 10. Only if the object move and is **no longer completely contained** by the outlet_boundary will it be inserted again.
3746///
38- /// `ID`: If you want different quadtree for different use cases with the same other parameters, set ID to different values.
39- /// # Panic
40- /// 1. duplicated shape in `P`.
41- ///
42- /// e.g. `P = ((CollisionRect, GlobalTransform), (CollisionRect, Sprite))` will lead a debug_assertion failure.
43- /// Try `P = (CollisionRect, (GlobalTransform, Sprite))` or `P = ((CollisionRect<0>, GlobalTransform), (CollisionRect<1>, Sprite))` in concret context.
44- ///
45- /// 2. invalid const parameters.
46- ///
47- /// N, D, W, H should > 0. K should >= 10.
47+ /// `ID`: Set a lucky number as you like for the quadtree.
48+ /// If you want multiple quadtrees, see [`MultiQuadTreePlugin`].
4849///
4950/// # Example
5051/// ```no_run
52+ /// # #[cfg(feature = "sprite")]
53+ /// # {
5154/// # use bevy_app::prelude::*;
5255/// # use bevy_transform::prelude::*;
53- /// # #[cfg(feature = "sprite")]
5456/// # use bevy_sprite::Sprite;
5557/// use bevy_quadtree::{CollisionCircle, CollisionRect, CollisionRotatedRect, QuadTreePlugin};
5658///
57- /// #[cfg(feature = "sprite")]
5859/// App::new()
5960/// .add_plugins(QuadTreePlugin::<(
6061/// (CollisionCircle, GlobalTransform),
61- /// (CollisionRotatedRect, GlobalTransform ),
62- /// (CollisionRect, Sprite),
62+ /// (CollisionRotatedRect, Sprite ),
63+ /// (CollisionRect, (GlobalTransform, Sprite) ),
6364/// ),
6465/// 40, 4, 100, 100, 20>::default());
66+ /// # }
6567/// ```
68+ ///
69+ /// # Panic
70+ /// 1. duplicated shapes in `P`. (Debug check only)
71+ ///
72+ /// e.g. `P = ((CollisionRect, GlobalTransform), (CollisionRect, Sprite))` will lead a debug_assertion failure.
73+ /// Try `P = (CollisionRect, (GlobalTransform, Sprite))` or `P = ((CollisionRect<0>, GlobalTransform), (CollisionRect<1>, Sprite))` in concret context.
74+ ///
75+ /// 2. invalid const parameters. (Debug check only)
76+ ///
77+ /// N, D, W, H should > 0. K should >= 10.
6678#[ derive( Debug ) ]
6779pub struct QuadTreePlugin <
6880 P ,
@@ -200,10 +212,9 @@ macro_rules! impl_tracking_pair_tuple {
200212 impl <S > TrackingPair for ( S , ( $( $c) ,+, ) )
201213 where
202214 S : Component + AsDynCollision + $( UpdateCollision <$c>+) + Clone ,
203- $( $c: Component ) ,+,
204- $( ( S , $c) : TrackingPair ) ,+,
205215 {
206216 fn update_collision( ) -> SystemConfigs {
217+ // update_collision has Mut<S>, so chain them
207218 ( $( update_collision:: <S , $c>) ,+, ) . chain( )
208219 }
209220 fn update_quadtree<const N : usize , const D : usize , const W : usize , const H : usize , const K : usize , const ID : usize >(
@@ -240,6 +251,7 @@ macro_rules! impl_tracking_pairs {
240251 $( [ <P $i>] : TrackingPair ) ,+
241252 {
242253 fn update_collision( ) -> SystemConfigs {
254+ // no duplicate shape in `P`s, so ambiguous_with_all
243255 ( $( [ <P $i>] :: update_collision( ) ) ,+, ) . ambiguous_with_all( )
244256 }
245257 fn update_quadtree<const N : usize , const D : usize , const W : usize , const H : usize , const K : usize , const ID : usize >(
@@ -249,7 +261,7 @@ macro_rules! impl_tracking_pairs {
249261 let mut set = std:: collections:: HashMap :: new( ) ;
250262 $(
251263 if let Some ( dup) = set. insert( [ <P $i>] :: shape_id( ) , std:: any:: type_name:: <[ <P $i>] >( ) ) {
252- panic!( "Duplicate quadtree updating system added:\n <{}>\n <{}>\n They have the same collision shape, merge them into one or use `ID` type parameter of shape." , dup, std:: any:: type_name:: <[ <P $i>] >( ) ) ;
264+ panic!( "Duplicated quadtree updating system added:\n <{}>\n <{}>\n They have the same collision shape, merge them into one or use `ID` type parameter of shape." , dup, std:: any:: type_name:: <[ <P $i>] >( ) ) ;
253265 }
254266 ) ;+
255267 }
@@ -263,15 +275,15 @@ macro_rules! impl_tracking_pairs {
263275 let mut set = std:: collections:: HashMap :: new( ) ;
264276 $(
265277 if let Some ( dup) = set. insert( [ <P $i>] :: shape_id( ) , std:: any:: type_name:: <[ <P $i>] >( ) ) {
266- panic!( "Duplicate gizmos box updating system added:\n <{}>\n <{}>\n They have the same collision shape, merge them into one or use `ID` type parameter of shape." , dup, std:: any:: type_name:: <[ <P $i>] >( ) ) ;
278+ panic!( "Duplicated gizmos box updating system added:\n <{}>\n <{}>\n They have the same collision shape, merge them into one or use `ID` type parameter of shape." , dup, std:: any:: type_name:: <[ <P $i>] >( ) ) ;
267279 }
268280 ) ;+
269281 }
270282 ( $( [ <P $i>] :: show_boundary:: <N , D , W , H , K , ID >( ) ) ,+, ) . ambiguous_with_all( )
271283 }
272284 #[ cfg( debug_assertions) ]
273285 fn shape_id( ) -> std:: any:: TypeId {
274- unreachable!( )
286+ unreachable!( "only (S, C) and ((S1, C), (S2, C), ...) are allowed" )
275287 }
276288 }
277289 }
@@ -295,7 +307,7 @@ mod tests {
295307 use crate :: { CollisionCircle , CollisionRect , CollisionRotatedRect } ;
296308
297309 #[ test]
298- #[ should_panic( expected = "Duplicate quadtree updating system added" ) ]
310+ #[ should_panic( expected = "Duplicated quadtree updating system added" ) ]
299311 fn duplicate_shape1 ( ) {
300312 App :: new ( ) . add_plugins ( QuadTreePlugin :: <
301313 (
@@ -312,7 +324,7 @@ mod tests {
312324
313325 #[ cfg( feature = "sprite" ) ]
314326 #[ test]
315- #[ should_panic( expected = "Duplicate quadtree updating system added" ) ]
327+ #[ should_panic( expected = "Duplicated quadtree updating system added" ) ]
316328 fn duplicate_shape2 ( ) {
317329 App :: new ( ) . add_plugins ( QuadTreePlugin :: <
318330 ( ( CollisionRect , GlobalTransform ) , ( CollisionRect , Sprite ) ) ,
@@ -326,7 +338,7 @@ mod tests {
326338
327339 #[ cfg( feature = "sprite" ) ]
328340 #[ test]
329- #[ should_panic( expected = "Duplicate quadtree updating system added" ) ]
341+ #[ should_panic( expected = "Duplicated quadtree updating system added" ) ]
330342 fn duplicate_shape3 ( ) {
331343 App :: new ( ) . add_plugins ( QuadTreePlugin :: <
332344 (
@@ -374,4 +386,20 @@ mod tests {
374386 20 ,
375387 > :: default ( ) ) ;
376388 }
389+
390+ #[ cfg( feature = "sprite" ) ]
391+ #[ test]
392+ fn plugin_test_tuple ( ) {
393+ App :: new ( ) . add_plugins ( QuadTreePlugin :: <
394+ (
395+ ( CollisionRect < 0 > , ( GlobalTransform , Sprite ) ) ,
396+ ( CollisionRect < 1 > , GlobalTransform ) ,
397+ ) ,
398+ 40 ,
399+ 4 ,
400+ 100 ,
401+ 100 ,
402+ 20 ,
403+ > :: default ( ) ) ;
404+ }
377405}
0 commit comments