bevy/crates/bevy_hierarchy/src/query_extension.rs

205 lines
6 KiB
Rust
Raw Normal View History

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},
system::Query,
};
use crate::{Children, Parent};
/// An extension trait for [`Query`] that adds hierarchy related methods.
pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
/// 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);
/// ```
fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
/// 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);
/// ```
fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>;
}
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>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
DescendantIter::new(self, entity)
}
fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
AncestorIter::new(self, entity)
}
}
/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].
///
/// Traverses the hierarchy breadth-first.
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
children_query: &'w Query<'w, 's, D, F>,
vecdeque: VecDeque<Entity>,
}
impl<'w, 's, D: QueryData, F: QueryFilter> DescendantIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
/// Returns a new [`DescendantIter`].
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
DescendantIter {
children_query,
vecdeque: children_query
.get(entity)
.into_iter()
.flatten()
.copied()
.collect(),
}
}
}
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for DescendantIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
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`].
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
parent_query: &'w Query<'w, 's, D, F>,
next: Option<Entity>,
}
impl<'w, 's, D: QueryData, F: QueryFilter> AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
/// Returns a new [`AncestorIter`].
pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
AncestorIter {
parent_query,
next: Some(entity),
}
}
}
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
type Item = Entity;
fn next(&mut self) -> Option<Self::Item> {
self.next = self.parent_query.get(self.next?).ok().map(Parent::get);
self.next
}
}
#[cfg(test)]
mod tests {
use bevy_ecs::{
prelude::Component,
system::{Query, SystemState},
world::World,
};
use crate::{query_extension::HierarchyQueryExt, BuildChildren, Children, Parent};
#[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());
world.entity_mut(a).add_children(&[b, c]);
world.entity_mut(c).add_children(&[d]);
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());
world.entity_mut(a).add_children(&[b]);
world.entity_mut(b).add_children(&[c]);
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());
}
}