@@ -8,6 +8,7 @@ use crate::{
8
8
world:: { Mut , World } ,
9
9
} ;
10
10
use bevy_ecs_macros:: all_tuples;
11
+ pub use bevy_ecs_macros:: { Fetch , FilterFetch } ;
11
12
use std:: {
12
13
cell:: UnsafeCell ,
13
14
marker:: PhantomData ,
@@ -21,6 +22,10 @@ use std::{
21
22
///
22
23
/// See [`Query`](crate::system::Query) for a primer on queries.
23
24
///
25
+ /// If you want to implement a custom query, see [`Fetch`] trait documentation.
26
+ ///
27
+ /// If you want to implement a custom query filter, see [`FilterFetch`] trait documentation.
28
+ ///
24
29
/// # Basic [`WorldQuery`]'s
25
30
///
26
31
/// Here is a small list of the most important world queries to know about where `C` stands for a
@@ -49,6 +54,213 @@ pub trait WorldQuery {
49
54
50
55
pub type QueryItem < ' w , ' s , Q > = <<Q as WorldQuery >:: Fetch as Fetch < ' w , ' s > >:: Item ;
51
56
57
+ /// Types that implement this trait are responsible for fetching query items from tables or
58
+ /// archetypes.
59
+ ///
60
+ /// Every type that implements [`WorldQuery`] have their associated [`WorldQuery::Fetch`] and
61
+ /// [`WorldQuery::State`] types that are essential for fetching component data. If you want to
62
+ /// implement a custom query type, you'll need to implement [`Fetch`] and [`FetchState`] for
63
+ /// those associated types.
64
+ ///
65
+ /// You may want to implement a custom query for the following reasons:
66
+ /// - Named structs can be clearer and easier to use than complex query tuples. Access via struct
67
+ /// fields is more convenient than destructuring tuples or accessing them via `q.0, q.1, ...`
68
+ /// pattern and saves a lot of maintenance burden when adding or removing components.
69
+ /// - Nested queries enable the composition pattern and makes query types easier to re-use.
70
+ /// - You can bypass the limit of 15 components that exists for query tuples.
71
+ ///
72
+ /// Implementing the trait manually can allow for a fundamentally new type of behaviour.
73
+ ///
74
+ /// # Derive
75
+ ///
76
+ /// This trait can be derived with the [`derive@super::Fetch`] macro.
77
+ /// To do so, all fields in the struct must themselves impl [`WorldQuery`].
78
+ ///
79
+ /// The derive macro implements [`WorldQuery`] for your type and declares two structs that
80
+ /// implement [`Fetch`] and [`FetchState`] and are used as [`WorldQuery::Fetch`] and
81
+ /// [`WorldQuery::State`] associated types respectively.
82
+ ///
83
+ /// **Note:** currently, the macro only supports named structs.
84
+ ///
85
+ /// ```
86
+ /// # use bevy_ecs::prelude::*;
87
+ /// use bevy_ecs::query::Fetch;
88
+ ///
89
+ /// #[derive(Component)]
90
+ /// struct Foo;
91
+ /// #[derive(Component)]
92
+ /// struct Bar;
93
+ /// #[derive(Component)]
94
+ /// struct OptionalFoo;
95
+ /// #[derive(Component)]
96
+ /// struct OptionalBar;
97
+ ///
98
+ /// #[derive(Fetch)]
99
+ /// struct MyQuery<'w> {
100
+ /// entity: Entity,
101
+ /// foo: &'w Foo,
102
+ /// // `Mut<'w, T>` is a necessary replacement for `&'w mut T`
103
+ /// bar: Mut<'w, Bar>,
104
+ /// optional_foo: Option<&'w OptionalFoo>,
105
+ /// optional_bar: Option<Mut<'w, OptionalBar>>,
106
+ /// }
107
+ ///
108
+ /// fn my_system(mut query: Query<MyQuery>) {
109
+ /// for q in query.iter_mut() {
110
+ /// q.foo;
111
+ /// }
112
+ /// }
113
+ ///
114
+ /// # my_system.system();
115
+ /// ```
116
+ ///
117
+ /// ## Nested queries
118
+ ///
119
+ /// Using nested queries enable the composition pattern, which makes it possible to re-use other
120
+ /// query types. All types that implement [`WorldQuery`] (including the ones that use this derive
121
+ /// macro) are supported.
122
+ ///
123
+ /// ```
124
+ /// # use bevy_ecs::prelude::*;
125
+ /// use bevy_ecs::query::Fetch;
126
+ ///
127
+ /// #[derive(Component)]
128
+ /// struct Foo;
129
+ /// #[derive(Component)]
130
+ /// struct Bar;
131
+ /// #[derive(Component)]
132
+ /// struct OptionalFoo;
133
+ /// #[derive(Component)]
134
+ /// struct OptionalBar;
135
+ ///
136
+ /// #[derive(Fetch)]
137
+ /// struct MyQuery<'w> {
138
+ /// foo: FooQuery<'w>,
139
+ /// bar: (&'w Bar, Option<&'w OptionalBar>)
140
+ /// }
141
+ ///
142
+ /// #[derive(Fetch)]
143
+ /// struct FooQuery<'w> {
144
+ /// foo: &'w Foo,
145
+ /// optional_foo: Option<&'w OptionalFoo>,
146
+ /// }
147
+ ///
148
+ /// ```
149
+ ///
150
+ /// ## Read-only queries
151
+ ///
152
+ /// All queries that are derived with `Fetch` macro have their read-only variants with `ReadOnly`
153
+ /// suffix. If you are going to use a query only for reading, you can mark it with `read_only`
154
+ /// attribute.
155
+ ///
156
+ /// ```
157
+ /// # use bevy_ecs::prelude::*;
158
+ /// use bevy_ecs::query::{Fetch, ReadOnlyFetch, WorldQuery};
159
+ ///
160
+ /// #[derive(Component)]
161
+ /// struct Foo;
162
+ /// #[derive(Component)]
163
+ /// struct Bar;
164
+ ///
165
+ /// #[derive(Fetch)]
166
+ /// #[read_only]
167
+ /// struct FooQuery<'w> {
168
+ /// foo: &'w Foo,
169
+ /// bar_query: BarQueryReadOnly<'w>,
170
+ /// }
171
+ ///
172
+ /// #[derive(Fetch)]
173
+ /// struct BarQuery<'w> {
174
+ /// bar: &'w Bar,
175
+ /// }
176
+ ///
177
+ /// fn assert_read_only<T: ReadOnlyFetch>() {}
178
+ ///
179
+ /// assert_read_only::<<FooQuery as WorldQuery>::Fetch>();
180
+ /// assert_read_only::<<BarQuery as WorldQuery>::ReadOnlyFetch>();
181
+ /// // the following will fail to compile:
182
+ /// // assert_read_only::<<BarQuery as WorldQuery>::Fetch>();
183
+ /// ```
184
+ ///
185
+ /// If you want to use derive macros with read-only query variants, you need to pass them with
186
+ /// using `read_only_derive` attribute.
187
+ ///
188
+ /// # use bevy_ecs::prelude::*;
189
+ /// use bevy_ecs::query::{Fetch, ReadOnlyFetch, WorldQuery};
190
+ ///
191
+ /// ```
192
+ /// # use bevy_ecs::prelude::*;
193
+ /// use bevy_ecs::query::{Fetch, ReadOnlyFetch, WorldQuery};
194
+ ///
195
+ /// #[derive(Component, Debug)]
196
+ /// struct Foo;
197
+ ///
198
+ /// #[derive(Fetch, Debug)]
199
+ /// #[read_only_derive(Debug)]
200
+ /// struct FooQuery<'w> {
201
+ /// foo: &'w Foo,
202
+ /// }
203
+ ///
204
+ /// fn assert_debug<T: std::fmt::Debug>() {}
205
+ ///
206
+ /// assert_debug::<FooQuery>();
207
+ /// assert_debug::<FooQueryReadOnly>();
208
+ /// ```
209
+ ///
210
+ /// **Note:** if you mark a query that doesn't implement `ReadOnlyFetch` as `read_only`,
211
+ /// compilation will fail. We insert static checks as in the example above for every nested query
212
+ /// marked as `read_only`. (They neither affect the runtime, nor pollute your local namespace.)
213
+ ///
214
+ /// ```compile_fail
215
+ /// # use bevy_ecs::prelude::*;
216
+ /// use bevy_ecs::query::{Fetch, ReadOnlyFetch, WorldQuery};
217
+ ///
218
+ /// #[derive(Component)]
219
+ /// struct Foo;
220
+ /// #[derive(Component)]
221
+ /// struct Bar;
222
+ ///
223
+ /// #[derive(Fetch)]
224
+ /// #[read_only]
225
+ /// struct FooQuery<'w> {
226
+ /// foo: &'w Foo,
227
+ /// bar_query: BarQuery<'w>,
228
+ /// }
229
+ ///
230
+ /// #[derive(Fetch)]
231
+ /// struct BarQuery<'w> {
232
+ /// bar: Mut<'w, Bar>,
233
+ /// }
234
+ /// ```
235
+ ///
236
+ /// ## Limitations
237
+ ///
238
+ /// Currently, we don't support members that have a manual [`WorldQuery`] implementation if their
239
+ /// [`Fetch::Item`] is different from the member type. For instance, the following code won't
240
+ /// compile:
241
+ ///
242
+ /// ```ignore
243
+ /// #[derive(Component)]
244
+ /// struct CustomQueryParameter;
245
+ /// #[derive(Component)]
246
+ /// struct ItemDataType;
247
+ ///
248
+ /// struct CustomQueryParameterFetch {
249
+ /// // ...
250
+ /// }
251
+ ///
252
+ /// impl<'w, 's> Fetch<'w, 's> for CustomQueryParameterFetch {
253
+ /// type Item = ItemDataType;
254
+ ///
255
+ /// // ...
256
+ /// }
257
+ ///
258
+ /// #[derive(Fetch)]
259
+ /// struct MyQuery {
260
+ /// custom_item: ItemDataType,
261
+ /// }
262
+ ///
263
+ /// ```
52
264
pub trait Fetch < ' world , ' state > : Sized {
53
265
type Item ;
54
266
type State : FetchState ;
0 commit comments