Skip to content

Commit e33a2b0

Browse files
committed
Update the example
1 parent 7016a9a commit e33a2b0

File tree

4 files changed

+170
-98
lines changed

4 files changed

+170
-98
lines changed

Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,12 @@ name = "component_change_detection"
267267
path = "examples/ecs/component_change_detection.rs"
268268

269269
[[example]]
270-
name = "event"
271-
path = "examples/ecs/event.rs"
270+
name = "custom_query_param"
271+
path = "examples/ecs/custom_query_param.rs"
272272

273273
[[example]]
274-
name = "fetch"
275-
path = "examples/ecs/fetch.rs"
274+
name = "event"
275+
path = "examples/ecs/event.rs"
276276

277277
[[example]]
278278
name = "fixed_timestep"

examples/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ Example | File | Description
157157
--- | --- | ---
158158
`ecs_guide` | [`ecs/ecs_guide.rs`](./ecs/ecs_guide.rs) | Full guide to Bevy's ECS
159159
`component_change_detection` | [`ecs/component_change_detection.rs`](./ecs/component_change_detection.rs) | Change detection on components
160+
`custom_query_param` | [`ecs/custom_query_param.rs`](./ecs/custom_query_param.rs) | Groups commonly used compound queries and query filters into a single type
160161
`event` | [`ecs/event.rs`](./ecs/event.rs) | Illustrates event creation, activation, and reception
161-
`fetch` | [`ecs/fetch.rs`](./ecs/fetch.rs) | Illustrates creating custom queries and query filters with `Fetch` and `FilterFetch`
162162
`fixed_timestep` | [`ecs/fixed_timestep.rs`](./ecs/fixed_timestep.rs) | Shows how to create systems that run every fixed timestep, rather than every tick
163163
`hierarchy` | [`ecs/hierarchy.rs`](./ecs/hierarchy.rs) | Creates a hierarchy of parents and children entities
164164
`iter_combinations` | [`ecs/iter_combinations.rs`](./ecs/iter_combinations.rs) | Shows how to iterate over combinations of query results.

examples/ecs/custom_query_param.rs

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
use bevy::{
2+
ecs::{
3+
component::Component,
4+
query::{Fetch, FilterFetch},
5+
},
6+
prelude::*,
7+
};
8+
use std::{fmt::Debug, marker::PhantomData};
9+
10+
/// This examples illustrates the usage of `Fetch` and `FilterFetch` derive macros, that allow
11+
/// defining custom query and filter types.
12+
///
13+
/// White regular tuple queries work great in most of simple scenarios, using custom queries
14+
/// declared as named structs can bring the following advantages:
15+
/// - They help to avoid destructuring or using `q.0, q.1, ...` access pattern
16+
/// - Adding, removing components or changing items order with structs greatly reduces maintenance
17+
/// burden, as you don't need to update statements that destructure tuples, care abort order
18+
/// of elements, etc. Instead, you can just add or remove places where a certain element is used
19+
/// - Named structs enable the composition pattern, that makes query types easier to re-use
20+
/// - They allow to go over the limit of 15 components that exists for query tuples
21+
///
22+
/// For more details on the `Fetch` and `FilterFetch` derive macros, see their documentation.
23+
fn main() {
24+
App::new()
25+
.add_startup_system(spawn)
26+
.add_system(print_components.system().label("print_components"))
27+
.add_system(
28+
print_components_readonly
29+
.system()
30+
.label("print_components_readonly")
31+
.after("print_components"),
32+
)
33+
.add_system(
34+
print_components_tuple
35+
.system()
36+
.after("print_components_readonly"),
37+
)
38+
.run();
39+
}
40+
41+
#[derive(Debug)]
42+
struct ComponentA;
43+
#[derive(Debug)]
44+
struct ComponentB;
45+
#[derive(Debug)]
46+
struct ComponentC;
47+
#[derive(Debug)]
48+
struct ComponentD;
49+
#[derive(Debug)]
50+
struct ComponentZ;
51+
52+
#[derive(Fetch)]
53+
struct MutQuery<'w, T: Component + Debug, P: Component + Debug> {
54+
entity: Entity,
55+
a: Mut<'w, ComponentA>,
56+
b: Option<Mut<'w, ComponentB>>,
57+
nested: NestedQuery<'w>,
58+
generic: GenericQuery<'w, T, P>,
59+
#[filter(QueryFilter<T, P>)]
60+
filter: bool,
61+
}
62+
63+
// If you want to declare a read-only query that uses nested `Fetch` structs, you need to
64+
// specify `readonly` attribute for the corresponding fields. This will generate static assertions
65+
// that those members implement `ReadOnlyFetch`.
66+
#[derive(Fetch)]
67+
struct ReadOnlyNumQuery<'w, T: Component, P: Component> {
68+
entity: Entity,
69+
a: &'w ComponentA,
70+
b: &'w ComponentB,
71+
#[readonly]
72+
nested: NestedQuery<'w>,
73+
#[readonly]
74+
generic: GenericQuery<'w, T, P>,
75+
#[filter(QueryFilter<T, P>)]
76+
filter: bool,
77+
}
78+
79+
#[derive(Fetch, Debug)]
80+
struct NestedQuery<'w> {
81+
c: &'w ComponentC,
82+
d: Option<&'w ComponentD>,
83+
}
84+
85+
#[derive(Fetch, Debug)]
86+
struct GenericQuery<'w, T: Component, P: Component> {
87+
generic: (&'w T, &'w P),
88+
}
89+
90+
#[derive(FilterFetch)]
91+
struct QueryFilter<T: Component, P: Component> {
92+
_c: With<ComponentC>,
93+
_d: With<ComponentD>,
94+
_or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
95+
_generic_tuple: (With<T>, With<P>),
96+
_tp: PhantomData<(T, P)>,
97+
}
98+
99+
fn spawn(mut commands: Commands) {
100+
commands
101+
.spawn()
102+
.insert(ComponentA)
103+
.insert(ComponentB)
104+
.insert(ComponentC)
105+
.insert(ComponentD);
106+
}
107+
108+
fn print_components(
109+
mut query: Query<MutQuery<ComponentC, ComponentD>, QueryFilter<ComponentC, ComponentD>>,
110+
) {
111+
println!("Print components:");
112+
for e in query.iter_mut() {
113+
println!("Entity: {:?}", e.entity);
114+
println!("A: {:?}", e.a);
115+
println!("B: {:?}", e.b);
116+
println!("Nested: {:?}", e.nested);
117+
println!("Generic: {:?}", e.generic);
118+
println!("Filter: {:?}", e.filter);
119+
}
120+
println!();
121+
}
122+
123+
fn print_components_readonly(
124+
query: Query<ReadOnlyNumQuery<ComponentC, ComponentD>, QueryFilter<ComponentC, ComponentD>>,
125+
) {
126+
println!("Print components (read-only):");
127+
for e in query.iter() {
128+
println!("Entity: {:?}", e.entity);
129+
println!("A: {:?}", e.a);
130+
println!("B: {:?}", e.b);
131+
println!("Nested: {:?}", e.nested);
132+
println!("Generic: {:?}", e.generic);
133+
println!("Filter: {:?}", e.filter);
134+
}
135+
println!();
136+
}
137+
138+
type NestedTupleQuery<'w> = (&'w ComponentC, &'w ComponentD);
139+
type GenericTupleQuery<'w, T, P> = (&'w T, &'w P);
140+
141+
fn print_components_tuple(
142+
query: Query<
143+
(
144+
Entity,
145+
&ComponentA,
146+
&ComponentB,
147+
NestedTupleQuery,
148+
GenericTupleQuery<ComponentC, ComponentD>,
149+
),
150+
(
151+
With<ComponentC>,
152+
With<ComponentD>,
153+
Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
154+
),
155+
>,
156+
) {
157+
println!("Print components (tuple):");
158+
for (entity, a, b, nested, (generic_c, generic_d)) in query.iter() {
159+
println!("Entity: {:?}", entity);
160+
println!("A: {:?}", a);
161+
println!("B: {:?}", b);
162+
println!("Nested: {:?} {:?}", nested.0, nested.1);
163+
println!("Generic: {:?} {:?}", generic_c, generic_d);
164+
}
165+
}

examples/ecs/fetch.rs

-93
This file was deleted.

0 commit comments

Comments
 (0)