Skip to content

Commit

Permalink
Update the example
Browse files Browse the repository at this point in the history
  • Loading branch information
mvlabat committed Aug 24, 2021
1 parent 7016a9a commit e33a2b0
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 98 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,12 @@ name = "component_change_detection"
path = "examples/ecs/component_change_detection.rs"

[[example]]
name = "event"
path = "examples/ecs/event.rs"
name = "custom_query_param"
path = "examples/ecs/custom_query_param.rs"

[[example]]
name = "fetch"
path = "examples/ecs/fetch.rs"
name = "event"
path = "examples/ecs/event.rs"

[[example]]
name = "fixed_timestep"
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ Example | File | Description
--- | --- | ---
`ecs_guide` | [`ecs/ecs_guide.rs`](./ecs/ecs_guide.rs) | Full guide to Bevy's ECS
`component_change_detection` | [`ecs/component_change_detection.rs`](./ecs/component_change_detection.rs) | Change detection on components
`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
`event` | [`ecs/event.rs`](./ecs/event.rs) | Illustrates event creation, activation, and reception
`fetch` | [`ecs/fetch.rs`](./ecs/fetch.rs) | Illustrates creating custom queries and query filters with `Fetch` and `FilterFetch`
`fixed_timestep` | [`ecs/fixed_timestep.rs`](./ecs/fixed_timestep.rs) | Shows how to create systems that run every fixed timestep, rather than every tick
`hierarchy` | [`ecs/hierarchy.rs`](./ecs/hierarchy.rs) | Creates a hierarchy of parents and children entities
`iter_combinations` | [`ecs/iter_combinations.rs`](./ecs/iter_combinations.rs) | Shows how to iterate over combinations of query results.
Expand Down
165 changes: 165 additions & 0 deletions examples/ecs/custom_query_param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
use bevy::{
ecs::{
component::Component,
query::{Fetch, FilterFetch},
},
prelude::*,
};
use std::{fmt::Debug, marker::PhantomData};

/// This examples illustrates the usage of `Fetch` and `FilterFetch` derive macros, that allow
/// defining custom query and filter types.
///
/// White regular tuple queries work great in most of simple scenarios, using custom queries
/// declared as named structs can bring the following advantages:
/// - They help to avoid destructuring or using `q.0, q.1, ...` access pattern
/// - Adding, removing components or changing items order with structs greatly reduces maintenance
/// burden, as you don't need to update statements that destructure tuples, care abort order
/// of elements, etc. Instead, you can just add or remove places where a certain element is used
/// - Named structs enable the composition pattern, that makes query types easier to re-use
/// - They allow to go over the limit of 15 components that exists for query tuples
///
/// For more details on the `Fetch` and `FilterFetch` derive macros, see their documentation.
fn main() {
App::new()
.add_startup_system(spawn)
.add_system(print_components.system().label("print_components"))
.add_system(
print_components_readonly
.system()
.label("print_components_readonly")
.after("print_components"),
)
.add_system(
print_components_tuple
.system()
.after("print_components_readonly"),
)
.run();
}

#[derive(Debug)]
struct ComponentA;
#[derive(Debug)]
struct ComponentB;
#[derive(Debug)]
struct ComponentC;
#[derive(Debug)]
struct ComponentD;
#[derive(Debug)]
struct ComponentZ;

#[derive(Fetch)]
struct MutQuery<'w, T: Component + Debug, P: Component + Debug> {
entity: Entity,
a: Mut<'w, ComponentA>,
b: Option<Mut<'w, ComponentB>>,
nested: NestedQuery<'w>,
generic: GenericQuery<'w, T, P>,
#[filter(QueryFilter<T, P>)]
filter: bool,
}

// If you want to declare a read-only query that uses nested `Fetch` structs, you need to
// specify `readonly` attribute for the corresponding fields. This will generate static assertions
// that those members implement `ReadOnlyFetch`.
#[derive(Fetch)]
struct ReadOnlyNumQuery<'w, T: Component, P: Component> {
entity: Entity,
a: &'w ComponentA,
b: &'w ComponentB,
#[readonly]
nested: NestedQuery<'w>,
#[readonly]
generic: GenericQuery<'w, T, P>,
#[filter(QueryFilter<T, P>)]
filter: bool,
}

#[derive(Fetch, Debug)]
struct NestedQuery<'w> {
c: &'w ComponentC,
d: Option<&'w ComponentD>,
}

#[derive(Fetch, Debug)]
struct GenericQuery<'w, T: Component, P: Component> {
generic: (&'w T, &'w P),
}

#[derive(FilterFetch)]
struct QueryFilter<T: Component, P: Component> {
_c: With<ComponentC>,
_d: With<ComponentD>,
_or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
_generic_tuple: (With<T>, With<P>),
_tp: PhantomData<(T, P)>,
}

fn spawn(mut commands: Commands) {
commands
.spawn()
.insert(ComponentA)
.insert(ComponentB)
.insert(ComponentC)
.insert(ComponentD);
}

fn print_components(
mut query: Query<MutQuery<ComponentC, ComponentD>, QueryFilter<ComponentC, ComponentD>>,
) {
println!("Print components:");
for e in query.iter_mut() {
println!("Entity: {:?}", e.entity);
println!("A: {:?}", e.a);
println!("B: {:?}", e.b);
println!("Nested: {:?}", e.nested);
println!("Generic: {:?}", e.generic);
println!("Filter: {:?}", e.filter);
}
println!();
}

fn print_components_readonly(
query: Query<ReadOnlyNumQuery<ComponentC, ComponentD>, QueryFilter<ComponentC, ComponentD>>,
) {
println!("Print components (read-only):");
for e in query.iter() {
println!("Entity: {:?}", e.entity);
println!("A: {:?}", e.a);
println!("B: {:?}", e.b);
println!("Nested: {:?}", e.nested);
println!("Generic: {:?}", e.generic);
println!("Filter: {:?}", e.filter);
}
println!();
}

type NestedTupleQuery<'w> = (&'w ComponentC, &'w ComponentD);
type GenericTupleQuery<'w, T, P> = (&'w T, &'w P);

fn print_components_tuple(
query: Query<
(
Entity,
&ComponentA,
&ComponentB,
NestedTupleQuery,
GenericTupleQuery<ComponentC, ComponentD>,
),
(
With<ComponentC>,
With<ComponentD>,
Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
),
>,
) {
println!("Print components (tuple):");
for (entity, a, b, nested, (generic_c, generic_d)) in query.iter() {
println!("Entity: {:?}", entity);
println!("A: {:?}", a);
println!("B: {:?}", b);
println!("Nested: {:?} {:?}", nested.0, nested.1);
println!("Generic: {:?} {:?}", generic_c, generic_d);
}
}
93 changes: 0 additions & 93 deletions examples/ecs/fetch.rs

This file was deleted.

0 comments on commit e33a2b0

Please sign in to comment.