Let query items borrow from query state to avoid needing to clone (#15396)
# Objective Improve the performance of `FilteredEntity(Ref|Mut)` and `Entity(Ref|Mut)Except`. `FilteredEntityRef` needs an `Access<ComponentId>` to determine what components it can access. There is one stored in the query state, but query items cannot borrow from the state, so it has to `clone()` the access for each row. Cloning the access involves memory allocations and can be expensive. ## Solution Let query items borrow from their query state. Add an `'s` lifetime to `WorldQuery::Item` and `WorldQuery::Fetch`, similar to the one in `SystemParam`, and provide `&'s Self::State` to the fetch so that it can borrow from the state. Unfortunately, there are a few cases where we currently return query items from temporary query states: the sorted iteration methods create a temporary state to query the sort keys, and the `EntityRef::components<Q>()` methods create a temporary state for their query. To allow these to continue to work with most `QueryData` implementations, introduce a new subtrait `ReleaseStateQueryData` that converts a `QueryItem<'w, 's>` to `QueryItem<'w, 'static>`, and is implemented for everything except `FilteredEntity(Ref|Mut)` and `Entity(Ref|Mut)Except`. `#[derive(QueryData)]` will generate `ReleaseStateQueryData` implementations that apply when all of the subqueries implement `ReleaseStateQueryData`. This PR does not actually change the implementation of `FilteredEntity(Ref|Mut)` or `Entity(Ref|Mut)Except`! That will be done as a follow-up PR so that the changes are easier to review. I have pushed the changes as chescock/bevy#5. ## Testing I ran performance traces of many_foxes, both against main and against chescock/bevy#5, both including #15282. These changes do appear to make generalized animation a bit faster: (Red is main, yellow is chescock/bevy#5)  ## Migration Guide The `WorldQuery::Item` and `WorldQuery::Fetch` associated types and the `QueryItem` and `ROQueryItem` type aliases now have an additional lifetime parameter corresponding to the `'s` lifetime in `Query`. Manual implementations of `WorldQuery` will need to update the method signatures to include the new lifetimes. Other uses of the types will need to be updated to include a lifetime parameter, although it can usually be passed as `'_`. In particular, `ROQueryItem` is used when implementing `RenderCommand`. Before: ```rust fn render<'w>( item: &P, view: ROQueryItem<'w, Self::ViewQuery>, entity: Option<ROQueryItem<'w, Self::ItemQuery>>, param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult; ``` After: ```rust fn render<'w>( item: &P, view: ROQueryItem<'w, '_, Self::ViewQuery>, entity: Option<ROQueryItem<'w, '_, Self::ItemQuery>>, param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult; ``` --- Methods on `QueryState` that take `&mut self` may now result in conflicting borrows if the query items capture the lifetime of the mutable reference. This affects `get()`, `iter()`, and others. To fix the errors, first call `QueryState::update_archetypes()`, and then replace a call `state.foo(world, param)` with `state.query_manual(world).foo_inner(param)`. Alternately, you may be able to restructure the code to call `state.query(world)` once and then make multiple calls using the `Query`. Before: ```rust let mut state: QueryState<_, _> = ...; let d1 = state.get(world, e1); let d2 = state.get(world, e2); // Error: cannot borrow `state` as mutable more than once at a time println!("{d1:?}"); println!("{d2:?}"); ``` After: ```rust let mut state: QueryState<_, _> = ...; state.update_archetypes(world); let d1 = state.get_manual(world, e1); let d2 = state.get_manual(world, e2); // OR state.update_archetypes(world); let d1 = state.query(world).get_inner(e1); let d2 = state.query(world).get_inner(e2); // OR let query = state.query(world); let d1 = query.get_inner(e1); let d1 = query.get_inner(e2); println!("{d1:?}"); println!("{d2:?}"); ```
This commit is contained in:
parent
e610badf6c
commit
f7e112a3c9
@ -847,7 +847,7 @@ impl ViewNode for SmaaNode {
|
||||
view_smaa_uniform_offset,
|
||||
smaa_textures,
|
||||
view_smaa_bind_groups,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
|
@ -150,20 +150,22 @@ pub struct AssetChangedState<A: AsAssetId> {
|
||||
#[expect(unsafe_code, reason = "WorldQuery is an unsafe trait.")]
|
||||
/// SAFETY: `ROQueryFetch<Self>` is the same as `QueryFetch<Self>`
|
||||
unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
|
||||
type Fetch<'w> = AssetChangedFetch<'w, A>;
|
||||
type Fetch<'w, 's> = AssetChangedFetch<'w, A>;
|
||||
|
||||
type State = AssetChangedState<A>;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
fetch: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
fetch
|
||||
}
|
||||
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
state: &Self::State,
|
||||
state: &'s Self::State,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self::Fetch<'w> {
|
||||
) -> Self::Fetch<'w, 's> {
|
||||
// SAFETY:
|
||||
// - `AssetChanges` is private and only accessed mutably in the `AssetEventSystems` system set.
|
||||
// - `resource_id` was obtained from the type ID of `AssetChanges<A::Asset>`.
|
||||
@ -201,9 +203,9 @@ unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
|
||||
|
||||
const IS_DENSE: bool = <&A>::IS_DENSE;
|
||||
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
state: &Self::State,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
state: &'s Self::State,
|
||||
archetype: &'w Archetype,
|
||||
table: &'w Table,
|
||||
) {
|
||||
@ -215,7 +217,11 @@ unsafe impl<A: AsAssetId> WorldQuery for AssetChanged<A> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) {
|
||||
unsafe fn set_table<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
state: &Self::State,
|
||||
table: &'w Table,
|
||||
) {
|
||||
if let Some(inner) = &mut fetch.inner {
|
||||
// SAFETY: We delegate to the inner `set_table` for `A`
|
||||
unsafe {
|
||||
@ -265,7 +271,7 @@ unsafe impl<A: AsAssetId> QueryFilter for AssetChanged<A> {
|
||||
|
||||
#[inline]
|
||||
unsafe fn filter_fetch(
|
||||
fetch: &mut Self::Fetch<'_>,
|
||||
fetch: &mut Self::Fetch<'_, '_>,
|
||||
entity: Entity,
|
||||
table_row: TableRow,
|
||||
) -> bool {
|
||||
|
@ -121,7 +121,7 @@ impl ViewNode for BloomNode {
|
||||
bloom_settings,
|
||||
upsampling_pipeline_ids,
|
||||
downsampling_pipeline_ids,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
if bloom_settings.intensity == 0.0 {
|
||||
|
@ -227,7 +227,7 @@ impl ExtractComponent for Bloom {
|
||||
type QueryFilter = With<Hdr>;
|
||||
type Out = (Self, BloomUniforms);
|
||||
|
||||
fn extract_component((bloom, camera): QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
|
||||
fn extract_component((bloom, camera): QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
|
||||
match (
|
||||
camera.physical_viewport_rect(),
|
||||
camera.physical_viewport_size(),
|
||||
|
@ -31,7 +31,7 @@ impl ViewNode for MainOpaquePass2dNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>,
|
||||
(camera, view, target, depth): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let (Some(opaque_phases), Some(alpha_mask_phases)) = (
|
||||
|
@ -28,7 +28,7 @@ impl ViewNode for MainTransparentPass2dNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, view, target, depth): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>,
|
||||
(camera, view, target, depth): bevy_ecs::query::QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let Some(transparent_phases) =
|
||||
|
@ -45,7 +45,7 @@ impl ViewNode for MainOpaquePass3dNode {
|
||||
skybox_pipeline,
|
||||
skybox_bind_group,
|
||||
view_uniform_offset,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let (Some(opaque_phases), Some(alpha_mask_phases)) = (
|
||||
|
@ -36,7 +36,7 @@ impl ViewNode for EarlyDeferredGBufferPrepassNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
view_query: QueryItem<'w, Self::ViewQuery>,
|
||||
view_query: QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
run_deferred_prepass(
|
||||
@ -74,7 +74,7 @@ impl ViewNode for LateDeferredGBufferPrepassNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
view_query: QueryItem<'w, Self::ViewQuery>,
|
||||
view_query: QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let (_, _, _, _, occlusion_culling, no_indirect_drawing) = view_query;
|
||||
@ -107,6 +107,7 @@ fn run_deferred_prepass<'w>(
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, extracted_view, view_depth_texture, view_prepass_textures, _, _): QueryItem<
|
||||
'w,
|
||||
'_,
|
||||
<LateDeferredGBufferPrepassNode as ViewNode>::ViewQuery,
|
||||
>,
|
||||
is_late: bool,
|
||||
|
@ -352,7 +352,7 @@ impl ViewNode for DepthOfFieldNode {
|
||||
view_bind_group_layouts,
|
||||
depth_of_field_uniform_index,
|
||||
auxiliary_dof_texture,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
|
@ -61,7 +61,7 @@ impl ViewNode for MsaaWritebackNode {
|
||||
&self,
|
||||
_graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(target, blit_pipeline_id, msaa): QueryItem<'w, Self::ViewQuery>,
|
||||
(target, blit_pipeline_id, msaa): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
if *msaa == Msaa::Off {
|
||||
|
@ -352,7 +352,7 @@ impl ViewNode for PostProcessingNode {
|
||||
&self,
|
||||
_: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(view_target, pipeline_id, chromatic_aberration, post_processing_uniform_buffer_offsets): QueryItem<'w, Self::ViewQuery>,
|
||||
(view_target, pipeline_id, chromatic_aberration, post_processing_uniform_buffer_offsets): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
@ -485,7 +485,7 @@ impl ExtractComponent for ChromaticAberration {
|
||||
type Out = ChromaticAberration;
|
||||
|
||||
fn extract_component(
|
||||
chromatic_aberration: QueryItem<'_, Self::QueryData>,
|
||||
chromatic_aberration: QueryItem<'_, '_, Self::QueryData>,
|
||||
) -> Option<Self::Out> {
|
||||
// Skip the postprocessing phase entirely if the intensity is zero.
|
||||
if chromatic_aberration.intensity > 0.0 {
|
||||
|
@ -36,7 +36,7 @@ impl ViewNode for EarlyPrepassNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
view_query: QueryItem<'w, Self::ViewQuery>,
|
||||
view_query: QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
run_prepass(graph, render_context, view_query, world, "early prepass")
|
||||
@ -73,7 +73,7 @@ impl ViewNode for LatePrepassNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
query: QueryItem<'w, Self::ViewQuery>,
|
||||
query: QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
// We only need a late prepass if we have occlusion culling and indirect
|
||||
@ -112,7 +112,7 @@ fn run_prepass<'w>(
|
||||
_,
|
||||
_,
|
||||
has_deferred,
|
||||
): QueryItem<'w, <LatePrepassNode as ViewNode>::ViewQuery>,
|
||||
): QueryItem<'w, '_, <LatePrepassNode as ViewNode>::ViewQuery>,
|
||||
world: &'w World,
|
||||
label: &'static str,
|
||||
) -> Result<(), NodeRunError> {
|
||||
|
@ -113,7 +113,9 @@ impl ExtractComponent for Skybox {
|
||||
type QueryFilter = ();
|
||||
type Out = (Self, SkyboxUniforms);
|
||||
|
||||
fn extract_component((skybox, exposure): QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
|
||||
fn extract_component(
|
||||
(skybox, exposure): QueryItem<'_, '_, Self::QueryData>,
|
||||
) -> Option<Self::Out> {
|
||||
let exposure = exposure
|
||||
.map(Exposure::exposure)
|
||||
.unwrap_or_else(|| Exposure::default().exposure());
|
||||
|
@ -76,6 +76,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
|
||||
let user_generics_with_world = {
|
||||
let mut generics = ast.generics;
|
||||
generics.params.insert(0, parse_quote!('__w));
|
||||
generics.params.insert(0, parse_quote!('__s));
|
||||
generics
|
||||
};
|
||||
let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) =
|
||||
@ -256,11 +257,11 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
|
||||
for #read_only_struct_name #user_ty_generics #user_where_clauses {
|
||||
const IS_READ_ONLY: bool = true;
|
||||
type ReadOnly = #read_only_struct_name #user_ty_generics;
|
||||
type Item<'__w> = #read_only_item_struct_name #user_ty_generics_with_world;
|
||||
type Item<'__w, '__s> = #read_only_item_struct_name #user_ty_generics_with_world;
|
||||
|
||||
fn shrink<'__wlong: '__wshort, '__wshort>(
|
||||
item: Self::Item<'__wlong>
|
||||
) -> Self::Item<'__wshort> {
|
||||
fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
|
||||
item: Self::Item<'__wlong, '__s>
|
||||
) -> Self::Item<'__wshort, '__s> {
|
||||
#read_only_item_struct_name {
|
||||
#(
|
||||
#field_idents: <#read_only_field_types>::shrink(item.#field_idents),
|
||||
@ -278,16 +279,28 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
|
||||
|
||||
/// SAFETY: we call `fetch` for each member that implements `Fetch`.
|
||||
#[inline(always)]
|
||||
unsafe fn fetch<'__w>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
|
||||
unsafe fn fetch<'__w, '__s>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
|
||||
_entity: #path::entity::Entity,
|
||||
_table_row: #path::storage::TableRow,
|
||||
) -> Self::Item<'__w> {
|
||||
) -> Self::Item<'__w, '__s> {
|
||||
Self::Item {
|
||||
#(#field_idents: <#read_only_field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl #user_impl_generics #path::query::ReleaseStateQueryData
|
||||
for #read_only_struct_name #user_ty_generics #user_where_clauses
|
||||
// Make these HRTBs with an unused lifetime parameter to allow trivial constraints
|
||||
// See https://github.com/rust-lang/rust/issues/48214
|
||||
where #(for<'__a> #field_types: #path::query::QueryData<ReadOnly: #path::query::ReleaseStateQueryData>,)* {
|
||||
fn release_state<'__w>(_item: Self::Item<'__w, '_>) -> Self::Item<'__w, 'static> {
|
||||
Self::Item {
|
||||
#(#field_idents: <#read_only_field_types>::release_state(_item.#field_idents),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
@ -301,11 +314,11 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
|
||||
for #struct_name #user_ty_generics #user_where_clauses {
|
||||
const IS_READ_ONLY: bool = #is_read_only;
|
||||
type ReadOnly = #read_only_struct_name #user_ty_generics;
|
||||
type Item<'__w> = #item_struct_name #user_ty_generics_with_world;
|
||||
type Item<'__w, '__s> = #item_struct_name #user_ty_generics_with_world;
|
||||
|
||||
fn shrink<'__wlong: '__wshort, '__wshort>(
|
||||
item: Self::Item<'__wlong>
|
||||
) -> Self::Item<'__wshort> {
|
||||
fn shrink<'__wlong: '__wshort, '__wshort, '__s>(
|
||||
item: Self::Item<'__wlong, '__s>
|
||||
) -> Self::Item<'__wshort, '__s> {
|
||||
#item_struct_name {
|
||||
#(
|
||||
#field_idents: <#field_types>::shrink(item.#field_idents),
|
||||
@ -323,17 +336,29 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream {
|
||||
|
||||
/// SAFETY: we call `fetch` for each member that implements `Fetch`.
|
||||
#[inline(always)]
|
||||
unsafe fn fetch<'__w>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
|
||||
unsafe fn fetch<'__w, '__s>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
|
||||
_entity: #path::entity::Entity,
|
||||
_table_row: #path::storage::TableRow,
|
||||
) -> Self::Item<'__w> {
|
||||
) -> Self::Item<'__w, '__s> {
|
||||
Self::Item {
|
||||
#(#field_idents: <#field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl #user_impl_generics #path::query::ReleaseStateQueryData
|
||||
for #struct_name #user_ty_generics #user_where_clauses
|
||||
// Make these HRTBs with an unused lifetime parameter to allow trivial constraints
|
||||
// See https://github.com/rust-lang/rust/issues/48214
|
||||
where #(for<'__a> #field_types: #path::query::ReleaseStateQueryData,)* {
|
||||
fn release_state<'__w>(_item: Self::Item<'__w, '_>) -> Self::Item<'__w, 'static> {
|
||||
Self::Item {
|
||||
#(#field_idents: <#field_types>::release_state(_item.#field_idents),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#read_only_data_impl
|
||||
}
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream {
|
||||
let user_generics_with_world = {
|
||||
let mut generics = ast.generics;
|
||||
generics.params.insert(0, parse_quote!('__w));
|
||||
generics.params.insert(0, parse_quote!('__s));
|
||||
generics
|
||||
};
|
||||
let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) =
|
||||
@ -101,8 +102,8 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream {
|
||||
|
||||
#[allow(unused_variables)]
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch<'__w>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
|
||||
unsafe fn filter_fetch<'__w, '__s>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
|
||||
_entity: #path::entity::Entity,
|
||||
_table_row: #path::storage::TableRow,
|
||||
) -> bool {
|
||||
|
@ -34,14 +34,14 @@ pub(crate) fn item_struct(
|
||||
#derive_macro_call
|
||||
#item_attrs
|
||||
#visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
|
||||
#(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::QueryData>::Item<'__w>,)*
|
||||
#(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::QueryData>::Item<'__w, '__s>,)*
|
||||
}
|
||||
},
|
||||
Fields::Unnamed(_) => quote! {
|
||||
#derive_macro_call
|
||||
#item_attrs
|
||||
#visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world(
|
||||
#( #field_visibilities <#field_types as #path::query::QueryData>::Item<'__w>, )*
|
||||
#( #field_visibilities <#field_types as #path::query::QueryData>::Item<'__w, '__s>, )*
|
||||
);
|
||||
},
|
||||
Fields::Unit => quote! {
|
||||
@ -78,8 +78,8 @@ pub(crate) fn world_query_impl(
|
||||
)]
|
||||
#[automatically_derived]
|
||||
#visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world {
|
||||
#(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w>,)*
|
||||
#marker_name: &'__w (),
|
||||
#(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w, '__s>,)*
|
||||
#marker_name: (&'__w(), &'__s()),
|
||||
}
|
||||
|
||||
impl #user_impl_generics_with_world Clone for #fetch_struct_name #user_ty_generics_with_world
|
||||
@ -87,7 +87,7 @@ pub(crate) fn world_query_impl(
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
#(#named_field_idents: self.#named_field_idents.clone(),)*
|
||||
#marker_name: &(),
|
||||
#marker_name: (&(), &()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -96,26 +96,26 @@ pub(crate) fn world_query_impl(
|
||||
unsafe impl #user_impl_generics #path::query::WorldQuery
|
||||
for #struct_name #user_ty_generics #user_where_clauses {
|
||||
|
||||
type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world;
|
||||
type Fetch<'__w, '__s> = #fetch_struct_name #user_ty_generics_with_world;
|
||||
type State = #state_struct_name #user_ty_generics;
|
||||
|
||||
fn shrink_fetch<'__wlong: '__wshort, '__wshort>(
|
||||
fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong>
|
||||
) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort> {
|
||||
fn shrink_fetch<'__wlong: '__wshort, '__wshort, '__s>(
|
||||
fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong, '__s>
|
||||
) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort, '__s> {
|
||||
#fetch_struct_name {
|
||||
#(
|
||||
#named_field_idents: <#field_types>::shrink_fetch(fetch.#named_field_idents),
|
||||
)*
|
||||
#marker_name: &(),
|
||||
#marker_name: (&(), &()),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn init_fetch<'__w>(
|
||||
unsafe fn init_fetch<'__w, '__s>(
|
||||
_world: #path::world::unsafe_world_cell::UnsafeWorldCell<'__w>,
|
||||
state: &Self::State,
|
||||
state: &'__s Self::State,
|
||||
_last_run: #path::component::Tick,
|
||||
_this_run: #path::component::Tick,
|
||||
) -> <Self as #path::query::WorldQuery>::Fetch<'__w> {
|
||||
) -> <Self as #path::query::WorldQuery>::Fetch<'__w, '__s> {
|
||||
#fetch_struct_name {
|
||||
#(#named_field_idents:
|
||||
<#field_types>::init_fetch(
|
||||
@ -125,7 +125,7 @@ pub(crate) fn world_query_impl(
|
||||
_this_run,
|
||||
),
|
||||
)*
|
||||
#marker_name: &(),
|
||||
#marker_name: (&(), &()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,9 +133,9 @@ pub(crate) fn world_query_impl(
|
||||
|
||||
/// SAFETY: we call `set_archetype` for each member that implements `Fetch`
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'__w>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
|
||||
_state: &Self::State,
|
||||
unsafe fn set_archetype<'__w, '__s>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
|
||||
_state: &'__s Self::State,
|
||||
_archetype: &'__w #path::archetype::Archetype,
|
||||
_table: &'__w #path::storage::Table
|
||||
) {
|
||||
@ -144,9 +144,9 @@ pub(crate) fn world_query_impl(
|
||||
|
||||
/// SAFETY: we call `set_table` for each member that implements `Fetch`
|
||||
#[inline]
|
||||
unsafe fn set_table<'__w>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w>,
|
||||
_state: &Self::State,
|
||||
unsafe fn set_table<'__w, '__s>(
|
||||
_fetch: &mut <Self as #path::query::WorldQuery>::Fetch<'__w, '__s>,
|
||||
_state: &'__s Self::State,
|
||||
_table: &'__w #path::storage::Table
|
||||
) {
|
||||
#(<#field_types>::set_table(&mut _fetch.#named_field_idents, &_state.#named_field_idents, _table);)*
|
||||
|
@ -141,7 +141,7 @@ pub struct NameOrEntity {
|
||||
pub entity: Entity,
|
||||
}
|
||||
|
||||
impl<'a> core::fmt::Display for NameOrEntityItem<'a> {
|
||||
impl<'w, 's> core::fmt::Display for NameOrEntityItem<'w, 's> {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
match self.name {
|
||||
@ -274,9 +274,9 @@ mod tests {
|
||||
let e2 = world.spawn(name.clone()).id();
|
||||
let mut query = world.query::<NameOrEntity>();
|
||||
let d1 = query.get(&world, e1).unwrap();
|
||||
let d2 = query.get(&world, e2).unwrap();
|
||||
// NameOrEntity Display for entities without a Name should be {index}v{generation}
|
||||
assert_eq!(d1.to_string(), "0v0");
|
||||
let d2 = query.get(&world, e2).unwrap();
|
||||
// NameOrEntity Display for entities with a Name should be the Name
|
||||
assert_eq!(d2.to_string(), "MyName");
|
||||
}
|
||||
|
@ -1078,7 +1078,7 @@ mod tests {
|
||||
struct ChildOf(Entity);
|
||||
|
||||
impl<D> Traversal<D> for &'_ ChildOf {
|
||||
fn traverse(item: Self::Item<'_>, _: &D) -> Option<Entity> {
|
||||
fn traverse(item: Self::Item<'_, '_>, _: &D) -> Option<Entity> {
|
||||
Some(item.0)
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -103,7 +103,7 @@ pub unsafe trait QueryFilter: WorldQuery {
|
||||
/// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and
|
||||
/// `table_row` must be in the range of the current table and archetype.
|
||||
unsafe fn filter_fetch(
|
||||
fetch: &mut Self::Fetch<'_>,
|
||||
fetch: &mut Self::Fetch<'_, '_>,
|
||||
entity: Entity,
|
||||
table_row: TableRow,
|
||||
) -> bool;
|
||||
@ -144,10 +144,13 @@ pub struct With<T>(PhantomData<T>);
|
||||
/// `update_component_access` adds a `With` filter for `T`.
|
||||
/// This is sound because `matches_component_set` returns whether the set contains the component.
|
||||
unsafe impl<T: Component> WorldQuery for With<T> {
|
||||
type Fetch<'w> = ();
|
||||
type Fetch<'w, 's> = ();
|
||||
type State = ComponentId;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
_: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch(
|
||||
@ -204,7 +207,7 @@ unsafe impl<T: Component> QueryFilter for With<T> {
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(
|
||||
_fetch: &mut Self::Fetch<'_>,
|
||||
_fetch: &mut Self::Fetch<'_, '_>,
|
||||
_entity: Entity,
|
||||
_table_row: TableRow,
|
||||
) -> bool {
|
||||
@ -244,10 +247,13 @@ pub struct Without<T>(PhantomData<T>);
|
||||
/// `update_component_access` adds a `Without` filter for `T`.
|
||||
/// This is sound because `matches_component_set` returns whether the set does not contain the component.
|
||||
unsafe impl<T: Component> WorldQuery for Without<T> {
|
||||
type Fetch<'w> = ();
|
||||
type Fetch<'w, 's> = ();
|
||||
type State = ComponentId;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
_: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch(
|
||||
@ -304,7 +310,7 @@ unsafe impl<T: Component> QueryFilter for Without<T> {
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(
|
||||
_fetch: &mut Self::Fetch<'_>,
|
||||
_fetch: &mut Self::Fetch<'_, '_>,
|
||||
_entity: Entity,
|
||||
_table_row: TableRow,
|
||||
) -> bool {
|
||||
@ -345,12 +351,12 @@ unsafe impl<T: Component> QueryFilter for Without<T> {
|
||||
pub struct Or<T>(PhantomData<T>);
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct OrFetch<'w, T: WorldQuery> {
|
||||
fetch: T::Fetch<'w>,
|
||||
pub struct OrFetch<'w, 's, T: WorldQuery> {
|
||||
fetch: T::Fetch<'w, 's>,
|
||||
matches: bool,
|
||||
}
|
||||
|
||||
impl<T: WorldQuery> Clone for OrFetch<'_, T> {
|
||||
impl<T: WorldQuery> Clone for OrFetch<'_, '_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
fetch: self.fetch.clone(),
|
||||
@ -384,10 +390,10 @@ macro_rules! impl_or_query_filter {
|
||||
/// `update_component_access` replace the filters with a disjunction where every element is a conjunction of the previous filters and the filters of one of the subqueries.
|
||||
/// This is sound because `matches_component_set` returns a disjunction of the results of the subqueries' implementations.
|
||||
unsafe impl<$($filter: QueryFilter),*> WorldQuery for Or<($($filter,)*)> {
|
||||
type Fetch<'w> = ($(OrFetch<'w, $filter>,)*);
|
||||
type Fetch<'w, 's> = ($(OrFetch<'w, 's, $filter>,)*);
|
||||
type State = ($($filter::State,)*);
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> {
|
||||
let ($($filter,)*) = fetch;
|
||||
($(
|
||||
OrFetch {
|
||||
@ -400,7 +406,7 @@ macro_rules! impl_or_query_filter {
|
||||
const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*;
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch<'w>(world: UnsafeWorldCell<'w>, state: &Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> {
|
||||
unsafe fn init_fetch<'w, 's>(world: UnsafeWorldCell<'w>, state: &'s Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w, 's> {
|
||||
let ($($filter,)*) = state;
|
||||
($(OrFetch {
|
||||
// SAFETY: The invariants are upheld by the caller.
|
||||
@ -410,7 +416,7 @@ macro_rules! impl_or_query_filter {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) {
|
||||
unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w, 's>, state: &'s Self::State, table: &'w Table) {
|
||||
let ($($filter,)*) = fetch;
|
||||
let ($($state,)*) = state;
|
||||
$(
|
||||
@ -423,9 +429,9 @@ macro_rules! impl_or_query_filter {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
state: & Self::State,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
state: &'s Self::State,
|
||||
archetype: &'w Archetype,
|
||||
table: &'w Table
|
||||
) {
|
||||
@ -495,7 +501,7 @@ macro_rules! impl_or_query_filter {
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(
|
||||
fetch: &mut Self::Fetch<'_>,
|
||||
fetch: &mut Self::Fetch<'_, '_>,
|
||||
entity: Entity,
|
||||
table_row: TableRow
|
||||
) -> bool {
|
||||
@ -528,7 +534,7 @@ macro_rules! impl_tuple_query_filter {
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(
|
||||
fetch: &mut Self::Fetch<'_>,
|
||||
fetch: &mut Self::Fetch<'_, '_>,
|
||||
entity: Entity,
|
||||
table_row: TableRow
|
||||
) -> bool {
|
||||
@ -568,10 +574,13 @@ pub struct Allows<T>(PhantomData<T>);
|
||||
/// `update_component_access` adds an archetypal filter for `T`.
|
||||
/// This is sound because it doesn't affect the query
|
||||
unsafe impl<T: Component> WorldQuery for Allows<T> {
|
||||
type Fetch<'w> = ();
|
||||
type Fetch<'w, 's> = ();
|
||||
type State = ComponentId;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
_: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch(_: UnsafeWorldCell, _: &ComponentId, _: Tick, _: Tick) {}
|
||||
@ -609,7 +618,7 @@ unsafe impl<T: Component> QueryFilter for Allows<T> {
|
||||
const IS_ARCHETYPAL: bool = true;
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(_: &mut Self::Fetch<'_>, _: Entity, _: TableRow) -> bool {
|
||||
unsafe fn filter_fetch(_: &mut Self::Fetch<'_, '_>, _: Entity, _: TableRow) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -710,21 +719,23 @@ impl<T: Component> Clone for AddedFetch<'_, T> {
|
||||
/// `update_component_access` adds a `With` filter for a component.
|
||||
/// This is sound because `matches_component_set` returns whether the set contains that component.
|
||||
unsafe impl<T: Component> WorldQuery for Added<T> {
|
||||
type Fetch<'w> = AddedFetch<'w, T>;
|
||||
type Fetch<'w, 's> = AddedFetch<'w, T>;
|
||||
type State = ComponentId;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
fetch: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
fetch
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
&id: &ComponentId,
|
||||
&id: &'s ComponentId,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self::Fetch<'w> {
|
||||
Self::Fetch::<'w> {
|
||||
) -> Self::Fetch<'w, 's> {
|
||||
Self::Fetch::<'w, 's> {
|
||||
ticks: StorageSwitch::new(
|
||||
|| None,
|
||||
|| {
|
||||
@ -748,9 +759,9 @@ unsafe impl<T: Component> WorldQuery for Added<T> {
|
||||
};
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
component_id: &ComponentId,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
component_id: &'s ComponentId,
|
||||
_archetype: &'w Archetype,
|
||||
table: &'w Table,
|
||||
) {
|
||||
@ -763,9 +774,9 @@ unsafe impl<T: Component> WorldQuery for Added<T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
&component_id: &ComponentId,
|
||||
unsafe fn set_table<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
&component_id: &'s ComponentId,
|
||||
table: &'w Table,
|
||||
) {
|
||||
let table_ticks = Some(
|
||||
@ -807,7 +818,7 @@ unsafe impl<T: Component> QueryFilter for Added<T> {
|
||||
const IS_ARCHETYPAL: bool = false;
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(
|
||||
fetch: &mut Self::Fetch<'_>,
|
||||
fetch: &mut Self::Fetch<'_, '_>,
|
||||
entity: Entity,
|
||||
table_row: TableRow,
|
||||
) -> bool {
|
||||
@ -936,21 +947,23 @@ impl<T: Component> Clone for ChangedFetch<'_, T> {
|
||||
/// `update_component_access` adds a `With` filter for a component.
|
||||
/// This is sound because `matches_component_set` returns whether the set contains that component.
|
||||
unsafe impl<T: Component> WorldQuery for Changed<T> {
|
||||
type Fetch<'w> = ChangedFetch<'w, T>;
|
||||
type Fetch<'w, 's> = ChangedFetch<'w, T>;
|
||||
type State = ComponentId;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
fetch: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
fetch
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
&id: &ComponentId,
|
||||
&id: &'s ComponentId,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self::Fetch<'w> {
|
||||
Self::Fetch::<'w> {
|
||||
) -> Self::Fetch<'w, 's> {
|
||||
Self::Fetch::<'w, 's> {
|
||||
ticks: StorageSwitch::new(
|
||||
|| None,
|
||||
|| {
|
||||
@ -974,9 +987,9 @@ unsafe impl<T: Component> WorldQuery for Changed<T> {
|
||||
};
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
component_id: &ComponentId,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
component_id: &'s ComponentId,
|
||||
_archetype: &'w Archetype,
|
||||
table: &'w Table,
|
||||
) {
|
||||
@ -989,9 +1002,9 @@ unsafe impl<T: Component> WorldQuery for Changed<T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
&component_id: &ComponentId,
|
||||
unsafe fn set_table<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
&component_id: &'s ComponentId,
|
||||
table: &'w Table,
|
||||
) {
|
||||
let table_ticks = Some(
|
||||
@ -1034,7 +1047,7 @@ unsafe impl<T: Component> QueryFilter for Changed<T> {
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(
|
||||
fetch: &mut Self::Fetch<'_>,
|
||||
fetch: &mut Self::Fetch<'_, '_>,
|
||||
entity: Entity,
|
||||
table_row: TableRow,
|
||||
) -> bool {
|
||||
@ -1133,20 +1146,22 @@ pub struct SpawnedFetch<'w> {
|
||||
|
||||
// SAFETY: WorldQuery impl accesses no components or component ticks
|
||||
unsafe impl WorldQuery for Spawned {
|
||||
type Fetch<'w> = SpawnedFetch<'w>;
|
||||
type Fetch<'w, 's> = SpawnedFetch<'w>;
|
||||
type State = ();
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
fetch: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
fetch
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
_state: &(),
|
||||
_state: &'s (),
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self::Fetch<'w> {
|
||||
) -> Self::Fetch<'w, 's> {
|
||||
SpawnedFetch {
|
||||
entities: world.entities(),
|
||||
last_run,
|
||||
@ -1157,16 +1172,21 @@ unsafe impl WorldQuery for Spawned {
|
||||
const IS_DENSE: bool = true;
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
_fetch: &mut Self::Fetch<'w>,
|
||||
_state: &(),
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
_fetch: &mut Self::Fetch<'w, 's>,
|
||||
_state: &'s (),
|
||||
_archetype: &'w Archetype,
|
||||
_table: &'w Table,
|
||||
) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &(), _table: &'w Table) {}
|
||||
unsafe fn set_table<'w, 's>(
|
||||
_fetch: &mut Self::Fetch<'w, 's>,
|
||||
_state: &'s (),
|
||||
_table: &'w Table,
|
||||
) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_component_access(_state: &(), _access: &mut FilteredAccess<ComponentId>) {}
|
||||
@ -1188,7 +1208,7 @@ unsafe impl QueryFilter for Spawned {
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn filter_fetch(
|
||||
fetch: &mut Self::Fetch<'_>,
|
||||
fetch: &mut Self::Fetch<'_, '_>,
|
||||
entity: Entity,
|
||||
_table_row: TableRow,
|
||||
) -> bool {
|
||||
|
@ -140,7 +140,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
range: Option<Range<u32>>,
|
||||
) -> B
|
||||
where
|
||||
Func: FnMut(B, D::Item<'w>) -> B,
|
||||
Func: FnMut(B, D::Item<'w, 's>) -> B,
|
||||
{
|
||||
if self.cursor.is_dense {
|
||||
// SAFETY: `self.cursor.is_dense` is true, so storage ids are guaranteed to be table ids.
|
||||
@ -203,7 +203,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
rows: Range<u32>,
|
||||
) -> B
|
||||
where
|
||||
Func: FnMut(B, D::Item<'w>) -> B,
|
||||
Func: FnMut(B, D::Item<'w, 's>) -> B,
|
||||
{
|
||||
if table.is_empty() {
|
||||
return accum;
|
||||
@ -255,7 +255,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
indices: Range<u32>,
|
||||
) -> B
|
||||
where
|
||||
Func: FnMut(B, D::Item<'w>) -> B,
|
||||
Func: FnMut(B, D::Item<'w, 's>) -> B,
|
||||
{
|
||||
if archetype.is_empty() {
|
||||
return accum;
|
||||
@ -324,7 +324,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
rows: Range<u32>,
|
||||
) -> B
|
||||
where
|
||||
Func: FnMut(B, D::Item<'w>) -> B,
|
||||
Func: FnMut(B, D::Item<'w, 's>) -> B,
|
||||
{
|
||||
if archetype.is_empty() {
|
||||
return accum;
|
||||
@ -492,7 +492,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
|
||||
>
|
||||
where
|
||||
for<'lw> L::Item<'lw>: Ord,
|
||||
for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
|
||||
{
|
||||
self.sort_impl::<L>(|keyed_query| keyed_query.sort())
|
||||
}
|
||||
@ -549,7 +549,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
|
||||
>
|
||||
where
|
||||
for<'lw> L::Item<'lw>: Ord,
|
||||
for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
|
||||
{
|
||||
self.sort_impl::<L>(|keyed_query| keyed_query.sort_unstable())
|
||||
}
|
||||
@ -605,7 +605,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
/// ```
|
||||
pub fn sort_by<L: ReadOnlyQueryData + 'w>(
|
||||
self,
|
||||
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
|
||||
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
|
||||
) -> QuerySortedIter<
|
||||
'w,
|
||||
's,
|
||||
@ -637,7 +637,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
|
||||
pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>(
|
||||
self,
|
||||
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
|
||||
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
|
||||
) -> QuerySortedIter<
|
||||
'w,
|
||||
's,
|
||||
@ -729,7 +729,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
/// ```
|
||||
pub fn sort_by_key<L: ReadOnlyQueryData + 'w, K>(
|
||||
self,
|
||||
mut f: impl FnMut(&L::Item<'_>) -> K,
|
||||
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
|
||||
) -> QuerySortedIter<
|
||||
'w,
|
||||
's,
|
||||
@ -762,7 +762,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
|
||||
pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>(
|
||||
self,
|
||||
mut f: impl FnMut(&L::Item<'_>) -> K,
|
||||
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
|
||||
) -> QuerySortedIter<
|
||||
'w,
|
||||
's,
|
||||
@ -797,7 +797,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
|
||||
pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>(
|
||||
self,
|
||||
mut f: impl FnMut(&L::Item<'_>) -> K,
|
||||
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
|
||||
) -> QuerySortedIter<
|
||||
'w,
|
||||
's,
|
||||
@ -827,7 +827,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
/// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty.
|
||||
fn sort_impl<L: ReadOnlyQueryData + 'w>(
|
||||
self,
|
||||
f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd<Entity>)>),
|
||||
f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd<Entity>)>),
|
||||
) -> QuerySortedIter<
|
||||
'w,
|
||||
's,
|
||||
@ -856,7 +856,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
.map(|(key, entity)| (key, NeutralOrd(entity)))
|
||||
.collect();
|
||||
f(&mut keyed_query);
|
||||
let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity.0);
|
||||
let entity_iter = keyed_query
|
||||
.into_iter()
|
||||
.map(|(.., entity)| entity.0)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter();
|
||||
// SAFETY:
|
||||
// `self.world` has permission to access the required components.
|
||||
// Each lens query item is dropped before the respective actual query item is accessed.
|
||||
@ -873,7 +877,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> {
|
||||
}
|
||||
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for QueryIter<'w, 's, D, F> {
|
||||
type Item = D::Item<'w>;
|
||||
type Item = D::Item<'w, 's>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -975,7 +979,7 @@ where
|
||||
entities: &'w Entities,
|
||||
tables: &'w Tables,
|
||||
archetypes: &'w Archetypes,
|
||||
fetch: D::Fetch<'w>,
|
||||
fetch: D::Fetch<'w, 's>,
|
||||
query_state: &'s QueryState<D, F>,
|
||||
}
|
||||
|
||||
@ -1010,7 +1014,7 @@ where
|
||||
/// # Safety
|
||||
/// `entity` must stem from `self.entity_iter`, and not have been passed before.
|
||||
#[inline(always)]
|
||||
unsafe fn fetch_next(&mut self, entity: Entity) -> D::Item<'w> {
|
||||
unsafe fn fetch_next(&mut self, entity: Entity) -> D::Item<'w, 's> {
|
||||
let (location, archetype, table);
|
||||
// SAFETY:
|
||||
// `tables` and `archetypes` belong to the same world that the [`QueryIter`]
|
||||
@ -1048,7 +1052,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Iterator
|
||||
where
|
||||
I: Iterator<Item = Entity>,
|
||||
{
|
||||
type Item = D::Item<'w>;
|
||||
type Item = D::Item<'w, 's>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -1119,8 +1123,8 @@ pub struct QueryManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item:
|
||||
entities: &'w Entities,
|
||||
tables: &'w Tables,
|
||||
archetypes: &'w Archetypes,
|
||||
fetch: D::Fetch<'w>,
|
||||
filter: F::Fetch<'w>,
|
||||
fetch: D::Fetch<'w, 's>,
|
||||
filter: F::Fetch<'w, 's>,
|
||||
query_state: &'s QueryState<D, F>,
|
||||
}
|
||||
|
||||
@ -1167,10 +1171,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
entities: &'w Entities,
|
||||
tables: &'w Tables,
|
||||
archetypes: &'w Archetypes,
|
||||
fetch: &mut D::Fetch<'w>,
|
||||
filter: &mut F::Fetch<'w>,
|
||||
fetch: &mut D::Fetch<'w, 's>,
|
||||
filter: &mut F::Fetch<'w, 's>,
|
||||
query_state: &'s QueryState<D, F>,
|
||||
) -> Option<D::Item<'w>> {
|
||||
) -> Option<D::Item<'w, 's>> {
|
||||
for entity_borrow in entity_iter {
|
||||
let entity = entity_borrow.entity();
|
||||
let Some(location) = entities.get(entity) else {
|
||||
@ -1212,7 +1216,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
|
||||
/// Get next result from the query
|
||||
#[inline(always)]
|
||||
pub fn fetch_next(&mut self) -> Option<D::Item<'_>> {
|
||||
pub fn fetch_next(&mut self) -> Option<D::Item<'_, 's>> {
|
||||
// SAFETY:
|
||||
// All arguments stem from self.
|
||||
// We are limiting the returned reference to self,
|
||||
@ -1336,7 +1340,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
|
||||
>
|
||||
where
|
||||
for<'lw> L::Item<'lw>: Ord,
|
||||
for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
|
||||
{
|
||||
self.sort_impl::<L>(|keyed_query| keyed_query.sort())
|
||||
}
|
||||
@ -1394,7 +1398,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
impl ExactSizeIterator<Item = Entity> + DoubleEndedIterator + FusedIterator + 'w,
|
||||
>
|
||||
where
|
||||
for<'lw> L::Item<'lw>: Ord,
|
||||
for<'lw, 'ls> L::Item<'lw, 'ls>: Ord,
|
||||
{
|
||||
self.sort_impl::<L>(|keyed_query| keyed_query.sort_unstable())
|
||||
}
|
||||
@ -1451,7 +1455,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
/// ```
|
||||
pub fn sort_by<L: ReadOnlyQueryData + 'w>(
|
||||
self,
|
||||
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
|
||||
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
|
||||
) -> QuerySortedManyIter<
|
||||
'w,
|
||||
's,
|
||||
@ -1482,7 +1486,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
/// called on [`QueryManyIter`] before.
|
||||
pub fn sort_unstable_by<L: ReadOnlyQueryData + 'w>(
|
||||
self,
|
||||
mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering,
|
||||
mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering,
|
||||
) -> QuerySortedManyIter<
|
||||
'w,
|
||||
's,
|
||||
@ -1576,7 +1580,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
/// ```
|
||||
pub fn sort_by_key<L: ReadOnlyQueryData + 'w, K>(
|
||||
self,
|
||||
mut f: impl FnMut(&L::Item<'_>) -> K,
|
||||
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
|
||||
) -> QuerySortedManyIter<
|
||||
'w,
|
||||
's,
|
||||
@ -1608,7 +1612,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
/// called on [`QueryManyIter`] before.
|
||||
pub fn sort_unstable_by_key<L: ReadOnlyQueryData + 'w, K>(
|
||||
self,
|
||||
mut f: impl FnMut(&L::Item<'_>) -> K,
|
||||
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
|
||||
) -> QuerySortedManyIter<
|
||||
'w,
|
||||
's,
|
||||
@ -1642,7 +1646,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
/// called on [`QueryManyIter`] before.
|
||||
pub fn sort_by_cached_key<L: ReadOnlyQueryData + 'w, K>(
|
||||
self,
|
||||
mut f: impl FnMut(&L::Item<'_>) -> K,
|
||||
mut f: impl FnMut(&L::Item<'_, '_>) -> K,
|
||||
) -> QuerySortedManyIter<
|
||||
'w,
|
||||
's,
|
||||
@ -1671,7 +1675,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>>
|
||||
/// called on [`QueryManyIter`] before.
|
||||
fn sort_impl<L: ReadOnlyQueryData + 'w>(
|
||||
self,
|
||||
f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd<Entity>)>),
|
||||
f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd<Entity>)>),
|
||||
) -> QuerySortedManyIter<
|
||||
'w,
|
||||
's,
|
||||
@ -1721,7 +1725,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item: EntityEq
|
||||
{
|
||||
/// Get next result from the back of the query
|
||||
#[inline(always)]
|
||||
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_>> {
|
||||
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_, 's>> {
|
||||
// SAFETY:
|
||||
// All arguments stem from self.
|
||||
// We are limiting the returned reference to self,
|
||||
@ -1745,7 +1749,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item: EntityEq
|
||||
impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator<Item: EntityEquivalent>> Iterator
|
||||
for QueryManyIter<'w, 's, D, F, I>
|
||||
{
|
||||
type Item = D::Item<'w>;
|
||||
type Item = D::Item<'w, 's>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -1861,7 +1865,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator>
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Iterator
|
||||
for QueryManyUniqueIter<'w, 's, D, F, I>
|
||||
{
|
||||
type Item = D::Item<'w>;
|
||||
type Item = D::Item<'w, 's>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -1915,7 +1919,7 @@ pub struct QuerySortedManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator
|
||||
entities: &'w Entities,
|
||||
tables: &'w Tables,
|
||||
archetypes: &'w Archetypes,
|
||||
fetch: D::Fetch<'w>,
|
||||
fetch: D::Fetch<'w, 's>,
|
||||
query_state: &'s QueryState<D, F>,
|
||||
}
|
||||
|
||||
@ -1954,7 +1958,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item = Entity>>
|
||||
/// It is always safe for shared access.
|
||||
/// `entity` must stem from `self.entity_iter`, and not have been passed before.
|
||||
#[inline(always)]
|
||||
unsafe fn fetch_next_aliased_unchecked(&mut self, entity: Entity) -> D::Item<'w> {
|
||||
unsafe fn fetch_next_aliased_unchecked(&mut self, entity: Entity) -> D::Item<'w, 's> {
|
||||
let (location, archetype, table);
|
||||
// SAFETY:
|
||||
// `tables` and `archetypes` belong to the same world that the [`QueryIter`]
|
||||
@ -1988,7 +1992,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator<Item = Entity>>
|
||||
|
||||
/// Get next result from the query
|
||||
#[inline(always)]
|
||||
pub fn fetch_next(&mut self) -> Option<D::Item<'_>> {
|
||||
pub fn fetch_next(&mut self) -> Option<D::Item<'_, 's>> {
|
||||
let entity = self.entity_iter.next()?;
|
||||
|
||||
// SAFETY:
|
||||
@ -2007,7 +2011,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item = Entity>
|
||||
{
|
||||
/// Get next result from the query
|
||||
#[inline(always)]
|
||||
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_>> {
|
||||
pub fn fetch_next_back(&mut self) -> Option<D::Item<'_, 's>> {
|
||||
let entity = self.entity_iter.next_back()?;
|
||||
|
||||
// SAFETY:
|
||||
@ -2024,7 +2028,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator<Item = Entity>
|
||||
impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator<Item = Entity>> Iterator
|
||||
for QuerySortedManyIter<'w, 's, D, F, I>
|
||||
{
|
||||
type Item = D::Item<'w>;
|
||||
type Item = D::Item<'w, 's>;
|
||||
|
||||
#[inline(always)]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -2185,7 +2189,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
|
||||
/// .
|
||||
/// It is always safe for shared access.
|
||||
#[inline]
|
||||
unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<[D::Item<'w>; K]> {
|
||||
unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<[D::Item<'w, 's>; K]> {
|
||||
// PERF: can speed up the following code using `cursor.remaining()` instead of `next_item.is_none()`
|
||||
// when D::IS_ARCHETYPAL && F::IS_ARCHETYPAL
|
||||
//
|
||||
@ -2211,9 +2215,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
|
||||
}
|
||||
}
|
||||
|
||||
let mut values = MaybeUninit::<[D::Item<'w>; K]>::uninit();
|
||||
let mut values = MaybeUninit::<[D::Item<'w, 's>; K]>::uninit();
|
||||
|
||||
let ptr = values.as_mut_ptr().cast::<D::Item<'w>>();
|
||||
let ptr = values.as_mut_ptr().cast::<D::Item<'w, 's>>();
|
||||
for (offset, cursor) in self.cursors.iter_mut().enumerate() {
|
||||
ptr.add(offset).write(cursor.peek_last().unwrap());
|
||||
}
|
||||
@ -2223,7 +2227,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
|
||||
|
||||
/// Get next combination of queried components
|
||||
#[inline]
|
||||
pub fn fetch_next(&mut self) -> Option<[D::Item<'_>; K]> {
|
||||
pub fn fetch_next(&mut self) -> Option<[D::Item<'_, 's>; K]> {
|
||||
// SAFETY: we are limiting the returned reference to self,
|
||||
// making sure this method cannot be called multiple times without getting rid
|
||||
// of any previously returned unique references first, thus preventing aliasing.
|
||||
@ -2240,7 +2244,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<
|
||||
impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, const K: usize> Iterator
|
||||
for QueryCombinationIter<'w, 's, D, F, K>
|
||||
{
|
||||
type Item = [D::Item<'w>; K];
|
||||
type Item = [D::Item<'w, 's>; K];
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@ -2309,8 +2313,8 @@ struct QueryIterationCursor<'w, 's, D: QueryData, F: QueryFilter> {
|
||||
storage_id_iter: core::slice::Iter<'s, StorageId>,
|
||||
table_entities: &'w [Entity],
|
||||
archetype_entities: &'w [ArchetypeEntity],
|
||||
fetch: D::Fetch<'w>,
|
||||
filter: F::Fetch<'w>,
|
||||
fetch: D::Fetch<'w, 's>,
|
||||
filter: F::Fetch<'w, 's>,
|
||||
// length of the table or length of the archetype, depending on whether both `D`'s and `F`'s fetches are dense
|
||||
current_len: u32,
|
||||
// either table row or archetype index, depending on whether both `D`'s and `F`'s fetches are dense
|
||||
@ -2390,7 +2394,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> {
|
||||
/// The result of `next` and any previous calls to `peek_last` with this row must have been
|
||||
/// dropped to prevent aliasing mutable references.
|
||||
#[inline]
|
||||
unsafe fn peek_last(&mut self) -> Option<D::Item<'w>> {
|
||||
unsafe fn peek_last(&mut self) -> Option<D::Item<'w, 's>> {
|
||||
if self.current_row > 0 {
|
||||
let index = self.current_row - 1;
|
||||
if self.is_dense {
|
||||
@ -2457,7 +2461,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> {
|
||||
tables: &'w Tables,
|
||||
archetypes: &'w Archetypes,
|
||||
query_state: &'s QueryState<D, F>,
|
||||
) -> Option<D::Item<'w>> {
|
||||
) -> Option<D::Item<'w, 's>> {
|
||||
if self.is_dense {
|
||||
loop {
|
||||
// we are on the beginning of the query, or finished processing a table, so skip to the next
|
||||
|
@ -819,34 +819,37 @@ mod tests {
|
||||
/// SAFETY:
|
||||
/// `update_component_access` adds resource read access for `R`.
|
||||
unsafe impl WorldQuery for ReadsRData {
|
||||
type Fetch<'w> = ();
|
||||
type Fetch<'w, 's> = ();
|
||||
type State = ComponentId;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
_: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
}
|
||||
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
_world: UnsafeWorldCell<'w>,
|
||||
_state: &Self::State,
|
||||
_state: &'s Self::State,
|
||||
_last_run: Tick,
|
||||
_this_run: Tick,
|
||||
) -> Self::Fetch<'w> {
|
||||
) -> Self::Fetch<'w, 's> {
|
||||
}
|
||||
|
||||
const IS_DENSE: bool = true;
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
_fetch: &mut Self::Fetch<'w>,
|
||||
_state: &Self::State,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
_fetch: &mut Self::Fetch<'w, 's>,
|
||||
_state: &'s Self::State,
|
||||
_archetype: &'w Archetype,
|
||||
_table: &Table,
|
||||
) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(
|
||||
_fetch: &mut Self::Fetch<'w>,
|
||||
_state: &Self::State,
|
||||
unsafe fn set_table<'w, 's>(
|
||||
_fetch: &mut Self::Fetch<'w, 's>,
|
||||
_state: &'s Self::State,
|
||||
_table: &'w Table,
|
||||
) {
|
||||
}
|
||||
@ -882,16 +885,19 @@ mod tests {
|
||||
unsafe impl QueryData for ReadsRData {
|
||||
const IS_READ_ONLY: bool = true;
|
||||
type ReadOnly = Self;
|
||||
type Item<'w> = ();
|
||||
type Item<'w, 's> = ();
|
||||
|
||||
fn shrink<'wlong: 'wshort, 'wshort>(_item: Self::Item<'wlong>) -> Self::Item<'wshort> {}
|
||||
fn shrink<'wlong: 'wshort, 'wshort, 's>(
|
||||
_item: Self::Item<'wlong, 's>,
|
||||
) -> Self::Item<'wshort, 's> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn fetch<'w>(
|
||||
_fetch: &mut Self::Fetch<'w>,
|
||||
unsafe fn fetch<'w, 's>(
|
||||
_fetch: &mut Self::Fetch<'w, 's>,
|
||||
_entity: Entity,
|
||||
_table_row: TableRow,
|
||||
) -> Self::Item<'w> {
|
||||
) -> Self::Item<'w, 's> {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> {
|
||||
///
|
||||
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
|
||||
#[inline]
|
||||
pub fn for_each<FN: Fn(QueryItem<'w, D>) + Send + Sync + Clone>(self, func: FN) {
|
||||
pub fn for_each<FN: Fn(QueryItem<'w, 's, D>) + Send + Sync + Clone>(self, func: FN) {
|
||||
self.for_each_init(|| {}, |_, item| func(item));
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> {
|
||||
#[inline]
|
||||
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
|
||||
where
|
||||
FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone,
|
||||
FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone,
|
||||
INIT: Fn() -> T + Sync + Send + Clone,
|
||||
{
|
||||
let func = |mut init, item| {
|
||||
@ -190,7 +190,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityEquivalent + Sync>
|
||||
///
|
||||
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
|
||||
#[inline]
|
||||
pub fn for_each<FN: Fn(QueryItem<'w, D>) + Send + Sync + Clone>(self, func: FN) {
|
||||
pub fn for_each<FN: Fn(QueryItem<'w, 's, D>) + Send + Sync + Clone>(self, func: FN) {
|
||||
self.for_each_init(|| {}, |_, item| func(item));
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityEquivalent + Sync>
|
||||
#[inline]
|
||||
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
|
||||
where
|
||||
FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone,
|
||||
FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone,
|
||||
INIT: Fn() -> T + Sync + Send + Clone,
|
||||
{
|
||||
let func = |mut init, item| {
|
||||
@ -345,7 +345,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: EntityEquivalent + Sync>
|
||||
///
|
||||
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
|
||||
#[inline]
|
||||
pub fn for_each<FN: Fn(QueryItem<'w, D>) + Send + Sync + Clone>(self, func: FN) {
|
||||
pub fn for_each<FN: Fn(QueryItem<'w, 's, D>) + Send + Sync + Clone>(self, func: FN) {
|
||||
self.for_each_init(|| {}, |_, item| func(item));
|
||||
}
|
||||
|
||||
@ -402,7 +402,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: EntityEquivalent + Sync>
|
||||
#[inline]
|
||||
pub fn for_each_init<FN, INIT, T>(self, init: INIT, func: FN)
|
||||
where
|
||||
FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone,
|
||||
FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone,
|
||||
INIT: Fn() -> T + Sync + Send + Clone,
|
||||
{
|
||||
let func = |mut init, item| {
|
||||
|
@ -845,13 +845,17 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
///
|
||||
/// This can only be called for read-only queries, see [`Self::get_mut`] for write-queries.
|
||||
///
|
||||
/// If you need to get multiple items at once but get borrowing errors,
|
||||
/// consider using [`Self::update_archetypes`] followed by multiple [`Self::get_manual`] calls,
|
||||
/// or making a single call with [`Self::get_many`] or [`Self::iter_many`].
|
||||
///
|
||||
/// This is always guaranteed to run in `O(1)` time.
|
||||
#[inline]
|
||||
pub fn get<'w>(
|
||||
&mut self,
|
||||
world: &'w World,
|
||||
entity: Entity,
|
||||
) -> Result<ROQueryItem<'w, D>, QueryEntityError> {
|
||||
) -> Result<ROQueryItem<'w, '_, D>, QueryEntityError> {
|
||||
self.query(world).get_inner(entity)
|
||||
}
|
||||
|
||||
@ -892,7 +896,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
&mut self,
|
||||
world: &'w World,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> {
|
||||
) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> {
|
||||
self.query(world).get_many_inner(entities)
|
||||
}
|
||||
|
||||
@ -930,7 +934,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
&mut self,
|
||||
world: &'w World,
|
||||
entities: UniqueEntityArray<N>,
|
||||
) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> {
|
||||
) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> {
|
||||
self.query(world).get_many_unique_inner(entities)
|
||||
}
|
||||
|
||||
@ -942,7 +946,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
&mut self,
|
||||
world: &'w mut World,
|
||||
entity: Entity,
|
||||
) -> Result<D::Item<'w>, QueryEntityError> {
|
||||
) -> Result<D::Item<'w, '_>, QueryEntityError> {
|
||||
self.query_mut(world).get_inner(entity)
|
||||
}
|
||||
|
||||
@ -989,7 +993,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
&mut self,
|
||||
world: &'w mut World,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[D::Item<'w>; N], QueryEntityError> {
|
||||
) -> Result<[D::Item<'w, '_>; N], QueryEntityError> {
|
||||
self.query_mut(world).get_many_mut_inner(entities)
|
||||
}
|
||||
|
||||
@ -1034,7 +1038,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
&mut self,
|
||||
world: &'w mut World,
|
||||
entities: UniqueEntityArray<N>,
|
||||
) -> Result<[D::Item<'w>; N], QueryEntityError> {
|
||||
) -> Result<[D::Item<'w, '_>; N], QueryEntityError> {
|
||||
self.query_mut(world).get_many_unique_inner(entities)
|
||||
}
|
||||
|
||||
@ -1056,7 +1060,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
&self,
|
||||
world: &'w World,
|
||||
entity: Entity,
|
||||
) -> Result<ROQueryItem<'w, D>, QueryEntityError> {
|
||||
) -> Result<ROQueryItem<'w, '_, D>, QueryEntityError> {
|
||||
self.query_manual(world).get_inner(entity)
|
||||
}
|
||||
|
||||
@ -1073,13 +1077,16 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
&mut self,
|
||||
world: UnsafeWorldCell<'w>,
|
||||
entity: Entity,
|
||||
) -> Result<D::Item<'w>, QueryEntityError> {
|
||||
) -> Result<D::Item<'w, '_>, QueryEntityError> {
|
||||
self.query_unchecked(world).get_inner(entity)
|
||||
}
|
||||
|
||||
/// Returns an [`Iterator`] over the query results for the given [`World`].
|
||||
///
|
||||
/// This can only be called for read-only queries, see [`Self::iter_mut`] for write-queries.
|
||||
///
|
||||
/// If you need to iterate multiple times at once but get borrowing errors,
|
||||
/// consider using [`Self::update_archetypes`] followed by multiple [`Self::iter_manual`] calls.
|
||||
#[inline]
|
||||
pub fn iter<'w, 's>(&'s mut self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> {
|
||||
self.query(world).into_iter()
|
||||
@ -1168,6 +1175,9 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
/// Items are returned in the order of the list of entities.
|
||||
/// Entities that don't match the query are skipped.
|
||||
///
|
||||
/// If you need to iterate multiple times at once but get borrowing errors,
|
||||
/// consider using [`Self::update_archetypes`] followed by multiple [`Self::iter_many_manual`] calls.
|
||||
///
|
||||
/// # See also
|
||||
///
|
||||
/// - [`iter_many_mut`](Self::iter_many_mut) to get mutable query items.
|
||||
@ -1387,8 +1397,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
///
|
||||
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
|
||||
pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, T, FN, INIT>(
|
||||
&self,
|
||||
pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, 's, T, FN, INIT>(
|
||||
&'s self,
|
||||
init_accum: INIT,
|
||||
world: UnsafeWorldCell<'w>,
|
||||
batch_size: u32,
|
||||
@ -1396,7 +1406,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) where
|
||||
FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone,
|
||||
FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone,
|
||||
INIT: Fn() -> T + Sync + Send + Clone,
|
||||
{
|
||||
// NOTE: If you are changing query iteration code, remember to update the following places, where relevant:
|
||||
@ -1501,8 +1511,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
///
|
||||
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
|
||||
pub(crate) unsafe fn par_many_unique_fold_init_unchecked_manual<'w, T, FN, INIT, E>(
|
||||
&self,
|
||||
pub(crate) unsafe fn par_many_unique_fold_init_unchecked_manual<'w, 's, T, FN, INIT, E>(
|
||||
&'s self,
|
||||
init_accum: INIT,
|
||||
world: UnsafeWorldCell<'w>,
|
||||
entity_list: &UniqueEntityEquivalentSlice<E>,
|
||||
@ -1511,7 +1521,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) where
|
||||
FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone,
|
||||
FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone,
|
||||
INIT: Fn() -> T + Sync + Send + Clone,
|
||||
E: EntityEquivalent + Sync,
|
||||
{
|
||||
@ -1564,8 +1574,8 @@ impl<D: ReadOnlyQueryData, F: QueryFilter> QueryState<D, F> {
|
||||
///
|
||||
/// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
|
||||
pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, T, FN, INIT, E>(
|
||||
&self,
|
||||
pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, 's, T, FN, INIT, E>(
|
||||
&'s self,
|
||||
init_accum: INIT,
|
||||
world: UnsafeWorldCell<'w>,
|
||||
entity_list: &[E],
|
||||
@ -1574,7 +1584,7 @@ impl<D: ReadOnlyQueryData, F: QueryFilter> QueryState<D, F> {
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) where
|
||||
FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone,
|
||||
FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone,
|
||||
INIT: Fn() -> T + Sync + Send + Clone,
|
||||
E: EntityEquivalent + Sync,
|
||||
{
|
||||
@ -1686,7 +1696,10 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
///
|
||||
/// Simply unwrapping the [`Result`] also works, but should generally be reserved for tests.
|
||||
#[inline]
|
||||
pub fn single<'w>(&mut self, world: &'w World) -> Result<ROQueryItem<'w, D>, QuerySingleError> {
|
||||
pub fn single<'w>(
|
||||
&mut self,
|
||||
world: &'w World,
|
||||
) -> Result<ROQueryItem<'w, '_, D>, QuerySingleError> {
|
||||
self.query(world).single_inner()
|
||||
}
|
||||
|
||||
@ -1703,7 +1716,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
pub fn single_mut<'w>(
|
||||
&mut self,
|
||||
world: &'w mut World,
|
||||
) -> Result<D::Item<'w>, QuerySingleError> {
|
||||
) -> Result<D::Item<'w, '_>, QuerySingleError> {
|
||||
self.query_mut(world).single_inner()
|
||||
}
|
||||
|
||||
@ -1720,7 +1733,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
pub unsafe fn single_unchecked<'w>(
|
||||
&mut self,
|
||||
world: UnsafeWorldCell<'w>,
|
||||
) -> Result<D::Item<'w>, QuerySingleError> {
|
||||
) -> Result<D::Item<'w, '_>, QuerySingleError> {
|
||||
self.query_unchecked(world).single_inner()
|
||||
}
|
||||
|
||||
@ -1742,7 +1755,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
|
||||
world: UnsafeWorldCell<'w>,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Result<D::Item<'w>, QuerySingleError> {
|
||||
) -> Result<D::Item<'w, '_>, QuerySingleError> {
|
||||
// SAFETY:
|
||||
// - The caller ensured we have the correct access to the world.
|
||||
// - The caller ensured that the world matches.
|
||||
|
@ -42,7 +42,7 @@ use variadics_please::all_tuples;
|
||||
/// [`QueryFilter`]: crate::query::QueryFilter
|
||||
pub unsafe trait WorldQuery {
|
||||
/// Per archetype/table state retrieved by this [`WorldQuery`] to compute [`Self::Item`](crate::query::QueryData::Item) for each entity.
|
||||
type Fetch<'a>: Clone;
|
||||
type Fetch<'w, 's>: Clone;
|
||||
|
||||
/// State used to construct a [`Self::Fetch`](WorldQuery::Fetch). This will be cached inside [`QueryState`](crate::query::QueryState),
|
||||
/// so it is best to move as much data / computation here as possible to reduce the cost of
|
||||
@ -50,7 +50,9 @@ pub unsafe trait WorldQuery {
|
||||
type State: Send + Sync + Sized;
|
||||
|
||||
/// This function manually implements subtyping for the query fetches.
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort>;
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
fetch: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's>;
|
||||
|
||||
/// Creates a new instance of [`Self::Fetch`](WorldQuery::Fetch),
|
||||
/// by combining data from the [`World`] with the cached [`Self::State`](WorldQuery::State).
|
||||
@ -62,12 +64,12 @@ pub unsafe trait WorldQuery {
|
||||
/// in to this function.
|
||||
/// - `world` must have the **right** to access any access registered in `update_component_access`.
|
||||
/// - There must not be simultaneous resource access conflicting with readonly resource access registered in [`WorldQuery::update_component_access`].
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
state: &Self::State,
|
||||
state: &'s Self::State,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self::Fetch<'w>;
|
||||
) -> Self::Fetch<'w, 's>;
|
||||
|
||||
/// Returns true if (and only if) every table of every archetype matched by this fetch contains
|
||||
/// all of the matched components.
|
||||
@ -87,9 +89,9 @@ pub unsafe trait WorldQuery {
|
||||
/// - `archetype` and `tables` must be from the same [`World`] that [`WorldQuery::init_state`] was called on.
|
||||
/// - `table` must correspond to `archetype`.
|
||||
/// - `state` must be the [`State`](Self::State) that `fetch` was initialized with.
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
state: &Self::State,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
state: &'s Self::State,
|
||||
archetype: &'w Archetype,
|
||||
table: &'w Table,
|
||||
);
|
||||
@ -101,7 +103,11 @@ pub unsafe trait WorldQuery {
|
||||
///
|
||||
/// - `table` must be from the same [`World`] that [`WorldQuery::init_state`] was called on.
|
||||
/// - `state` must be the [`State`](Self::State) that `fetch` was initialized with.
|
||||
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table);
|
||||
unsafe fn set_table<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
state: &'s Self::State,
|
||||
table: &'w Table,
|
||||
);
|
||||
|
||||
/// Adds any component accesses used by this [`WorldQuery`] to `access`.
|
||||
///
|
||||
@ -154,11 +160,11 @@ macro_rules! impl_tuple_world_query {
|
||||
/// `update_component_access` adds all `With` and `Without` filters from the subqueries.
|
||||
/// This is sound because `matches_component_set` always returns `false` if any the subqueries' implementations return `false`.
|
||||
unsafe impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) {
|
||||
type Fetch<'w> = ($($name::Fetch<'w>,)*);
|
||||
type Fetch<'w, 's> = ($($name::Fetch<'w, 's>,)*);
|
||||
type State = ($($name::State,)*);
|
||||
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> {
|
||||
let ($($name,)*) = fetch;
|
||||
($(
|
||||
$name::shrink_fetch($name),
|
||||
@ -166,7 +172,7 @@ macro_rules! impl_tuple_world_query {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch<'w>(world: UnsafeWorldCell<'w>, state: &Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> {
|
||||
unsafe fn init_fetch<'w, 's>(world: UnsafeWorldCell<'w>, state: &'s Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w, 's> {
|
||||
let ($($name,)*) = state;
|
||||
// SAFETY: The invariants are upheld by the caller.
|
||||
($(unsafe { $name::init_fetch(world, $name, last_run, this_run) },)*)
|
||||
@ -175,9 +181,9 @@ macro_rules! impl_tuple_world_query {
|
||||
const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
state: &Self::State,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
state: &'s Self::State,
|
||||
archetype: &'w Archetype,
|
||||
table: &'w Table
|
||||
) {
|
||||
@ -188,7 +194,7 @@ macro_rules! impl_tuple_world_query {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) {
|
||||
unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w, 's>, state: &'s Self::State, table: &'w Table) {
|
||||
let ($($name,)*) = fetch;
|
||||
let ($($state,)*) = state;
|
||||
// SAFETY: The invariants are upheld by the caller.
|
||||
|
@ -14,7 +14,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
/// target entity of that relationship.
|
||||
pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity>
|
||||
where
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w R>,
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
|
||||
{
|
||||
self.get(entity).map(R::get).ok()
|
||||
}
|
||||
@ -26,7 +26,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
entity: Entity,
|
||||
) -> impl Iterator<Item = Entity> + 'w
|
||||
where
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
{
|
||||
self.get(entity)
|
||||
.into_iter()
|
||||
@ -42,7 +42,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.
|
||||
pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity
|
||||
where
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w R>,
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
|
||||
{
|
||||
// Recursively search up the tree until we're out of parents
|
||||
match self.get(entity) {
|
||||
@ -60,9 +60,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn iter_leaves<S: RelationshipTarget>(
|
||||
&'w self,
|
||||
entity: Entity,
|
||||
) -> impl Iterator<Item = Entity> + 'w
|
||||
) -> impl Iterator<Item = Entity> + use<'w, 's, S, D, F>
|
||||
where
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
SourceIter<'w, S>: DoubleEndedIterator,
|
||||
{
|
||||
self.iter_descendants_depth_first(entity).filter(|entity| {
|
||||
@ -80,7 +80,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
entity: Entity,
|
||||
) -> impl Iterator<Item = Entity> + 'w
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>,
|
||||
{
|
||||
self.get(entity)
|
||||
.ok()
|
||||
@ -103,7 +103,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
entity: Entity,
|
||||
) -> DescendantIter<'w, 's, D, F, S>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
{
|
||||
DescendantIter::new(self, entity)
|
||||
}
|
||||
@ -120,7 +120,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
entity: Entity,
|
||||
) -> DescendantDepthFirstIter<'w, 's, D, F, S>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
SourceIter<'w, S>: DoubleEndedIterator,
|
||||
{
|
||||
DescendantDepthFirstIter::new(self, entity)
|
||||
@ -137,7 +137,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
entity: Entity,
|
||||
) -> AncestorIter<'w, 's, D, F, R>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w R>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
|
||||
{
|
||||
AncestorIter::new(self, entity)
|
||||
}
|
||||
@ -148,7 +148,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
/// Traverses the hierarchy breadth-first.
|
||||
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
{
|
||||
children_query: &'w Query<'w, 's, D, F>,
|
||||
vecdeque: VecDeque<Entity>,
|
||||
@ -156,7 +156,7 @@ where
|
||||
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
{
|
||||
/// Returns a new [`DescendantIter`].
|
||||
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
|
||||
@ -174,7 +174,7 @@ where
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator
|
||||
for DescendantIter<'w, 's, D, F, S>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
{
|
||||
type Item = Entity;
|
||||
|
||||
@ -194,7 +194,7 @@ where
|
||||
/// Traverses the hierarchy depth-first.
|
||||
pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
{
|
||||
children_query: &'w Query<'w, 's, D, F>,
|
||||
stack: SmallVec<[Entity; 8]>,
|
||||
@ -203,7 +203,7 @@ where
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
|
||||
DescendantDepthFirstIter<'w, 's, D, F, S>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
SourceIter<'w, S>: DoubleEndedIterator,
|
||||
{
|
||||
/// Returns a new [`DescendantDepthFirstIter`].
|
||||
@ -220,7 +220,7 @@ where
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator
|
||||
for DescendantDepthFirstIter<'w, 's, D, F, S>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w S>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,
|
||||
SourceIter<'w, S>: DoubleEndedIterator,
|
||||
{
|
||||
type Item = Entity;
|
||||
@ -239,7 +239,7 @@ where
|
||||
/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
|
||||
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w R>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
|
||||
{
|
||||
parent_query: &'w Query<'w, 's, D, F>,
|
||||
next: Option<Entity>,
|
||||
@ -247,7 +247,7 @@ where
|
||||
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w R>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
|
||||
{
|
||||
/// Returns a new [`AncestorIter`].
|
||||
pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
|
||||
@ -261,7 +261,7 @@ where
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator
|
||||
for AncestorIter<'w, 's, D, F, R>
|
||||
where
|
||||
D::ReadOnly: QueryData<Item<'w> = &'w R>,
|
||||
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,
|
||||
{
|
||||
type Item = Entity;
|
||||
|
||||
|
@ -1185,7 +1185,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
/// [`par_iter_mut`]: Self::par_iter_mut
|
||||
/// [`World`]: crate::world::World
|
||||
#[inline]
|
||||
pub fn par_iter(&self) -> QueryParIter<'_, '_, D::ReadOnly, F> {
|
||||
pub fn par_iter(&self) -> QueryParIter<'_, 's, D::ReadOnly, F> {
|
||||
self.as_readonly().par_iter_inner()
|
||||
}
|
||||
|
||||
@ -1220,7 +1220,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
/// [`par_iter`]: Self::par_iter
|
||||
/// [`World`]: crate::world::World
|
||||
#[inline]
|
||||
pub fn par_iter_mut(&mut self) -> QueryParIter<'_, '_, D, F> {
|
||||
pub fn par_iter_mut(&mut self) -> QueryParIter<'_, 's, D, F> {
|
||||
self.reborrow().par_iter_inner()
|
||||
}
|
||||
|
||||
@ -1280,7 +1280,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn par_iter_many<EntityList: IntoIterator<Item: EntityEquivalent>>(
|
||||
&self,
|
||||
entities: EntityList,
|
||||
) -> QueryParManyIter<'_, '_, D::ReadOnly, F, EntityList::Item> {
|
||||
) -> QueryParManyIter<'_, 's, D::ReadOnly, F, EntityList::Item> {
|
||||
QueryParManyIter {
|
||||
world: self.world,
|
||||
state: self.state.as_readonly(),
|
||||
@ -1309,7 +1309,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn par_iter_many_unique<EntityList: EntitySet<Item: Sync>>(
|
||||
&self,
|
||||
entities: EntityList,
|
||||
) -> QueryParManyUniqueIter<'_, '_, D::ReadOnly, F, EntityList::Item> {
|
||||
) -> QueryParManyUniqueIter<'_, 's, D::ReadOnly, F, EntityList::Item> {
|
||||
QueryParManyUniqueIter {
|
||||
world: self.world,
|
||||
state: self.state.as_readonly(),
|
||||
@ -1338,7 +1338,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn par_iter_many_unique_mut<EntityList: EntitySet<Item: Sync>>(
|
||||
&mut self,
|
||||
entities: EntityList,
|
||||
) -> QueryParManyUniqueIter<'_, '_, D, F, EntityList::Item> {
|
||||
) -> QueryParManyUniqueIter<'_, 's, D, F, EntityList::Item> {
|
||||
QueryParManyUniqueIter {
|
||||
world: self.world,
|
||||
state: self.state,
|
||||
@ -1383,7 +1383,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
///
|
||||
/// - [`get_mut`](Self::get_mut) to get a mutable query item.
|
||||
#[inline]
|
||||
pub fn get(&self, entity: Entity) -> Result<ROQueryItem<'_, D>, QueryEntityError> {
|
||||
pub fn get(&self, entity: Entity) -> Result<ROQueryItem<'_, 's, D>, QueryEntityError> {
|
||||
self.as_readonly().get_inner(entity)
|
||||
}
|
||||
|
||||
@ -1434,7 +1434,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn get_many<const N: usize>(
|
||||
&self,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[ROQueryItem<'_, D>; N], QueryEntityError> {
|
||||
) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> {
|
||||
// Note that we call a separate `*_inner` method from `get_many_mut`
|
||||
// because we don't need to check for duplicates.
|
||||
self.as_readonly().get_many_inner(entities)
|
||||
@ -1485,7 +1485,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn get_many_unique<const N: usize>(
|
||||
&self,
|
||||
entities: UniqueEntityArray<N>,
|
||||
) -> Result<[ROQueryItem<'_, D>; N], QueryEntityError> {
|
||||
) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> {
|
||||
self.as_readonly().get_many_unique_inner(entities)
|
||||
}
|
||||
|
||||
@ -1519,7 +1519,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
///
|
||||
/// - [`get`](Self::get) to get a read-only query item.
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self, entity: Entity) -> Result<D::Item<'_>, QueryEntityError> {
|
||||
pub fn get_mut(&mut self, entity: Entity) -> Result<D::Item<'_, 's>, QueryEntityError> {
|
||||
self.reborrow().get_inner(entity)
|
||||
}
|
||||
|
||||
@ -1534,7 +1534,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
///
|
||||
/// - [`get_mut`](Self::get_mut) to get the item using a mutable borrow of the [`Query`].
|
||||
#[inline]
|
||||
pub fn get_inner(self, entity: Entity) -> Result<D::Item<'w>, QueryEntityError> {
|
||||
pub fn get_inner(self, entity: Entity) -> Result<D::Item<'w, 's>, QueryEntityError> {
|
||||
// SAFETY: system runs without conflicts with other systems.
|
||||
// same-system queries have runtime borrow checks when they conflict
|
||||
unsafe {
|
||||
@ -1662,7 +1662,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn get_many_mut<const N: usize>(
|
||||
&mut self,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[D::Item<'_>; N], QueryEntityError> {
|
||||
) -> Result<[D::Item<'_, 's>; N], QueryEntityError> {
|
||||
self.reborrow().get_many_mut_inner(entities)
|
||||
}
|
||||
|
||||
@ -1730,7 +1730,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn get_many_unique_mut<const N: usize>(
|
||||
&mut self,
|
||||
entities: UniqueEntityArray<N>,
|
||||
) -> Result<[D::Item<'_>; N], QueryEntityError> {
|
||||
) -> Result<[D::Item<'_, 's>; N], QueryEntityError> {
|
||||
self.reborrow().get_many_unique_inner(entities)
|
||||
}
|
||||
|
||||
@ -1749,7 +1749,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn get_many_mut_inner<const N: usize>(
|
||||
self,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[D::Item<'w>; N], QueryEntityError> {
|
||||
) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
|
||||
// Verify that all entities are unique
|
||||
for i in 0..N {
|
||||
for j in 0..i {
|
||||
@ -1777,7 +1777,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn get_many_inner<const N: usize>(
|
||||
self,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[D::Item<'w>; N], QueryEntityError>
|
||||
) -> Result<[D::Item<'w, 's>; N], QueryEntityError>
|
||||
where
|
||||
D: ReadOnlyQueryData,
|
||||
{
|
||||
@ -1799,7 +1799,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
pub fn get_many_unique_inner<const N: usize>(
|
||||
self,
|
||||
entities: UniqueEntityArray<N>,
|
||||
) -> Result<[D::Item<'w>; N], QueryEntityError> {
|
||||
) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
|
||||
// SAFETY: All entities are unique, so the results don't alias.
|
||||
unsafe { self.get_many_impl(entities.into_inner()) }
|
||||
}
|
||||
@ -1814,7 +1814,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
unsafe fn get_many_impl<const N: usize>(
|
||||
self,
|
||||
entities: [Entity; N],
|
||||
) -> Result<[D::Item<'w>; N], QueryEntityError> {
|
||||
) -> Result<[D::Item<'w, 's>; N], QueryEntityError> {
|
||||
let mut values = [(); N].map(|_| MaybeUninit::uninit());
|
||||
|
||||
for (value, entity) in core::iter::zip(&mut values, entities) {
|
||||
@ -1842,7 +1842,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
///
|
||||
/// - [`get_mut`](Self::get_mut) for the safe version.
|
||||
#[inline]
|
||||
pub unsafe fn get_unchecked(&self, entity: Entity) -> Result<D::Item<'_>, QueryEntityError> {
|
||||
pub unsafe fn get_unchecked(
|
||||
&self,
|
||||
entity: Entity,
|
||||
) -> Result<D::Item<'_, 's>, QueryEntityError> {
|
||||
// SAFETY: The caller promises that this will not result in multiple mutable references.
|
||||
unsafe { self.reborrow_unsafe() }.get_inner(entity)
|
||||
}
|
||||
@ -1878,7 +1881,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
///
|
||||
/// - [`single_mut`](Self::single_mut) to get the mutable query item.
|
||||
#[inline]
|
||||
pub fn single(&self) -> Result<ROQueryItem<'_, D>, QuerySingleError> {
|
||||
pub fn single(&self) -> Result<ROQueryItem<'_, 's, D>, QuerySingleError> {
|
||||
self.as_readonly().single_inner()
|
||||
}
|
||||
|
||||
@ -1907,7 +1910,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
///
|
||||
/// - [`single`](Self::single) to get the read-only query item.
|
||||
#[inline]
|
||||
pub fn single_mut(&mut self) -> Result<D::Item<'_>, QuerySingleError> {
|
||||
pub fn single_mut(&mut self) -> Result<D::Item<'_, 's>, QuerySingleError> {
|
||||
self.reborrow().single_inner()
|
||||
}
|
||||
|
||||
@ -1939,7 +1942,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
/// - [`single_mut`](Self::single_mut) to get the mutable query item.
|
||||
/// - [`single_inner`](Self::single_inner) for the panicking version.
|
||||
#[inline]
|
||||
pub fn single_inner(self) -> Result<D::Item<'w>, QuerySingleError> {
|
||||
pub fn single_inner(self) -> Result<D::Item<'w, 's>, QuerySingleError> {
|
||||
let mut query = self.into_iter();
|
||||
let first = query.next();
|
||||
let extra = query.next().is_some();
|
||||
@ -2451,7 +2454,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
|
||||
}
|
||||
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for Query<'w, 's, D, F> {
|
||||
type Item = D::Item<'w>;
|
||||
type Item = D::Item<'w, 's>;
|
||||
type IntoIter = QueryIter<'w, 's, D, F>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
@ -2464,7 +2467,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for Query<'w, 's, D, F>
|
||||
}
|
||||
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D, F> {
|
||||
type Item = ROQueryItem<'w, D>;
|
||||
type Item = ROQueryItem<'w, 's, D>;
|
||||
type IntoIter = QueryIter<'w, 's, D::ReadOnly, F>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
@ -2473,7 +2476,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D,
|
||||
}
|
||||
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w mut Query<'_, 's, D, F> {
|
||||
type Item = D::Item<'w>;
|
||||
type Item = D::Item<'w, 's>;
|
||||
type IntoIter = QueryIter<'w, 's, D, F>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
@ -2588,28 +2591,28 @@ impl<'w, 'q, Q: QueryData, F: QueryFilter> From<&'q mut Query<'w, '_, Q, F>>
|
||||
/// ```
|
||||
/// Note that because [`Single`] implements [`Deref`] and [`DerefMut`], methods and fields like `health` can be accessed directly.
|
||||
/// You can also access the underlying data manually, by calling `.deref`/`.deref_mut`, or by using the `*` operator.
|
||||
pub struct Single<'w, D: QueryData, F: QueryFilter = ()> {
|
||||
pub(crate) item: D::Item<'w>,
|
||||
pub struct Single<'w, 's, D: QueryData, F: QueryFilter = ()> {
|
||||
pub(crate) item: D::Item<'w, 's>,
|
||||
pub(crate) _filter: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<'w, D: QueryData, F: QueryFilter> Deref for Single<'w, D, F> {
|
||||
type Target = D::Item<'w>;
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter> Deref for Single<'w, 's, D, F> {
|
||||
type Target = D::Item<'w, 's>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.item
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, D: QueryData, F: QueryFilter> DerefMut for Single<'w, D, F> {
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter> DerefMut for Single<'w, 's, D, F> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.item
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, D: QueryData, F: QueryFilter> Single<'w, D, F> {
|
||||
impl<'w, 's, D: QueryData, F: QueryFilter> Single<'w, 's, D, F> {
|
||||
/// Returns the inner item with ownership.
|
||||
pub fn into_inner(self) -> D::Item<'w> {
|
||||
pub fn into_inner(self) -> D::Item<'w, 's> {
|
||||
self.item
|
||||
}
|
||||
}
|
||||
|
@ -389,9 +389,11 @@ fn assert_component_access_compatibility(
|
||||
|
||||
// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
|
||||
// this Query conflicts with any prior access, a panic will occur.
|
||||
unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Single<'a, D, F> {
|
||||
unsafe impl<'a, 'b, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
|
||||
for Single<'a, 'b, D, F>
|
||||
{
|
||||
type State = QueryState<D, F>;
|
||||
type Item<'w, 's> = Single<'w, D, F>;
|
||||
type Item<'w, 's> = Single<'w, 's, D, F>;
|
||||
|
||||
fn init_state(world: &mut World) -> Self::State {
|
||||
Query::init_state(world)
|
||||
@ -451,8 +453,8 @@ unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam fo
|
||||
}
|
||||
|
||||
// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
|
||||
unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
|
||||
for Single<'a, D, F>
|
||||
unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
|
||||
for Single<'a, 'b, D, F>
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
//! A trait for components that let you traverse the ECS.
|
||||
|
||||
use crate::{entity::Entity, query::ReadOnlyQueryData, relationship::Relationship};
|
||||
use crate::{
|
||||
entity::Entity,
|
||||
query::{ReadOnlyQueryData, ReleaseStateQueryData},
|
||||
relationship::Relationship,
|
||||
};
|
||||
|
||||
/// A component that can point to another entity, and which can be used to define a path through the ECS.
|
||||
///
|
||||
@ -20,13 +24,13 @@ use crate::{entity::Entity, query::ReadOnlyQueryData, relationship::Relationship
|
||||
/// [specify the direction]: crate::event::EntityEvent::Traversal
|
||||
/// [event propagation]: crate::observer::On::propagate
|
||||
/// [observers]: crate::observer::Observer
|
||||
pub trait Traversal<D: ?Sized>: ReadOnlyQueryData {
|
||||
pub trait Traversal<D: ?Sized>: ReadOnlyQueryData + ReleaseStateQueryData {
|
||||
/// Returns the next entity to visit.
|
||||
fn traverse(item: Self::Item<'_>, data: &D) -> Option<Entity>;
|
||||
fn traverse(item: Self::Item<'_, '_>, data: &D) -> Option<Entity>;
|
||||
}
|
||||
|
||||
impl<D> Traversal<D> for () {
|
||||
fn traverse(_: Self::Item<'_>, _data: &D) -> Option<Entity> {
|
||||
fn traverse(_: Self::Item<'_, '_>, _data: &D) -> Option<Entity> {
|
||||
None
|
||||
}
|
||||
}
|
||||
@ -39,7 +43,7 @@ impl<D> Traversal<D> for () {
|
||||
///
|
||||
/// [event propagation]: crate::observer::On::propagate
|
||||
impl<R: Relationship, D> Traversal<D> for &R {
|
||||
fn traverse(item: Self::Item<'_>, _data: &D) -> Option<Entity> {
|
||||
fn traverse(item: Self::Item<'_, '_>, _data: &D) -> Option<Entity> {
|
||||
Some(item.get())
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use crate::{
|
||||
event::EntityEvent,
|
||||
lifecycle::{DESPAWN, REMOVE, REPLACE},
|
||||
observer::Observer,
|
||||
query::{Access, DebugCheckedUnwrap, ReadOnlyQueryData},
|
||||
query::{Access, DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData},
|
||||
relationship::RelationshipHookMode,
|
||||
resource::Resource,
|
||||
system::IntoObserverSystem,
|
||||
@ -279,14 +279,16 @@ impl<'w> EntityRef<'w> {
|
||||
/// # Panics
|
||||
///
|
||||
/// If the entity does not have the components required by the query `Q`.
|
||||
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'w> {
|
||||
pub fn components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(&self) -> Q::Item<'w, 'static> {
|
||||
self.get_components::<Q>()
|
||||
.expect("Query does not match the current entity")
|
||||
}
|
||||
|
||||
/// Returns read-only components for the current entity that match the query `Q`,
|
||||
/// or `None` if the entity does not have the components required by the query `Q`.
|
||||
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> {
|
||||
pub fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
|
||||
&self,
|
||||
) -> Option<Q::Item<'w, 'static>> {
|
||||
// SAFETY: We have read-only access to all components of this entity.
|
||||
unsafe { self.cell.get_components::<Q>() }
|
||||
}
|
||||
@ -546,13 +548,15 @@ impl<'w> EntityMut<'w> {
|
||||
/// # Panics
|
||||
///
|
||||
/// If the entity does not have the components required by the query `Q`.
|
||||
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> {
|
||||
pub fn components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(&self) -> Q::Item<'_, 'static> {
|
||||
self.as_readonly().components::<Q>()
|
||||
}
|
||||
|
||||
/// Returns read-only components for the current entity that match the query `Q`,
|
||||
/// or `None` if the entity does not have the components required by the query `Q`.
|
||||
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> {
|
||||
pub fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
|
||||
&self,
|
||||
) -> Option<Q::Item<'_, 'static>> {
|
||||
self.as_readonly().get_components::<Q>()
|
||||
}
|
||||
|
||||
@ -1310,7 +1314,7 @@ impl<'w> EntityWorldMut<'w> {
|
||||
/// If the entity does not have the components required by the query `Q` or if the entity
|
||||
/// has been despawned while this `EntityWorldMut` is still alive.
|
||||
#[inline]
|
||||
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> {
|
||||
pub fn components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(&self) -> Q::Item<'_, 'static> {
|
||||
self.as_readonly().components::<Q>()
|
||||
}
|
||||
|
||||
@ -1321,7 +1325,9 @@ impl<'w> EntityWorldMut<'w> {
|
||||
///
|
||||
/// If the entity has been despawned while this `EntityWorldMut` is still alive.
|
||||
#[inline]
|
||||
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> {
|
||||
pub fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
|
||||
&self,
|
||||
) -> Option<Q::Item<'_, 'static>> {
|
||||
self.as_readonly().get_components::<Q>()
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ use crate::{
|
||||
lifecycle::RemovedComponentEvents,
|
||||
observer::Observers,
|
||||
prelude::Component,
|
||||
query::{DebugCheckedUnwrap, ReadOnlyQueryData},
|
||||
query::{DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData},
|
||||
resource::Resource,
|
||||
storage::{ComponentSparseSet, Storages, Table},
|
||||
world::RawCommandQueue,
|
||||
@ -998,7 +998,9 @@ impl<'w> UnsafeEntityCell<'w> {
|
||||
/// It is the caller's responsibility to ensure that
|
||||
/// - the [`UnsafeEntityCell`] has permission to access the queried data immutably
|
||||
/// - no mutable references to the queried data exist at the same time
|
||||
pub(crate) unsafe fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> {
|
||||
pub(crate) unsafe fn get_components<Q: ReadOnlyQueryData + ReleaseStateQueryData>(
|
||||
&self,
|
||||
) -> Option<Q::Item<'w, 'static>> {
|
||||
// SAFETY: World is only used to access query data and initialize query state
|
||||
let state = unsafe {
|
||||
let world = self.world().world();
|
||||
@ -1028,7 +1030,8 @@ impl<'w> UnsafeEntityCell<'w> {
|
||||
// Table corresponds to archetype. State is the same state used to init fetch above.
|
||||
unsafe { Q::set_archetype(&mut fetch, &state, archetype, table) }
|
||||
// SAFETY: Called after set_archetype above. Entity and location are guaranteed to exist.
|
||||
unsafe { Some(Q::fetch(&mut fetch, self.id(), location.table_row)) }
|
||||
let item = unsafe { Q::fetch(&mut fetch, self.id(), location.table_row) };
|
||||
Some(Q::release_state(item))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -631,8 +631,8 @@ impl<const I: usize, P: PhaseItem> RenderCommand<P> for SetLineGizmoBindGroup<I>
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
_view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
uniform_index: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
_view: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
uniform_index: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
|
||||
bind_group: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
@ -662,8 +662,8 @@ impl<P: PhaseItem, const STRIP: bool> RenderCommand<P> for DrawLineGizmo<STRIP>
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
_view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
config: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
_view: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
config: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
|
||||
line_gizmos: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
@ -725,8 +725,8 @@ impl<P: PhaseItem> RenderCommand<P> for DrawLineJointGizmo {
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
_view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
config: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
_view: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
config: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
|
||||
line_gizmos: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
|
@ -155,7 +155,7 @@ pub struct WindowTraversal {
|
||||
}
|
||||
|
||||
impl<E: BufferedEvent + Clone> Traversal<FocusedInput<E>> for WindowTraversal {
|
||||
fn traverse(item: Self::Item<'_>, event: &FocusedInput<E>) -> Option<Entity> {
|
||||
fn traverse(item: Self::Item<'_, '_>, event: &FocusedInput<E>) -> Option<Entity> {
|
||||
let WindowTraversalItem { child_of, window } = item;
|
||||
|
||||
// Send event to parent, if it has one.
|
||||
|
@ -309,7 +309,7 @@ impl ExtractComponent for Atmosphere {
|
||||
|
||||
type Out = Atmosphere;
|
||||
|
||||
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
|
||||
fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
|
||||
Some(item.clone())
|
||||
}
|
||||
}
|
||||
@ -405,7 +405,7 @@ impl ExtractComponent for AtmosphereSettings {
|
||||
|
||||
type Out = AtmosphereSettings;
|
||||
|
||||
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
|
||||
fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
|
||||
Some(item.clone())
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ impl ViewNode for RenderSkyNode {
|
||||
view_uniforms_offset,
|
||||
lights_uniforms_offset,
|
||||
render_sky_pipeline_id,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
|
@ -192,7 +192,7 @@ impl ExtractInstance for EnvironmentMapIds {
|
||||
|
||||
type QueryFilter = ();
|
||||
|
||||
fn extract(item: QueryItem<'_, Self::QueryData>) -> Option<Self> {
|
||||
fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self> {
|
||||
Some(EnvironmentMapIds {
|
||||
diffuse: item.diffuse_map.id(),
|
||||
specular: item.specular_map.id(),
|
||||
|
@ -1540,7 +1540,7 @@ fn extract_mesh_for_gpu_building(
|
||||
not_shadow_caster,
|
||||
no_automatic_batching,
|
||||
visibility_range,
|
||||
): <GpuMeshExtractionQuery as QueryData>::Item<'_>,
|
||||
): <GpuMeshExtractionQuery as QueryData>::Item<'_, '_>,
|
||||
render_visibility_ranges: &RenderVisibilityRanges,
|
||||
render_mesh_instances: &RenderMeshInstancesGpu,
|
||||
queue: &mut RenderMeshInstanceGpuQueue,
|
||||
@ -2874,7 +2874,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindGroup<I>
|
||||
view_environment_map,
|
||||
mesh_view_bind_group,
|
||||
maybe_oit_layers_count_offset,
|
||||
): ROQueryItem<'w, Self::ViewQuery>,
|
||||
): ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_entity: Option<()>,
|
||||
_: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
|
@ -280,7 +280,7 @@ impl ViewNode for ScreenSpaceReflectionsNode {
|
||||
view_environment_map_offset,
|
||||
view_bind_group,
|
||||
ssr_pipeline_id,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
// Grab the render pipeline.
|
||||
@ -498,7 +498,7 @@ impl ExtractComponent for ScreenSpaceReflections {
|
||||
|
||||
type Out = ScreenSpaceReflectionsUniform;
|
||||
|
||||
fn extract_component(settings: QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
|
||||
fn extract_component(settings: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
|
||||
if !DEPTH_TEXTURE_SAMPLING_SUPPORTED {
|
||||
once!(info!(
|
||||
"Disabling screen-space reflections on this platform because depth textures \
|
||||
|
@ -347,7 +347,7 @@ impl ViewNode for VolumetricFogNode {
|
||||
view_ssr_offset,
|
||||
msaa,
|
||||
view_environment_map_offset,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
|
@ -374,7 +374,7 @@ impl ViewNode for Wireframe3dNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>,
|
||||
(camera, view, target, depth): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let Some(wireframe_phase) = world.get_resource::<ViewBinnedRenderPhases<Wireframe3d>>()
|
||||
|
@ -86,7 +86,7 @@ impl<E> Traversal<Pointer<E>> for PointerTraversal
|
||||
where
|
||||
E: Debug + Clone + Reflect,
|
||||
{
|
||||
fn traverse(item: Self::Item<'_>, pointer: &Pointer<E>) -> Option<Entity> {
|
||||
fn traverse(item: Self::Item<'_, '_>, pointer: &Pointer<E>) -> Option<Entity> {
|
||||
let PointerTraversalItem { child_of, window } = item;
|
||||
|
||||
// Send event to parent, if it has one.
|
||||
|
@ -43,7 +43,7 @@ pub fn derive_extract_component(input: TokenStream) -> TokenStream {
|
||||
type QueryFilter = #filter;
|
||||
type Out = Self;
|
||||
|
||||
fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, Self::QueryData>) -> Option<Self::Out> {
|
||||
fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
|
||||
Some(item.clone())
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ pub trait ExtractComponent: Component {
|
||||
// type Out: Component = Self;
|
||||
|
||||
/// Defines how the component is transferred into the "render world".
|
||||
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self::Out>;
|
||||
fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out>;
|
||||
}
|
||||
|
||||
/// This plugin prepares the components of the corresponding type for the GPU
|
||||
|
@ -34,7 +34,7 @@ pub trait ExtractInstance: Send + Sync + Sized + 'static {
|
||||
type QueryFilter: QueryFilter;
|
||||
|
||||
/// Defines how the component is transferred into the "render world".
|
||||
fn extract(item: QueryItem<'_, Self::QueryData>) -> Option<Self>;
|
||||
fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self>;
|
||||
}
|
||||
|
||||
/// This plugin extracts one or more components into the "render world" as
|
||||
|
@ -366,7 +366,7 @@ pub trait ViewNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
view_query: QueryItem<'w, Self::ViewQuery>,
|
||||
view_query: QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError>;
|
||||
}
|
||||
|
@ -213,8 +213,8 @@ pub trait RenderCommand<P: PhaseItem> {
|
||||
/// issuing draw calls, etc.) via the [`TrackedRenderPass`].
|
||||
fn render<'w>(
|
||||
item: &P,
|
||||
view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
entity: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
view: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
entity: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
|
||||
param: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult;
|
||||
@ -246,8 +246,8 @@ macro_rules! render_command_tuple_impl {
|
||||
)]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
($($view,)*): ROQueryItem<'w, Self::ViewQuery>,
|
||||
maybe_entities: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
($($view,)*): ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
maybe_entities: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
|
||||
($($name,)*): SystemParamItem<'w, '_, Self::Param>,
|
||||
_pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
|
@ -281,7 +281,7 @@ mod render_entities_world_query_impls {
|
||||
archetype::Archetype,
|
||||
component::{ComponentId, Components, Tick},
|
||||
entity::Entity,
|
||||
query::{FilteredAccess, QueryData, ReadOnlyQueryData, WorldQuery},
|
||||
query::{FilteredAccess, QueryData, ReadOnlyQueryData, ReleaseStateQueryData, WorldQuery},
|
||||
storage::{Table, TableRow},
|
||||
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
||||
};
|
||||
@ -289,22 +289,22 @@ mod render_entities_world_query_impls {
|
||||
/// SAFETY: defers completely to `&RenderEntity` implementation,
|
||||
/// and then only modifies the output safely.
|
||||
unsafe impl WorldQuery for RenderEntity {
|
||||
type Fetch<'w> = <&'static RenderEntity as WorldQuery>::Fetch<'w>;
|
||||
type Fetch<'w, 's> = <&'static RenderEntity as WorldQuery>::Fetch<'w, 's>;
|
||||
type State = <&'static RenderEntity as WorldQuery>::State;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(
|
||||
fetch: Self::Fetch<'wlong>,
|
||||
) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
fetch: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
fetch
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
component_id: &ComponentId,
|
||||
component_id: &'s ComponentId,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self::Fetch<'w> {
|
||||
) -> Self::Fetch<'w, 's> {
|
||||
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
||||
unsafe {
|
||||
<&RenderEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
|
||||
@ -314,9 +314,9 @@ mod render_entities_world_query_impls {
|
||||
const IS_DENSE: bool = <&'static RenderEntity as WorldQuery>::IS_DENSE;
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
component_id: &ComponentId,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
component_id: &'s ComponentId,
|
||||
archetype: &'w Archetype,
|
||||
table: &'w Table,
|
||||
) {
|
||||
@ -327,9 +327,9 @@ mod render_entities_world_query_impls {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
&component_id: &ComponentId,
|
||||
unsafe fn set_table<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
&component_id: &'s ComponentId,
|
||||
table: &'w Table,
|
||||
) {
|
||||
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
||||
@ -364,18 +364,20 @@ mod render_entities_world_query_impls {
|
||||
unsafe impl QueryData for RenderEntity {
|
||||
const IS_READ_ONLY: bool = true;
|
||||
type ReadOnly = RenderEntity;
|
||||
type Item<'w> = Entity;
|
||||
type Item<'w, 's> = Entity;
|
||||
|
||||
fn shrink<'wlong: 'wshort, 'wshort>(item: Entity) -> Entity {
|
||||
fn shrink<'wlong: 'wshort, 'wshort, 's>(
|
||||
item: Self::Item<'wlong, 's>,
|
||||
) -> Self::Item<'wshort, 's> {
|
||||
item
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn fetch<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
unsafe fn fetch<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
entity: Entity,
|
||||
table_row: TableRow,
|
||||
) -> Self::Item<'w> {
|
||||
) -> Self::Item<'w, 's> {
|
||||
// SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`.
|
||||
let component =
|
||||
unsafe { <&RenderEntity as QueryData>::fetch(fetch, entity, table_row) };
|
||||
@ -386,25 +388,31 @@ mod render_entities_world_query_impls {
|
||||
// SAFETY: the underlying `Entity` is copied, and no mutable access is provided.
|
||||
unsafe impl ReadOnlyQueryData for RenderEntity {}
|
||||
|
||||
impl ReleaseStateQueryData for RenderEntity {
|
||||
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
|
||||
item
|
||||
}
|
||||
}
|
||||
|
||||
/// SAFETY: defers completely to `&RenderEntity` implementation,
|
||||
/// and then only modifies the output safely.
|
||||
unsafe impl WorldQuery for MainEntity {
|
||||
type Fetch<'w> = <&'static MainEntity as WorldQuery>::Fetch<'w>;
|
||||
type Fetch<'w, 's> = <&'static MainEntity as WorldQuery>::Fetch<'w, 's>;
|
||||
type State = <&'static MainEntity as WorldQuery>::State;
|
||||
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort>(
|
||||
fetch: Self::Fetch<'wlong>,
|
||||
) -> Self::Fetch<'wshort> {
|
||||
fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(
|
||||
fetch: Self::Fetch<'wlong, 's>,
|
||||
) -> Self::Fetch<'wshort, 's> {
|
||||
fetch
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn init_fetch<'w>(
|
||||
unsafe fn init_fetch<'w, 's>(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
component_id: &ComponentId,
|
||||
component_id: &'s ComponentId,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self::Fetch<'w> {
|
||||
) -> Self::Fetch<'w, 's> {
|
||||
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
||||
unsafe {
|
||||
<&MainEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run)
|
||||
@ -414,8 +422,8 @@ mod render_entities_world_query_impls {
|
||||
const IS_DENSE: bool = <&'static MainEntity as WorldQuery>::IS_DENSE;
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_archetype<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
unsafe fn set_archetype<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
component_id: &ComponentId,
|
||||
archetype: &'w Archetype,
|
||||
table: &'w Table,
|
||||
@ -427,9 +435,9 @@ mod render_entities_world_query_impls {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_table<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
&component_id: &ComponentId,
|
||||
unsafe fn set_table<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
&component_id: &'s ComponentId,
|
||||
table: &'w Table,
|
||||
) {
|
||||
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
||||
@ -464,18 +472,20 @@ mod render_entities_world_query_impls {
|
||||
unsafe impl QueryData for MainEntity {
|
||||
const IS_READ_ONLY: bool = true;
|
||||
type ReadOnly = MainEntity;
|
||||
type Item<'w> = Entity;
|
||||
type Item<'w, 's> = Entity;
|
||||
|
||||
fn shrink<'wlong: 'wshort, 'wshort>(item: Entity) -> Entity {
|
||||
fn shrink<'wlong: 'wshort, 'wshort, 's>(
|
||||
item: Self::Item<'wlong, 's>,
|
||||
) -> Self::Item<'wshort, 's> {
|
||||
item
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn fetch<'w>(
|
||||
fetch: &mut Self::Fetch<'w>,
|
||||
unsafe fn fetch<'w, 's>(
|
||||
fetch: &mut Self::Fetch<'w, 's>,
|
||||
entity: Entity,
|
||||
table_row: TableRow,
|
||||
) -> Self::Item<'w> {
|
||||
) -> Self::Item<'w, 's> {
|
||||
// SAFETY: defers to the `&T` implementation, with T set to `MainEntity`.
|
||||
let component = unsafe { <&MainEntity as QueryData>::fetch(fetch, entity, table_row) };
|
||||
component.id()
|
||||
@ -484,6 +494,12 @@ mod render_entities_world_query_impls {
|
||||
|
||||
// SAFETY: the underlying `Entity` is copied, and no mutable access is provided.
|
||||
unsafe impl ReadOnlyQueryData for MainEntity {}
|
||||
|
||||
impl ReleaseStateQueryData for MainEntity {
|
||||
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
|
||||
item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -778,7 +778,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMesh2dViewBindGroup<I
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
(view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, Self::ViewQuery>,
|
||||
(view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_view: Option<()>,
|
||||
_param: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
|
@ -372,7 +372,7 @@ impl ViewNode for Wireframe2dNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, view, target, depth): QueryItem<'w, Self::ViewQuery>,
|
||||
(camera, view, target, depth): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let Some(wireframe_phase) =
|
||||
|
@ -908,7 +908,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetSpriteViewBindGroup<I
|
||||
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
(view_uniform, sprite_view_bind_group): ROQueryItem<'w, Self::ViewQuery>,
|
||||
(view_uniform, sprite_view_bind_group): ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_entity: Option<()>,
|
||||
_param: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
@ -925,7 +925,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetSpriteTextureBindGrou
|
||||
|
||||
fn render<'w>(
|
||||
item: &P,
|
||||
view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
view: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_entity: Option<()>,
|
||||
(image_bind_groups, batches): SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
@ -955,7 +955,7 @@ impl<P: PhaseItem> RenderCommand<P> for DrawSpriteBatch {
|
||||
|
||||
fn render<'w>(
|
||||
item: &P,
|
||||
view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
view: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_entity: Option<()>,
|
||||
(sprite_meta, batches): SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
|
@ -276,7 +276,7 @@ impl<P: PhaseItem, M: UiMaterial, const I: usize> RenderCommand<P>
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
_view: (),
|
||||
material_handle: Option<ROQueryItem<'_, Self::ItemQuery>>,
|
||||
material_handle: Option<ROQueryItem<'_, '_, Self::ItemQuery>>,
|
||||
materials: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
|
@ -137,7 +137,7 @@ fn print_components_iter_mut(
|
||||
println!("Print components (iter_mut):");
|
||||
for e in &mut query {
|
||||
// Re-declaring the variable to illustrate the type of the actual iterator item.
|
||||
let e: CustomQueryItem<'_, _, _> = e;
|
||||
let e: CustomQueryItem<'_, '_, _, _> = e;
|
||||
println!("Entity: {}", e.entity);
|
||||
println!("A: {:?}", e.a);
|
||||
println!("B: {:?}", e.b);
|
||||
@ -155,7 +155,7 @@ fn print_components_iter(
|
||||
println!("Print components (iter):");
|
||||
for e in &query {
|
||||
// Re-declaring the variable to illustrate the type of the actual iterator item.
|
||||
let e: CustomQueryReadOnlyItem<'_, _, _> = e;
|
||||
let e: CustomQueryReadOnlyItem<'_, '_, _, _> = e;
|
||||
println!("Entity: {}", e.entity);
|
||||
println!("A: {:?}", e.a);
|
||||
println!("B: {:?}", e.b);
|
||||
|
@ -73,8 +73,8 @@ where
|
||||
|
||||
fn render<'w>(
|
||||
_: &P,
|
||||
_: ROQueryItem<'w, Self::ViewQuery>,
|
||||
_: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
_: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
|
||||
custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
|
@ -588,7 +588,7 @@ impl ViewNode for CustomDrawNode {
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, view, target): QueryItem<'w, Self::ViewQuery>,
|
||||
(camera, view, target): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
// First, we need to get our phases resource
|
||||
|
@ -88,7 +88,7 @@ impl ExtractComponent for InstanceMaterialData {
|
||||
type QueryFilter = ();
|
||||
type Out = Self;
|
||||
|
||||
fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option<Self> {
|
||||
fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self> {
|
||||
Some(InstanceMaterialData(item.0.clone()))
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
---
|
||||
title: Query items can borrow from query state
|
||||
pull_requests: [15396]
|
||||
---
|
||||
|
||||
The `QueryData::Item` and `WorldQuery::Fetch` associated types and the `QueryItem` and `ROQueryItem` type aliases now have an additional lifetime parameter corresponding to the `'s` lifetime in `Query`.
|
||||
Manual implementations of `WorldQuery` and `QueryData` will need to update the method signatures to include the new lifetimes.
|
||||
Other uses of the types will need to be updated to include a lifetime parameter, although it can usually be passed as `'_`.
|
||||
In particular, `ROQueryItem` is used when implementing `RenderCommand`.
|
||||
|
||||
Before:
|
||||
|
||||
```rust
|
||||
// 0.16
|
||||
fn render<'w>(
|
||||
item: &P,
|
||||
view: ROQueryItem<'w, Self::ViewQuery>,
|
||||
entity: Option<ROQueryItem<'w, Self::ItemQuery>>,
|
||||
param: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult;
|
||||
|
||||
// 0.17
|
||||
fn render<'w>(
|
||||
item: &P,
|
||||
view: ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
entity: Option<ROQueryItem<'w, '_, Self::ItemQuery>>,
|
||||
param: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Methods on `QueryState` that take `&mut self` may now result in conflicting borrows if the query items capture the lifetime of the mutable reference.
|
||||
This affects `get()`, `iter()`, and others.
|
||||
To fix the errors, first call `QueryState::update_archetypes()`, and then replace a call `state.foo(world, param)` with `state.query_manual(world).foo_inner(param)`.
|
||||
Alternately, you may be able to restructure the code to call `state.query(world)` once and then make multiple calls using the `Query`.
|
||||
|
||||
```rust
|
||||
let mut state: QueryState<_, _> = ...;
|
||||
|
||||
// 0.16
|
||||
let d1 = state.get(world, e1);
|
||||
let d2 = state.get(world, e2); // Error: cannot borrow `state` as mutable more than once at a time
|
||||
|
||||
println!("{d1:?}");
|
||||
println!("{d2:?}");
|
||||
|
||||
// 0.17
|
||||
state.update_archetypes(world);
|
||||
let d1 = state.get_manual(world, e1);
|
||||
let d2 = state.get_manual(world, e2);
|
||||
// OR
|
||||
state.update_archetypes(world);
|
||||
let d1 = state.query_manual(world).get_inner(e1);
|
||||
let d2 = state.query_manual(world).get_inner(e2);
|
||||
// OR
|
||||
let query = state.query(world);
|
||||
let d1 = query.get_inner(e1);
|
||||
let d1 = query.get_inner(e2);
|
||||
|
||||
println!("{d1:?}");
|
||||
println!("{d2:?}");
|
||||
```
|
Loading…
Reference in New Issue
Block a user