11use std:: collections:: VecDeque ;
22
33use bevy_ecs:: {
4- entity:: Entity ,
4+ component:: Component ,
5+ entity:: { Entity , IterEntities } ,
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,102 +56,102 @@ 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 [`IterEntities`].
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 >
85+ where
86+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
87+ C : Component + IterEntities ;
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 >
6992 where
70- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
93+ <D as QueryData >:: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
94+ C : Component + IterEntities ,
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+ /// [`IterEntities`].
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 + IterEntities ,
82110{
83- children_query : & ' w Query < ' w , ' s , D , F > ,
111+ related_query : & ' w Query < ' w , ' s , D , F > ,
84112 vecdeque : VecDeque < 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 + IterEntities ,
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. get ( entity) . into_iter ( ) . flatten ( ) . collect ( ) ,
122+ /// Create a new [`RelatedIter`].
123+ pub fn new ( related_query : & ' w Query < ' w , ' s , D , F > , entity : Entity ) -> Self {
124+ RelatedIter {
125+ related_query,
126+ vecdeque : related_query
127+ . get ( entity)
128+ . iter ( )
129+ . flat_map ( |t| t. iter_entities ( ) )
130+ . collect ( ) ,
96131 }
97132 }
98133}
99134
100- impl < ' w , ' s , D : QueryData , F : QueryFilter > Iterator for DescendantIter < ' w , ' s , D , F >
135+ impl < ' w , ' s , C , D , F > Iterator for RelatedIter < ' w , ' s , C , D , F >
101136where
102- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Children > ,
137+ D : QueryData ,
138+ F : QueryFilter ,
139+ D :: ReadOnly : WorldQuery < Item < ' w > = & ' w C > ,
140+ C : Component + IterEntities ,
103141{
104142 type Item = Entity ;
105143
106144 fn next ( & mut self ) -> Option < Self :: Item > {
107145 let entity = self . vecdeque . pop_front ( ) ?;
108146
109- if let Ok ( children) = self . children_query . get ( entity) {
110- self . vecdeque . extend ( children) ;
147+ if let Ok ( children) = self . related_query . get ( entity) {
148+ self . vecdeque . extend ( children. iter_entities ( ) ) ;
111149 }
112150
113151 Some ( entity)
114152 }
115153}
116154
117- /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
118- pub struct AncestorIter < ' w , ' s , D : QueryData , F : QueryFilter >
119- where
120- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
121- {
122- parent_query : & ' w Query < ' w , ' s , D , F > ,
123- next : Option < Entity > ,
124- }
125-
126- impl < ' w , ' s , D : QueryData , F : QueryFilter > AncestorIter < ' w , ' s , D , F >
127- where
128- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
129- {
130- /// Returns a new [`AncestorIter`].
131- pub fn new ( parent_query : & ' w Query < ' w , ' s , D , F > , entity : Entity ) -> Self {
132- AncestorIter {
133- parent_query,
134- next : Some ( entity) ,
135- }
136- }
137- }
138-
139- impl < ' w , ' s , D : QueryData , F : QueryFilter > Iterator for AncestorIter < ' w , ' s , D , F >
140- where
141- D :: ReadOnly : WorldQuery < Item < ' w > = & ' w Parent > ,
142- {
143- type Item = Entity ;
144-
145- fn next ( & mut self ) -> Option < Self :: Item > {
146- self . next = self . parent_query . get ( self . next ?) . ok ( ) . map ( Parent :: get) ;
147- self . next
148- }
149- }
150-
151155#[ cfg( test) ]
152156mod tests {
153157 use bevy_ecs:: {
@@ -196,4 +200,38 @@ mod tests {
196200
197201 assert_eq ! ( [ & A ( 1 ) , & A ( 0 ) ] , result. as_slice( ) ) ;
198202 }
203+
204+ #[ test]
205+ fn related_children_iter ( ) {
206+ let world = & mut World :: new ( ) ;
207+
208+ let [ a, b, c, d] = std:: array:: from_fn ( |i| world. spawn ( A ( i) ) . id ( ) ) ;
209+
210+ world. entity_mut ( a) . add_children ( & [ b, c] ) ;
211+ world. entity_mut ( c) . add_children ( & [ d] ) ;
212+
213+ let mut system_state = SystemState :: < ( Query < & Children > , Query < & A > ) > :: new ( world) ;
214+ let ( children_query, a_query) = system_state. get ( world) ;
215+
216+ let result: Vec < _ > = a_query. iter_many ( children_query. iter_related ( a) ) . collect ( ) ;
217+
218+ assert_eq ! ( [ & A ( 1 ) , & A ( 2 ) , & A ( 3 ) ] , result. as_slice( ) ) ;
219+ }
220+
221+ #[ test]
222+ fn related_parent_iter ( ) {
223+ let world = & mut World :: new ( ) ;
224+
225+ let [ a, b, c] = std:: array:: from_fn ( |i| world. spawn ( A ( i) ) . id ( ) ) ;
226+
227+ world. entity_mut ( a) . add_children ( & [ b] ) ;
228+ world. entity_mut ( b) . add_children ( & [ c] ) ;
229+
230+ let mut system_state = SystemState :: < ( Query < & Parent > , Query < & A > ) > :: new ( world) ;
231+ let ( parent_query, a_query) = system_state. get ( world) ;
232+
233+ let result: Vec < _ > = a_query. iter_many ( parent_query. iter_related ( c) ) . collect ( ) ;
234+
235+ assert_eq ! ( [ & A ( 1 ) , & A ( 0 ) ] , result. as_slice( ) ) ;
236+ }
199237}
0 commit comments