pub struct Query<'world, 'state, D, F = ()>where
D: QueryData,
F: QueryFilter,{ /* private fields */ }
Expand description
A system parameter that provides selective access to the Component
data stored in a World
.
Queries enable systems to access entity identifiers and components without requiring direct access to the World
.
Its iterators and getter methods return query items, which are types containing data related to an entity.
Query
is a generic data structure that accepts two type parameters:
D
(query data): The type of data fetched by the query, which will be returned as the query item. Only entities that match the requested data will generate an item. Must implement theQueryData
trait.F
(query filter): An optional set of conditions that determine whether query items should be kept or discarded. This defaults tounit
, which means no additional filters will be applied. Must implement theQueryFilter
trait.
§Similar parameters
Query
has few sibling SystemParam
s, which perform additional validation:
Single
- Exactly one matching query item.Option<Single>
- Zero or one matching query item.Populated
- At least one matching query item.
These parameters will prevent systems from running if their requirements are not met.
§System parameter declaration
A query should always be declared as a system parameter.
This section shows the most common idioms involving the declaration of Query
.
§Component access
You can fetch an entity’s component by specifying a reference to that component in the query’s data parameter:
// A component can be accessed by a shared reference...
fn immutable_query(query: Query<&ComponentA>) {
// ...
}
// ...or by a mutable reference.
fn mutable_query(query: Query<&mut ComponentA>) {
// ...
}
Note that components need to be behind a reference (&
or &mut
), or the query will not compile:
// This needs to be `&ComponentA` or `&mut ComponentA` in order to compile.
fn invalid_query(query: Query<ComponentA>) {
// ...
}
§Query filtering
Setting the query filter type parameter will ensure that each query item satisfies the given condition:
// `ComponentA` data will be accessed, but only for entities that also contain `ComponentB`.
fn filtered_query(query: Query<&ComponentA, With<ComponentB>>) {
// ...
}
Note that the filter is With<ComponentB>
, not With<&ComponentB>
. Unlike query data, With
does require components to be behind a reference.
§QueryData
or QueryFilter
tuples
Using tuple
s, each Query
type parameter can contain multiple elements.
In the following example two components are accessed simultaneously, and the query items are filtered on two conditions:
fn complex_query(
query: Query<(&mut ComponentA, &ComponentB), (With<ComponentC>, Without<ComponentD>)>
) {
// ...
}
Note that this currently only works on tuples with 15 or fewer items. You may nest tuples to get around this limit:
fn nested_query(
query: Query<(&ComponentA, &ComponentB, (&mut ComponentC, &mut ComponentD))>
) {
// ...
}
§Entity identifier access
You can access Entity
, the entity identifier, by including it in the query data parameter:
fn entity_id_query(query: Query<(Entity, &ComponentA)>) {
// ...
}
Be aware that Entity
is not a component, so it does not need to be behind a reference.
§Optional component access
A component can be made optional by wrapping it into an Option
. In the following example, a
query item will still be generated even if the queried entity does not contain ComponentB
.
When this is the case, Option<&ComponentB>
’s corresponding value will be None
.
// A queried items must contain `ComponentA`. If they also contain `ComponentB`, its value will
// be fetched as well.
fn optional_component_query(query: Query<(&ComponentA, Option<&ComponentB>)>) {
// ...
}
Optional components can hurt performance in some cases, so please read the performance
section to learn more about them. Additionally, if you need to declare several optional
components, you may be interested in using AnyOf
.
§Disjoint queries
A system cannot contain two queries that break Rust’s mutability rules, or else it will panic
when initialized. This can often be fixed with the Without
filter, which makes the queries
disjoint.
In the following example, the two queries can mutably access the same &mut Health
component
if an entity has both the Player
and Enemy
components. Bevy will catch this and panic,
however, instead of breaking Rust’s mutability rules:
fn randomize_health(
player_query: Query<&mut Health, With<Player>>,
enemy_query: Query<&mut Health, With<Enemy>>,
) {
// ...
}
Adding a Without
filter will disjoint the queries. In the following example, any entity
that has both the Player
and Enemy
components will be excluded from both queries:
fn randomize_health(
player_query: Query<&mut Health, (With<Player>, Without<Enemy>)>,
enemy_query: Query<&mut Health, (With<Enemy>, Without<Player>)>,
) {
// ...
}
An alternative solution to this problem would be to wrap the conflicting queries in
ParamSet
.
§Whole Entity Access
EntityRef
can be used in a query to gain read-only access to all components of an entity.
This is useful when dynamically fetching components instead of baking them into the query type.
fn all_components_query(query: Query<(EntityRef, &ComponentA)>) {
// ...
}
As EntityRef
can read any component on an entity, a query using it will conflict with any
mutable component access.
// `EntityRef` provides read access to *all* components on an entity. When combined with
// `&mut ComponentA` in the same query, it creates a conflict because `EntityRef` could read
// `&ComponentA` while `&mut ComponentA` attempts to modify it - violating Rust's borrowing
// rules.
fn invalid_query(query: Query<(EntityRef, &mut ComponentA)>) {
// ...
}
It is strongly advised to couple EntityRef
queries with the use of either With
/
Without
filters or ParamSet
s. Not only does this improve the performance and
parallelization of the system, but it enables systems to gain mutable access to other
components:
// The first query only reads entities that have `ComponentA`, while the second query only
// modifies entities that *don't* have `ComponentA`. Because neither query will access the same
// entity, this system does not conflict.
fn disjoint_query(
query_a: Query<EntityRef, With<ComponentA>>,
query_b: Query<&mut ComponentB, Without<ComponentA>>,
) {
// ...
}
The fundamental rule: EntityRef
’s ability to read all components means it can never
coexist with mutable access. With
/ Without
filters can guarantee this by keeping the
queries on completely separate entities.
§Accessing query items
The following table summarizes the behavior of safe methods that can be used to get query items:
Query methods | Effect |
---|---|
iter [_mut ] | Returns an iterator over all query items. |
iter[_mut]().for_each() ,par_iter [_mut ] | Runs a specified function for each query item. |
iter_many [_unique ][_mut ] | Iterates over query items that match a list of entities. |
iter_combinations [_mut ] | Iterates over all combinations of query items. |
single [_mut ] | Returns a single query item if only one exists. |
get [_mut ] | Returns the query item for a specified entity. |
get_many [_unique ][_mut ] | Returns all query items that match a list of entities. |
There are two methods for each type of query operation: immutable and mutable (ending with _mut
).
When using immutable methods, the query items returned are of type ROQueryItem
, a read-only version of the query item.
In this circumstance, every mutable reference in the query fetch type parameter is substituted by a shared reference.
§Performance
Creating a Query
is a low-cost constant operation. Iterating it, on the other hand, fetches
data from the world and generates items, which can have a significant computational cost.
Two systems cannot be executed in parallel if both access the same component type where at least one of the accesses is mutable. Because of this, it is recommended for queries to only fetch mutable access to components when necessary, since immutable access can be parallelized.
Query filters (With
/ Without
) can improve performance because they narrow the kinds of
entities that can be fetched. Systems that access fewer kinds of entities are more likely to be
parallelized by the scheduler.
On the other hand, be careful using optional components (Option<&ComponentA>
) and
EntityRef
because they broaden the amount of entities kinds that can be accessed. This is
especially true of a query that only fetches optional components or EntityRef
, as the
query would iterate over all entities in the world.
There are two types of component storage types: Table
and SparseSet
. Table
offers
fast iteration speeds, but slower insertion and removal speeds. SparseSet
is the opposite:
it offers fast component insertion and removal speeds, but slower iteration speeds.
The following table compares the computational complexity of the various methods and operations, where:
- n is the number of entities that match the query.
- r is the number of elements in a combination.
- k is the number of involved entities in the operation.
- a is the number of archetypes in the world.
- C is the binomial coefficient, used to count combinations. nCr is read as “n choose r” and is equivalent to the number of distinct unordered subsets of r elements that can be taken from a set of n elements.
Query operation | Computational complexity |
---|---|
iter [_mut ] | O(n) |
iter[_mut]().for_each() ,par_iter [_mut ] | O(n) |
iter_many [_mut ] | O(k) |
iter_combinations [_mut ] | O(nCr) |
single [_mut ] | O(a) |
get [_mut ] | O(1) |
get_many | O(k) |
get_many_mut | O(k2) |
Archetype-based filtering (With , Without , Or ) | O(a) |
Change detection filtering (Added , Changed ) | O(a + n) |
§Iterator::for_each
The for_each
methods appear to be generally faster than for
-loops when run on worlds with
high archetype fragmentation, and may enable additional optimizations like autovectorization. It
is strongly advised to only use Iterator::for_each
if it tangibly improves performance.
Always profile or benchmark before and after the change!
fn system(query: Query<&ComponentA>) {
// This may result in better performance...
query.iter().for_each(|component| {
// ...
});
// ...than this. Always benchmark to validate the difference!
for component in query.iter() {
// ...
}
}
Implementations§
Source§impl<'w, 's, D, F> Query<'w, 's, D, F>where
D: QueryData,
F: QueryFilter,
impl<'w, 's, D, F> Query<'w, 's, D, F>where
D: QueryData,
F: QueryFilter,
If the given entity
contains the R
Relationship
component, returns the
target entity of that relationship.
Sourcepub fn relationship_sources<S>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'w
pub fn relationship_sources<S>( &'w self, entity: Entity, ) -> impl Iterator<Item = Entity> + 'w
If the given entity
contains the S
RelationshipTarget
component, returns the
source entities stored on that component.
Sourcepub fn root_ancestor<R>(&'w self, entity: Entity) -> Entity
pub fn root_ancestor<R>(&'w self, entity: Entity) -> Entity
Recursively walks up the tree defined by the given R
Relationship
until
there are no more related entities, returning the “root entity” of the relationship hierarchy.
§Warning
For relationship graphs that contain loops, this could loop infinitely. If your relationship is not a tree (like Bevy’s hierarchy), be sure to stop if you encounter a duplicate entity.
Sourcepub fn iter_leaves<S>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'wwhere
S: RelationshipTarget,
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
<<S as RelationshipTarget>::Collection as RelationshipSourceCollection>::SourceIter<'w>: DoubleEndedIterator,
pub fn iter_leaves<S>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'wwhere
S: RelationshipTarget,
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
<<S as RelationshipTarget>::Collection as RelationshipSourceCollection>::SourceIter<'w>: DoubleEndedIterator,
Iterates all “leaf entities” as defined by the RelationshipTarget
hierarchy.
§Warning
For relationship graphs that contain loops, this could loop infinitely. If your relationship is not a tree (like Bevy’s hierarchy), be sure to stop if you encounter a duplicate entity.
Sourcepub fn iter_siblings<R>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'wwhere
R: Relationship,
<D as QueryData>::ReadOnly: QueryData<Item<'w> = (Option<&'w R>, Option<&'w <R as Relationship>::RelationshipTarget>)>,
pub fn iter_siblings<R>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'wwhere
R: Relationship,
<D as QueryData>::ReadOnly: QueryData<Item<'w> = (Option<&'w R>, Option<&'w <R as Relationship>::RelationshipTarget>)>,
Iterates all sibling entities that also have the R
Relationship
with the same target entity.
Sourcepub fn iter_descendants<S>(
&'w self,
entity: Entity,
) -> DescendantIter<'w, 's, D, F, S> ⓘ
pub fn iter_descendants<S>( &'w self, entity: Entity, ) -> DescendantIter<'w, 's, D, F, S> ⓘ
Iterates all descendant entities as defined by the given entity
’s RelationshipTarget
and their recursive
RelationshipTarget
.
§Warning
For relationship graphs that contain loops, this could loop infinitely. If your relationship is not a tree (like Bevy’s hierarchy), be sure to stop if you encounter a duplicate entity.
Examples found in repository?
57fn move_scene_entities(
58 time: Res<Time>,
59 moved_scene: Query<Entity, With<MovedScene>>,
60 children: Query<&Children>,
61 mut transforms: Query<&mut Transform>,
62) {
63 for moved_scene_entity in &moved_scene {
64 let mut offset = 0.;
65 for entity in children.iter_descendants(moved_scene_entity) {
66 if let Ok(mut transform) = transforms.get_mut(entity) {
67 transform.translation = Vec3::new(
68 offset * ops::sin(time.elapsed_secs()) / 20.,
69 0.,
70 ops::cos(time.elapsed_secs()) / 20.,
71 );
72 offset += 0.5;
73 }
74 }
75 }
76}
More examples
282 fn pause_animation_frame(
283 trigger: Trigger<SceneInstanceReady>,
284 children: Query<&Children>,
285 mut commands: Commands,
286 animation: Res<Animation>,
287 mut players: Query<(Entity, &mut AnimationPlayer)>,
288 ) {
289 for child in children.iter_descendants(trigger.target()) {
290 if let Ok((entity, mut player)) = players.get_mut(child) {
291 let mut transitions = AnimationTransitions::new();
292 transitions
293 .play(&mut player, animation.animation, Duration::ZERO)
294 .seek_to(0.5)
295 .pause();
296
297 commands
298 .entity(entity)
299 .insert(AnimationGraphHandle(animation.graph.clone()))
300 .insert(transitions);
301 }
302 }
303 }
59fn change_material(
60 trigger: Trigger<SceneInstanceReady>,
61 mut commands: Commands,
62 children: Query<&Children>,
63 color_override: Query<&ColorOverride>,
64 mesh_materials: Query<&MeshMaterial3d<StandardMaterial>>,
65 mut asset_materials: ResMut<Assets<StandardMaterial>>,
66) {
67 // Get the `ColorOverride` of the entity, if it does not have a color override, skip
68 let Ok(color_override) = color_override.get(trigger.target()) else {
69 return;
70 };
71
72 // Iterate over all children recursively
73 for descendants in children.iter_descendants(trigger.target()) {
74 // Get the material of the descendant
75 if let Some(material) = mesh_materials
76 .get(descendants)
77 .ok()
78 .and_then(|id| asset_materials.get_mut(id.id()))
79 {
80 // Create a copy of the material and override base color
81 // If you intend on creating multiple models with the same tint, it
82 // is best to cache the handle somewhere, as having multiple materials
83 // that are identical is expensive
84 let mut new_material = material.clone();
85 new_material.base_color = color_override.0;
86
87 // Override `MeshMaterial3d` with new material
88 commands
89 .entity(descendants)
90 .insert(MeshMaterial3d(asset_materials.add(new_material)));
91 }
92 }
93}
64fn play_animation_when_ready(
65 trigger: Trigger<SceneInstanceReady>,
66 mut commands: Commands,
67 children: Query<&Children>,
68 animations_to_play: Query<&AnimationToPlay>,
69 mut players: Query<&mut AnimationPlayer>,
70) {
71 // The entity we spawned in `setup_mesh_and_animation` is the trigger's target.
72 // Start by finding the AnimationToPlay component we added to that entity.
73 if let Ok(animation_to_play) = animations_to_play.get(trigger.target()) {
74 // The SceneRoot component will have spawned the scene as a hierarchy
75 // of entities parented to our entity. Since the asset contained a skinned
76 // mesh and animations, it will also have spawned an animation player
77 // component. Search our entity's descendants to find the animation player.
78 for child in children.iter_descendants(trigger.target()) {
79 if let Ok(mut player) = players.get_mut(child) {
80 // Tell the animation player to start the animation and keep
81 // repeating it.
82 //
83 // If you want to try stopping and switching animations, see the
84 // `animated_mesh_control.rs` example.
85 player.play(animation_to_play.index).repeat();
86
87 // Add the animation graph. This only needs to be done once to
88 // connect the animation player to the mesh.
89 commands
90 .entity(child)
91 .insert(AnimationGraphHandle(animation_to_play.graph_handle.clone()));
92 }
93 }
94 }
95}
Sourcepub fn iter_descendants_depth_first<S>(
&'w self,
entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F, S> ⓘwhere
S: RelationshipTarget,
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
<<S as RelationshipTarget>::Collection as RelationshipSourceCollection>::SourceIter<'w>: DoubleEndedIterator,
pub fn iter_descendants_depth_first<S>(
&'w self,
entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F, S> ⓘwhere
S: RelationshipTarget,
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
<<S as RelationshipTarget>::Collection as RelationshipSourceCollection>::SourceIter<'w>: DoubleEndedIterator,
Iterates all descendant entities as defined by the given entity
’s RelationshipTarget
and their recursive
RelationshipTarget
in depth-first order.
§Warning
For relationship graphs that contain loops, this could loop infinitely. If your relationship is not a tree (like Bevy’s hierarchy), be sure to stop if you encounter a duplicate entity.
Sourcepub fn iter_ancestors<R>(
&'w self,
entity: Entity,
) -> AncestorIter<'w, 's, D, F, R> ⓘ
pub fn iter_ancestors<R>( &'w self, entity: Entity, ) -> AncestorIter<'w, 's, D, F, R> ⓘ
Iterates all ancestors of the given entity
as defined by the R
Relationship
.
§Warning
For relationship graphs that contain loops, this could loop infinitely. If your relationship is not a tree (like Bevy’s hierarchy), be sure to stop if you encounter a duplicate entity.
Examples found in repository?
152 fn check_for_cycles(
153 // We want to check every entity for cycles
154 query_to_check: Query<Entity, With<Targeting>>,
155 // Fetch the names for easier debugging.
156 name_query: Query<&Name>,
157 // The targeting_query allows us to traverse the relationship graph.
158 targeting_query: Query<&Targeting>,
159 ) -> Result<(), TargetingCycle> {
160 for initial_entity in query_to_check.iter() {
161 let mut visited = EntityHashSet::new();
162 let mut targeting_name = name_query.get(initial_entity).unwrap().clone();
163 println!("Checking for cycles starting at {targeting_name}",);
164
165 // There's all sorts of methods like this; check the `Query` docs for more!
166 // This would also be easy to do by just manually checking the `Targeting` component,
167 // and calling `query.get(targeted_entity)` on the entity that it targets in a loop.
168 for targeting in targeting_query.iter_ancestors(initial_entity) {
169 let target_name = name_query.get(targeting).unwrap();
170 println!("{targeting_name} is targeting {target_name}",);
171 targeting_name = target_name.clone();
172
173 if !visited.insert(targeting) {
174 return Err(TargetingCycle {
175 initial_entity,
176 visited,
177 });
178 }
179 }
180 }
181
182 // If we've checked all the entities and haven't found a cycle, we're good!
183 Ok(())
184 }
Source§impl<'w, 's, D, F> Query<'w, 's, D, F>where
D: QueryData,
F: QueryFilter,
impl<'w, 's, D, F> Query<'w, 's, D, F>where
D: QueryData,
F: QueryFilter,
Sourcepub fn as_readonly(&self) -> Query<'_, 's, <D as QueryData>::ReadOnly, F>
pub fn as_readonly(&self) -> Query<'_, 's, <D as QueryData>::ReadOnly, F>
Returns another Query
from this that fetches the read-only version of the query items.
For example, Query<(&mut D1, &D2, &mut D3), With<F>>
will become Query<(&D1, &D2, &D3), With<F>>
.
This can be useful when working around the borrow checker,
or reusing functionality between systems via functions that accept query types.
§See also
into_readonly
for a version that consumes the Query
to return one with the full 'world
lifetime.
Sourcepub fn into_readonly(self) -> Query<'w, 's, <D as QueryData>::ReadOnly, F>
pub fn into_readonly(self) -> Query<'w, 's, <D as QueryData>::ReadOnly, F>
Returns another Query
from this that fetches the read-only version of the query items.
For example, Query<(&mut D1, &D2, &mut D3), With<F>>
will become Query<(&D1, &D2, &D3), With<F>>
.
This can be useful when working around the borrow checker,
or reusing functionality between systems via functions that accept query types.
§See also
as_readonly
for a version that borrows the Query
instead of consuming it.
Sourcepub fn reborrow(&mut self) -> Query<'_, 's, D, F>
pub fn reborrow(&mut self) -> Query<'_, 's, D, F>
Returns a new Query
reborrowing the access from this one. The current query will be unusable
while the new one exists.
§Example
For example this allows to call other methods or other systems that require an owned Query
without
completely giving up ownership of it.
fn helper_system(query: Query<&ComponentA>) { /* ... */}
fn system(mut query: Query<&ComponentA>) {
helper_system(query.reborrow());
// Can still use query here:
for component in &query {
// ...
}
}
Sourcepub unsafe fn reborrow_unsafe(&self) -> Query<'_, 's, D, F>
pub unsafe fn reborrow_unsafe(&self) -> Query<'_, 's, D, F>
Returns a new Query
reborrowing the access from this one.
The current query will still be usable while the new one exists, but must not be used in a way that violates aliasing.
§Safety
This function makes it possible to violate Rust’s aliasing guarantees. You must make sure this call does not result in a mutable or shared reference to a component with a mutable reference.
§See also
reborrow
for the safe versions.
Sourcepub fn iter(&self) -> QueryIter<'_, 's, <D as QueryData>::ReadOnly, F> ⓘ
pub fn iter(&self) -> QueryIter<'_, 's, <D as QueryData>::ReadOnly, F> ⓘ
Returns an Iterator
over the read-only query items.
This iterator is always guaranteed to return results from each matching entity once and only once. Iteration order is not guaranteed.
§Example
Here, the report_names_system
iterates over the Player
component of every entity that contains it:
fn report_names_system(query: Query<&Player>) {
for player in &query {
println!("Say hello to {}!", player.name);
}
}
§See also
iter_mut
for mutable query items.
Examples found in repository?
More examples
324fn image_copy_extract(mut commands: Commands, image_copiers: Extract<Query<&ImageCopier>>) {
325 commands.insert_resource(ImageCopiers(
326 image_copiers.iter().cloned().collect::<Vec<ImageCopier>>(),
327 ));
328}
329
330/// `RenderGraph` label for `ImageCopyDriver`
331#[derive(Debug, PartialEq, Eq, Clone, Hash, RenderLabel)]
332struct ImageCopy;
333
334/// `RenderGraph` node
335#[derive(Default)]
336struct ImageCopyDriver;
337
338// Copies image content from render target to buffer
339impl render_graph::Node for ImageCopyDriver {
340 fn run(
341 &self,
342 _graph: &mut RenderGraphContext,
343 render_context: &mut RenderContext,
344 world: &World,
345 ) -> Result<(), NodeRunError> {
346 let image_copiers = world.get_resource::<ImageCopiers>().unwrap();
347 let gpu_images = world
348 .get_resource::<RenderAssets<bevy::render::texture::GpuImage>>()
349 .unwrap();
350
351 for image_copier in image_copiers.iter() {
352 if !image_copier.enabled() {
353 continue;
354 }
355
356 let src_image = gpu_images.get(&image_copier.src_image).unwrap();
357
358 let mut encoder = render_context
359 .render_device()
360 .create_command_encoder(&CommandEncoderDescriptor::default());
361
362 let block_dimensions = src_image.texture_format.block_dimensions();
363 let block_size = src_image.texture_format.block_copy_size(None).unwrap();
364
365 // Calculating correct size of image row because
366 // copy_texture_to_buffer can copy image only by rows aligned wgpu::COPY_BYTES_PER_ROW_ALIGNMENT
367 // That's why image in buffer can be little bit wider
368 // This should be taken into account at copy from buffer stage
369 let padded_bytes_per_row = RenderDevice::align_copy_bytes_per_row(
370 (src_image.size.width as usize / block_dimensions.0 as usize) * block_size as usize,
371 );
372
373 encoder.copy_texture_to_buffer(
374 src_image.texture.as_image_copy(),
375 TexelCopyBufferInfo {
376 buffer: &image_copier.buffer,
377 layout: TexelCopyBufferLayout {
378 offset: 0,
379 bytes_per_row: Some(
380 std::num::NonZero::<u32>::new(padded_bytes_per_row as u32)
381 .unwrap()
382 .into(),
383 ),
384 rows_per_image: None,
385 },
386 },
387 src_image.size,
388 );
389
390 let render_queue = world.get_resource::<RenderQueue>().unwrap();
391 render_queue.submit(std::iter::once(encoder.finish()));
392 }
393
394 Ok(())
395 }
396}
397
398/// runs in render world after Render stage to send image from buffer via channel (receiver is in main world)
399fn receive_image_from_buffer(
400 image_copiers: Res<ImageCopiers>,
401 render_device: Res<RenderDevice>,
402 sender: Res<RenderWorldSender>,
403) {
404 for image_copier in image_copiers.0.iter() {
405 if !image_copier.enabled() {
406 continue;
407 }
408
409 // Finally time to get our data back from the gpu.
410 // First we get a buffer slice which represents a chunk of the buffer (which we
411 // can't access yet).
412 // We want the whole thing so use unbounded range.
413 let buffer_slice = image_copier.buffer.slice(..);
414
415 // Now things get complicated. WebGPU, for safety reasons, only allows either the GPU
416 // or CPU to access a buffer's contents at a time. We need to "map" the buffer which means
417 // flipping ownership of the buffer over to the CPU and making access legal. We do this
418 // with `BufferSlice::map_async`.
419 //
420 // The problem is that map_async is not an async function so we can't await it. What
421 // we need to do instead is pass in a closure that will be executed when the slice is
422 // either mapped or the mapping has failed.
423 //
424 // The problem with this is that we don't have a reliable way to wait in the main
425 // code for the buffer to be mapped and even worse, calling get_mapped_range or
426 // get_mapped_range_mut prematurely will cause a panic, not return an error.
427 //
428 // Using channels solves this as awaiting the receiving of a message from
429 // the passed closure will force the outside code to wait. It also doesn't hurt
430 // if the closure finishes before the outside code catches up as the message is
431 // buffered and receiving will just pick that up.
432 //
433 // It may also be worth noting that although on native, the usage of asynchronous
434 // channels is wholly unnecessary, for the sake of portability to Wasm
435 // we'll use async channels that work on both native and Wasm.
436
437 let (s, r) = crossbeam_channel::bounded(1);
438
439 // Maps the buffer so it can be read on the cpu
440 buffer_slice.map_async(MapMode::Read, move |r| match r {
441 // This will execute once the gpu is ready, so after the call to poll()
442 Ok(r) => s.send(r).expect("Failed to send map update"),
443 Err(err) => panic!("Failed to map buffer {err}"),
444 });
445
446 // In order for the mapping to be completed, one of three things must happen.
447 // One of those can be calling `Device::poll`. This isn't necessary on the web as devices
448 // are polled automatically but natively, we need to make sure this happens manually.
449 // `Maintain::Wait` will cause the thread to wait on native but not on WebGpu.
450
451 // This blocks until the gpu is done executing everything
452 render_device.poll(Maintain::wait()).panic_on_timeout();
453
454 // This blocks until the buffer is mapped
455 r.recv().expect("Failed to receive the map_async message");
456
457 // This could fail on app exit, if Main world clears resources (including receiver) while Render world still renders
458 let _ = sender.send(buffer_slice.get_mapped_range().to_vec());
459
460 // We need to make sure all `BufferView`'s are dropped before we do what we're about
461 // to do.
462 // Unmap so that we can copy to the staging buffer in the next iteration.
463 image_copier.buffer.unmap();
464 }
465}
466
467/// CPU-side image for saving
468#[derive(Component, Deref, DerefMut)]
469struct ImageToSave(Handle<Image>);
470
471// Takes from channel image content sent from render world and saves it to disk
472fn update(
473 images_to_save: Query<&ImageToSave>,
474 receiver: Res<MainWorldReceiver>,
475 mut images: ResMut<Assets<Image>>,
476 mut scene_controller: ResMut<SceneController>,
477 mut app_exit_writer: EventWriter<AppExit>,
478 mut file_number: Local<u32>,
479) {
480 if let SceneState::Render(n) = scene_controller.state {
481 if n < 1 {
482 // We don't want to block the main world on this,
483 // so we use try_recv which attempts to receive without blocking
484 let mut image_data = Vec::new();
485 while let Ok(data) = receiver.try_recv() {
486 // image generation could be faster than saving to fs,
487 // that's why use only last of them
488 image_data = data;
489 }
490 if !image_data.is_empty() {
491 for image in images_to_save.iter() {
492 // Fill correct data from channel to image
493 let img_bytes = images.get_mut(image.id()).unwrap();
494
495 // We need to ensure that this works regardless of the image dimensions
496 // If the image became wider when copying from the texture to the buffer,
497 // then the data is reduced to its original size when copying from the buffer to the image.
498 let row_bytes = img_bytes.width() as usize
499 * img_bytes.texture_descriptor.format.pixel_size();
500 let aligned_row_bytes = RenderDevice::align_copy_bytes_per_row(row_bytes);
501 if row_bytes == aligned_row_bytes {
502 img_bytes.data.as_mut().unwrap().clone_from(&image_data);
503 } else {
504 // shrink data to original image size
505 img_bytes.data = Some(
506 image_data
507 .chunks(aligned_row_bytes)
508 .take(img_bytes.height() as usize)
509 .flat_map(|row| &row[..row_bytes.min(row.len())])
510 .cloned()
511 .collect(),
512 );
513 }
514
515 // Create RGBA Image Buffer
516 let img = match img_bytes.clone().try_into_dynamic() {
517 Ok(img) => img.to_rgba8(),
518 Err(e) => panic!("Failed to create image buffer {e:?}"),
519 };
520
521 // Prepare directory for images, test_images in bevy folder is used here for example
522 // You should choose the path depending on your needs
523 let images_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test_images");
524 info!("Saving image to: {images_dir:?}");
525 std::fs::create_dir_all(&images_dir).unwrap();
526
527 // Choose filename starting from 000.png
528 let image_path = images_dir.join(format!("{:03}.png", file_number.deref()));
529 *file_number.deref_mut() += 1;
530
531 // Finally saving image to file, this heavy blocking operation is kept here
532 // for example simplicity, but in real app you should move it to a separate task
533 if let Err(e) = img.save(image_path) {
534 panic!("Failed to save image: {e}");
535 };
536 }
537 if scene_controller.single_image {
538 app_exit_writer.write(AppExit::Success);
539 }
540 }
541 } else {
542 // clears channel for skipped frames
543 while receiver.try_recv().is_ok() {}
544 scene_controller.state = SceneState::Render(n - 1);
545 }
546 }
547}
145fn print_light_count(time: Res<Time>, mut timer: Local<PrintingTimer>, lights: Query<&PointLight>) {
146 timer.0.tick(time.delta());
147
148 if timer.0.just_finished() {
149 info!("Lights: {}", lights.iter().len());
150 }
151}
152
153struct LogVisibleLights;
154
155impl Plugin for LogVisibleLights {
156 fn build(&self, app: &mut App) {
157 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
158 return;
159 };
160
161 render_app.add_systems(Render, print_visible_light_count.in_set(RenderSet::Prepare));
162 }
163}
164
165// System for printing the number of meshes on every tick of the timer
166fn print_visible_light_count(
167 time: Res<Time>,
168 mut timer: Local<PrintingTimer>,
169 visible: Query<&ExtractedPointLight>,
170 global_light_meta: Res<GlobalClusterableObjectMeta>,
171) {
172 timer.0.tick(time.delta());
173
174 if timer.0.just_finished() {
175 info!(
176 "Visible Lights: {}, Rendered Lights: {}",
177 visible.iter().len(),
178 global_light_meta.entity_to_index.len()
179 );
180 }
181}
- examples/games/loading_screen.rs
- examples/ecs/observer_propagation.rs
- examples/ecs/removal_detection.rs
- examples/stress_tests/many_cubes.rs
- examples/asset/multi_asset_sync.rs
- examples/picking/mesh_picking.rs
- examples/3d/animated_material.rs
- examples/3d/reflection_probes.rs
- examples/window/screenshot.rs
- examples/3d/depth_of_field.rs
- examples/stress_tests/many_materials.rs
- examples/3d/specular_tint.rs
- examples/asset/asset_decompression.rs
- examples/stress_tests/many_text2d.rs
- examples/3d/visibility_range.rs
- examples/stress_tests/many_foxes.rs
- examples/ecs/entity_disabling.rs
- examples/3d/anisotropy.rs
- examples/math/sampling_primitives.rs
- examples/3d/irradiance_volumes.rs
- examples/math/bounding_2d.rs
- examples/3d/shadow_caster_receiver.rs
- examples/ecs/fallible_params.rs
- examples/ui/directional_navigation.rs
- examples/math/render_primitives.rs
- examples/math/custom_primitives.rs
- examples/3d/load_gltf_extras.rs
- examples/animation/animation_graph.rs
- examples/ecs/relationships.rs
- examples/3d/mixed_lighting.rs
- examples/3d/query_gltf_primitives.rs
- examples/audio/soundtrack.rs
- examples/3d/lightmaps.rs
- examples/stress_tests/many_components.rs
- examples/ui/size_constraints.rs
- examples/3d/color_grading.rs
- examples/3d/occlusion_culling.rs
- examples/window/monitor_info.rs
- examples/shader/custom_phase_item.rs
- examples/shader/specialized_mesh_pipeline.rs
Sourcepub fn iter_mut(&mut self) -> QueryIter<'_, 's, D, F> ⓘ
pub fn iter_mut(&mut self) -> QueryIter<'_, 's, D, F> ⓘ
Returns an Iterator
over the query items.
This iterator is always guaranteed to return results from each matching entity once and only once. Iteration order is not guaranteed.
§Example
Here, the gravity_system
updates the Velocity
component of every entity that contains it:
fn gravity_system(mut query: Query<&mut Velocity>) {
const DELTA: f32 = 1.0 / 60.0;
for mut velocity in &mut query {
velocity.y -= 9.8 * DELTA;
}
}
§See also
iter
for read-only query items.
Examples found in repository?
305fn update_text(mut text_query: Query<&mut Text>, app_status: Res<AppStatus>) {
306 for mut text in text_query.iter_mut() {
307 *text = app_status.create_text();
308 }
309}
310
311impl AppStatus {
312 // Constructs the help text at the bottom of the screen based on the
313 // application status.
314 fn create_text(&self) -> Text {
315 let irradiance_volume_help_text = if self.irradiance_volume_present {
316 DISABLE_IRRADIANCE_VOLUME_HELP_TEXT
317 } else {
318 ENABLE_IRRADIANCE_VOLUME_HELP_TEXT
319 };
320
321 let voxels_help_text = if self.voxels_visible {
322 HIDE_VOXELS_HELP_TEXT
323 } else {
324 SHOW_VOXELS_HELP_TEXT
325 };
326
327 let rotation_help_text = if self.rotating {
328 STOP_ROTATION_HELP_TEXT
329 } else {
330 START_ROTATION_HELP_TEXT
331 };
332
333 let switch_mesh_help_text = match self.model {
334 ExampleModel::Sphere => SWITCH_TO_FOX_HELP_TEXT,
335 ExampleModel::Fox => SWITCH_TO_SPHERE_HELP_TEXT,
336 };
337
338 format!(
339 "{CLICK_TO_MOVE_HELP_TEXT}\n\
340 {voxels_help_text}\n\
341 {irradiance_volume_help_text}\n\
342 {rotation_help_text}\n\
343 {switch_mesh_help_text}"
344 )
345 .into()
346 }
347}
348
349// Rotates the camera a bit every frame.
350fn rotate_camera(
351 mut camera_query: Query<&mut Transform, With<Camera3d>>,
352 time: Res<Time>,
353 app_status: Res<AppStatus>,
354) {
355 if !app_status.rotating {
356 return;
357 }
358
359 for mut transform in camera_query.iter_mut() {
360 transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
361 .rotate(transform.translation.xz())
362 .extend(transform.translation.y)
363 .xzy();
364 transform.look_at(Vec3::ZERO, Vec3::Y);
365 }
366}
367
368// Toggles between the unskinned sphere model and the skinned fox model if the
369// user requests it.
370fn change_main_object(
371 keyboard: Res<ButtonInput<KeyCode>>,
372 mut app_status: ResMut<AppStatus>,
373 mut sphere_query: Query<&mut Visibility, (With<MainObject>, With<Mesh3d>, Without<SceneRoot>)>,
374 mut fox_query: Query<&mut Visibility, (With<MainObject>, With<SceneRoot>)>,
375) {
376 if !keyboard.just_pressed(KeyCode::Tab) {
377 return;
378 }
379 let Some(mut sphere_visibility) = sphere_query.iter_mut().next() else {
380 return;
381 };
382 let Some(mut fox_visibility) = fox_query.iter_mut().next() else {
383 return;
384 };
385
386 match app_status.model {
387 ExampleModel::Sphere => {
388 *sphere_visibility = Visibility::Hidden;
389 *fox_visibility = Visibility::Visible;
390 app_status.model = ExampleModel::Fox;
391 }
392 ExampleModel::Fox => {
393 *sphere_visibility = Visibility::Visible;
394 *fox_visibility = Visibility::Hidden;
395 app_status.model = ExampleModel::Sphere;
396 }
397 }
398}
399
400impl Default for AppStatus {
401 fn default() -> Self {
402 Self {
403 irradiance_volume_present: true,
404 rotating: true,
405 model: ExampleModel::Sphere,
406 voxels_visible: false,
407 }
408 }
409}
410
411// Turns on and off the irradiance volume as requested by the user.
412fn toggle_irradiance_volumes(
413 mut commands: Commands,
414 keyboard: Res<ButtonInput<KeyCode>>,
415 light_probe_query: Query<Entity, With<LightProbe>>,
416 mut app_status: ResMut<AppStatus>,
417 assets: Res<ExampleAssets>,
418 mut ambient_light: ResMut<AmbientLight>,
419) {
420 if !keyboard.just_pressed(KeyCode::Space) {
421 return;
422 };
423
424 let Some(light_probe) = light_probe_query.iter().next() else {
425 return;
426 };
427
428 if app_status.irradiance_volume_present {
429 commands.entity(light_probe).remove::<IrradianceVolume>();
430 ambient_light.brightness = AMBIENT_LIGHT_BRIGHTNESS * IRRADIANCE_VOLUME_INTENSITY;
431 app_status.irradiance_volume_present = false;
432 } else {
433 commands.entity(light_probe).insert(IrradianceVolume {
434 voxels: assets.irradiance_volume.clone(),
435 intensity: IRRADIANCE_VOLUME_INTENSITY,
436 ..default()
437 });
438 ambient_light.brightness = 0.0;
439 app_status.irradiance_volume_present = true;
440 }
441}
442
443fn toggle_rotation(keyboard: Res<ButtonInput<KeyCode>>, mut app_status: ResMut<AppStatus>) {
444 if keyboard.just_pressed(KeyCode::Enter) {
445 app_status.rotating = !app_status.rotating;
446 }
447}
448
449// Handles clicks on the plane that reposition the object.
450fn handle_mouse_clicks(
451 buttons: Res<ButtonInput<MouseButton>>,
452 windows: Query<&Window, With<PrimaryWindow>>,
453 cameras: Query<(&Camera, &GlobalTransform)>,
454 mut main_objects: Query<&mut Transform, With<MainObject>>,
455) {
456 if !buttons.pressed(MouseButton::Left) {
457 return;
458 }
459 let Some(mouse_position) = windows.iter().next().and_then(Window::cursor_position) else {
460 return;
461 };
462 let Some((camera, camera_transform)) = cameras.iter().next() else {
463 return;
464 };
465
466 // Figure out where the user clicked on the plane.
467 let Ok(ray) = camera.viewport_to_world(camera_transform, mouse_position) else {
468 return;
469 };
470 let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) else {
471 return;
472 };
473 let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance;
474
475 // Move all the main objects.
476 for mut transform in main_objects.iter_mut() {
477 transform.translation = vec3(
478 plane_intersection.x,
479 transform.translation.y,
480 plane_intersection.z,
481 );
482 }
483}
484
485impl FromWorld for ExampleAssets {
486 fn from_world(world: &mut World) -> Self {
487 let fox_animation =
488 world.load_asset(GltfAssetLabel::Animation(1).from_asset("models/animated/Fox.glb"));
489 let (fox_animation_graph, fox_animation_node) =
490 AnimationGraph::from_clip(fox_animation.clone());
491
492 ExampleAssets {
493 main_sphere: world.add_asset(Sphere::default().mesh().uv(32, 18)),
494 fox: world.load_asset(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")),
495 main_sphere_material: world.add_asset(Color::from(SILVER)),
496 main_scene: world.load_asset(
497 GltfAssetLabel::Scene(0)
498 .from_asset("models/IrradianceVolumeExample/IrradianceVolumeExample.glb"),
499 ),
500 irradiance_volume: world.load_asset("irradiance_volumes/Example.vxgi.ktx2"),
501 fox_animation_graph: world.add_asset(fox_animation_graph),
502 fox_animation_node,
503 voxel_cube: world.add_asset(Cuboid::default()),
504 // Just use a specular map for the skybox since it's not too blurry.
505 // In reality you wouldn't do this--you'd use a real skybox texture--but
506 // reusing the textures like this saves space in the Bevy repository.
507 skybox: world.load_asset("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"),
508 }
509 }
510}
511
512// Plays the animation on the fox.
513fn play_animations(
514 mut commands: Commands,
515 assets: Res<ExampleAssets>,
516 mut players: Query<(Entity, &mut AnimationPlayer), Without<AnimationGraphHandle>>,
517) {
518 for (entity, mut player) in players.iter_mut() {
519 commands
520 .entity(entity)
521 .insert(AnimationGraphHandle(assets.fox_animation_graph.clone()));
522 player.play(assets.fox_animation_node).repeat();
523 }
524}
525
526fn create_cubes(
527 image_assets: Res<Assets<Image>>,
528 mut commands: Commands,
529 irradiance_volumes: Query<(&IrradianceVolume, &GlobalTransform)>,
530 voxel_cube_parents: Query<Entity, With<VoxelCubeParent>>,
531 voxel_cubes: Query<Entity, With<VoxelCube>>,
532 example_assets: Res<ExampleAssets>,
533 mut voxel_visualization_material_assets: ResMut<Assets<VoxelVisualizationMaterial>>,
534) {
535 // If voxel cubes have already been spawned, don't do anything.
536 if !voxel_cubes.is_empty() {
537 return;
538 }
539
540 let Some(voxel_cube_parent) = voxel_cube_parents.iter().next() else {
541 return;
542 };
543
544 for (irradiance_volume, global_transform) in irradiance_volumes.iter() {
545 let Some(image) = image_assets.get(&irradiance_volume.voxels) else {
546 continue;
547 };
548
549 let resolution = image.texture_descriptor.size;
550
551 let voxel_cube_material = voxel_visualization_material_assets.add(ExtendedMaterial {
552 base: StandardMaterial::from(Color::from(RED)),
553 extension: VoxelVisualizationExtension {
554 irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo {
555 world_from_voxel: VOXEL_FROM_WORLD.inverse(),
556 voxel_from_world: VOXEL_FROM_WORLD,
557 resolution: uvec3(
558 resolution.width,
559 resolution.height,
560 resolution.depth_or_array_layers,
561 ),
562 intensity: IRRADIANCE_VOLUME_INTENSITY,
563 },
564 },
565 });
566
567 let scale = vec3(
568 1.0 / resolution.width as f32,
569 1.0 / resolution.height as f32,
570 1.0 / resolution.depth_or_array_layers as f32,
571 );
572
573 // Spawn a cube for each voxel.
574 for z in 0..resolution.depth_or_array_layers {
575 for y in 0..resolution.height {
576 for x in 0..resolution.width {
577 let uvw = (uvec3(x, y, z).as_vec3() + 0.5) * scale - 0.5;
578 let pos = global_transform.transform_point(uvw);
579 let voxel_cube = commands
580 .spawn((
581 Mesh3d(example_assets.voxel_cube.clone()),
582 MeshMaterial3d(voxel_cube_material.clone()),
583 Transform::from_scale(Vec3::splat(VOXEL_CUBE_SCALE))
584 .with_translation(pos),
585 ))
586 .insert(VoxelCube)
587 .insert(NotShadowCaster)
588 .id();
589
590 commands.entity(voxel_cube_parent).add_child(voxel_cube);
591 }
592 }
593 }
594 }
595}
596
597// Draws a gizmo showing the bounds of the irradiance volume.
598fn draw_gizmo(
599 mut gizmos: Gizmos,
600 irradiance_volume_query: Query<&GlobalTransform, With<IrradianceVolume>>,
601 app_status: Res<AppStatus>,
602) {
603 if app_status.voxels_visible {
604 for transform in irradiance_volume_query.iter() {
605 gizmos.cuboid(*transform, GIZMO_COLOR);
606 }
607 }
608}
609
610// Handles a request from the user to toggle the voxel visibility on and off.
611fn toggle_voxel_visibility(
612 keyboard: Res<ButtonInput<KeyCode>>,
613 mut app_status: ResMut<AppStatus>,
614 mut voxel_cube_parent_query: Query<&mut Visibility, With<VoxelCubeParent>>,
615) {
616 if !keyboard.just_pressed(KeyCode::Backspace) {
617 return;
618 }
619
620 app_status.voxels_visible = !app_status.voxels_visible;
621
622 for mut visibility in voxel_cube_parent_query.iter_mut() {
623 *visibility = if app_status.voxels_visible {
624 Visibility::Visible
625 } else {
626 Visibility::Hidden
627 };
628 }
629}
More examples
236fn update_text(mut text_query: Query<&mut Text>, app_status: Res<AppStatus>) {
237 for mut text in text_query.iter_mut() {
238 *text = app_status.create_text();
239 }
240}
241
242impl TryFrom<u32> for ReflectionMode {
243 type Error = ();
244
245 fn try_from(value: u32) -> Result<Self, Self::Error> {
246 match value {
247 0 => Ok(ReflectionMode::None),
248 1 => Ok(ReflectionMode::EnvironmentMap),
249 2 => Ok(ReflectionMode::ReflectionProbe),
250 _ => Err(()),
251 }
252 }
253}
254
255impl Display for ReflectionMode {
256 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
257 let text = match *self {
258 ReflectionMode::None => "No reflections",
259 ReflectionMode::EnvironmentMap => "Environment map",
260 ReflectionMode::ReflectionProbe => "Reflection probe",
261 };
262 formatter.write_str(text)
263 }
264}
265
266impl AppStatus {
267 // Constructs the help text at the bottom of the screen based on the
268 // application status.
269 fn create_text(&self) -> Text {
270 let rotation_help_text = if self.rotating {
271 STOP_ROTATION_HELP_TEXT
272 } else {
273 START_ROTATION_HELP_TEXT
274 };
275
276 format!(
277 "{}\n{}\n{}",
278 self.reflection_mode, rotation_help_text, REFLECTION_MODE_HELP_TEXT
279 )
280 .into()
281 }
282}
283
284// Creates the world environment map light, used as a fallback if no reflection
285// probe is applicable to a mesh.
286fn create_camera_environment_map_light(cubemaps: &Cubemaps) -> EnvironmentMapLight {
287 EnvironmentMapLight {
288 diffuse_map: cubemaps.diffuse.clone(),
289 specular_map: cubemaps.specular_environment_map.clone(),
290 intensity: 5000.0,
291 ..default()
292 }
293}
294
295// Rotates the camera a bit every frame.
296fn rotate_camera(
297 time: Res<Time>,
298 mut camera_query: Query<&mut Transform, With<Camera3d>>,
299 app_status: Res<AppStatus>,
300) {
301 if !app_status.rotating {
302 return;
303 }
304
305 for mut transform in camera_query.iter_mut() {
306 transform.translation = Vec2::from_angle(time.delta_secs() * PI / 5.0)
307 .rotate(transform.translation.xz())
308 .extend(transform.translation.y)
309 .xzy();
310 transform.look_at(Vec3::ZERO, Vec3::Y);
311 }
312}
39fn spin(time: Res<Time>, mut query: Query<&mut Transform, With<Spin>>) {
40 for mut transform in query.iter_mut() {
41 transform.rotation *= Quat::from_rotation_z(time.delta_secs() / 5.);
42 }
43}
44
45#[derive(States, Default, Debug, Hash, PartialEq, Eq, Clone, Copy)]
46enum Test {
47 AabbSweep,
48 CircleSweep,
49 #[default]
50 RayCast,
51 AabbCast,
52 CircleCast,
53}
54
55fn update_test_state(
56 keycode: Res<ButtonInput<KeyCode>>,
57 cur_state: Res<State<Test>>,
58 mut state: ResMut<NextState<Test>>,
59) {
60 if !keycode.just_pressed(KeyCode::Space) {
61 return;
62 }
63
64 use Test::*;
65 let next = match **cur_state {
66 AabbSweep => CircleSweep,
67 CircleSweep => RayCast,
68 RayCast => AabbCast,
69 AabbCast => CircleCast,
70 CircleCast => AabbSweep,
71 };
72 state.set(next);
73}
74
75fn update_text(mut text: Single<&mut Text>, cur_state: Res<State<Test>>) {
76 if !cur_state.is_changed() {
77 return;
78 }
79
80 text.clear();
81
82 text.push_str("Intersection test:\n");
83 use Test::*;
84 for &test in &[AabbSweep, CircleSweep, RayCast, AabbCast, CircleCast] {
85 let s = if **cur_state == test { "*" } else { " " };
86 text.push_str(&format!(" {s} {test:?} {s}\n"));
87 }
88 text.push_str("\nPress space to cycle");
89}
90
91#[derive(Component)]
92enum Shape {
93 Rectangle(Rectangle),
94 Circle(Circle),
95 Triangle(Triangle2d),
96 Line(Segment2d),
97 Capsule(Capsule2d),
98 Polygon(RegularPolygon),
99}
100
101fn render_shapes(mut gizmos: Gizmos, query: Query<(&Shape, &Transform)>) {
102 let color = GRAY;
103 for (shape, transform) in query.iter() {
104 let translation = transform.translation.xy();
105 let rotation = transform.rotation.to_euler(EulerRot::YXZ).2;
106 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
107 match shape {
108 Shape::Rectangle(r) => {
109 gizmos.primitive_2d(r, isometry, color);
110 }
111 Shape::Circle(c) => {
112 gizmos.primitive_2d(c, isometry, color);
113 }
114 Shape::Triangle(t) => {
115 gizmos.primitive_2d(t, isometry, color);
116 }
117 Shape::Line(l) => {
118 gizmos.primitive_2d(l, isometry, color);
119 }
120 Shape::Capsule(c) => {
121 gizmos.primitive_2d(c, isometry, color);
122 }
123 Shape::Polygon(p) => {
124 gizmos.primitive_2d(p, isometry, color);
125 }
126 }
127 }
128}
129
130#[derive(Component)]
131enum DesiredVolume {
132 Aabb,
133 Circle,
134}
135
136#[derive(Component, Debug)]
137enum CurrentVolume {
138 Aabb(Aabb2d),
139 Circle(BoundingCircle),
140}
141
142fn update_volumes(
143 mut commands: Commands,
144 query: Query<
145 (Entity, &DesiredVolume, &Shape, &Transform),
146 Or<(Changed<DesiredVolume>, Changed<Shape>, Changed<Transform>)>,
147 >,
148) {
149 for (entity, desired_volume, shape, transform) in query.iter() {
150 let translation = transform.translation.xy();
151 let rotation = transform.rotation.to_euler(EulerRot::YXZ).2;
152 let isometry = Isometry2d::new(translation, Rot2::radians(rotation));
153 match desired_volume {
154 DesiredVolume::Aabb => {
155 let aabb = match shape {
156 Shape::Rectangle(r) => r.aabb_2d(isometry),
157 Shape::Circle(c) => c.aabb_2d(isometry),
158 Shape::Triangle(t) => t.aabb_2d(isometry),
159 Shape::Line(l) => l.aabb_2d(isometry),
160 Shape::Capsule(c) => c.aabb_2d(isometry),
161 Shape::Polygon(p) => p.aabb_2d(isometry),
162 };
163 commands.entity(entity).insert(CurrentVolume::Aabb(aabb));
164 }
165 DesiredVolume::Circle => {
166 let circle = match shape {
167 Shape::Rectangle(r) => r.bounding_circle(isometry),
168 Shape::Circle(c) => c.bounding_circle(isometry),
169 Shape::Triangle(t) => t.bounding_circle(isometry),
170 Shape::Line(l) => l.bounding_circle(isometry),
171 Shape::Capsule(c) => c.bounding_circle(isometry),
172 Shape::Polygon(p) => p.bounding_circle(isometry),
173 };
174 commands
175 .entity(entity)
176 .insert(CurrentVolume::Circle(circle));
177 }
178 }
179 }
180}
181
182fn render_volumes(mut gizmos: Gizmos, query: Query<(&CurrentVolume, &Intersects)>) {
183 for (volume, intersects) in query.iter() {
184 let color = if **intersects { AQUA } else { ORANGE_RED };
185 match volume {
186 CurrentVolume::Aabb(a) => {
187 gizmos.rect_2d(a.center(), a.half_size() * 2., color);
188 }
189 CurrentVolume::Circle(c) => {
190 gizmos.circle_2d(c.center(), c.radius(), color);
191 }
192 }
193 }
194}
195
196#[derive(Component, Deref, DerefMut, Default)]
197struct Intersects(bool);
198
199const OFFSET_X: f32 = 125.;
200const OFFSET_Y: f32 = 75.;
201
202fn setup(mut commands: Commands) {
203 commands.spawn(Camera2d);
204
205 commands.spawn((
206 Transform::from_xyz(-OFFSET_X, OFFSET_Y, 0.),
207 Shape::Circle(Circle::new(45.)),
208 DesiredVolume::Aabb,
209 Intersects::default(),
210 ));
211
212 commands.spawn((
213 Transform::from_xyz(0., OFFSET_Y, 0.),
214 Shape::Rectangle(Rectangle::new(80., 80.)),
215 Spin,
216 DesiredVolume::Circle,
217 Intersects::default(),
218 ));
219
220 commands.spawn((
221 Transform::from_xyz(OFFSET_X, OFFSET_Y, 0.),
222 Shape::Triangle(Triangle2d::new(
223 Vec2::new(-40., -40.),
224 Vec2::new(-20., 40.),
225 Vec2::new(40., 50.),
226 )),
227 Spin,
228 DesiredVolume::Aabb,
229 Intersects::default(),
230 ));
231
232 commands.spawn((
233 Transform::from_xyz(-OFFSET_X, -OFFSET_Y, 0.),
234 Shape::Line(Segment2d::from_direction_and_length(
235 Dir2::from_xy(1., 0.3).unwrap(),
236 90.,
237 )),
238 Spin,
239 DesiredVolume::Circle,
240 Intersects::default(),
241 ));
242
243 commands.spawn((
244 Transform::from_xyz(0., -OFFSET_Y, 0.),
245 Shape::Capsule(Capsule2d::new(25., 50.)),
246 Spin,
247 DesiredVolume::Aabb,
248 Intersects::default(),
249 ));
250
251 commands.spawn((
252 Transform::from_xyz(OFFSET_X, -OFFSET_Y, 0.),
253 Shape::Polygon(RegularPolygon::new(50., 6)),
254 Spin,
255 DesiredVolume::Circle,
256 Intersects::default(),
257 ));
258
259 commands.spawn((
260 Text::default(),
261 Node {
262 position_type: PositionType::Absolute,
263 top: Val::Px(12.0),
264 left: Val::Px(12.0),
265 ..default()
266 },
267 ));
268}
269
270fn draw_filled_circle(gizmos: &mut Gizmos, position: Vec2, color: Srgba) {
271 for r in [1., 2., 3.] {
272 gizmos.circle_2d(position, r, color);
273 }
274}
275
276fn draw_ray(gizmos: &mut Gizmos, ray: &RayCast2d) {
277 gizmos.line_2d(
278 ray.ray.origin,
279 ray.ray.origin + *ray.ray.direction * ray.max,
280 WHITE,
281 );
282 draw_filled_circle(gizmos, ray.ray.origin, FUCHSIA);
283}
284
285fn get_and_draw_ray(gizmos: &mut Gizmos, time: &Time) -> RayCast2d {
286 let ray = Vec2::new(ops::cos(time.elapsed_secs()), ops::sin(time.elapsed_secs()));
287 let dist = 150. + ops::sin(0.5 * time.elapsed_secs()).abs() * 500.;
288
289 let aabb_ray = Ray2d {
290 origin: ray * 250.,
291 direction: Dir2::new_unchecked(-ray),
292 };
293 let ray_cast = RayCast2d::from_ray(aabb_ray, dist - 20.);
294
295 draw_ray(gizmos, &ray_cast);
296 ray_cast
297}
298
299fn ray_cast_system(
300 mut gizmos: Gizmos,
301 time: Res<Time>,
302 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
303) {
304 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
305
306 for (volume, mut intersects) in volumes.iter_mut() {
307 let toi = match volume {
308 CurrentVolume::Aabb(a) => ray_cast.aabb_intersection_at(a),
309 CurrentVolume::Circle(c) => ray_cast.circle_intersection_at(c),
310 };
311 **intersects = toi.is_some();
312 if let Some(toi) = toi {
313 draw_filled_circle(
314 &mut gizmos,
315 ray_cast.ray.origin + *ray_cast.ray.direction * toi,
316 LIME,
317 );
318 }
319 }
320}
321
322fn aabb_cast_system(
323 mut gizmos: Gizmos,
324 time: Res<Time>,
325 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
326) {
327 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
328 let aabb_cast = AabbCast2d {
329 aabb: Aabb2d::new(Vec2::ZERO, Vec2::splat(15.)),
330 ray: ray_cast,
331 };
332
333 for (volume, mut intersects) in volumes.iter_mut() {
334 let toi = match *volume {
335 CurrentVolume::Aabb(a) => aabb_cast.aabb_collision_at(a),
336 CurrentVolume::Circle(_) => None,
337 };
338
339 **intersects = toi.is_some();
340 if let Some(toi) = toi {
341 gizmos.rect_2d(
342 aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi,
343 aabb_cast.aabb.half_size() * 2.,
344 LIME,
345 );
346 }
347 }
348}
349
350fn bounding_circle_cast_system(
351 mut gizmos: Gizmos,
352 time: Res<Time>,
353 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
354) {
355 let ray_cast = get_and_draw_ray(&mut gizmos, &time);
356 let circle_cast = BoundingCircleCast {
357 circle: BoundingCircle::new(Vec2::ZERO, 15.),
358 ray: ray_cast,
359 };
360
361 for (volume, mut intersects) in volumes.iter_mut() {
362 let toi = match *volume {
363 CurrentVolume::Aabb(_) => None,
364 CurrentVolume::Circle(c) => circle_cast.circle_collision_at(c),
365 };
366
367 **intersects = toi.is_some();
368 if let Some(toi) = toi {
369 gizmos.circle_2d(
370 circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi,
371 circle_cast.circle.radius(),
372 LIME,
373 );
374 }
375 }
376}
377
378fn get_intersection_position(time: &Time) -> Vec2 {
379 let x = ops::cos(0.8 * time.elapsed_secs()) * 250.;
380 let y = ops::sin(0.4 * time.elapsed_secs()) * 100.;
381 Vec2::new(x, y)
382}
383
384fn aabb_intersection_system(
385 mut gizmos: Gizmos,
386 time: Res<Time>,
387 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
388) {
389 let center = get_intersection_position(&time);
390 let aabb = Aabb2d::new(center, Vec2::splat(50.));
391 gizmos.rect_2d(center, aabb.half_size() * 2., YELLOW);
392
393 for (volume, mut intersects) in volumes.iter_mut() {
394 let hit = match volume {
395 CurrentVolume::Aabb(a) => aabb.intersects(a),
396 CurrentVolume::Circle(c) => aabb.intersects(c),
397 };
398
399 **intersects = hit;
400 }
401}
402
403fn circle_intersection_system(
404 mut gizmos: Gizmos,
405 time: Res<Time>,
406 mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
407) {
408 let center = get_intersection_position(&time);
409 let circle = BoundingCircle::new(center, 50.);
410 gizmos.circle_2d(center, circle.radius(), YELLOW);
411
412 for (volume, mut intersects) in volumes.iter_mut() {
413 let hit = match volume {
414 CurrentVolume::Aabb(a) => circle.intersects(a),
415 CurrentVolume::Circle(c) => circle.intersects(c),
416 };
417
418 **intersects = hit;
419 }
420}
- examples/stress_tests/many_cameras_lights.rs
- examples/shader/shader_prepass.rs
- examples/stress_tests/text_pipeline.rs
- examples/math/custom_primitives.rs
- examples/3d/bloom_3d.rs
- examples/3d/ssr.rs
- examples/3d/specular_tint.rs
- examples/shader/automatic_instancing.rs
- examples/3d/fog_volumes.rs
- examples/ui/directional_navigation.rs
- examples/3d/parallax_mapping.rs
- examples/3d/anisotropy.rs
- examples/3d/volumetric_fog.rs
- examples/math/cubic_splines.rs
- examples/3d/rotate_environment_map.rs
- examples/3d/camera_sub_view.rs
- examples/3d/deferred_rendering.rs
- examples/input/text_input.rs
- examples/ui/overflow.rs
- examples/3d/clearcoat.rs
- examples/3d/color_grading.rs
- examples/3d/../helpers/widgets.rs
- examples/audio/soundtrack.rs
- examples/time/virtual_time.rs
- examples/3d/spotlight.rs
- examples/ui/tab_navigation.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/animation/animation_graph.rs
- examples/shader/shader_material_wesl.rs
- examples/ui/viewport_debug.rs
- examples/audio/spatial_audio_2d.rs
- examples/3d/tonemapping.rs
- examples/audio/spatial_audio_3d.rs
- examples/math/render_primitives.rs
- examples/window/window_drag_move.rs
- examples/3d/depth_of_field.rs
- examples/3d/pcss.rs
- examples/ui/display_and_visibility.rs
- examples/movement/physics_in_fixed_timestep.rs
- examples/testbed/full_ui.rs
- examples/3d/visibility_range.rs
- examples/3d/mixed_lighting.rs
- examples/animation/animation_masks.rs
- examples/games/alien_cake_addict.rs
- examples/camera/2d_screen_shake.rs
- examples/stress_tests/many_buttons.rs
- examples/ui/size_constraints.rs
- examples/math/sampling_primitives.rs
Sourcepub fn iter_combinations<const K: usize>(
&self,
) -> QueryCombinationIter<'_, 's, <D as QueryData>::ReadOnly, F, K> ⓘ
pub fn iter_combinations<const K: usize>( &self, ) -> QueryCombinationIter<'_, 's, <D as QueryData>::ReadOnly, F, K> ⓘ
Returns a QueryCombinationIter
over all combinations of K
read-only query items without repetition.
This iterator is always guaranteed to return results from each unique pair of matching entities. Iteration order is not guaranteed.
§Example
fn some_system(query: Query<&ComponentA>) {
for [a1, a2] in query.iter_combinations() {
// ...
}
}
§See also
iter_combinations_mut
for mutable query item combinations.iter_combinations_inner
for mutable query item combinations with the full'world
lifetime.
Sourcepub fn iter_combinations_mut<const K: usize>(
&mut self,
) -> QueryCombinationIter<'_, 's, D, F, K> ⓘ
pub fn iter_combinations_mut<const K: usize>( &mut self, ) -> QueryCombinationIter<'_, 's, D, F, K> ⓘ
Returns a QueryCombinationIter
over all combinations of K
query items without repetition.
This iterator is always guaranteed to return results from each unique pair of matching entities. Iteration order is not guaranteed.
§Example
fn some_system(mut query: Query<&mut ComponentA>) {
let mut combinations = query.iter_combinations_mut();
while let Some([mut a1, mut a2]) = combinations.fetch_next() {
// mutably access components data
}
}
§See also
iter_combinations
for read-only query item combinations.iter_combinations_inner
for mutable query item combinations with the full'world
lifetime.
Examples found in repository?
122fn interact_bodies(mut query: Query<(&Mass, &GlobalTransform, &mut Acceleration)>) {
123 let mut iter = query.iter_combinations_mut();
124 while let Some([(Mass(m1), transform1, mut acc1), (Mass(m2), transform2, mut acc2)]) =
125 iter.fetch_next()
126 {
127 let delta = transform2.translation() - transform1.translation();
128 let distance_sq: f32 = delta.length_squared();
129
130 let f = GRAVITY_CONSTANT / distance_sq;
131 let force_unit_mass = delta * f;
132 acc1.0 += force_unit_mass * *m2;
133 acc2.0 -= force_unit_mass * *m1;
134 }
135}
Sourcepub fn iter_combinations_inner<const K: usize>(
self,
) -> QueryCombinationIter<'w, 's, D, F, K> ⓘ
pub fn iter_combinations_inner<const K: usize>( self, ) -> QueryCombinationIter<'w, 's, D, F, K> ⓘ
Returns a QueryCombinationIter
over all combinations of K
query items without repetition.
This consumes the Query
to return results with the actual “inner” world lifetime.
This iterator is always guaranteed to return results from each unique pair of matching entities. Iteration order is not guaranteed.
§Example
fn some_system(query: Query<&mut ComponentA>) {
let mut combinations = query.iter_combinations_inner();
while let Some([mut a1, mut a2]) = combinations.fetch_next() {
// mutably access components data
}
}
§See also
iter_combinations
for read-only query item combinations.iter_combinations_mut
for mutable query item combinations.
Sourcepub fn iter_many<EntityList>(
&self,
entities: EntityList,
) -> QueryManyIter<'_, 's, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::IntoIter> ⓘ
pub fn iter_many<EntityList>( &self, entities: EntityList, ) -> QueryManyIter<'_, 's, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::IntoIter> ⓘ
Returns an Iterator
over the read-only query items generated from an Entity
list.
Items are returned in the order of the list of entities, and may not be unique if the input doesn’t guarantee uniqueness. Entities that don’t match the query are skipped.
§Example
// A component containing an entity list.
#[derive(Component)]
struct Friends {
list: Vec<Entity>,
}
fn system(
friends_query: Query<&Friends>,
counter_query: Query<&Counter>,
) {
for friends in &friends_query {
for counter in counter_query.iter_many(&friends.list) {
println!("Friend's counter: {}", counter.value);
}
}
}
§See also
iter_many_mut
to get mutable query items.iter_many_inner
to get mutable query items with the full'world
lifetime.
Sourcepub fn iter_many_mut<EntityList>(
&mut self,
entities: EntityList,
) -> QueryManyIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘ
pub fn iter_many_mut<EntityList>( &mut self, entities: EntityList, ) -> QueryManyIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘ
Returns an iterator over the query items generated from an Entity
list.
Items are returned in the order of the list of entities, and may not be unique if the input doesn’t guarantee uniqueness. Entities that don’t match the query are skipped.
§Examples
#[derive(Component)]
struct Counter {
value: i32
}
#[derive(Component)]
struct Friends {
list: Vec<Entity>,
}
fn system(
friends_query: Query<&Friends>,
mut counter_query: Query<&mut Counter>,
) {
for friends in &friends_query {
let mut iter = counter_query.iter_many_mut(&friends.list);
while let Some(mut counter) = iter.fetch_next() {
println!("Friend's counter: {}", counter.value);
counter.value += 1;
}
}
}
§See also
iter_many
to get read-only query items.iter_many_inner
to get mutable query items with the full'world
lifetime.
Examples found in repository?
418fn update_ui(
419 mut text_query: Query<&mut Text>,
420 mut background_query: Query<&mut Node, Without<Text>>,
421 container_query: Query<(&Children, &ClipNode)>,
422 animation_weights_query: Query<&ExampleAnimationWeights, Changed<ExampleAnimationWeights>>,
423) {
424 for animation_weights in animation_weights_query.iter() {
425 for (children, clip_node) in &container_query {
426 // Draw the green background color to visually indicate the weight.
427 let mut bg_iter = background_query.iter_many_mut(children);
428 if let Some(mut node) = bg_iter.fetch_next() {
429 // All nodes are the same width, so `NODE_RECTS[0]` is as good as any other.
430 node.width =
431 Val::Px(NODE_RECTS[0].width * animation_weights.weights[clip_node.index]);
432 }
433
434 // Update the node labels with the current weights.
435 let mut text_iter = text_query.iter_many_mut(children);
436 if let Some(mut text) = text_iter.fetch_next() {
437 **text = format!(
438 "{}\n{:.2}",
439 clip_node.text, animation_weights.weights[clip_node.index]
440 );
441 }
442 }
443 }
444}
Sourcepub fn iter_many_inner<EntityList>(
self,
entities: EntityList,
) -> QueryManyIter<'w, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘ
pub fn iter_many_inner<EntityList>( self, entities: EntityList, ) -> QueryManyIter<'w, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘ
Returns an iterator over the query items generated from an Entity
list.
This consumes the Query
to return results with the actual “inner” world lifetime.
Items are returned in the order of the list of entities, and may not be unique if the input doesn’t guarantee uniqueness. Entities that don’t match the query are skipped.
§See also
iter_many
to get read-only query items.iter_many_mut
to get mutable query items.
Sourcepub fn iter_many_unique<EntityList>(
&self,
entities: EntityList,
) -> QueryManyUniqueIter<'_, 's, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
pub fn iter_many_unique<EntityList>(
&self,
entities: EntityList,
) -> QueryManyUniqueIter<'_, 's, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
Returns an Iterator
over the unique read-only query items generated from an EntitySet
.
Items are returned in the order of the list of entities. Entities that don’t match the query are skipped.
§Example
// `Friends` ensures that it only lists unique entities.
#[derive(Component)]
struct Friends {
unique_list: Vec<Entity>,
}
impl<'a> IntoIterator for &'a Friends {
type Item = &'a Entity;
type IntoIter = UniqueEntityIter<slice::Iter<'a, Entity>>;
fn into_iter(self) -> Self::IntoIter {
// SAFETY: `Friends` ensures that it unique_list contains only unique entities.
unsafe { UniqueEntityIter::from_iterator_unchecked(self.unique_list.iter()) }
}
}
fn system(
friends_query: Query<&Friends>,
counter_query: Query<&Counter>,
) {
for friends in &friends_query {
for counter in counter_query.iter_many_unique(friends) {
println!("Friend's counter: {:?}", counter.value);
}
}
}
§See also
iter_many_unique_mut
to get mutable query items.iter_many_unique_inner
to get with the actual “inner” world lifetime.
Sourcepub fn iter_many_unique_mut<EntityList>(
&mut self,
entities: EntityList,
) -> QueryManyUniqueIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
pub fn iter_many_unique_mut<EntityList>(
&mut self,
entities: EntityList,
) -> QueryManyUniqueIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
Returns an iterator over the unique query items generated from an EntitySet
.
Items are returned in the order of the list of entities. Entities that don’t match the query are skipped.
§Examples
#[derive(Component)]
struct Counter {
value: i32
}
// `Friends` ensures that it only lists unique entities.
#[derive(Component)]
struct Friends {
unique_list: Vec<Entity>,
}
impl<'a> IntoIterator for &'a Friends {
type Item = &'a Entity;
type IntoIter = UniqueEntityIter<slice::Iter<'a, Entity>>;
fn into_iter(self) -> Self::IntoIter {
// SAFETY: `Friends` ensures that it unique_list contains only unique entities.
unsafe { UniqueEntityIter::from_iterator_unchecked(self.unique_list.iter()) }
}
}
fn system(
friends_query: Query<&Friends>,
mut counter_query: Query<&mut Counter>,
) {
for friends in &friends_query {
for mut counter in counter_query.iter_many_unique_mut(friends) {
println!("Friend's counter: {:?}", counter.value);
counter.value += 1;
}
}
}
§See also
iter_many_unique
to get read-only query items.iter_many_unique_inner
to get with the actual “inner” world lifetime.
Sourcepub fn iter_many_unique_inner<EntityList>(
self,
entities: EntityList,
) -> QueryManyUniqueIter<'w, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
pub fn iter_many_unique_inner<EntityList>(
self,
entities: EntityList,
) -> QueryManyUniqueIter<'w, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
Returns an iterator over the unique query items generated from an EntitySet
.
This consumes the Query
to return results with the actual “inner” world lifetime.
Items are returned in the order of the list of entities. Entities that don’t match the query are skipped.
§Examples
#[derive(Component)]
struct Counter {
value: i32
}
// `Friends` ensures that it only lists unique entities.
#[derive(Component)]
struct Friends {
unique_list: Vec<Entity>,
}
impl<'a> IntoIterator for &'a Friends {
type Item = &'a Entity;
type IntoIter = UniqueEntityIter<slice::Iter<'a, Entity>>;
fn into_iter(self) -> Self::IntoIter {
// SAFETY: `Friends` ensures that it unique_list contains only unique entities.
unsafe { UniqueEntityIter::from_iterator_unchecked(self.unique_list.iter()) }
}
}
fn system(
friends_query: Query<&Friends>,
mut counter_query: Query<&mut Counter>,
) {
let friends = friends_query.single().unwrap();
for mut counter in counter_query.iter_many_unique_inner(friends) {
println!("Friend's counter: {:?}", counter.value);
counter.value += 1;
}
}
§See also
iter_many_unique
to get read-only query items.iter_many_unique_mut
to get mutable query items.
Sourcepub unsafe fn iter_unsafe(&self) -> QueryIter<'_, 's, D, F> ⓘ
pub unsafe fn iter_unsafe(&self) -> QueryIter<'_, 's, D, F> ⓘ
Returns an Iterator
over the query items.
This iterator is always guaranteed to return results from each matching entity once and only once. Iteration order is not guaranteed.
§Safety
This function makes it possible to violate Rust’s aliasing guarantees. You must make sure this call does not result in multiple mutable references to the same component.
§See also
Sourcepub unsafe fn iter_combinations_unsafe<const K: usize>(
&self,
) -> QueryCombinationIter<'_, 's, D, F, K> ⓘ
pub unsafe fn iter_combinations_unsafe<const K: usize>( &self, ) -> QueryCombinationIter<'_, 's, D, F, K> ⓘ
Iterates over all possible combinations of K
query items without repetition.
This iterator is always guaranteed to return results from each unique pair of matching entities. Iteration order is not guaranteed.
§Safety
This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component.
§See also
iter_combinations
anditer_combinations_mut
for the safe versions.
Sourcepub unsafe fn iter_many_unsafe<EntityList>(
&self,
entities: EntityList,
) -> QueryManyIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘ
pub unsafe fn iter_many_unsafe<EntityList>( &self, entities: EntityList, ) -> QueryManyIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘ
Returns an Iterator
over the query items generated from an Entity
list.
Items are returned in the order of the list of entities, and may not be unique if the input doesnn’t guarantee uniqueness. Entities that don’t match the query are skipped.
§Safety
This allows aliased mutability and does not check for entity uniqueness.
You must make sure this call does not result in multiple mutable references to the same component.
Particular care must be taken when collecting the data (rather than iterating over it one item at a time) such as via Iterator::collect
.
§See also
iter_many_mut
to safely access the query items.
Sourcepub unsafe fn iter_many_unique_unsafe<EntityList>(
&self,
entities: EntityList,
) -> QueryManyUniqueIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
pub unsafe fn iter_many_unique_unsafe<EntityList>(
&self,
entities: EntityList,
) -> QueryManyUniqueIter<'_, 's, D, F, <EntityList as IntoIterator>::IntoIter> ⓘwhere
EntityList: EntitySet,
Returns an Iterator
over the unique query items generated from an Entity
list.
Items are returned in the order of the list of entities. Entities that don’t match the query are skipped.
§Safety
This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component.
§See also
iter_many_unique
to get read-only query items.iter_many_unique_mut
to get mutable query items.iter_many_unique_inner
to get with the actual “inner” world lifetime.
Sourcepub fn par_iter(&self) -> QueryParIter<'_, '_, <D as QueryData>::ReadOnly, F>
pub fn par_iter(&self) -> QueryParIter<'_, '_, <D as QueryData>::ReadOnly, F>
Returns a parallel iterator over the query results for the given World
.
This parallel iterator is always guaranteed to return results from each matching entity once and only once. Iteration order and thread assignment is not guaranteed.
If the multithreaded
feature is disabled, iterating with this operates identically to Iterator::for_each
on QueryIter
.
This can only be called for read-only queries, see par_iter_mut
for write-queries.
Note that you must use the for_each
method to iterate over the
results, see par_iter_mut
for an example.
Sourcepub fn par_iter_mut(&mut self) -> QueryParIter<'_, '_, D, F>
pub fn par_iter_mut(&mut self) -> QueryParIter<'_, '_, D, F>
Returns a parallel iterator over the query results for the given World
.
This parallel iterator is always guaranteed to return results from each matching entity once and only once. Iteration order and thread assignment is not guaranteed.
If the multithreaded
feature is disabled, iterating with this operates identically to Iterator::for_each
on QueryIter
.
This can only be called for mutable queries, see par_iter
for read-only-queries.
§Example
Here, the gravity_system
updates the Velocity
component of every entity that contains it:
fn gravity_system(mut query: Query<&mut Velocity>) {
const DELTA: f32 = 1.0 / 60.0;
query.par_iter_mut().for_each(|mut velocity| {
velocity.y -= 9.8 * DELTA;
});
}
Examples found in repository?
28fn move_system(mut sprites: Query<(&mut Transform, &Velocity)>) {
29 // Compute the new location of each sprite in parallel on the
30 // ComputeTaskPool
31 //
32 // This example is only for demonstrative purposes. Using a
33 // ParallelIterator for an inexpensive operation like addition on only 128
34 // elements will not typically be faster than just using a normal Iterator.
35 // See the ParallelIterator documentation for more information on when
36 // to use or not use ParallelIterator over a normal Iterator.
37 sprites
38 .par_iter_mut()
39 .for_each(|(mut transform, velocity)| {
40 transform.translation += velocity.extend(0.0);
41 });
42}
43
44// Bounce sprites outside the window
45fn bounce_system(window: Query<&Window>, mut sprites: Query<(&Transform, &mut Velocity)>) {
46 let Ok(window) = window.single() else {
47 return;
48 };
49 let width = window.width();
50 let height = window.height();
51 let left = width / -2.0;
52 let right = width / 2.0;
53 let bottom = height / -2.0;
54 let top = height / 2.0;
55 // The default batch size can also be overridden.
56 // In this case a batch size of 32 is chosen to limit the overhead of
57 // ParallelIterator, since negating a vector is very inexpensive.
58 sprites
59 .par_iter_mut()
60 .batching_strategy(BatchingStrategy::fixed(32))
61 .for_each(|(transform, mut v)| {
62 if !(left < transform.translation.x
63 && transform.translation.x < right
64 && bottom < transform.translation.y
65 && transform.translation.y < top)
66 {
67 // For simplicity, just reverse the velocity; don't use realistic bounces
68 v.0 = -v.0;
69 }
70 });
71}
Sourcepub fn par_iter_inner(self) -> QueryParIter<'w, 's, D, F>
pub fn par_iter_inner(self) -> QueryParIter<'w, 's, D, F>
Returns a parallel iterator over the query results for the given World
.
This consumes the Query
to return results with the actual “inner” world lifetime.
This parallel iterator is always guaranteed to return results from each matching entity once and only once. Iteration order and thread assignment is not guaranteed.
If the multithreaded
feature is disabled, iterating with this operates identically to Iterator::for_each
on QueryIter
.
§Example
Here, the gravity_system
updates the Velocity
component of every entity that contains it:
fn gravity_system(query: Query<&mut Velocity>) {
const DELTA: f32 = 1.0 / 60.0;
query.par_iter_inner().for_each(|mut velocity| {
velocity.y -= 9.8 * DELTA;
});
}
Sourcepub fn par_iter_many<EntityList>(
&self,
entities: EntityList,
) -> QueryParManyIter<'_, '_, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::Item>
pub fn par_iter_many<EntityList>( &self, entities: EntityList, ) -> QueryParManyIter<'_, '_, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::Item>
Returns a parallel iterator over the read-only query items generated from an Entity
list.
Entities that don’t match the query are skipped. Iteration order and thread assignment is not guaranteed.
If the multithreaded
feature is disabled, iterating with this operates identically to Iterator::for_each
on QueryManyIter
.
This can only be called for read-only queries. To avoid potential aliasing, there is no par_iter_many_mut
equivalent.
See par_iter_many_unique_mut
for an alternative using EntitySet
.
Note that you must use the for_each
method to iterate over the
results, see par_iter_mut
for an example.
Sourcepub fn par_iter_many_unique<EntityList>(
&self,
entities: EntityList,
) -> QueryParManyUniqueIter<'_, '_, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::Item>
pub fn par_iter_many_unique<EntityList>( &self, entities: EntityList, ) -> QueryParManyUniqueIter<'_, '_, <D as QueryData>::ReadOnly, F, <EntityList as IntoIterator>::Item>
Returns a parallel iterator over the unique read-only query items generated from an EntitySet
.
Entities that don’t match the query are skipped. Iteration order and thread assignment is not guaranteed.
If the multithreaded
feature is disabled, iterating with this operates identically to Iterator::for_each
on QueryManyUniqueIter
.
This can only be called for read-only queries, see par_iter_many_unique_mut
for write-queries.
Note that you must use the for_each
method to iterate over the
results, see par_iter_mut
for an example.
Sourcepub fn par_iter_many_unique_mut<EntityList>(
&mut self,
entities: EntityList,
) -> QueryParManyUniqueIter<'_, '_, D, F, <EntityList as IntoIterator>::Item>
pub fn par_iter_many_unique_mut<EntityList>( &mut self, entities: EntityList, ) -> QueryParManyUniqueIter<'_, '_, D, F, <EntityList as IntoIterator>::Item>
Returns a parallel iterator over the unique query items generated from an EntitySet
.
Entities that don’t match the query are skipped. Iteration order and thread assignment is not guaranteed.
If the multithreaded
feature is disabled, iterating with this operates identically to Iterator::for_each
on QueryManyUniqueIter
.
This can only be called for mutable queries, see par_iter_many_unique
for read-only-queries.
Note that you must use the for_each
method to iterate over the
results, see par_iter_mut
for an example.
Sourcepub fn get(
&self,
entity: Entity,
) -> Result<<<D as QueryData>::ReadOnly as QueryData>::Item<'_>, QueryEntityError>
pub fn get( &self, entity: Entity, ) -> Result<<<D as QueryData>::ReadOnly as QueryData>::Item<'_>, QueryEntityError>
Returns the read-only query item for the given Entity
.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
This is always guaranteed to run in O(1)
time.
§Example
Here, get
is used to retrieve the exact query item of the entity specified by the SelectedCharacter
resource.
fn print_selected_character_name_system(
query: Query<&Character>,
selection: Res<SelectedCharacter>
)
{
if let Ok(selected_character) = query.get(selection.entity) {
println!("{}", selected_character.name);
}
}
§See also
get_mut
to get a mutable query item.
Examples found in repository?
80fn attack_hits(trigger: Trigger<Attack>, name: Query<&Name>) {
81 if let Ok(name) = name.get(trigger.target()) {
82 info!("Attack hit {}", name);
83 }
84}
85
86/// A callback placed on [`Armor`], checking if it absorbed all the [`Attack`] damage.
87fn block_attack(mut trigger: Trigger<Attack>, armor: Query<(&Armor, &Name)>) {
88 let (armor, name) = armor.get(trigger.target()).unwrap();
89 let attack = trigger.event_mut();
90 let damage = attack.damage.saturating_sub(**armor);
91 if damage > 0 {
92 info!("🩸 {} damage passed through {}", damage, name);
93 // The attack isn't stopped by the armor. We reduce the damage of the attack, and allow
94 // it to continue on to the goblin.
95 attack.damage = damage;
96 } else {
97 info!("🛡️ {} damage blocked by {}", attack.damage, name);
98 // Armor stopped the attack, the event stops here.
99 trigger.propagate(false);
100 info!("(propagation halted early)\n");
101 }
102}
More examples
104fn button_system(
105 mut interaction_query: Query<(&Interaction, &ChildOf), (Changed<Interaction>, With<Button>)>,
106 labels_query: Query<(&Children, &ChildOf), With<Button>>,
107 mut text_query: Query<&mut Text>,
108 mut counter_query: Query<&mut Counter>,
109) {
110 // Update parent counter on click
111 for (interaction, child_of) in &mut interaction_query {
112 if matches!(interaction, Interaction::Pressed) {
113 let mut counter = counter_query.get_mut(child_of.parent()).unwrap();
114 counter.0 += 1;
115 }
116 }
117
118 // Update button labels to match their parent counter
119 for (children, child_of) in &labels_query {
120 let counter = counter_query.get(child_of.parent()).unwrap();
121 let mut text = text_query.get_mut(children[0]).unwrap();
122
123 **text = counter.0.to_string();
124 }
125}
464fn update_ui(
465 mut animation_controls: Query<(&AnimationControl, &mut BackgroundColor, &Children)>,
466 texts: Query<Entity, With<Text>>,
467 mut writer: TextUiWriter,
468 app_state: Res<AppState>,
469) {
470 for (animation_control, mut background_color, kids) in animation_controls.iter_mut() {
471 let enabled =
472 app_state.0[animation_control.group_id as usize].clip == animation_control.label as u8;
473
474 *background_color = if enabled {
475 BackgroundColor(Color::WHITE)
476 } else {
477 BackgroundColor(Color::BLACK)
478 };
479
480 for &kid in kids {
481 let Ok(text) = texts.get(kid) else {
482 continue;
483 };
484
485 writer.for_each_color(text, |mut color| {
486 color.0 = if enabled { Color::BLACK } else { Color::WHITE };
487 });
488 }
489 }
490}
162fn set_camera_viewports(
163 windows: Query<&Window>,
164 mut resize_events: EventReader<WindowResized>,
165 mut query: Query<(&CameraPosition, &mut Camera)>,
166) {
167 // We need to dynamically resize the camera's viewports whenever the window size changes
168 // so then each camera always takes up half the screen.
169 // A resize_event is sent when the window is first created, allowing us to reuse this system for initial setup.
170 for resize_event in resize_events.read() {
171 let window = windows.get(resize_event.window).unwrap();
172 let size = window.physical_size() / 2;
173
174 for (camera_position, mut camera) in &mut query {
175 camera.viewport = Some(Viewport {
176 physical_position: camera_position.pos * size,
177 physical_size: size,
178 ..default()
179 });
180 }
181 }
182}
45fn joint_animation(
46 time: Res<Time>,
47 children: Query<&ChildOf, With<SkinnedMesh>>,
48 parents: Query<&Children>,
49 mut transform_query: Query<&mut Transform>,
50) {
51 // Iter skinned mesh entity
52 for child_of in &children {
53 // Mesh node is the parent of the skinned mesh entity.
54 let mesh_node_entity = child_of.parent();
55 // Get `Children` in the mesh node.
56 let mesh_node_parent = parents.get(mesh_node_entity).unwrap();
57
58 // First joint is the second child of the mesh node.
59 let first_joint_entity = mesh_node_parent[1];
60 // Get `Children` in the first joint.
61 let first_joint_children = parents.get(first_joint_entity).unwrap();
62
63 // Second joint is the first child of the first joint.
64 let second_joint_entity = first_joint_children[0];
65 // Get `Transform` in the second joint.
66 let mut second_joint_transform = transform_query.get_mut(second_joint_entity).unwrap();
67
68 second_joint_transform.rotation =
69 Quat::from_rotation_z(FRAC_PI_2 * ops::sin(time.elapsed_secs()));
70 }
71}
43fn observe_on_step(
44 trigger: Trigger<OnStep>,
45 particle: Res<ParticleAssets>,
46 mut commands: Commands,
47 transforms: Query<&GlobalTransform>,
48 mut seeded_rng: ResMut<SeededRng>,
49) {
50 let translation = transforms.get(trigger.target()).unwrap().translation();
51 // Spawn a bunch of particles.
52 for _ in 0..14 {
53 let horizontal = seeded_rng.0.r#gen::<Dir2>() * seeded_rng.0.gen_range(8.0..12.0);
54 let vertical = seeded_rng.0.gen_range(0.0..4.0);
55 let size = seeded_rng.0.gen_range(0.2..1.0);
56
57 commands.spawn((
58 Particle {
59 lifetime_timer: Timer::from_seconds(
60 seeded_rng.0.gen_range(0.2..0.6),
61 TimerMode::Once,
62 ),
63 size,
64 velocity: Vec3::new(horizontal.x, vertical, horizontal.y) * 10.0,
65 },
66 Mesh3d(particle.mesh.clone()),
67 MeshMaterial3d(particle.material.clone()),
68 Transform {
69 translation,
70 scale: Vec3::splat(size),
71 ..Default::default()
72 },
73 ));
74 }
75}
Sourcepub fn get_many<const N: usize>(
&self,
entities: [Entity; N],
) -> Result<[<<D as QueryData>::ReadOnly as QueryData>::Item<'_>; N], QueryEntityError>
pub fn get_many<const N: usize>( &self, entities: [Entity; N], ) -> Result<[<<D as QueryData>::ReadOnly as QueryData>::Item<'_>; N], QueryEntityError>
Returns the read-only query items for the given array of Entity
.
The returned query items are in the same order as the input.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
The elements of the array do not need to be unique, unlike get_many_mut
.
§Examples
use bevy_ecs::prelude::*;
use bevy_ecs::query::QueryEntityError;
#[derive(Component, PartialEq, Debug)]
struct A(usize);
let mut world = World::new();
let entity_vec: Vec<Entity> = (0..3).map(|i| world.spawn(A(i)).id()).collect();
let entities: [Entity; 3] = entity_vec.try_into().unwrap();
world.spawn(A(73));
let mut query_state = world.query::<&A>();
let query = query_state.query(&world);
let component_values = query.get_many(entities).unwrap();
assert_eq!(component_values, [&A(0), &A(1), &A(2)]);
let wrong_entity = Entity::from_raw(365);
assert_eq!(
match query.get_many([wrong_entity]).unwrap_err() {
QueryEntityError::EntityDoesNotExist(error) => error.entity,
_ => panic!(),
},
wrong_entity
);
§See also
get_many_mut
to get mutable query items.get_many_unique
to only handle unique inputs.many
for the panicking version.
Sourcepub fn get_many_unique<const N: usize>(
&self,
entities: UniqueEntityEquivalentArray<Entity, N>,
) -> Result<[<<D as QueryData>::ReadOnly as QueryData>::Item<'_>; N], QueryEntityError>
pub fn get_many_unique<const N: usize>( &self, entities: UniqueEntityEquivalentArray<Entity, N>, ) -> Result<[<<D as QueryData>::ReadOnly as QueryData>::Item<'_>; N], QueryEntityError>
Returns the read-only query items for the given UniqueEntityArray
.
The returned query items are in the same order as the input.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
§Examples
use bevy_ecs::{prelude::*, query::QueryEntityError, entity::{EntitySetIterator, UniqueEntityArray, UniqueEntityVec}};
#[derive(Component, PartialEq, Debug)]
struct A(usize);
let mut world = World::new();
let entity_set: UniqueEntityVec = world.spawn_batch((0..3).map(A)).collect_set();
let entity_set: UniqueEntityArray<3> = entity_set.try_into().unwrap();
world.spawn(A(73));
let mut query_state = world.query::<&A>();
let query = query_state.query(&world);
let component_values = query.get_many_unique(entity_set).unwrap();
assert_eq!(component_values, [&A(0), &A(1), &A(2)]);
let wrong_entity = Entity::from_raw(365);
assert_eq!(
match query.get_many_unique(UniqueEntityArray::from([wrong_entity])).unwrap_err() {
QueryEntityError::EntityDoesNotExist(error) => error.entity,
_ => panic!(),
},
wrong_entity
);
§See also
get_many_unique_mut
to get mutable query items.get_many
to handle inputs with duplicates.
Sourcepub fn many<const N: usize>(
&self,
entities: [Entity; N],
) -> [<<D as QueryData>::ReadOnly as QueryData>::Item<'_>; N]
👎Deprecated since 0.16.0: Use get_many
instead and handle the Result.
pub fn many<const N: usize>( &self, entities: [Entity; N], ) -> [<<D as QueryData>::ReadOnly as QueryData>::Item<'_>; N]
get_many
instead and handle the Result.Returns the read-only query items for the given array of Entity
.
§Panics
This method panics if there is a query mismatch or a non-existing entity.
§Examples
use bevy_ecs::prelude::*;
#[derive(Component)]
struct Targets([Entity; 3]);
#[derive(Component)]
struct Position{
x: i8,
y: i8
};
impl Position {
fn distance(&self, other: &Position) -> i8 {
// Manhattan distance is way easier to compute!
(self.x - other.x).abs() + (self.y - other.y).abs()
}
}
fn check_all_targets_in_range(targeting_query: Query<(Entity, &Targets, &Position)>, targets_query: Query<&Position>){
for (targeting_entity, targets, origin) in &targeting_query {
// We can use "destructuring" to unpack the results nicely
let [target_1, target_2, target_3] = targets_query.many(targets.0);
assert!(target_1.distance(origin) <= 5);
assert!(target_2.distance(origin) <= 5);
assert!(target_3.distance(origin) <= 5);
}
}
§See also
get_many
for the non-panicking version.
Sourcepub fn get_mut(
&mut self,
entity: Entity,
) -> Result<<D as QueryData>::Item<'_>, QueryEntityError>
pub fn get_mut( &mut self, entity: Entity, ) -> Result<<D as QueryData>::Item<'_>, QueryEntityError>
Returns the query item for the given Entity
.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
This is always guaranteed to run in O(1)
time.
§Example
Here, get_mut
is used to retrieve the exact query item of the entity specified by the PoisonedCharacter
resource.
fn poison_system(mut query: Query<&mut Health>, poisoned: Res<PoisonedCharacter>) {
if let Ok(mut health) = query.get_mut(poisoned.character_id) {
health.0 -= 1;
}
}
§See also
get
to get a read-only query item.
Examples found in repository?
More examples
106fn take_damage(
107 trigger: Trigger<Attack>,
108 mut hp: Query<(&mut HitPoints, &Name)>,
109 mut commands: Commands,
110 mut app_exit: EventWriter<AppExit>,
111) {
112 let attack = trigger.event();
113 let (mut hp, name) = hp.get_mut(trigger.target()).unwrap();
114 **hp = hp.saturating_sub(attack.damage);
115
116 if **hp > 0 {
117 info!("{} has {:.1} HP", name, hp.0);
118 } else {
119 warn!("💀 {} has died a gruesome death", name);
120 commands.entity(trigger.target()).despawn();
121 app_exit.write(AppExit::Success);
122 }
123
124 info!("(propagation reached root)\n");
125}
160fn update_material_on<E>(
161 new_material: Handle<StandardMaterial>,
162) -> impl Fn(Trigger<E>, Query<&mut MeshMaterial3d<StandardMaterial>>) {
163 // An observer closure that captures `new_material`. We do this to avoid needing to write four
164 // versions of this observer, each triggered by a different event and with a different hardcoded
165 // material. Instead, the event type is a generic, and the material is passed in.
166 move |trigger, mut query| {
167 if let Ok(mut material) = query.get_mut(trigger.target()) {
168 material.0 = new_material.clone();
169 }
170 }
171}
172
173/// A system that draws hit indicators for every pointer.
174fn draw_mesh_intersections(pointers: Query<&PointerInteraction>, mut gizmos: Gizmos) {
175 for (point, normal) in pointers
176 .iter()
177 .filter_map(|interaction| interaction.get_nearest_hit())
178 .filter_map(|(_entity, hit)| hit.position.zip(hit.normal))
179 {
180 gizmos.sphere(point, 0.05, RED_500);
181 gizmos.arrow(point, point + normal.normalize() * 0.5, PINK_100);
182 }
183}
184
185/// A system that rotates all shapes.
186fn rotate(mut query: Query<&mut Transform, With<Shape>>, time: Res<Time>) {
187 for mut transform in &mut query {
188 transform.rotate_y(time.delta_secs() / 2.);
189 }
190}
191
192/// An observer to rotate an entity when it is dragged
193fn rotate_on_drag(drag: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>) {
194 let mut transform = transforms.get_mut(drag.target()).unwrap();
195 transform.rotate_y(drag.delta.x * 0.02);
196 transform.rotate_x(drag.delta.y * 0.02);
197}
69fn universal_button_click_behavior(
70 mut trigger: Trigger<Pointer<Click>>,
71 mut button_query: Query<(&mut BackgroundColor, &mut ResetTimer)>,
72) {
73 let button_entity = trigger.target();
74 if let Ok((mut color, mut reset_timer)) = button_query.get_mut(button_entity) {
75 // This would be a great place to play a little sound effect too!
76 color.0 = PRESSED_BUTTON.into();
77 reset_timer.0 = Timer::from_seconds(0.3, TimerMode::Once);
78
79 // Picking events propagate up the hierarchy,
80 // so we need to stop the propagation here now that we've handled it
81 trigger.propagate(false);
82 }
83}
57fn move_scene_entities(
58 time: Res<Time>,
59 moved_scene: Query<Entity, With<MovedScene>>,
60 children: Query<&Children>,
61 mut transforms: Query<&mut Transform>,
62) {
63 for moved_scene_entity in &moved_scene {
64 let mut offset = 0.;
65 for entity in children.iter_descendants(moved_scene_entity) {
66 if let Ok(mut transform) = transforms.get_mut(entity) {
67 transform.translation = Vec3::new(
68 offset * ops::sin(time.elapsed_secs()) / 20.,
69 0.,
70 ops::cos(time.elapsed_secs()) / 20.,
71 );
72 offset += 0.5;
73 }
74 }
75 }
76}
- examples/ui/ui_texture_slice.rs
- examples/testbed/3d.rs
- examples/ui/ghost_nodes.rs
- examples/ui/ui_texture_atlas_slice.rs
- examples/3d/split_screen.rs
- examples/ui/display_and_visibility.rs
- examples/testbed/full_ui.rs
- examples/ui/button.rs
- examples/ui/tab_navigation.rs
- examples/animation/gltf_skinned_mesh.rs
- examples/ui/scroll.rs
- examples/3d/motion_blur.rs
- examples/games/contributors.rs
- examples/ecs/hierarchy.rs
- examples/3d/mixed_lighting.rs
- examples/picking/simple_picking.rs
- examples/animation/animated_mesh.rs
- examples/picking/debug_picking.rs
- examples/games/alien_cake_addict.rs
- examples/animation/easing_functions.rs
- examples/ui/size_constraints.rs
Sourcepub fn get_inner(
self,
entity: Entity,
) -> Result<<D as QueryData>::Item<'w>, QueryEntityError>
pub fn get_inner( self, entity: Entity, ) -> Result<<D as QueryData>::Item<'w>, QueryEntityError>
Returns the query item for the given Entity
.
This consumes the Query
to return results with the actual “inner” world lifetime.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
This is always guaranteed to run in O(1)
time.
§See also
Sourcepub fn get_many_mut<const N: usize>(
&mut self,
entities: [Entity; N],
) -> Result<[<D as QueryData>::Item<'_>; N], QueryEntityError>
pub fn get_many_mut<const N: usize>( &mut self, entities: [Entity; N], ) -> Result<[<D as QueryData>::Item<'_>; N], QueryEntityError>
Returns the query items for the given array of Entity
.
The returned query items are in the same order as the input.
In case of a nonexisting entity, duplicate entities or mismatched component, a QueryEntityError
is returned instead.
§Examples
use bevy_ecs::prelude::*;
use bevy_ecs::query::QueryEntityError;
#[derive(Component, PartialEq, Debug)]
struct A(usize);
let mut world = World::new();
let entities: Vec<Entity> = (0..3).map(|i| world.spawn(A(i)).id()).collect();
let entities: [Entity; 3] = entities.try_into().unwrap();
world.spawn(A(73));
let wrong_entity = Entity::from_raw(57);
let invalid_entity = world.spawn_empty().id();
let mut query_state = world.query::<&mut A>();
let mut query = query_state.query_mut(&mut world);
let mut mutable_component_values = query.get_many_mut(entities).unwrap();
for mut a in &mut mutable_component_values {
a.0 += 5;
}
let component_values = query.get_many(entities).unwrap();
assert_eq!(component_values, [&A(5), &A(6), &A(7)]);
assert_eq!(
match query
.get_many_mut([wrong_entity])
.unwrap_err()
{
QueryEntityError::EntityDoesNotExist(error) => error.entity,
_ => panic!(),
},
wrong_entity
);
assert_eq!(
match query
.get_many_mut([invalid_entity])
.unwrap_err()
{
QueryEntityError::QueryDoesNotMatch(entity, _) => entity,
_ => panic!(),
},
invalid_entity
);
assert_eq!(
query
.get_many_mut([entities[0], entities[0]])
.unwrap_err(),
QueryEntityError::AliasedMutability(entities[0])
);
§See also
Sourcepub fn get_many_unique_mut<const N: usize>(
&mut self,
entities: UniqueEntityEquivalentArray<Entity, N>,
) -> Result<[<D as QueryData>::Item<'_>; N], QueryEntityError>
pub fn get_many_unique_mut<const N: usize>( &mut self, entities: UniqueEntityEquivalentArray<Entity, N>, ) -> Result<[<D as QueryData>::Item<'_>; N], QueryEntityError>
Returns the query items for the given UniqueEntityArray
.
The returned query items are in the same order as the input.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
§Examples
use bevy_ecs::{prelude::*, query::QueryEntityError, entity::{EntitySetIterator, UniqueEntityArray, UniqueEntityVec}};
#[derive(Component, PartialEq, Debug)]
struct A(usize);
let mut world = World::new();
let entity_set: UniqueEntityVec = world.spawn_batch((0..3).map(A)).collect_set();
let entity_set: UniqueEntityArray<3> = entity_set.try_into().unwrap();
world.spawn(A(73));
let wrong_entity = Entity::from_raw(57);
let invalid_entity = world.spawn_empty().id();
let mut query_state = world.query::<&mut A>();
let mut query = query_state.query_mut(&mut world);
let mut mutable_component_values = query.get_many_unique_mut(entity_set).unwrap();
for mut a in &mut mutable_component_values {
a.0 += 5;
}
let component_values = query.get_many_unique(entity_set).unwrap();
assert_eq!(component_values, [&A(5), &A(6), &A(7)]);
assert_eq!(
match query
.get_many_unique_mut(UniqueEntityArray::from([wrong_entity]))
.unwrap_err()
{
QueryEntityError::EntityDoesNotExist(error) => error.entity,
_ => panic!(),
},
wrong_entity
);
assert_eq!(
match query
.get_many_unique_mut(UniqueEntityArray::from([invalid_entity]))
.unwrap_err()
{
QueryEntityError::QueryDoesNotMatch(entity, _) => entity,
_ => panic!(),
},
invalid_entity
);
§See also
get_many_unique
to get read-only query items.
Sourcepub fn get_many_mut_inner<const N: usize>(
self,
entities: [Entity; N],
) -> Result<[<D as QueryData>::Item<'w>; N], QueryEntityError>
pub fn get_many_mut_inner<const N: usize>( self, entities: [Entity; N], ) -> Result<[<D as QueryData>::Item<'w>; N], QueryEntityError>
Returns the query items for the given array of Entity
.
This consumes the Query
to return results with the actual “inner” world lifetime.
The returned query items are in the same order as the input.
In case of a nonexisting entity, duplicate entities or mismatched component, a QueryEntityError
is returned instead.
§See also
get_many
to get read-only query items without checking for duplicate entities.get_many_mut
to get items using a mutable reference.get_many_inner
to get read-only query items with the actual “inner” world lifetime.
Sourcepub fn get_many_inner<const N: usize>(
self,
entities: [Entity; N],
) -> Result<[<D as QueryData>::Item<'w>; N], QueryEntityError>where
D: ReadOnlyQueryData,
pub fn get_many_inner<const N: usize>(
self,
entities: [Entity; N],
) -> Result<[<D as QueryData>::Item<'w>; N], QueryEntityError>where
D: ReadOnlyQueryData,
Returns the query items for the given array of Entity
.
This consumes the Query
to return results with the actual “inner” world lifetime.
The returned query items are in the same order as the input.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
§See also
get_many
to get read-only query items without checking for duplicate entities.get_many_mut
to get items using a mutable reference.get_many_mut_inner
to get mutable query items with the actual “inner” world lifetime.
Sourcepub fn get_many_unique_inner<const N: usize>(
self,
entities: UniqueEntityEquivalentArray<Entity, N>,
) -> Result<[<D as QueryData>::Item<'w>; N], QueryEntityError>
pub fn get_many_unique_inner<const N: usize>( self, entities: UniqueEntityEquivalentArray<Entity, N>, ) -> Result<[<D as QueryData>::Item<'w>; N], QueryEntityError>
Returns the query items for the given UniqueEntityArray
.
This consumes the Query
to return results with the actual “inner” world lifetime.
The returned query items are in the same order as the input.
In case of a nonexisting entity, duplicate entities or mismatched component, a QueryEntityError
is returned instead.
§See also
get_many_unique
to get read-only query items without checking for duplicate entities.get_many_unique_mut
to get items using a mutable reference.
Sourcepub fn many_mut<const N: usize>(
&mut self,
entities: [Entity; N],
) -> [<D as QueryData>::Item<'_>; N]
👎Deprecated since 0.16.0: Use get_many_mut
instead and handle the Result.
pub fn many_mut<const N: usize>( &mut self, entities: [Entity; N], ) -> [<D as QueryData>::Item<'_>; N]
get_many_mut
instead and handle the Result.Returns the query items for the given array of Entity
.
§Panics
This method panics if there is a query mismatch, a non-existing entity, or the same Entity
is included more than once in the array.
§Examples
use bevy_ecs::prelude::*;
#[derive(Component)]
struct Spring{
connected_entities: [Entity; 2],
strength: f32,
}
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
#[derive(Component)]
struct Force {
x: f32,
y: f32,
}
fn spring_forces(spring_query: Query<&Spring>, mut mass_query: Query<(&Position, &mut Force)>){
for spring in &spring_query {
// We can use "destructuring" to unpack our query items nicely
let [(position_1, mut force_1), (position_2, mut force_2)] = mass_query.many_mut(spring.connected_entities);
force_1.x += spring.strength * (position_1.x - position_2.x);
force_1.y += spring.strength * (position_1.y - position_2.y);
// Silence borrow-checker: I have split your mutable borrow!
force_2.x += spring.strength * (position_2.x - position_1.x);
force_2.y += spring.strength * (position_2.y - position_1.y);
}
}
§See also
get_many_mut
for the non panicking version.many
to get read-only query items.
Sourcepub unsafe fn get_unchecked(
&self,
entity: Entity,
) -> Result<<D as QueryData>::Item<'_>, QueryEntityError>
pub unsafe fn get_unchecked( &self, entity: Entity, ) -> Result<<D as QueryData>::Item<'_>, QueryEntityError>
Returns the query item for the given Entity
.
In case of a nonexisting entity or mismatched component, a QueryEntityError
is returned instead.
This is always guaranteed to run in O(1)
time.
§Safety
This function makes it possible to violate Rust’s aliasing guarantees. You must make sure this call does not result in multiple mutable references to the same component.
§See also
get_mut
for the safe version.
Sourcepub fn single(
&self,
) -> Result<<<D as QueryData>::ReadOnly as QueryData>::Item<'_>, QuerySingleError>
pub fn single( &self, ) -> Result<<<D as QueryData>::ReadOnly as QueryData>::Item<'_>, QuerySingleError>
Returns a single read-only query item when there is exactly one entity matching the query.
If the number of query items is not exactly one, a QuerySingleError
is returned instead.
§Example
fn player_scoring_system(query: Query<&PlayerScore>) {
match query.single() {
Ok(PlayerScore(score)) => {
println!("Score: {}", score);
}
Err(QuerySingleError::NoEntities(_)) => {
println!("Error: There is no player!");
}
Err(QuerySingleError::MultipleEntities(_)) => {
println!("Error: There is more than one player!");
}
}
}
§See also
single_mut
to get the mutable query item.
Examples found in repository?
37fn update_speed(music_controller: Query<&AudioSink, With<MyMusic>>, time: Res<Time>) {
38 let Ok(sink) = music_controller.single() else {
39 return;
40 };
41
42 sink.set_speed((ops::sin(time.elapsed_secs() / 5.0) + 1.0).max(0.1));
43}
44
45fn pause(
46 keyboard_input: Res<ButtonInput<KeyCode>>,
47 music_controller: Query<&AudioSink, With<MyMusic>>,
48) {
49 let Ok(sink) = music_controller.single() else {
50 return;
51 };
52
53 if keyboard_input.just_pressed(KeyCode::Space) {
54 sink.toggle_playback();
55 }
56}
More examples
172fn handle_click(
173 mouse_button_input: Res<ButtonInput<MouseButton>>,
174 camera: Single<(&Camera, &GlobalTransform)>,
175 windows: Query<&Window>,
176 mut commands: Commands,
177) {
178 let Ok(windows) = windows.single() else {
179 return;
180 };
181
182 let (camera, camera_transform) = *camera;
183 if let Some(pos) = windows
184 .cursor_position()
185 .and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
186 .map(|ray| ray.origin.truncate())
187 {
188 if mouse_button_input.just_pressed(MouseButton::Left) {
189 commands.trigger(ExplodeMines { pos, radius: 1.0 });
190 }
191 }
192}
193fn drag_drop_image(
194 image_mat: Query<&MeshMaterial3d<StandardMaterial>, With<HDRViewer>>,
195 text: Query<Entity, (With<Text>, With<SceneNumber>)>,
196 mut materials: ResMut<Assets<StandardMaterial>>,
197 mut drop_events: EventReader<FileDragAndDrop>,
198 asset_server: Res<AssetServer>,
199 mut commands: Commands,
200) {
201 let Some(new_image) = drop_events.read().find_map(|e| match e {
202 FileDragAndDrop::DroppedFile { path_buf, .. } => {
203 Some(asset_server.load(path_buf.to_string_lossy().to_string()))
204 }
205 _ => None,
206 }) else {
207 return;
208 };
209
210 for mat_h in &image_mat {
211 if let Some(mat) = materials.get_mut(mat_h) {
212 mat.base_color_texture = Some(new_image.clone());
213
214 // Despawn the image viewer instructions
215 if let Ok(text_entity) = text.single() {
216 commands.entity(text_entity).despawn();
217 }
218 }
219 }
220}
89fn handle_input(
90 input: Res<ButtonInput<KeyCode>>,
91 mut action: ResMut<LeftClickAction>,
92 mut dir: ResMut<ResizeDir>,
93 example_text: Query<Entity, With<Text>>,
94 mut writer: TextUiWriter,
95) -> Result {
96 use LeftClickAction::*;
97 if input.just_pressed(KeyCode::KeyA) {
98 *action = match *action {
99 Move => Resize,
100 Resize => Nothing,
101 Nothing => Move,
102 };
103 *writer.text(example_text.single()?, 4) = format!("{:?}", *action);
104 }
105
106 if input.just_pressed(KeyCode::KeyS) {
107 dir.0 = dir
108 .0
109 .checked_sub(1)
110 .unwrap_or(DIRECTIONS.len().saturating_sub(1));
111 *writer.text(example_text.single()?, 7) = format!("{:?}", DIRECTIONS[dir.0]);
112 }
113
114 if input.just_pressed(KeyCode::KeyD) {
115 dir.0 = (dir.0 + 1) % DIRECTIONS.len();
116 *writer.text(example_text.single()?, 7) = format!("{:?}", DIRECTIONS[dir.0]);
117 }
118
119 Ok(())
120}
25fn draw_cursor(
26 camera_query: Single<(&Camera, &GlobalTransform)>,
27 window: Query<&Window>,
28 mut gizmos: Gizmos,
29) {
30 let (camera, camera_transform) = *camera_query;
31 let Ok(window) = window.single() else {
32 return;
33 };
34
35 let Some(cursor_position) = window.cursor_position() else {
36 return;
37 };
38
39 // Calculate a world position based on the cursor's position.
40 let Ok(world_pos) = camera.viewport_to_world_2d(camera_transform, cursor_position) else {
41 return;
42 };
43
44 // To test Camera::world_to_viewport, convert result back to viewport space and then back to world space.
45 let Ok(viewport_check) = camera.world_to_viewport(camera_transform, world_pos.extend(0.0))
46 else {
47 return;
48 };
49 let Ok(world_check) = camera.viewport_to_world_2d(camera_transform, viewport_check.xy()) else {
50 return;
51 };
52
53 gizmos.circle_2d(world_pos, 10., WHITE);
54 // Should be the same as world_pos
55 gizmos.circle_2d(world_check, 8., RED);
56}
57
58fn controls(
59 mut camera_query: Query<(&mut Camera, &mut Transform, &mut Projection)>,
60 window: Query<&Window>,
61 input: Res<ButtonInput<KeyCode>>,
62 time: Res<Time<Fixed>>,
63) {
64 let Ok(window) = window.single() else {
65 return;
66 };
67 let Ok((mut camera, mut transform, mut projection)) = camera_query.single_mut() else {
68 return;
69 };
70 let fspeed = 600.0 * time.delta_secs();
71 let uspeed = fspeed as u32;
72 let window_size = window.resolution.physical_size();
73
74 // Camera movement controls
75 if input.pressed(KeyCode::ArrowUp) {
76 transform.translation.y += fspeed;
77 }
78 if input.pressed(KeyCode::ArrowDown) {
79 transform.translation.y -= fspeed;
80 }
81 if input.pressed(KeyCode::ArrowLeft) {
82 transform.translation.x -= fspeed;
83 }
84 if input.pressed(KeyCode::ArrowRight) {
85 transform.translation.x += fspeed;
86 }
87
88 // Camera zoom controls
89 if let Projection::Orthographic(projection2d) = &mut *projection {
90 if input.pressed(KeyCode::Comma) {
91 projection2d.scale *= powf(4.0f32, time.delta_secs());
92 }
93
94 if input.pressed(KeyCode::Period) {
95 projection2d.scale *= powf(0.25f32, time.delta_secs());
96 }
97 }
98
99 if let Some(viewport) = camera.viewport.as_mut() {
100 // Viewport movement controls
101 if input.pressed(KeyCode::KeyW) {
102 viewport.physical_position.y = viewport.physical_position.y.saturating_sub(uspeed);
103 }
104 if input.pressed(KeyCode::KeyS) {
105 viewport.physical_position.y += uspeed;
106 }
107 if input.pressed(KeyCode::KeyA) {
108 viewport.physical_position.x = viewport.physical_position.x.saturating_sub(uspeed);
109 }
110 if input.pressed(KeyCode::KeyD) {
111 viewport.physical_position.x += uspeed;
112 }
113
114 // Bound viewport position so it doesn't go off-screen
115 viewport.physical_position = viewport
116 .physical_position
117 .min(window_size - viewport.physical_size);
118
119 // Viewport size controls
120 if input.pressed(KeyCode::KeyI) {
121 viewport.physical_size.y = viewport.physical_size.y.saturating_sub(uspeed);
122 }
123 if input.pressed(KeyCode::KeyK) {
124 viewport.physical_size.y += uspeed;
125 }
126 if input.pressed(KeyCode::KeyJ) {
127 viewport.physical_size.x = viewport.physical_size.x.saturating_sub(uspeed);
128 }
129 if input.pressed(KeyCode::KeyL) {
130 viewport.physical_size.x += uspeed;
131 }
132
133 // Bound viewport size so it doesn't go off-screen
134 viewport.physical_size = viewport
135 .physical_size
136 .min(window_size - viewport.physical_position)
137 .max(UVec2::new(20, 20));
138 }
139}
45fn bounce_system(window: Query<&Window>, mut sprites: Query<(&Transform, &mut Velocity)>) {
46 let Ok(window) = window.single() else {
47 return;
48 };
49 let width = window.width();
50 let height = window.height();
51 let left = width / -2.0;
52 let right = width / 2.0;
53 let bottom = height / -2.0;
54 let top = height / 2.0;
55 // The default batch size can also be overridden.
56 // In this case a batch size of 32 is chosen to limit the overhead of
57 // ParallelIterator, since negating a vector is very inexpensive.
58 sprites
59 .par_iter_mut()
60 .batching_strategy(BatchingStrategy::fixed(32))
61 .for_each(|(transform, mut v)| {
62 if !(left < transform.translation.x
63 && transform.translation.x < right
64 && bottom < transform.translation.y
65 && transform.translation.y < top)
66 {
67 // For simplicity, just reverse the velocity; don't use realistic bounces
68 v.0 = -v.0;
69 }
70 });
71}
Sourcepub fn get_single(
&self,
) -> Result<<<D as QueryData>::ReadOnly as QueryData>::Item<'_>, QuerySingleError>
👎Deprecated since 0.16.0: Please use single
instead
pub fn get_single( &self, ) -> Result<<<D as QueryData>::ReadOnly as QueryData>::Item<'_>, QuerySingleError>
single
insteadA deprecated alias for single
.
Sourcepub fn single_mut(
&mut self,
) -> Result<<D as QueryData>::Item<'_>, QuerySingleError>
pub fn single_mut( &mut self, ) -> Result<<D as QueryData>::Item<'_>, QuerySingleError>
Returns a single query item when there is exactly one entity matching the query.
If the number of query items is not exactly one, a QuerySingleError
is returned instead.
§Example
fn regenerate_player_health_system(mut query: Query<&mut Health, With<Player>>) {
let mut health = query.single_mut().expect("Error: Could not find a single player.");
health.0 += 1;
}
§See also
single
to get the read-only query item.
Examples found in repository?
58fn mute(
59 keyboard_input: Res<ButtonInput<KeyCode>>,
60 mut music_controller: Query<&mut AudioSink, With<MyMusic>>,
61) {
62 let Ok(mut sink) = music_controller.single_mut() else {
63 return;
64 };
65
66 if keyboard_input.just_pressed(KeyCode::KeyM) {
67 sink.toggle_mute();
68 }
69}
70
71fn volume(
72 keyboard_input: Res<ButtonInput<KeyCode>>,
73 mut music_controller: Query<&mut AudioSink, With<MyMusic>>,
74) {
75 let Ok(mut sink) = music_controller.single_mut() else {
76 return;
77 };
78
79 if keyboard_input.just_pressed(KeyCode::Equal) {
80 let current_volume = sink.volume();
81 sink.set_volume(current_volume + Volume::Linear(0.1));
82 } else if keyboard_input.just_pressed(KeyCode::Minus) {
83 let current_volume = sink.volume();
84 sink.set_volume(current_volume - Volume::Linear(0.1));
85 }
86}
More examples
250fn get_async_loading_state(
251 state: Res<AsyncLoadingState>,
252 mut next_loading_state: ResMut<NextState<LoadingState>>,
253 mut text: Query<&mut Text, With<LoadingText>>,
254) {
255 // Load the value written by the `Future`.
256 let is_loaded = state.0.load(Ordering::Acquire);
257
258 // If loaded, change the state.
259 if is_loaded {
260 next_loading_state.set(LoadingState::Loaded);
261 if let Ok(mut text) = text.single_mut() {
262 "Loaded!".clone_into(&mut **text);
263 }
264 }
265}
60fn list_all_named_entities(
61 query: Query<&Name>,
62 mut name_text_query: Query<&mut Text, With<EntityNameText>>,
63 mut commands: Commands,
64) {
65 let mut text_string = String::from("Named entities found:\n");
66 // Query iteration order is not guaranteed, so we sort the names
67 // to ensure the output is consistent.
68 for name in query.iter().sort::<&Name>() {
69 text_string.push_str(&format!("{:?}\n", name));
70 }
71
72 if let Ok(mut text) = name_text_query.single_mut() {
73 *text = Text::new(text_string);
74 } else {
75 commands.spawn((
76 EntityNameText,
77 Text::default(),
78 Node {
79 position_type: PositionType::Absolute,
80 top: Val::Px(12.0),
81 right: Val::Px(12.0),
82 ..default()
83 },
84 ));
85 }
86}
136fn screen_shake(
137 time: Res<Time>,
138 mut screen_shake: ResMut<ScreenShake>,
139 mut query: Query<(&mut Camera, &mut Transform)>,
140) {
141 let mut rng = ChaCha8Rng::from_entropy();
142 let shake = screen_shake.trauma * screen_shake.trauma;
143 let angle = (screen_shake.max_angle * shake).to_radians() * rng.gen_range(-1.0..1.0);
144 let offset_x = screen_shake.max_offset * shake * rng.gen_range(-1.0..1.0);
145 let offset_y = screen_shake.max_offset * shake * rng.gen_range(-1.0..1.0);
146
147 if shake > 0.0 {
148 for (mut camera, mut transform) in query.iter_mut() {
149 // Position
150 let sub_view = camera.sub_camera_view.as_mut().unwrap();
151 let target = sub_view.offset
152 + Vec2 {
153 x: offset_x,
154 y: offset_y,
155 };
156 sub_view
157 .offset
158 .smooth_nudge(&target, CAMERA_DECAY_RATE, time.delta_secs());
159
160 // Rotation
161 let rotation = Quat::from_rotation_z(angle);
162 transform.rotation = transform
163 .rotation
164 .interpolate_stable(&(transform.rotation.mul_quat(rotation)), CAMERA_DECAY_RATE);
165 }
166 } else {
167 // return camera to the latest position of player (it's fixed in this example case)
168 if let Ok((mut camera, mut transform)) = query.single_mut() {
169 let sub_view = camera.sub_camera_view.as_mut().unwrap();
170 let target = screen_shake.latest_position.unwrap();
171 sub_view
172 .offset
173 .smooth_nudge(&target, 1.0, time.delta_secs());
174 transform.rotation = transform.rotation.interpolate_stable(&Quat::IDENTITY, 0.1);
175 }
176 }
177 // Decay the trauma over time
178 screen_shake.trauma -= TRAUMA_DECAY_SPEED * time.delta_secs();
179 screen_shake.trauma = screen_shake.trauma.clamp(0.0, 1.0);
180}
58fn controls(
59 mut camera_query: Query<(&mut Camera, &mut Transform, &mut Projection)>,
60 window: Query<&Window>,
61 input: Res<ButtonInput<KeyCode>>,
62 time: Res<Time<Fixed>>,
63) {
64 let Ok(window) = window.single() else {
65 return;
66 };
67 let Ok((mut camera, mut transform, mut projection)) = camera_query.single_mut() else {
68 return;
69 };
70 let fspeed = 600.0 * time.delta_secs();
71 let uspeed = fspeed as u32;
72 let window_size = window.resolution.physical_size();
73
74 // Camera movement controls
75 if input.pressed(KeyCode::ArrowUp) {
76 transform.translation.y += fspeed;
77 }
78 if input.pressed(KeyCode::ArrowDown) {
79 transform.translation.y -= fspeed;
80 }
81 if input.pressed(KeyCode::ArrowLeft) {
82 transform.translation.x -= fspeed;
83 }
84 if input.pressed(KeyCode::ArrowRight) {
85 transform.translation.x += fspeed;
86 }
87
88 // Camera zoom controls
89 if let Projection::Orthographic(projection2d) = &mut *projection {
90 if input.pressed(KeyCode::Comma) {
91 projection2d.scale *= powf(4.0f32, time.delta_secs());
92 }
93
94 if input.pressed(KeyCode::Period) {
95 projection2d.scale *= powf(0.25f32, time.delta_secs());
96 }
97 }
98
99 if let Some(viewport) = camera.viewport.as_mut() {
100 // Viewport movement controls
101 if input.pressed(KeyCode::KeyW) {
102 viewport.physical_position.y = viewport.physical_position.y.saturating_sub(uspeed);
103 }
104 if input.pressed(KeyCode::KeyS) {
105 viewport.physical_position.y += uspeed;
106 }
107 if input.pressed(KeyCode::KeyA) {
108 viewport.physical_position.x = viewport.physical_position.x.saturating_sub(uspeed);
109 }
110 if input.pressed(KeyCode::KeyD) {
111 viewport.physical_position.x += uspeed;
112 }
113
114 // Bound viewport position so it doesn't go off-screen
115 viewport.physical_position = viewport
116 .physical_position
117 .min(window_size - viewport.physical_size);
118
119 // Viewport size controls
120 if input.pressed(KeyCode::KeyI) {
121 viewport.physical_size.y = viewport.physical_size.y.saturating_sub(uspeed);
122 }
123 if input.pressed(KeyCode::KeyK) {
124 viewport.physical_size.y += uspeed;
125 }
126 if input.pressed(KeyCode::KeyJ) {
127 viewport.physical_size.x = viewport.physical_size.x.saturating_sub(uspeed);
128 }
129 if input.pressed(KeyCode::KeyL) {
130 viewport.physical_size.x += uspeed;
131 }
132
133 // Bound viewport size so it doesn't go off-screen
134 viewport.physical_size = viewport
135 .physical_size
136 .min(window_size - viewport.physical_position)
137 .max(UVec2::new(20, 20));
138 }
139}
Sourcepub fn get_single_mut(
&mut self,
) -> Result<<D as QueryData>::Item<'_>, QuerySingleError>
👎Deprecated since 0.16.0: Please use single_mut
instead
pub fn get_single_mut( &mut self, ) -> Result<<D as QueryData>::Item<'_>, QuerySingleError>
single_mut
insteadA deprecated alias for single_mut
.
Sourcepub fn single_inner(
self,
) -> Result<<D as QueryData>::Item<'w>, QuerySingleError>
pub fn single_inner( self, ) -> Result<<D as QueryData>::Item<'w>, QuerySingleError>
Returns a single query item when there is exactly one entity matching the query.
This consumes the Query
to return results with the actual “inner” world lifetime.
If the number of query items is not exactly one, a QuerySingleError
is returned instead.
§Example
fn regenerate_player_health_system(query: Query<&mut Health, With<Player>>) {
let mut health = query.single_inner().expect("Error: Could not find a single player.");
health.0 += 1;
}
§See also
single
to get the read-only query item.single_mut
to get the mutable query item.single_inner
for the panicking version.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true
if there are no query items.
This is equivalent to self.iter().next().is_none()
, and thus the worst case runtime will be O(n)
where n
is the number of potential matches. This can be notably expensive for queries that rely
on non-archetypal filters such as Added
or Changed
which must individually check each query
result for a match.
§Example
Here, the score is increased only if an entity with a Player
component is present in the world:
fn update_score_system(query: Query<(), With<Player>>, mut score: ResMut<Score>) {
if !query.is_empty() {
score.0 += 1;
}
}
Examples found in repository?
526fn create_cubes(
527 image_assets: Res<Assets<Image>>,
528 mut commands: Commands,
529 irradiance_volumes: Query<(&IrradianceVolume, &GlobalTransform)>,
530 voxel_cube_parents: Query<Entity, With<VoxelCubeParent>>,
531 voxel_cubes: Query<Entity, With<VoxelCube>>,
532 example_assets: Res<ExampleAssets>,
533 mut voxel_visualization_material_assets: ResMut<Assets<VoxelVisualizationMaterial>>,
534) {
535 // If voxel cubes have already been spawned, don't do anything.
536 if !voxel_cubes.is_empty() {
537 return;
538 }
539
540 let Some(voxel_cube_parent) = voxel_cube_parents.iter().next() else {
541 return;
542 };
543
544 for (irradiance_volume, global_transform) in irradiance_volumes.iter() {
545 let Some(image) = image_assets.get(&irradiance_volume.voxels) else {
546 continue;
547 };
548
549 let resolution = image.texture_descriptor.size;
550
551 let voxel_cube_material = voxel_visualization_material_assets.add(ExtendedMaterial {
552 base: StandardMaterial::from(Color::from(RED)),
553 extension: VoxelVisualizationExtension {
554 irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo {
555 world_from_voxel: VOXEL_FROM_WORLD.inverse(),
556 voxel_from_world: VOXEL_FROM_WORLD,
557 resolution: uvec3(
558 resolution.width,
559 resolution.height,
560 resolution.depth_or_array_layers,
561 ),
562 intensity: IRRADIANCE_VOLUME_INTENSITY,
563 },
564 },
565 });
566
567 let scale = vec3(
568 1.0 / resolution.width as f32,
569 1.0 / resolution.height as f32,
570 1.0 / resolution.depth_or_array_layers as f32,
571 );
572
573 // Spawn a cube for each voxel.
574 for z in 0..resolution.depth_or_array_layers {
575 for y in 0..resolution.height {
576 for x in 0..resolution.width {
577 let uvw = (uvec3(x, y, z).as_vec3() + 0.5) * scale - 0.5;
578 let pos = global_transform.transform_point(uvw);
579 let voxel_cube = commands
580 .spawn((
581 Mesh3d(example_assets.voxel_cube.clone()),
582 MeshMaterial3d(voxel_cube_material.clone()),
583 Transform::from_scale(Vec3::splat(VOXEL_CUBE_SCALE))
584 .with_translation(pos),
585 ))
586 .insert(VoxelCube)
587 .insert(NotShadowCaster)
588 .id();
589
590 commands.entity(voxel_cube_parent).add_child(voxel_cube);
591 }
592 }
593 }
594 }
595}
Sourcepub fn contains(&self, entity: Entity) -> bool
pub fn contains(&self, entity: Entity) -> bool
Returns true
if the given Entity
matches the query.
This is always guaranteed to run in O(1)
time.
§Example
fn targeting_system(in_range_query: Query<&InRange>, target: Res<Target>) {
if in_range_query.contains(target.entity) {
println!("Bam!")
}
}
Examples found in repository?
38fn disable_entities_on_click(
39 trigger: Trigger<Pointer<Click>>,
40 valid_query: Query<&DisableOnClick>,
41 mut commands: Commands,
42) {
43 let clicked_entity = trigger.target();
44 // Windows and text are entities and can be clicked!
45 // We definitely don't want to disable the window itself,
46 // because that would cause the app to close!
47 if valid_query.contains(clicked_entity) {
48 // Just add the `Disabled` component to the entity to disable it.
49 // Note that the `Disabled` component is *only* added to the entity,
50 // its children are not affected.
51 commands.entity(clicked_entity).insert(Disabled);
52 }
53}
Sourcepub fn transmute_lens<NewD>(&mut self) -> QueryLens<'_, NewD>where
NewD: QueryData,
pub fn transmute_lens<NewD>(&mut self) -> QueryLens<'_, NewD>where
NewD: QueryData,
Returns a QueryLens
that can be used to get a query with a more general fetch.
For example, this can transform a Query<(&A, &mut B)>
to a Query<&B>
.
This can be useful for passing the query to another function. Note that since
filter terms are dropped, non-archetypal filters like Added
and
Changed
will not be respected. To maintain or change filter
terms see Self::transmute_lens_filtered
§Panics
This will panic if NewD
is not a subset of the original fetch D
§Example
fn reusable_function(lens: &mut QueryLens<&A>) {
assert_eq!(lens.query().single().unwrap().0, 10);
}
// We can use the function in a system that takes the exact query.
fn system_1(mut query: Query<&A>) {
reusable_function(&mut query.as_query_lens());
}
// We can also use it with a query that does not match exactly
// by transmuting it.
fn system_2(mut query: Query<(&mut A, &B)>) {
let mut lens = query.transmute_lens::<&A>();
reusable_function(&mut lens);
}
§Allowed Transmutes
Besides removing parameters from the query, you can also make limited changes to the types of parameters. The new query must have a subset of the read, write, and required access of the original query.
&mut T
andMut<T>
have read, write, and required access toT
&T
andRef<T>
have read and required access toT
Option<D>
andAnyOf<(D, ...)>
have the read and write access of the subqueries, but no required access- Tuples of query data and
#[derive(QueryData)]
structs have the union of the access of their subqueries EntityMut
has read and write access to all components, but no required accessEntityRef
has read access to all components, but no required accessEntity
,EntityLocation
,&Archetype
,Has<T>
, andPhantomData<T>
have no access at all, so can be added to any queryFilteredEntityRef
andFilteredEntityMut
have access determined by theQueryBuilder
used to construct them. Any query can be transmuted to them, and they will receive the access of the source query, but only if they are the top-level query and not nestedAdded<T>
andChanged<T>
filters have read and required access toT
With<T>
andWithout<T>
filters have no access at all, so can be added to any query- Tuples of query filters and
#[derive(QueryFilter)]
structs have the union of the access of their subqueries Or<(F, ...)>
filters have the read access of the subqueries, but no required access
§Examples of valid transmutes
// `&mut T` and `Mut<T>` access the same data and can be transmuted to each other,
// `&T` and `Ref<T>` access the same data and can be transmuted to each other,
// and mutable versions can be transmuted to read-only versions
assert_valid_transmute::<&mut T, &T>();
assert_valid_transmute::<&mut T, Mut<T>>();
assert_valid_transmute::<Mut<T>, &mut T>();
assert_valid_transmute::<&T, Ref<T>>();
assert_valid_transmute::<Ref<T>, &T>();
// The structure can be rearranged, or subqueries dropped
assert_valid_transmute::<(&T, &U), &T>();
assert_valid_transmute::<((&T, &U), &V), (&T, (&U, &V))>();
assert_valid_transmute::<Option<(&T, &U)>, (Option<&T>, Option<&U>)>();
// Queries with no access can be freely added
assert_valid_transmute::<
&T,
(&T, Entity, EntityLocation, &Archetype, Has<U>, PhantomData<T>),
>();
// Required access can be transmuted to optional,
// and optional access can be transmuted to other optional access
assert_valid_transmute::<&T, Option<&T>>();
assert_valid_transmute::<AnyOf<(&mut T, &mut U)>, Option<&T>>();
// Note that removing subqueries from `AnyOf` will result
// in an `AnyOf` where all subqueries can yield `None`!
assert_valid_transmute::<AnyOf<(&T, &U, &V)>, AnyOf<(&T, &U)>>();
assert_valid_transmute::<EntityMut, Option<&mut T>>();
// Anything can be transmuted to `FilteredEntityRef` or `FilteredEntityMut`
// This will create a `FilteredEntityMut` that only has read access to `T`
assert_valid_transmute::<&T, FilteredEntityMut>();
// This transmute will succeed, but the `FilteredEntityMut` will have no access!
// It must be the top-level query to be given access, but here it is nested in a tuple.
assert_valid_transmute::<&T, (Entity, FilteredEntityMut)>();
// `Added<T>` and `Changed<T>` filters have the same access as `&T` data
// Remember that they are only evaluated on the transmuted query, not the original query!
assert_valid_transmute_filtered::<Entity, Changed<T>, &T, ()>();
assert_valid_transmute_filtered::<&mut T, (), &T, Added<T>>();
// Nested inside of an `Or` filter, they have the same access as `Option<&T>`.
assert_valid_transmute_filtered::<Option<&T>, (), Entity, Or<(Changed<T>, With<U>)>>();
Sourcepub fn transmute_lens_inner<NewD>(self) -> QueryLens<'w, NewD>where
NewD: QueryData,
pub fn transmute_lens_inner<NewD>(self) -> QueryLens<'w, NewD>where
NewD: QueryData,
Returns a QueryLens
that can be used to get a query with a more general fetch.
This consumes the Query
to return results with the actual “inner” world lifetime.
For example, this can transform a Query<(&A, &mut B)>
to a Query<&B>
.
This can be useful for passing the query to another function. Note that since
filter terms are dropped, non-archetypal filters like Added
and
Changed
will not be respected. To maintain or change filter
terms see Self::transmute_lens_filtered
§Panics
This will panic if NewD
is not a subset of the original fetch Q
§Example
fn reusable_function(mut lens: QueryLens<&A>) {
assert_eq!(lens.query().single().unwrap().0, 10);
}
// We can use the function in a system that takes the exact query.
fn system_1(query: Query<&A>) {
reusable_function(query.into_query_lens());
}
// We can also use it with a query that does not match exactly
// by transmuting it.
fn system_2(query: Query<(&mut A, &B)>) {
let mut lens = query.transmute_lens_inner::<&A>();
reusable_function(lens);
}
§Allowed Transmutes
Besides removing parameters from the query, you can also make limited changes to the types of parameters.
- Can always add/remove
Entity
- Can always add/remove
EntityLocation
- Can always add/remove
&Archetype
Ref<T>
<->&T
&mut T
->&T
&mut T
->Ref<T>
EntityMut
->EntityRef
§See also
transmute_lens
to convert to a lens using a mutable borrow of theQuery
.
Sourcepub fn transmute_lens_filtered<NewD, NewF>(
&mut self,
) -> QueryLens<'_, NewD, NewF>where
NewD: QueryData,
NewF: QueryFilter,
pub fn transmute_lens_filtered<NewD, NewF>(
&mut self,
) -> QueryLens<'_, NewD, NewF>where
NewD: QueryData,
NewF: QueryFilter,
Equivalent to Self::transmute_lens
but also includes a QueryFilter
type.
Note that the lens will iterate the same tables and archetypes as the original query. This means that
additional archetypal query terms like With
and Without
will not necessarily be respected and non-archetypal terms like Added
and
Changed
will only be respected if they are in the type signature.
Sourcepub fn transmute_lens_filtered_inner<NewD, NewF>(
self,
) -> QueryLens<'w, NewD, NewF>where
NewD: QueryData,
NewF: QueryFilter,
pub fn transmute_lens_filtered_inner<NewD, NewF>(
self,
) -> QueryLens<'w, NewD, NewF>where
NewD: QueryData,
NewF: QueryFilter,
Equivalent to Self::transmute_lens_inner
but also includes a QueryFilter
type.
This consumes the Query
to return results with the actual “inner” world lifetime.
Note that the lens will iterate the same tables and archetypes as the original query. This means that
additional archetypal query terms like With
and Without
will not necessarily be respected and non-archetypal terms like Added
and
Changed
will only be respected if they are in the type signature.
§See also
transmute_lens_filtered
to convert to a lens using a mutable borrow of theQuery
.
Sourcepub fn as_query_lens(&mut self) -> QueryLens<'_, D>
pub fn as_query_lens(&mut self) -> QueryLens<'_, D>
Gets a QueryLens
with the same accesses as the existing query
Sourcepub fn into_query_lens(self) -> QueryLens<'w, D>
pub fn into_query_lens(self) -> QueryLens<'w, D>
Gets a QueryLens
with the same accesses as the existing query
§See also
as_query_lens
to convert to a lens using a mutable borrow of theQuery
.
Sourcepub fn join<'a, OtherD, NewD>(
&'a mut self,
other: &'a mut Query<'_, '_, OtherD>,
) -> QueryLens<'a, NewD>
pub fn join<'a, OtherD, NewD>( &'a mut self, other: &'a mut Query<'_, '_, OtherD>, ) -> QueryLens<'a, NewD>
Returns a QueryLens
that can be used to get a query with the combined fetch.
For example, this can take a Query<&A>
and a Query<&B>
and return a Query<(&A, &B)>
.
The returned query will only return items with both A
and B
. Note that since filters
are dropped, non-archetypal filters like Added
and Changed
will not be respected.
To maintain or change filter terms see Self::join_filtered
.
§Example
fn system(
mut transforms: Query<&Transform>,
mut players: Query<&Player>,
mut enemies: Query<&Enemy>
) {
let mut players_transforms: QueryLens<(&Transform, &Player)> = transforms.join(&mut players);
for (transform, player) in &players_transforms.query() {
// do something with a and b
}
let mut enemies_transforms: QueryLens<(&Transform, &Enemy)> = transforms.join(&mut enemies);
for (transform, enemy) in &enemies_transforms.query() {
// do something with a and b
}
}
§Panics
This will panic if NewD
is not a subset of the union of the original fetch Q
and OtherD
.
§Allowed Transmutes
Like transmute_lens
the query terms can be changed with some restrictions.
See Self::transmute_lens
for more details.
Sourcepub fn join_inner<OtherD, NewD>(
self,
other: Query<'w, '_, OtherD>,
) -> QueryLens<'w, NewD>
pub fn join_inner<OtherD, NewD>( self, other: Query<'w, '_, OtherD>, ) -> QueryLens<'w, NewD>
Returns a QueryLens
that can be used to get a query with the combined fetch.
This consumes the Query
to return results with the actual “inner” world lifetime.
For example, this can take a Query<&A>
and a Query<&B>
and return a Query<(&A, &B)>
.
The returned query will only return items with both A
and B
. Note that since filters
are dropped, non-archetypal filters like Added
and Changed
will not be respected.
To maintain or change filter terms see Self::join_filtered
.
§Panics
This will panic if NewD
is not a subset of the union of the original fetch Q
and OtherD
.
§Allowed Transmutes
Like transmute_lens
the query terms can be changed with some restrictions.
See Self::transmute_lens
for more details.
§See also
Sourcepub fn join_filtered<'a, OtherD, OtherF, NewD, NewF>(
&'a mut self,
other: &'a mut Query<'_, '_, OtherD, OtherF>,
) -> QueryLens<'a, NewD, NewF>
pub fn join_filtered<'a, OtherD, OtherF, NewD, NewF>( &'a mut self, other: &'a mut Query<'_, '_, OtherD, OtherF>, ) -> QueryLens<'a, NewD, NewF>
Equivalent to Self::join
but also includes a QueryFilter
type.
Note that the lens with iterate a subset of the original queries’ tables
and archetypes. This means that additional archetypal query terms like
With
and Without
will not necessarily be respected and non-archetypal
terms like Added
and Changed
will only be respected if they are in
the type signature.
Sourcepub fn join_filtered_inner<OtherD, OtherF, NewD, NewF>(
self,
other: Query<'w, '_, OtherD, OtherF>,
) -> QueryLens<'w, NewD, NewF>
pub fn join_filtered_inner<OtherD, OtherF, NewD, NewF>( self, other: Query<'w, '_, OtherD, OtherF>, ) -> QueryLens<'w, NewD, NewF>
Equivalent to Self::join_inner
but also includes a QueryFilter
type.
This consumes the Query
to return results with the actual “inner” world lifetime.
Note that the lens with iterate a subset of the original queries’ tables
and archetypes. This means that additional archetypal query terms like
With
and Without
will not necessarily be respected and non-archetypal
terms like Added
and Changed
will only be respected if they are in
the type signature.
§See also
join_filtered
to join using a mutable borrow of theQuery
.
Source§impl<'w, 's, D, F> Query<'w, 's, D, F>where
D: ReadOnlyQueryData,
F: QueryFilter,
impl<'w, 's, D, F> Query<'w, 's, D, F>where
D: ReadOnlyQueryData,
F: QueryFilter,
Sourcepub fn iter_inner(&self) -> QueryIter<'w, 's, <D as QueryData>::ReadOnly, F> ⓘ
pub fn iter_inner(&self) -> QueryIter<'w, 's, <D as QueryData>::ReadOnly, F> ⓘ
Returns an Iterator
over the query items, with the actual “inner” world lifetime.
This can only return immutable data (mutable data will be cast to an immutable form).
See Self::iter_mut
for queries that contain at least one mutable component.
§Example
Here, the report_names_system
iterates over the Player
component of every entity
that contains it:
fn report_names_system(query: Query<&Player>) {
for player in &query {
println!("Say hello to {}!", player.name);
}
}
Trait Implementations§
Source§impl<D, F> Clone for Query<'_, '_, D, F>where
D: ReadOnlyQueryData,
F: QueryFilter,
impl<D, F> Clone for Query<'_, '_, D, F>where
D: ReadOnlyQueryData,
F: QueryFilter,
Source§impl<'w, 'q, Q, F> From<&'q mut Query<'w, '_, Q, F>> for QueryLens<'q, Q, F>where
Q: QueryData,
F: QueryFilter,
impl<'w, 'q, Q, F> From<&'q mut Query<'w, '_, Q, F>> for QueryLens<'q, Q, F>where
Q: QueryData,
F: QueryFilter,
Source§impl<'w, 's, Q, F> From<&'s mut QueryLens<'w, Q, F>> for Query<'s, 's, Q, F>where
Q: QueryData,
F: QueryFilter,
impl<'w, 's, Q, F> From<&'s mut QueryLens<'w, Q, F>> for Query<'s, 's, Q, F>where
Q: QueryData,
F: QueryFilter,
Source§impl<'w, 's, D, F> IntoIterator for &'w Query<'_, 's, D, F>where
D: QueryData,
F: QueryFilter,
impl<'w, 's, D, F> IntoIterator for &'w Query<'_, 's, D, F>where
D: QueryData,
F: QueryFilter,
Source§impl<'w, 's, D, F> IntoIterator for &'w mut Query<'_, 's, D, F>where
D: QueryData,
F: QueryFilter,
impl<'w, 's, D, F> IntoIterator for &'w mut Query<'_, 's, D, F>where
D: QueryData,
F: QueryFilter,
Source§impl<'w, 's, D, F> IntoIterator for Query<'w, 's, D, F>where
D: QueryData,
F: QueryFilter,
impl<'w, 's, D, F> IntoIterator for Query<'w, 's, D, F>where
D: QueryData,
F: QueryFilter,
Source§impl<D, F> SystemParam for Query<'_, '_, D, F>where
D: QueryData + 'static,
F: QueryFilter + 'static,
impl<D, F> SystemParam for Query<'_, '_, D, F>where
D: QueryData + 'static,
F: QueryFilter + 'static,
Source§type State = QueryState<D, F>
type State = QueryState<D, F>
Source§type Item<'w, 's> = Query<'w, 's, D, F>
type Item<'w, 's> = Query<'w, 's, D, F>
Self
, instantiated with new lifetimes. Read moreSource§fn init_state(
world: &mut World,
system_meta: &mut SystemMeta,
) -> <Query<'_, '_, D, F> as SystemParam>::State
fn init_state( world: &mut World, system_meta: &mut SystemMeta, ) -> <Query<'_, '_, D, F> as SystemParam>::State
World
access used by this SystemParam
and creates a new instance of this param’s State
.Source§unsafe fn new_archetype(
state: &mut <Query<'_, '_, D, F> as SystemParam>::State,
archetype: &Archetype,
system_meta: &mut SystemMeta,
)
unsafe fn new_archetype( state: &mut <Query<'_, '_, D, F> as SystemParam>::State, archetype: &Archetype, system_meta: &mut SystemMeta, )
Archetype
, registers the components accessed by this SystemParam
(if applicable).a Read moreSource§unsafe fn get_param<'w, 's>(
state: &'s mut <Query<'_, '_, D, F> as SystemParam>::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>,
change_tick: Tick,
) -> <Query<'_, '_, D, F> as SystemParam>::Item<'w, 's>
unsafe fn get_param<'w, 's>( state: &'s mut <Query<'_, '_, D, F> as SystemParam>::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> <Query<'_, '_, D, F> as SystemParam>::Item<'w, 's>
SystemParamFunction
. Read moreSource§fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World)
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World)
SystemParam
’s state.
This is used to apply Commands
during ApplyDeferred
.Source§fn queue(
state: &mut Self::State,
system_meta: &SystemMeta,
world: DeferredWorld<'_>,
)
fn queue( state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld<'_>, )
ApplyDeferred
.Source§unsafe fn validate_param(
state: &Self::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'_>,
) -> Result<(), SystemParamValidationError>
unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'_>, ) -> Result<(), SystemParamValidationError>
Source§impl<'w, 's, D, F, T> SystemParamBuilder<Query<'w, 's, D, F>> for QueryParamBuilder<T>
impl<'w, 's, D, F, T> SystemParamBuilder<Query<'w, 's, D, F>> for QueryParamBuilder<T>
Source§fn build(
self,
world: &mut World,
system_meta: &mut SystemMeta,
) -> QueryState<D, F>
fn build( self, world: &mut World, system_meta: &mut SystemMeta, ) -> QueryState<D, F>
World
access used by this SystemParam
and creates a new instance of this param’s State
.Source§fn build_state(self, world: &mut World) -> SystemState<P>
fn build_state(self, world: &mut World) -> SystemState<P>
SystemState
from a SystemParamBuilder
.
To create a system, call SystemState::build_system
on the result.Source§impl<'w, 's, D, F> SystemParamBuilder<Query<'w, 's, D, F>> for QueryState<D, F>where
D: QueryData + 'static,
F: QueryFilter + 'static,
impl<'w, 's, D, F> SystemParamBuilder<Query<'w, 's, D, F>> for QueryState<D, F>where
D: QueryData + 'static,
F: QueryFilter + 'static,
Source§fn build(
self,
world: &mut World,
system_meta: &mut SystemMeta,
) -> QueryState<D, F>
fn build( self, world: &mut World, system_meta: &mut SystemMeta, ) -> QueryState<D, F>
World
access used by this SystemParam
and creates a new instance of this param’s State
.Source§fn build_state(self, world: &mut World) -> SystemState<P>
fn build_state(self, world: &mut World) -> SystemState<P>
SystemState
from a SystemParamBuilder
.
To create a system, call SystemState::build_system
on the result.impl<D, F> Copy for Query<'_, '_, D, F>where
D: ReadOnlyQueryData,
F: QueryFilter,
impl<'w, 's, D, F> ReadOnlySystemParam for Query<'w, 's, D, F>where
D: ReadOnlyQueryData + 'static,
F: QueryFilter + 'static,
Auto Trait Implementations§
impl<'world, 'state, D, F> Freeze for Query<'world, 'state, D, F>
impl<'world, 'state, D, F = ()> !RefUnwindSafe for Query<'world, 'state, D, F>
impl<'world, 'state, D, F> Send for Query<'world, 'state, D, F>
impl<'world, 'state, D, F> Sync for Query<'world, 'state, D, F>
impl<'world, 'state, D, F> Unpin for Query<'world, 'state, D, F>
impl<'world, 'state, D, F = ()> !UnwindSafe for Query<'world, 'state, D, F>
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.