11use alloc:: collections:: VecDeque ;
22
33use bevy_ecs:: {
4- entity:: Entity ,
4+ component:: Component ,
5+ entity:: { Entity , VisitEntities } ,
56 query:: { QueryData , QueryFilter , WorldQuery } ,
67 system:: Query ,
78} ;
@@ -30,9 +31,12 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
3031 /// }
3132 /// # bevy_ecs::system::assert_is_system(system);
3233 /// ```
33- fn iter_descendants ( & ' w self , entity : Entity ) -> DescendantIter < ' w , ' s , D , F >
34+ fn iter_descendants ( & ' w self , entity : Entity ) -> RelatedIter < ' w , ' s , Children , D , F >
3435 where
35- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Children > ;
36+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Children > ,
37+ {
38+ self . iter_related ( entity)
39+ }
3640
3741 /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s ancestors.
3842 ///
@@ -52,104 +56,132 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
5256 /// }
5357 /// # bevy_ecs::system::assert_is_system(system);
5458 /// ```
55- fn iter_ancestors ( & ' w self , entity : Entity ) -> AncestorIter < ' w , ' s , D , F >
56- where
57- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ;
58- }
59-
60- impl < ' w , ' s , D : QueryData , F : QueryFilter > HierarchyQueryExt < ' w , ' s , D , F > for Query < ' w , ' s , D , F > {
61- fn iter_descendants ( & ' w self , entity : Entity ) -> DescendantIter < ' w , ' s , D , F >
59+ fn iter_ancestors ( & ' w self , entity : Entity ) -> RelatedIter < ' w , ' s , Parent , D , F >
6260 where
63- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Children > ,
61+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
6462 {
65- DescendantIter :: new ( self , entity)
63+ self . iter_related ( entity)
6664 }
6765
68- fn iter_ancestors ( & ' w self , entity : Entity ) -> AncestorIter < ' w , ' s , D , F >
66+ /// Returns an [`Iterator`] of [`Entity`]'s over all of `entity`'s `C` relations.
67+ ///
68+ /// Can only be called on a [`Query`] of `C` (i.e. `Query<&C>`), where `C`
69+ /// is some type implementing [`VisitEntities`].
70+ /// # Examples
71+ /// ```
72+ /// # use bevy_ecs::prelude::*;
73+ /// # use bevy_hierarchy::prelude::*;
74+ /// # #[derive(Component)]
75+ /// # struct Marker;
76+ /// fn system(query: Query<Entity, With<Marker>>, parent_query: Query<&Parent>) {
77+ /// let entity = query.single();
78+ /// for ancestor in parent_query.iter_related(entity) {
79+ /// // Do something!
80+ /// }
81+ /// }
82+ /// # bevy_ecs::system::assert_is_system(system);
83+ /// ```
84+ fn iter_related < C > ( & ' w self , entity : Entity ) -> RelatedIter < ' w , ' s , C , D , F >
6985 where
70- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
86+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
87+ C : Component + VisitEntities ;
88+ }
89+
90+ impl < ' w , ' s , D : QueryData , F : QueryFilter > HierarchyQueryExt < ' w , ' s , D , F > for Query < ' w , ' s , D , F > {
91+ fn iter_related < C > ( & ' w self , entity : Entity ) -> RelatedIter < ' w , ' s , C , D , F >
92+ where
93+ <D as QueryData >:: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
94+ C : Component + VisitEntities ,
7195 {
72- AncestorIter :: new ( self , entity)
96+ RelatedIter :: new ( self , entity)
7397 }
7498}
7599
76- /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].
100+ /// An iterator over entities related via some component `C` that implements
101+ /// [`VisitEntities`].
77102///
78103/// Traverses the hierarchy breadth-first.
79- pub struct DescendantIter < ' w , ' s , D : QueryData , F : QueryFilter >
104+ pub struct RelatedIter < ' w , ' s , C , D , F >
80105where
81- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Children > ,
106+ D : QueryData ,
107+ F : QueryFilter ,
108+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
109+ C : Component + VisitEntities ,
82110{
83- children_query : & ' w Query < ' w , ' s , D , F > ,
84- vecdeque : VecDeque < Entity > ,
111+ related_query : & ' w Query < ' w , ' s , D , F > ,
112+ vecdeque : VecDeque < ( usize , Entity ) > ,
85113}
86114
87- impl < ' w , ' s , D : QueryData , F : QueryFilter > DescendantIter < ' w , ' s , D , F >
115+ impl < ' w , ' s , C , D , F > RelatedIter < ' w , ' s , C , D , F >
88116where
89- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Children > ,
117+ D : QueryData ,
118+ F : QueryFilter ,
119+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
120+ C : Component + VisitEntities ,
90121{
91- /// Returns a new [`DescendantIter`].
92- pub fn new ( children_query : & ' w Query < ' w , ' s , D , F > , entity : Entity ) -> Self {
93- DescendantIter {
94- children_query,
95- vecdeque : children_query
96- . get ( entity)
97- . into_iter ( )
98- . flatten ( )
99- . copied ( )
100- . collect ( ) ,
122+ /// Create a new [`RelatedIter`].
123+ fn new ( related_query : & ' w Query < ' w , ' s , D , F > , entity : Entity ) -> Self {
124+ let mut vecdeque = VecDeque :: new ( ) ;
125+ related_query. get ( entity) . into_iter ( ) . for_each ( |t| {
126+ t. visit_entities ( |entity| {
127+ vecdeque. push_back ( ( 1 , entity) ) ;
128+ } )
129+ } ) ;
130+ RelatedIter {
131+ related_query,
132+ vecdeque,
101133 }
102134 }
103- }
104135
105- impl < ' w , ' s , D : QueryData , F : QueryFilter > Iterator for DescendantIter < ' w , ' s , D , F >
106- where
107- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Children > ,
108- {
109- type Item = Entity ;
136+ fn next ( & mut self ) -> Option < ( usize , Entity ) > {
137+ let ( depth, entity) = self . vecdeque . pop_front ( ) ?;
110138
111- fn next ( & mut self ) -> Option < Self :: Item > {
112- let entity = self . vecdeque . pop_front ( ) ?;
113-
114- if let Ok ( children) = self . children_query . get ( entity) {
115- self . vecdeque . extend ( children) ;
139+ if let Ok ( children) = self . related_query . get ( entity) {
140+ children. visit_entities ( |entity| {
141+ self . vecdeque . push_back ( ( depth + 1 , entity) ) ;
142+ } ) ;
116143 }
117144
118- Some ( entity)
145+ Some ( ( depth , entity) )
119146 }
120- }
121147
122- /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
123- pub struct AncestorIter < ' w , ' s , D : QueryData , F : QueryFilter >
124- where
125- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
126- {
127- parent_query : & ' w Query < ' w , ' s , D , F > ,
128- next : Option < Entity > ,
148+ pub fn with_depth ( self ) -> RelatedDepthIter < ' w , ' s , C , D , F > {
149+ RelatedDepthIter ( self )
150+ }
129151}
130152
131- impl < ' w , ' s , D : QueryData , F : QueryFilter > AncestorIter < ' w , ' s , D , F >
153+ impl < ' w , ' s , C , D , F > Iterator for RelatedIter < ' w , ' s , C , D , F >
132154where
133- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
155+ D : QueryData ,
156+ F : QueryFilter ,
157+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
158+ C : Component + VisitEntities ,
134159{
135- /// Returns a new [`AncestorIter`].
136- pub fn new ( parent_query : & ' w Query < ' w , ' s , D , F > , entity : Entity ) -> Self {
137- AncestorIter {
138- parent_query,
139- next : Some ( entity) ,
140- }
160+ type Item = Entity ;
161+
162+ fn next ( & mut self ) -> Option < Self :: Item > {
163+ RelatedIter :: next ( self ) . map ( |( _, e) | e)
141164 }
142165}
143166
144- impl < ' w , ' s , D : QueryData , F : QueryFilter > Iterator for AncestorIter < ' w , ' s , D , F >
167+ pub struct RelatedDepthIter < ' w , ' s , C , D , F > ( RelatedIter < ' w , ' s , C , D , F > )
145168where
146- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
169+ D : QueryData ,
170+ F : QueryFilter ,
171+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
172+ C : Component + VisitEntities ;
173+
174+ impl < ' w , ' s , C , D , F > Iterator for RelatedDepthIter < ' w , ' s , C , D , F >
175+ where
176+ D : QueryData ,
177+ F : QueryFilter ,
178+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
179+ C : Component + VisitEntities ,
147180{
148- type Item = Entity ;
181+ type Item = ( usize , Entity ) ;
149182
150183 fn next ( & mut self ) -> Option < Self :: Item > {
151- self . next = self . parent_query . get ( self . next ?) . ok ( ) . map ( Parent :: get) ;
152- self . next
184+ RelatedIter :: next ( & mut self . 0 )
153185 }
154186}
155187
@@ -201,4 +233,42 @@ mod tests {
201233
202234 assert_eq ! ( [ & A ( 1 ) , & A ( 0 ) ] , result. as_slice( ) ) ;
203235 }
236+
237+ #[ test]
238+ fn related_children_iter ( ) {
239+ let world = & mut World :: new ( ) ;
240+
241+ let [ a, b, c, d] = std:: array:: from_fn ( |i| world. spawn ( A ( i) ) . id ( ) ) ;
242+
243+ world. entity_mut ( a) . add_children ( & [ b, c] ) ;
244+ world. entity_mut ( c) . add_children ( & [ d] ) ;
245+
246+ let mut system_state = SystemState :: < ( Query < & Children > , Query < & A > ) > :: new ( world) ;
247+ let ( children_query, a_query) = system_state. get ( world) ;
248+
249+ let result: Vec < _ > = children_query
250+ . iter_related ( a)
251+ . with_depth ( )
252+ . filter_map ( |( d, e) | Some ( ( d, a_query. get ( e) . ok ( ) ?) ) )
253+ . collect ( ) ;
254+
255+ assert_eq ! ( [ ( 1 , & A ( 1 ) ) , ( 1 , & A ( 2 ) ) , ( 2 , & A ( 3 ) ) ] , result. as_slice( ) ) ;
256+ }
257+
258+ #[ test]
259+ fn related_parent_iter ( ) {
260+ let world = & mut World :: new ( ) ;
261+
262+ let [ a, b, c] = std:: array:: from_fn ( |i| world. spawn ( A ( i) ) . id ( ) ) ;
263+
264+ world. entity_mut ( a) . add_children ( & [ b] ) ;
265+ world. entity_mut ( b) . add_children ( & [ c] ) ;
266+
267+ let mut system_state = SystemState :: < ( Query < & Parent > , Query < & A > ) > :: new ( world) ;
268+ let ( parent_query, a_query) = system_state. get ( world) ;
269+
270+ let result: Vec < _ > = a_query. iter_many ( parent_query. iter_related ( c) ) . collect ( ) ;
271+
272+ assert_eq ! ( [ & A ( 1 ) , & A ( 0 ) ] , result. as_slice( ) ) ;
273+ }
204274}
0 commit comments