2022-10-31 15:57:50 +00:00
|
|
|
use std::collections::VecDeque;
|
|
|
|
|
|
|
|
use bevy_ecs::{
|
|
|
|
entity::Entity,
|
Rename `WorldQueryData` & `WorldQueryFilter` to `QueryData` & `QueryFilter` (#10779)
# Rename `WorldQueryData` & `WorldQueryFilter` to `QueryData` &
`QueryFilter`
Fixes #10776
## Solution
Traits `WorldQueryData` & `WorldQueryFilter` were renamed to `QueryData`
and `QueryFilter`, respectively. Related Trait types were also renamed.
---
## Changelog
- Trait `WorldQueryData` has been renamed to `QueryData`. Derive macro's
`QueryData` attribute `world_query_data` has been renamed to
`query_data`.
- Trait `WorldQueryFilter` has been renamed to `QueryFilter`. Derive
macro's `QueryFilter` attribute `world_query_filter` has been renamed to
`query_filter`.
- Trait's `ExtractComponent` type `Query` has been renamed to `Data`.
- Trait's `GetBatchData` types `Query` & `QueryFilter` has been renamed
to `Data` & `Filter`, respectively.
- Trait's `ExtractInstance` type `Query` has been renamed to `Data`.
- Trait's `ViewNode` type `ViewQuery` has been renamed to `ViewData`.
- Trait's `RenderCommand` types `ViewWorldQuery` & `ItemWorldQuery` has
been renamed to `ViewData` & `ItemData`, respectively.
## Migration Guide
Note: if merged before 0.13 is released, this should instead modify the
migration guide of #10776 with the updated names.
- Rename `WorldQueryData` & `WorldQueryFilter` trait usages to
`QueryData` & `QueryFilter` and their respective derive macro attributes
`world_query_data` & `world_query_filter` to `query_data` &
`query_filter`.
- Rename the following trait type usages:
- Trait's `ExtractComponent` type `Query` to `Data`.
- Trait's `GetBatchData` type `Query` to `Data`.
- Trait's `ExtractInstance` type `Query` to `Data`.
- Trait's `ViewNode` type `ViewQuery` to `ViewData`'
- Trait's `RenderCommand` types `ViewWolrdQuery` & `ItemWorldQuery` to
`ViewData` & `ItemData`, respectively.
```rust
// Before
#[derive(WorldQueryData)]
#[world_query_data(derive(Debug))]
struct EmptyQuery {
empty: (),
}
// After
#[derive(QueryData)]
#[query_data(derive(Debug))]
struct EmptyQuery {
empty: (),
}
// Before
#[derive(WorldQueryFilter)]
struct CustomQueryFilter<T: Component, P: Component> {
_c: With<ComponentC>,
_d: With<ComponentD>,
_or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
_generic_tuple: (With<T>, With<P>),
}
// After
#[derive(QueryFilter)]
struct CustomQueryFilter<T: Component, P: Component> {
_c: With<ComponentC>,
_d: With<ComponentD>,
_or: Or<(Added<ComponentC>, Changed<ComponentD>, Without<ComponentZ>)>,
_generic_tuple: (With<T>, With<P>),
}
// Before
impl ExtractComponent for ContrastAdaptiveSharpeningSettings {
type Query = &'static Self;
type Filter = With<Camera>;
type Out = (DenoiseCAS, CASUniform);
fn extract_component(item: QueryItem<Self::Query>) -> Option<Self::Out> {
//...
}
}
// After
impl ExtractComponent for ContrastAdaptiveSharpeningSettings {
type Data = &'static Self;
type Filter = With<Camera>;
type Out = (DenoiseCAS, CASUniform);
fn extract_component(item: QueryItem<Self::Data>) -> Option<Self::Out> {
//...
}
}
// Before
impl GetBatchData for MeshPipeline {
type Param = SRes<RenderMeshInstances>;
type Query = Entity;
type QueryFilter = With<Mesh3d>;
type CompareData = (MaterialBindGroupId, AssetId<Mesh>);
type BufferData = MeshUniform;
fn get_batch_data(
mesh_instances: &SystemParamItem<Self::Param>,
entity: &QueryItem<Self::Query>,
) -> (Self::BufferData, Option<Self::CompareData>) {
// ....
}
}
// After
impl GetBatchData for MeshPipeline {
type Param = SRes<RenderMeshInstances>;
type Data = Entity;
type Filter = With<Mesh3d>;
type CompareData = (MaterialBindGroupId, AssetId<Mesh>);
type BufferData = MeshUniform;
fn get_batch_data(
mesh_instances: &SystemParamItem<Self::Param>,
entity: &QueryItem<Self::Data>,
) -> (Self::BufferData, Option<Self::CompareData>) {
// ....
}
}
// Before
impl<A> ExtractInstance for AssetId<A>
where
A: Asset,
{
type Query = Read<Handle<A>>;
type Filter = ();
fn extract(item: QueryItem<'_, Self::Query>) -> Option<Self> {
Some(item.id())
}
}
// After
impl<A> ExtractInstance for AssetId<A>
where
A: Asset,
{
type Data = Read<Handle<A>>;
type Filter = ();
fn extract(item: QueryItem<'_, Self::Data>) -> Option<Self> {
Some(item.id())
}
}
// Before
impl ViewNode for PostProcessNode {
type ViewQuery = (
&'static ViewTarget,
&'static PostProcessSettings,
);
fn run(
&self,
_graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
(view_target, _post_process_settings): QueryItem<Self::ViewQuery>,
world: &World,
) -> Result<(), NodeRunError> {
// ...
}
}
// After
impl ViewNode for PostProcessNode {
type ViewData = (
&'static ViewTarget,
&'static PostProcessSettings,
);
fn run(
&self,
_graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
(view_target, _post_process_settings): QueryItem<Self::ViewData>,
world: &World,
) -> Result<(), NodeRunError> {
// ...
}
}
// Before
impl<P: CachedRenderPipelinePhaseItem> RenderCommand<P> for SetItemPipeline {
type Param = SRes<PipelineCache>;
type ViewWorldQuery = ();
type ItemWorldQuery = ();
#[inline]
fn render<'w>(
item: &P,
_view: (),
_entity: (),
pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
// ...
}
}
// After
impl<P: CachedRenderPipelinePhaseItem> RenderCommand<P> for SetItemPipeline {
type Param = SRes<PipelineCache>;
type ViewData = ();
type ItemData = ();
#[inline]
fn render<'w>(
item: &P,
_view: (),
_entity: (),
pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
// ...
}
}
```
2023-12-12 19:45:50 +00:00
|
|
|
query::{QueryData, QueryFilter, WorldQuery},
|
2022-10-31 15:57:50 +00:00
|
|
|
system::Query,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::{Children, Parent};
|
|
|
|
|
|
|
|
/// An extension trait for [`Query`] that adds hierarchy related methods.
|
2023-12-13 18:50:46 +00:00
|
|
|
pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
|
2022-10-31 15:57:50 +00:00
|
|
|
/// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s descendants.
|
|
|
|
///
|
|
|
|
/// Can only be called on a [`Query`] of [`Children`] (i.e. `Query<&Children>`).
|
|
|
|
///
|
|
|
|
/// Traverses the hierarchy breadth-first.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
/// ```
|
|
|
|
/// # use bevy_ecs::prelude::*;
|
|
|
|
/// # use bevy_hierarchy::prelude::*;
|
|
|
|
/// # #[derive(Component)]
|
|
|
|
/// # struct Marker;
|
|
|
|
/// fn system(query: Query<Entity, With<Marker>>, children_query: Query<&Children>) {
|
|
|
|
/// let entity = query.single();
|
|
|
|
/// for descendant in children_query.iter_descendants(entity) {
|
|
|
|
/// // Do something!
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// # bevy_ecs::system::assert_is_system(system);
|
|
|
|
/// ```
|
2023-12-13 18:50:46 +00:00
|
|
|
fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
|
2022-10-31 15:57:50 +00:00
|
|
|
|
|
|
|
/// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s ancestors.
|
|
|
|
///
|
|
|
|
/// Can only be called on a [`Query`] of [`Parent`] (i.e. `Query<&Parent>`).
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
/// ```
|
|
|
|
/// # use bevy_ecs::prelude::*;
|
|
|
|
/// # use bevy_hierarchy::prelude::*;
|
|
|
|
/// # #[derive(Component)]
|
|
|
|
/// # struct Marker;
|
|
|
|
/// fn system(query: Query<Entity, With<Marker>>, parent_query: Query<&Parent>) {
|
|
|
|
/// let entity = query.single();
|
|
|
|
/// for ancestor in parent_query.iter_ancestors(entity) {
|
|
|
|
/// // Do something!
|
|
|
|
/// }
|
|
|
|
/// }
|
|
|
|
/// # bevy_ecs::system::assert_is_system(system);
|
|
|
|
/// ```
|
2023-12-13 18:50:46 +00:00
|
|
|
fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>;
|
2022-10-31 15:57:50 +00:00
|
|
|
}
|
|
|
|
|
2023-12-13 18:50:46 +00:00
|
|
|
impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Query<'w, 's, D, F> {
|
|
|
|
fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
|
|
|
DescendantIter::new(self, entity)
|
|
|
|
}
|
|
|
|
|
2023-12-13 18:50:46 +00:00
|
|
|
fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
|
|
|
AncestorIter::new(self, entity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].
|
|
|
|
///
|
|
|
|
/// Traverses the hierarchy breadth-first.
|
2023-12-13 18:50:46 +00:00
|
|
|
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
2023-12-13 18:50:46 +00:00
|
|
|
children_query: &'w Query<'w, 's, D, F>,
|
2022-10-31 15:57:50 +00:00
|
|
|
vecdeque: VecDeque<Entity>,
|
|
|
|
}
|
|
|
|
|
2023-12-13 18:50:46 +00:00
|
|
|
impl<'w, 's, D: QueryData, F: QueryFilter> DescendantIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
|
|
|
/// Returns a new [`DescendantIter`].
|
2023-12-13 18:50:46 +00:00
|
|
|
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
|
2022-10-31 15:57:50 +00:00
|
|
|
DescendantIter {
|
|
|
|
children_query,
|
|
|
|
vecdeque: children_query
|
|
|
|
.get(entity)
|
|
|
|
.into_iter()
|
|
|
|
.flatten()
|
|
|
|
.copied()
|
|
|
|
.collect(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-13 18:50:46 +00:00
|
|
|
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for DescendantIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
|
|
|
type Item = Entity;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
let entity = self.vecdeque.pop_front()?;
|
|
|
|
|
|
|
|
if let Ok(children) = self.children_query.get(entity) {
|
|
|
|
self.vecdeque.extend(children);
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(entity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
|
2023-12-13 18:50:46 +00:00
|
|
|
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
2023-12-13 18:50:46 +00:00
|
|
|
parent_query: &'w Query<'w, 's, D, F>,
|
2022-10-31 15:57:50 +00:00
|
|
|
next: Option<Entity>,
|
|
|
|
}
|
|
|
|
|
2023-12-13 18:50:46 +00:00
|
|
|
impl<'w, 's, D: QueryData, F: QueryFilter> AncestorIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
|
|
|
/// Returns a new [`AncestorIter`].
|
2023-12-13 18:50:46 +00:00
|
|
|
pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
|
2022-10-31 15:57:50 +00:00
|
|
|
AncestorIter {
|
|
|
|
parent_query,
|
|
|
|
next: Some(entity),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-13 18:50:46 +00:00
|
|
|
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for AncestorIter<'w, 's, D, F>
|
2022-10-31 15:57:50 +00:00
|
|
|
where
|
2023-12-13 18:50:46 +00:00
|
|
|
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
|
2022-10-31 15:57:50 +00:00
|
|
|
{
|
|
|
|
type Item = Entity;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
2024-07-01 15:54:40 +00:00
|
|
|
self.next = self.parent_query.get(self.next?).ok().map(Parent::get);
|
2022-10-31 15:57:50 +00:00
|
|
|
self.next
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use bevy_ecs::{
|
|
|
|
prelude::Component,
|
|
|
|
system::{Query, SystemState},
|
|
|
|
world::World,
|
|
|
|
};
|
|
|
|
|
2024-07-01 14:29:39 +00:00
|
|
|
use crate::{query_extension::HierarchyQueryExt, BuildChildren, Children, Parent};
|
2022-10-31 15:57:50 +00:00
|
|
|
|
|
|
|
#[derive(Component, PartialEq, Debug)]
|
|
|
|
struct A(usize);
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn descendant_iter() {
|
|
|
|
let world = &mut World::new();
|
|
|
|
|
|
|
|
let [a, b, c, d] = std::array::from_fn(|i| world.spawn(A(i)).id());
|
|
|
|
|
2024-09-16 23:16:04 +00:00
|
|
|
world.entity_mut(a).add_children(&[b, c]);
|
|
|
|
world.entity_mut(c).add_children(&[d]);
|
2022-10-31 15:57:50 +00:00
|
|
|
|
|
|
|
let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world);
|
|
|
|
let (children_query, a_query) = system_state.get(world);
|
|
|
|
|
|
|
|
let result: Vec<_> = a_query
|
|
|
|
.iter_many(children_query.iter_descendants(a))
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
assert_eq!([&A(1), &A(2), &A(3)], result.as_slice());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn ancestor_iter() {
|
|
|
|
let world = &mut World::new();
|
|
|
|
|
|
|
|
let [a, b, c] = std::array::from_fn(|i| world.spawn(A(i)).id());
|
|
|
|
|
2024-09-16 23:16:04 +00:00
|
|
|
world.entity_mut(a).add_children(&[b]);
|
|
|
|
world.entity_mut(b).add_children(&[c]);
|
2022-10-31 15:57:50 +00:00
|
|
|
|
|
|
|
let mut system_state = SystemState::<(Query<&Parent>, Query<&A>)>::new(world);
|
|
|
|
let (parent_query, a_query) = system_state.get(world);
|
|
|
|
|
|
|
|
let result: Vec<_> = a_query.iter_many(parent_query.iter_ancestors(c)).collect();
|
|
|
|
|
|
|
|
assert_eq!([&A(1), &A(0)], result.as_slice());
|
|
|
|
}
|
|
|
|
}
|