Clean up Fetch code (#4800)
# Objective Clean up code surrounding fetch by pulling out the common parts into the iteration code. ## Solution Merge `Fetch::table_fetch` and `Fetch::archetype_fetch` into a single API: `Fetch::fetch(&mut self, entity: &Entity, table_row: &usize)`. This provides everything any fetch requires to internally decide which storage to read from and get the underlying data. All of these functions are marked as `#[inline(always)]` and the arguments are passed as references to attempt to optimize out the argument that isn't being used. External to `Fetch`, Query iteration has been changed to keep track of the table row and entity outside of fetch, which moves a lot of the expensive bookkeeping `Fetch` structs had previously done internally into the outer loop. ~~TODO: Benchmark, docs~~ Done. --- ## Changelog Changed: `Fetch::table_fetch` and `Fetch::archetype_fetch` have been merged into a single `Fetch::fetch` function. ## Migration Guide TODO Co-authored-by: Brian Merchant <bhmerchang@gmail.com> Co-authored-by: Saverio Miroddi <saverio.pub2@gmail.com>
This commit is contained in:
		
							parent
							
								
									284b1f1302
								
							
						
					
					
						commit
						fe7ebd4326
					
				@ -261,9 +261,9 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
 | 
			
		||||
                    _fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
 | 
			
		||||
                    _state: &Self::State,
 | 
			
		||||
                    _archetype: &'__w #path::archetype::Archetype,
 | 
			
		||||
                    _tables: &'__w #path::storage::Tables
 | 
			
		||||
                    _table: &'__w #path::storage::Table
 | 
			
		||||
                ) {
 | 
			
		||||
                    #(<#field_types>::set_archetype(&mut _fetch.#field_idents, &_state.#field_idents, _archetype, _tables);)*
 | 
			
		||||
                    #(<#field_types>::set_archetype(&mut _fetch.#field_idents, &_state.#field_idents, _archetype, _table);)*
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /// SAFETY: we call `set_table` for each member that implements `Fetch`
 | 
			
		||||
@ -276,40 +276,27 @@ pub fn derive_world_query_impl(ast: DeriveInput) -> TokenStream {
 | 
			
		||||
                    #(<#field_types>::set_table(&mut _fetch.#field_idents, &_state.#field_idents, _table);)*
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /// SAFETY: we call `table_fetch` for each member that implements `Fetch`.
 | 
			
		||||
                #[inline]
 | 
			
		||||
                unsafe fn table_fetch<'__w>(
 | 
			
		||||
                /// SAFETY: we call `fetch` for each member that implements `Fetch`.
 | 
			
		||||
                #[inline(always)]
 | 
			
		||||
                unsafe fn fetch<'__w>(
 | 
			
		||||
                    _fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
 | 
			
		||||
                    _entity: Entity,
 | 
			
		||||
                    _table_row: usize
 | 
			
		||||
                ) -> <Self as #path::query::WorldQueryGats<'__w>>::Item {
 | 
			
		||||
                    Self::Item {
 | 
			
		||||
                        #(#field_idents: <#field_types>::table_fetch(&mut _fetch.#field_idents, _table_row),)*
 | 
			
		||||
                        #(#field_idents: <#field_types>::fetch(&mut _fetch.#field_idents, _entity, _table_row),)*
 | 
			
		||||
                        #(#ignored_field_idents: Default::default(),)*
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /// SAFETY: we call `archetype_fetch` for each member that implements `Fetch`.
 | 
			
		||||
                #[inline]
 | 
			
		||||
                unsafe fn archetype_fetch<'__w>(
 | 
			
		||||
                #[allow(unused_variables)]
 | 
			
		||||
                #[inline(always)]
 | 
			
		||||
                unsafe fn filter_fetch<'__w>(
 | 
			
		||||
                    _fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
 | 
			
		||||
                    _archetype_index: usize
 | 
			
		||||
                ) -> <Self as #path::query::WorldQueryGats<'__w>>::Item {
 | 
			
		||||
                    Self::Item {
 | 
			
		||||
                        #(#field_idents: <#field_types>::archetype_fetch(&mut _fetch.#field_idents, _archetype_index),)*
 | 
			
		||||
                        #(#ignored_field_idents: Default::default(),)*
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                #[allow(unused_variables)]
 | 
			
		||||
                #[inline]
 | 
			
		||||
                unsafe fn table_filter_fetch<'__w>(_fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch, _table_row: usize) -> bool {
 | 
			
		||||
                    true #(&& <#field_types>::table_filter_fetch(&mut _fetch.#field_idents, _table_row))*
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                #[allow(unused_variables)]
 | 
			
		||||
                #[inline]
 | 
			
		||||
                unsafe fn archetype_filter_fetch<'__w>(_fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch, _archetype_index: usize) -> bool {
 | 
			
		||||
                    true #(&& <#field_types>::archetype_filter_fetch(&mut _fetch.#field_idents, _archetype_index))*
 | 
			
		||||
                    _entity: Entity,
 | 
			
		||||
                    _table_row: usize
 | 
			
		||||
                ) -> bool {
 | 
			
		||||
                    true #(&& <#field_types>::filter_fetch(&mut _fetch.#field_idents, _entity, _table_row))*
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                fn update_component_access(state: &Self::State, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
 | 
			
		||||
 | 
			
		||||
@ -121,9 +121,19 @@ impl Edges {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct TableInfo {
 | 
			
		||||
    id: TableId,
 | 
			
		||||
    entity_rows: Vec<usize>,
 | 
			
		||||
pub struct ArchetypeEntity {
 | 
			
		||||
    pub(crate) entity: Entity,
 | 
			
		||||
    pub(crate) table_row: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ArchetypeEntity {
 | 
			
		||||
    pub fn entity(&self) -> Entity {
 | 
			
		||||
        self.entity
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn table_row(&self) -> usize {
 | 
			
		||||
        self.table_row
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) struct ArchetypeSwapRemoveResult {
 | 
			
		||||
@ -138,9 +148,9 @@ pub(crate) struct ArchetypeComponentInfo {
 | 
			
		||||
 | 
			
		||||
pub struct Archetype {
 | 
			
		||||
    id: ArchetypeId,
 | 
			
		||||
    entities: Vec<Entity>,
 | 
			
		||||
    table_id: TableId,
 | 
			
		||||
    edges: Edges,
 | 
			
		||||
    table_info: TableInfo,
 | 
			
		||||
    entities: Vec<ArchetypeEntity>,
 | 
			
		||||
    table_components: Box<[ComponentId]>,
 | 
			
		||||
    sparse_set_components: Box<[ComponentId]>,
 | 
			
		||||
    components: SparseSet<ComponentId, ArchetypeComponentInfo>,
 | 
			
		||||
@ -183,14 +193,11 @@ impl Archetype {
 | 
			
		||||
        }
 | 
			
		||||
        Self {
 | 
			
		||||
            id,
 | 
			
		||||
            table_info: TableInfo {
 | 
			
		||||
                id: table_id,
 | 
			
		||||
                entity_rows: Default::default(),
 | 
			
		||||
            },
 | 
			
		||||
            table_id,
 | 
			
		||||
            entities: Vec::new(),
 | 
			
		||||
            components,
 | 
			
		||||
            table_components,
 | 
			
		||||
            sparse_set_components,
 | 
			
		||||
            entities: Default::default(),
 | 
			
		||||
            edges: Default::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -202,19 +209,14 @@ impl Archetype {
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn table_id(&self) -> TableId {
 | 
			
		||||
        self.table_info.id
 | 
			
		||||
        self.table_id
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn entities(&self) -> &[Entity] {
 | 
			
		||||
    pub fn entities(&self) -> &[ArchetypeEntity] {
 | 
			
		||||
        &self.entities
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn entity_table_rows(&self) -> &[usize] {
 | 
			
		||||
        &self.table_info.entity_rows
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn table_components(&self) -> &[ComponentId] {
 | 
			
		||||
        &self.table_components
 | 
			
		||||
@ -242,20 +244,19 @@ impl Archetype {
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn entity_table_row(&self, index: usize) -> usize {
 | 
			
		||||
        self.table_info.entity_rows[index]
 | 
			
		||||
        self.entities[index].table_row
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub(crate) fn set_entity_table_row(&mut self, index: usize, table_row: usize) {
 | 
			
		||||
        self.table_info.entity_rows[index] = table_row;
 | 
			
		||||
        self.entities[index].table_row = table_row;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// # Safety
 | 
			
		||||
    /// valid component values must be immediately written to the relevant storages
 | 
			
		||||
    /// `table_row` must be valid
 | 
			
		||||
    pub(crate) unsafe fn allocate(&mut self, entity: Entity, table_row: usize) -> EntityLocation {
 | 
			
		||||
        self.entities.push(entity);
 | 
			
		||||
        self.table_info.entity_rows.push(table_row);
 | 
			
		||||
        self.entities.push(ArchetypeEntity { entity, table_row });
 | 
			
		||||
 | 
			
		||||
        EntityLocation {
 | 
			
		||||
            archetype_id: self.id,
 | 
			
		||||
@ -265,21 +266,20 @@ impl Archetype {
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn reserve(&mut self, additional: usize) {
 | 
			
		||||
        self.entities.reserve(additional);
 | 
			
		||||
        self.table_info.entity_rows.reserve(additional);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Removes the entity at `index` by swapping it out. Returns the table row the entity is stored
 | 
			
		||||
    /// in.
 | 
			
		||||
    pub(crate) fn swap_remove(&mut self, index: usize) -> ArchetypeSwapRemoveResult {
 | 
			
		||||
        let is_last = index == self.entities.len() - 1;
 | 
			
		||||
        self.entities.swap_remove(index);
 | 
			
		||||
        let entity = self.entities.swap_remove(index);
 | 
			
		||||
        ArchetypeSwapRemoveResult {
 | 
			
		||||
            swapped_entity: if is_last {
 | 
			
		||||
                None
 | 
			
		||||
            } else {
 | 
			
		||||
                Some(self.entities[index])
 | 
			
		||||
                Some(self.entities[index].entity)
 | 
			
		||||
            },
 | 
			
		||||
            table_row: self.table_info.entity_rows.swap_remove(index),
 | 
			
		||||
            table_row: entity.table_row,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -317,7 +317,6 @@ impl Archetype {
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn clear_entities(&mut self) {
 | 
			
		||||
        self.entities.clear();
 | 
			
		||||
        self.table_info.entity_rows.clear();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -540,8 +540,8 @@ mod tests {
 | 
			
		||||
        let f = world
 | 
			
		||||
            .spawn((TableStored("def"), A(456), SparseStored(1)))
 | 
			
		||||
            .id();
 | 
			
		||||
        // // this should be skipped
 | 
			
		||||
        // SparseStored(1).spawn("abc");
 | 
			
		||||
        // this should be skipped
 | 
			
		||||
        // world.spawn(SparseStored(1));
 | 
			
		||||
        let ents = world
 | 
			
		||||
            .query::<(Entity, Option<&SparseStored>, &A)>()
 | 
			
		||||
            .iter(&world)
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ use crate::{
 | 
			
		||||
    component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
 | 
			
		||||
    entity::Entity,
 | 
			
		||||
    query::{debug_checked_unreachable, Access, FilteredAccess},
 | 
			
		||||
    storage::{ComponentSparseSet, Table, Tables},
 | 
			
		||||
    storage::{ComponentSparseSet, Table},
 | 
			
		||||
    world::{Mut, World},
 | 
			
		||||
};
 | 
			
		||||
use bevy_ecs_macros::all_tuples;
 | 
			
		||||
@ -285,11 +285,10 @@ use std::{cell::UnsafeCell, marker::PhantomData};
 | 
			
		||||
/// exactly reflects the results of the following methods:
 | 
			
		||||
///
 | 
			
		||||
/// - [`matches_component_set`]
 | 
			
		||||
/// - [`archetype_fetch`]
 | 
			
		||||
/// - [`table_fetch`]
 | 
			
		||||
/// - [`fetch`]
 | 
			
		||||
///
 | 
			
		||||
/// [`Added`]: crate::query::Added
 | 
			
		||||
/// [`archetype_fetch`]: Self::archetype_fetch
 | 
			
		||||
/// [`fetch`]: Self::fetch
 | 
			
		||||
/// [`Changed`]: crate::query::Changed
 | 
			
		||||
/// [`Fetch`]: crate::query::WorldQueryGats::Fetch
 | 
			
		||||
/// [`matches_component_set`]: Self::matches_component_set
 | 
			
		||||
@ -297,7 +296,6 @@ use std::{cell::UnsafeCell, marker::PhantomData};
 | 
			
		||||
/// [`Query`]: crate::system::Query
 | 
			
		||||
/// [`ReadOnly`]: Self::ReadOnly
 | 
			
		||||
/// [`State`]: Self::State
 | 
			
		||||
/// [`table_fetch`]: Self::table_fetch
 | 
			
		||||
/// [`update_archetype_component_access`]: Self::update_archetype_component_access
 | 
			
		||||
/// [`update_component_access`]: Self::update_component_access
 | 
			
		||||
/// [`With`]: crate::query::With
 | 
			
		||||
@ -339,9 +337,10 @@ pub unsafe trait WorldQuery: for<'w> WorldQueryGats<'w> {
 | 
			
		||||
 | 
			
		||||
    /// Returns true if (and only if) every table of every archetype matched by this fetch contains
 | 
			
		||||
    /// all of the matched components. This is used to select a more efficient "table iterator"
 | 
			
		||||
    /// for "dense" queries. If this returns true, [`WorldQuery::set_table`] and [`WorldQuery::table_fetch`]
 | 
			
		||||
    /// will be called for iterators. If this returns false, [`WorldQuery::set_archetype`] and
 | 
			
		||||
    /// [`WorldQuery::archetype_fetch`] will be called for iterators.
 | 
			
		||||
    /// for "dense" queries. If this returns true, [`WorldQuery::set_table`] must be used before
 | 
			
		||||
    /// [`WorldQuery::fetch`] can be called for iterators. If this returns false,
 | 
			
		||||
    /// [`WorldQuery::set_archetype`] must be used before [`WorldQuery::fetch`] can be called for
 | 
			
		||||
    /// iterators.
 | 
			
		||||
    const IS_DENSE: bool;
 | 
			
		||||
 | 
			
		||||
    /// Returns true if (and only if) this Fetch relies strictly on archetypes to limit which
 | 
			
		||||
@ -362,7 +361,7 @@ pub unsafe trait WorldQuery: for<'w> WorldQueryGats<'w> {
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        state: &Self::State,
 | 
			
		||||
        archetype: &'w Archetype,
 | 
			
		||||
        tables: &'w Tables,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// Adjusts internal state to account for the next [`Table`]. This will always be called on tables
 | 
			
		||||
@ -378,51 +377,30 @@ pub unsafe trait WorldQuery: for<'w> WorldQueryGats<'w> {
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// Fetch [`Self::Item`](`WorldQueryGats::Item`) for the given `archetype_index` in the current [`Archetype`]. This must
 | 
			
		||||
    /// always be called after [`WorldQuery::set_archetype`] with an `archetype_index` in the range of
 | 
			
		||||
    /// the current [`Archetype`]
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Safety
 | 
			
		||||
    /// Must always be called _after_ [`WorldQuery::set_archetype`]. `archetype_index` must be in the range
 | 
			
		||||
    /// of the current archetype
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        archetype_index: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item;
 | 
			
		||||
 | 
			
		||||
    /// Fetch [`Self::Item`](`WorldQueryGats::Item`) for the given `table_row` in the current [`Table`]. This must always be
 | 
			
		||||
    /// called after [`WorldQuery::set_table`] with a `table_row` in the range of the current [`Table`]
 | 
			
		||||
    /// Fetch [`Self::Item`](`WorldQueryGats::Item`) for either the given `entity` in the current [`Table`],
 | 
			
		||||
    /// or for the given `entity` in the current [`Archetype`]. This must always be called after
 | 
			
		||||
    /// [`WorldQuery::set_table`] with a `table_row` in the range of the current [`Table`] or after
 | 
			
		||||
    /// [`WorldQuery::set_archetype`]  with a `entity` in the current archetype.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Safety
 | 
			
		||||
    ///
 | 
			
		||||
    /// Must always be called _after_ [`WorldQuery::set_table`]. `table_row` must be in the range of the
 | 
			
		||||
    /// current table
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
    /// 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 fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item;
 | 
			
		||||
 | 
			
		||||
    /// # Safety
 | 
			
		||||
    ///
 | 
			
		||||
    /// Must always be called _after_ [`WorldQuery::set_archetype`]. `archetype_index` must be in the range
 | 
			
		||||
    /// of the current archetype.
 | 
			
		||||
    /// 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.
 | 
			
		||||
    #[allow(unused_variables)]
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_filter_fetch(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'_>>::Fetch,
 | 
			
		||||
        archetype_index: usize,
 | 
			
		||||
    ) -> bool {
 | 
			
		||||
        true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// # Safety
 | 
			
		||||
    ///
 | 
			
		||||
    /// Must always be called _after_ [`WorldQuery::set_table`]. `table_row` must be in the range of the
 | 
			
		||||
    /// current table.
 | 
			
		||||
    #[allow(unused_variables)]
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_filter_fetch(
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn filter_fetch(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'_>>::Fetch,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> bool {
 | 
			
		||||
        true
 | 
			
		||||
@ -470,11 +448,6 @@ pub type ROQueryFetch<'w, Q> = QueryFetch<'w, <Q as WorldQuery>::ReadOnly>;
 | 
			
		||||
/// The read-only variant of the item type returned when a [`WorldQuery`] is iterated over immutably
 | 
			
		||||
pub type ROQueryItem<'w, Q> = QueryItem<'w, <Q as WorldQuery>::ReadOnly>;
 | 
			
		||||
 | 
			
		||||
#[doc(hidden)]
 | 
			
		||||
pub struct EntityFetch<'w> {
 | 
			
		||||
    entities: Option<ThinSlicePtr<'w, Entity>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// SAFETY: no component or archetype access
 | 
			
		||||
unsafe impl WorldQuery for Entity {
 | 
			
		||||
    type ReadOnly = Self;
 | 
			
		||||
@ -490,56 +463,41 @@ unsafe impl WorldQuery for Entity {
 | 
			
		||||
 | 
			
		||||
    unsafe fn init_fetch<'w>(
 | 
			
		||||
        _world: &'w World,
 | 
			
		||||
        _state: &(),
 | 
			
		||||
        _state: &Self::State,
 | 
			
		||||
        _last_change_tick: u32,
 | 
			
		||||
        _change_tick: u32,
 | 
			
		||||
    ) -> EntityFetch<'w> {
 | 
			
		||||
        EntityFetch { entities: None }
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Fetch {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsafe fn clone_fetch<'w>(
 | 
			
		||||
        fetch: &<Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _fetch: &<Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Fetch {
 | 
			
		||||
        EntityFetch {
 | 
			
		||||
            entities: fetch.entities,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_archetype<'w>(
 | 
			
		||||
        fetch: &mut EntityFetch<'w>,
 | 
			
		||||
        _state: &(),
 | 
			
		||||
        archetype: &'w Archetype,
 | 
			
		||||
        _tables: &Tables,
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _state: &Self::State,
 | 
			
		||||
        _archetype: &'w Archetype,
 | 
			
		||||
        _table: &Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        fetch.entities = Some(archetype.entities().into());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_table<'w>(fetch: &mut EntityFetch<'w>, _state: &(), table: &'w Table) {
 | 
			
		||||
        fetch.entities = Some(table.entities().into());
 | 
			
		||||
    unsafe fn set_table<'w>(
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _state: &Self::State,
 | 
			
		||||
        _table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> QueryItem<'w, Self> {
 | 
			
		||||
        let entities = fetch
 | 
			
		||||
            .entities
 | 
			
		||||
            .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
        *entities.get(table_row)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        archetype_index: usize,
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        _table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        let entities = fetch
 | 
			
		||||
            .entities
 | 
			
		||||
            .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
        *entities.get(archetype_index)
 | 
			
		||||
        entity
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {}
 | 
			
		||||
@ -562,7 +520,7 @@ unsafe impl WorldQuery for Entity {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'w> WorldQueryGats<'w> for Entity {
 | 
			
		||||
    type Fetch = EntityFetch<'w>;
 | 
			
		||||
    type Fetch = ();
 | 
			
		||||
    type Item = Entity;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -573,9 +531,7 @@ unsafe impl ReadOnlyWorldQuery for Entity {}
 | 
			
		||||
pub struct ReadFetch<'w, T> {
 | 
			
		||||
    // T::Storage = TableStorage
 | 
			
		||||
    table_components: Option<ThinSlicePtr<'w, UnsafeCell<T>>>,
 | 
			
		||||
    entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
 | 
			
		||||
    // T::Storage = SparseStorage
 | 
			
		||||
    entities: Option<ThinSlicePtr<'w, Entity>>,
 | 
			
		||||
    sparse_set: Option<&'w ComponentSparseSet>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -605,10 +561,13 @@ unsafe impl<T: Component> WorldQuery for &T {
 | 
			
		||||
    ) -> ReadFetch<'w, T> {
 | 
			
		||||
        ReadFetch {
 | 
			
		||||
            table_components: None,
 | 
			
		||||
            entity_table_rows: None,
 | 
			
		||||
            entities: None,
 | 
			
		||||
            sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
 | 
			
		||||
                .then(|| world.storages().sparse_sets.get(component_id).unwrap()),
 | 
			
		||||
            sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
 | 
			
		||||
                world
 | 
			
		||||
                    .storages()
 | 
			
		||||
                    .sparse_sets
 | 
			
		||||
                    .get(component_id)
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
            }),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -617,8 +576,6 @@ unsafe impl<T: Component> WorldQuery for &T {
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Fetch {
 | 
			
		||||
        ReadFetch {
 | 
			
		||||
            table_components: fetch.table_components,
 | 
			
		||||
            entity_table_rows: fetch.entity_table_rows,
 | 
			
		||||
            entities: fetch.entities,
 | 
			
		||||
            sparse_set: fetch.sparse_set,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -626,64 +583,49 @@ unsafe impl<T: Component> WorldQuery for &T {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_archetype<'w>(
 | 
			
		||||
        fetch: &mut ReadFetch<'w, T>,
 | 
			
		||||
        &component_id: &ComponentId,
 | 
			
		||||
        archetype: &'w Archetype,
 | 
			
		||||
        tables: &'w Tables,
 | 
			
		||||
        component_id: &ComponentId,
 | 
			
		||||
        _archetype: &'w Archetype,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                fetch.entity_table_rows = Some(archetype.entity_table_rows().into());
 | 
			
		||||
                let column = tables[archetype.table_id()]
 | 
			
		||||
        if Self::IS_DENSE {
 | 
			
		||||
            Self::set_table(fetch, component_id, table);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_table<'w>(
 | 
			
		||||
        fetch: &mut ReadFetch<'w, T>,
 | 
			
		||||
        &component_id: &ComponentId,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        fetch.table_components = Some(
 | 
			
		||||
            table
 | 
			
		||||
                .get_column(component_id)
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
                fetch.table_components = Some(column.get_data_slice().into());
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => fetch.entities = Some(archetype.entities().into()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_table<'w>(fetch: &mut ReadFetch<'w, T>, &id: &ComponentId, table: &'w Table) {
 | 
			
		||||
        fetch.table_components = Some(table.get_column(id).unwrap().get_data_slice().into());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        archetype_index: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                let (entity_table_rows, table_components) = fetch
 | 
			
		||||
                    .entity_table_rows
 | 
			
		||||
                    .zip(fetch.table_components)
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                let table_row = *entity_table_rows.get(archetype_index);
 | 
			
		||||
                table_components.get(table_row).deref()
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => {
 | 
			
		||||
                let (entities, sparse_set) = fetch
 | 
			
		||||
                    .entities
 | 
			
		||||
                    .zip(fetch.sparse_set)
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                let entity = *entities.get(archetype_index);
 | 
			
		||||
                sparse_set
 | 
			
		||||
                    .get(entity)
 | 
			
		||||
                .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                    .deref::<T>()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
                .get_data_slice()
 | 
			
		||||
                .into(),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        let components = fetch
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => fetch
 | 
			
		||||
                .table_components
 | 
			
		||||
            .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
        components.get(table_row).deref()
 | 
			
		||||
                .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                .get(table_row)
 | 
			
		||||
                .deref(),
 | 
			
		||||
            StorageType::SparseSet => fetch
 | 
			
		||||
                .sparse_set
 | 
			
		||||
                .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                .get(entity)
 | 
			
		||||
                .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                .deref(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_component_access(
 | 
			
		||||
@ -731,11 +673,11 @@ impl<'w, T: Component> WorldQueryGats<'w> for &T {
 | 
			
		||||
#[doc(hidden)]
 | 
			
		||||
pub struct WriteFetch<'w, T> {
 | 
			
		||||
    // T::Storage = TableStorage
 | 
			
		||||
    table_components: Option<ThinSlicePtr<'w, UnsafeCell<T>>>,
 | 
			
		||||
    table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
 | 
			
		||||
    entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
 | 
			
		||||
    table_data: Option<(
 | 
			
		||||
        ThinSlicePtr<'w, UnsafeCell<T>>,
 | 
			
		||||
        ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>,
 | 
			
		||||
    )>,
 | 
			
		||||
    // T::Storage = SparseStorage
 | 
			
		||||
    entities: Option<ThinSlicePtr<'w, Entity>>,
 | 
			
		||||
    sparse_set: Option<&'w ComponentSparseSet>,
 | 
			
		||||
 | 
			
		||||
    last_change_tick: u32,
 | 
			
		||||
@ -767,12 +709,14 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) -> WriteFetch<'w, T> {
 | 
			
		||||
        WriteFetch {
 | 
			
		||||
            table_components: None,
 | 
			
		||||
            entities: None,
 | 
			
		||||
            entity_table_rows: None,
 | 
			
		||||
            sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
 | 
			
		||||
                .then(|| world.storages().sparse_sets.get(component_id).unwrap()),
 | 
			
		||||
            table_ticks: None,
 | 
			
		||||
            table_data: None,
 | 
			
		||||
            sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
 | 
			
		||||
                world
 | 
			
		||||
                    .storages()
 | 
			
		||||
                    .sparse_sets
 | 
			
		||||
                    .get(component_id)
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
            }),
 | 
			
		||||
            last_change_tick,
 | 
			
		||||
            change_tick,
 | 
			
		||||
        }
 | 
			
		||||
@ -782,10 +726,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
 | 
			
		||||
        fetch: &<Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Fetch {
 | 
			
		||||
        WriteFetch {
 | 
			
		||||
            table_components: fetch.table_components,
 | 
			
		||||
            table_ticks: fetch.table_ticks,
 | 
			
		||||
            entities: fetch.entities,
 | 
			
		||||
            entity_table_rows: fetch.entity_table_rows,
 | 
			
		||||
            table_data: fetch.table_data,
 | 
			
		||||
            sparse_set: fetch.sparse_set,
 | 
			
		||||
            last_change_tick: fetch.last_change_tick,
 | 
			
		||||
            change_tick: fetch.change_tick,
 | 
			
		||||
@ -795,20 +736,12 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_archetype<'w>(
 | 
			
		||||
        fetch: &mut WriteFetch<'w, T>,
 | 
			
		||||
        &component_id: &ComponentId,
 | 
			
		||||
        archetype: &'w Archetype,
 | 
			
		||||
        tables: &'w Tables,
 | 
			
		||||
        component_id: &ComponentId,
 | 
			
		||||
        _archetype: &'w Archetype,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                fetch.entity_table_rows = Some(archetype.entity_table_rows().into());
 | 
			
		||||
                let column = tables[archetype.table_id()]
 | 
			
		||||
                    .get_column(component_id)
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
                fetch.table_components = Some(column.get_data_slice().into());
 | 
			
		||||
                fetch.table_ticks = Some(column.get_ticks_slice().into());
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => fetch.entities = Some(archetype.entities().into()),
 | 
			
		||||
        if Self::IS_DENSE {
 | 
			
		||||
            Self::set_table(fetch, component_id, table);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -818,23 +751,26 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
 | 
			
		||||
        &component_id: &ComponentId,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        let column = table.get_column(component_id).unwrap();
 | 
			
		||||
        fetch.table_components = Some(column.get_data_slice().into());
 | 
			
		||||
        fetch.table_ticks = Some(column.get_ticks_slice().into());
 | 
			
		||||
        let column = table
 | 
			
		||||
            .get_column(component_id)
 | 
			
		||||
            .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
        fetch.table_data = Some((
 | 
			
		||||
            column.get_data_slice().into(),
 | 
			
		||||
            column.get_ticks_slice().into(),
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        archetype_index: usize,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                let (entity_table_rows, (table_components, table_ticks)) = fetch
 | 
			
		||||
                    .entity_table_rows
 | 
			
		||||
                    .zip(fetch.table_components.zip(fetch.table_ticks))
 | 
			
		||||
                let (table_components, table_ticks) = fetch
 | 
			
		||||
                    .table_data
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                let table_row = *entity_table_rows.get(archetype_index);
 | 
			
		||||
                Mut {
 | 
			
		||||
                    value: table_components.get(table_row).deref_mut(),
 | 
			
		||||
                    ticks: Ticks {
 | 
			
		||||
@ -845,12 +781,9 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => {
 | 
			
		||||
                let (entities, sparse_set) = fetch
 | 
			
		||||
                    .entities
 | 
			
		||||
                    .zip(fetch.sparse_set)
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                let entity = *entities.get(archetype_index);
 | 
			
		||||
                let (component, component_ticks) = sparse_set
 | 
			
		||||
                let (component, component_ticks) = fetch
 | 
			
		||||
                    .sparse_set
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                    .get_with_ticks(entity)
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                Mut {
 | 
			
		||||
@ -865,25 +798,6 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        let (table_components, table_ticks) = fetch
 | 
			
		||||
            .table_components
 | 
			
		||||
            .zip(fetch.table_ticks)
 | 
			
		||||
            .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
        Mut {
 | 
			
		||||
            value: table_components.get(table_row).deref_mut(),
 | 
			
		||||
            ticks: Ticks {
 | 
			
		||||
                component_ticks: table_ticks.get(table_row).deref_mut(),
 | 
			
		||||
                change_tick: fetch.change_tick,
 | 
			
		||||
                last_change_tick: fetch.last_change_tick,
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_component_access(
 | 
			
		||||
        &component_id: &ComponentId,
 | 
			
		||||
        access: &mut FilteredAccess<ComponentId>,
 | 
			
		||||
@ -968,11 +882,11 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
 | 
			
		||||
        fetch: &mut OptionFetch<'w, T>,
 | 
			
		||||
        state: &T::State,
 | 
			
		||||
        archetype: &'w Archetype,
 | 
			
		||||
        tables: &'w Tables,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        fetch.matches = T::matches_component_set(state, &|id| archetype.contains(id));
 | 
			
		||||
        if fetch.matches {
 | 
			
		||||
            T::set_archetype(&mut fetch.fetch, state, archetype, tables);
 | 
			
		||||
            T::set_archetype(&mut fetch.fetch, state, archetype, table);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -984,28 +898,15 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        archetype_index: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        if fetch.matches {
 | 
			
		||||
            Some(T::archetype_fetch(&mut fetch.fetch, archetype_index))
 | 
			
		||||
        } else {
 | 
			
		||||
            None
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        if fetch.matches {
 | 
			
		||||
            Some(T::table_fetch(&mut fetch.fetch, table_row))
 | 
			
		||||
        } else {
 | 
			
		||||
            None
 | 
			
		||||
        }
 | 
			
		||||
        fetch
 | 
			
		||||
            .matches
 | 
			
		||||
            .then(|| T::fetch(&mut fetch.fetch, entity, table_row))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_component_access(state: &T::State, access: &mut FilteredAccess<ComponentId>) {
 | 
			
		||||
@ -1127,9 +1028,7 @@ impl<T: Component> ChangeTrackers<T> {
 | 
			
		||||
pub struct ChangeTrackersFetch<'w, T> {
 | 
			
		||||
    // T::Storage = TableStorage
 | 
			
		||||
    table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
 | 
			
		||||
    entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
 | 
			
		||||
    // T::Storage = SparseStorage
 | 
			
		||||
    entities: Option<ThinSlicePtr<'w, Entity>>,
 | 
			
		||||
    sparse_set: Option<&'w ComponentSparseSet>,
 | 
			
		||||
 | 
			
		||||
    marker: PhantomData<T>,
 | 
			
		||||
@ -1157,16 +1056,19 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
 | 
			
		||||
 | 
			
		||||
    unsafe fn init_fetch<'w>(
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        &id: &ComponentId,
 | 
			
		||||
        &component_id: &ComponentId,
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) -> ChangeTrackersFetch<'w, T> {
 | 
			
		||||
        ChangeTrackersFetch {
 | 
			
		||||
            table_ticks: None,
 | 
			
		||||
            entities: None,
 | 
			
		||||
            entity_table_rows: None,
 | 
			
		||||
            sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
 | 
			
		||||
                .then(|| world.storages().sparse_sets.get(id).unwrap()),
 | 
			
		||||
            sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
 | 
			
		||||
                world
 | 
			
		||||
                    .storages()
 | 
			
		||||
                    .sparse_sets
 | 
			
		||||
                    .get(component_id)
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
            }),
 | 
			
		||||
            marker: PhantomData,
 | 
			
		||||
            last_change_tick,
 | 
			
		||||
            change_tick,
 | 
			
		||||
@ -1178,8 +1080,6 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Fetch {
 | 
			
		||||
        ChangeTrackersFetch {
 | 
			
		||||
            table_ticks: fetch.table_ticks,
 | 
			
		||||
            entity_table_rows: fetch.entity_table_rows,
 | 
			
		||||
            entities: fetch.entities,
 | 
			
		||||
            sparse_set: fetch.sparse_set,
 | 
			
		||||
            marker: fetch.marker,
 | 
			
		||||
            last_change_tick: fetch.last_change_tick,
 | 
			
		||||
@ -1190,17 +1090,12 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_archetype<'w>(
 | 
			
		||||
        fetch: &mut ChangeTrackersFetch<'w, T>,
 | 
			
		||||
        &id: &ComponentId,
 | 
			
		||||
        archetype: &'w Archetype,
 | 
			
		||||
        tables: &'w Tables,
 | 
			
		||||
        component_id: &ComponentId,
 | 
			
		||||
        _archetype: &'w Archetype,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                fetch.entity_table_rows = Some(archetype.entity_table_rows().into());
 | 
			
		||||
                let column = tables[archetype.table_id()].get_column(id).unwrap();
 | 
			
		||||
                fetch.table_ticks = Some(column.get_ticks_slice().into());
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => fetch.entities = Some(archetype.entities().into()),
 | 
			
		||||
        if Self::IS_DENSE {
 | 
			
		||||
            Self::set_table(fetch, component_id, table);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1210,21 +1105,23 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
 | 
			
		||||
        &id: &ComponentId,
 | 
			
		||||
        table: &'w Table,
 | 
			
		||||
    ) {
 | 
			
		||||
        fetch.table_ticks = Some(table.get_column(id).unwrap().get_ticks_slice().into());
 | 
			
		||||
        fetch.table_ticks = Some(
 | 
			
		||||
            table
 | 
			
		||||
                .get_column(id)
 | 
			
		||||
                .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                .get_ticks_slice()
 | 
			
		||||
                .into(),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        archetype_index: usize,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                let entity_table_rows = fetch
 | 
			
		||||
                    .entity_table_rows
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                let table_row = *entity_table_rows.get(archetype_index);
 | 
			
		||||
                ChangeTrackers {
 | 
			
		||||
            StorageType::Table => ChangeTrackers {
 | 
			
		||||
                component_ticks: {
 | 
			
		||||
                    let table_ticks = fetch
 | 
			
		||||
                        .table_ticks
 | 
			
		||||
@ -1234,44 +1131,18 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
 | 
			
		||||
                marker: PhantomData,
 | 
			
		||||
                last_change_tick: fetch.last_change_tick,
 | 
			
		||||
                change_tick: fetch.change_tick,
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => {
 | 
			
		||||
                let entities = fetch
 | 
			
		||||
                    .entities
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                let entity = *entities.get(archetype_index);
 | 
			
		||||
                ChangeTrackers {
 | 
			
		||||
                    component_ticks: fetch
 | 
			
		||||
            },
 | 
			
		||||
            StorageType::SparseSet => ChangeTrackers {
 | 
			
		||||
                component_ticks: *fetch
 | 
			
		||||
                    .sparse_set
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                    .get_ticks(entity)
 | 
			
		||||
                        .map(|ticks| &*ticks.get())
 | 
			
		||||
                        .cloned()
 | 
			
		||||
                        .unwrap_or_else(|| debug_checked_unreachable()),
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                    .get(),
 | 
			
		||||
                marker: PhantomData,
 | 
			
		||||
                last_change_tick: fetch.last_change_tick,
 | 
			
		||||
                change_tick: fetch.change_tick,
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
        fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
        ChangeTrackers {
 | 
			
		||||
            component_ticks: {
 | 
			
		||||
                let table_ticks = fetch
 | 
			
		||||
                    .table_ticks
 | 
			
		||||
                    .unwrap_or_else(|| debug_checked_unreachable());
 | 
			
		||||
                table_ticks.get(table_row).read()
 | 
			
		||||
            },
 | 
			
		||||
            marker: PhantomData,
 | 
			
		||||
            last_change_tick: fetch.last_change_tick,
 | 
			
		||||
            change_tick: fetch.change_tick,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1355,10 +1226,15 @@ macro_rules! impl_tuple_fetch {
 | 
			
		||||
            const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn set_archetype<'w>(_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, _state: &Self::State, _archetype: &'w Archetype, _tables: &'w Tables) {
 | 
			
		||||
            unsafe fn set_archetype<'w>(
 | 
			
		||||
                _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                _state: &Self::State,
 | 
			
		||||
                _archetype: &'w Archetype,
 | 
			
		||||
                _table: &'w Table
 | 
			
		||||
            ) {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                let ($($state,)*) = _state;
 | 
			
		||||
                $($name::set_archetype($name, $state, _archetype, _tables);)*
 | 
			
		||||
                $($name::set_archetype($name, $state, _archetype, _table);)*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
@ -1368,32 +1244,25 @@ macro_rules! impl_tuple_fetch {
 | 
			
		||||
                $($name::set_table($name, $state, _table);)*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            #[inline(always)]
 | 
			
		||||
            #[allow(clippy::unused_unit)]
 | 
			
		||||
            unsafe fn table_fetch<'w>(_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, _table_row: usize) -> QueryItem<'w, Self> {
 | 
			
		||||
            unsafe fn fetch<'w>(
 | 
			
		||||
                _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                _entity: Entity,
 | 
			
		||||
                _table_row: usize
 | 
			
		||||
            ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                ($($name::table_fetch($name, _table_row),)*)
 | 
			
		||||
                ($($name::fetch($name, _entity, _table_row),)*)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            #[allow(clippy::unused_unit)]
 | 
			
		||||
            unsafe fn archetype_fetch<'w>(_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, _archetype_index: usize) -> QueryItem<'w, Self> {
 | 
			
		||||
            #[inline(always)]
 | 
			
		||||
            unsafe fn filter_fetch<'w>(
 | 
			
		||||
                _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                _entity: Entity,
 | 
			
		||||
                _table_row: usize
 | 
			
		||||
            ) -> bool {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                ($($name::archetype_fetch($name, _archetype_index),)*)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[allow(unused_variables)]
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn table_filter_fetch(_fetch: &mut QueryFetch<'_, Self>, table_row: usize) -> bool {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                true $(&& $name::table_filter_fetch($name, table_row))*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[allow(unused_variables)]
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn archetype_filter_fetch(_fetch: &mut QueryFetch<'_, Self>, archetype_index: usize) -> bool {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                true $(&& $name::archetype_filter_fetch($name, archetype_index))*
 | 
			
		||||
                true $(&& $name::filter_fetch($name, _entity, _table_row))*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn update_component_access(state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {
 | 
			
		||||
@ -1471,13 +1340,18 @@ macro_rules! impl_anytuple_fetch {
 | 
			
		||||
            const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn set_archetype<'w>(_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, _state: &Self::State, _archetype: &'w Archetype, _tables: &'w Tables) {
 | 
			
		||||
            unsafe fn set_archetype<'w>(
 | 
			
		||||
                _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                _state: &Self::State,
 | 
			
		||||
                _archetype: &'w Archetype,
 | 
			
		||||
                _table: &'w Table
 | 
			
		||||
            ) {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                let ($($state,)*) = _state;
 | 
			
		||||
                $(
 | 
			
		||||
                    $name.1 = $name::matches_component_set($state, &|id| _archetype.contains(id));
 | 
			
		||||
                    if $name.1 {
 | 
			
		||||
                        $name::set_archetype(&mut $name.0, $state, _archetype, _tables);
 | 
			
		||||
                        $name::set_archetype(&mut $name.0, $state, _archetype, _table);
 | 
			
		||||
                    }
 | 
			
		||||
                )*
 | 
			
		||||
            }
 | 
			
		||||
@ -1494,21 +1368,16 @@ macro_rules! impl_anytuple_fetch {
 | 
			
		||||
                )*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            #[inline(always)]
 | 
			
		||||
            #[allow(clippy::unused_unit)]
 | 
			
		||||
            unsafe fn table_fetch<'w>(_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, _table_row: usize) -> QueryItem<'w, Self> {
 | 
			
		||||
            unsafe fn fetch<'w>(
 | 
			
		||||
                _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                _entity: Entity,
 | 
			
		||||
                _table_row: usize
 | 
			
		||||
            ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                ($(
 | 
			
		||||
                    $name.1.then(|| $name::table_fetch(&mut $name.0, _table_row)),
 | 
			
		||||
                )*)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            #[allow(clippy::unused_unit)]
 | 
			
		||||
            unsafe fn archetype_fetch<'w>(_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, _archetype_index: usize) -> QueryItem<'w, Self> {
 | 
			
		||||
                let ($($name,)*) = _fetch;
 | 
			
		||||
                ($(
 | 
			
		||||
                    $name.1.then(|| $name::archetype_fetch(&mut $name.0, _archetype_index)),
 | 
			
		||||
                    $name.1.then(|| $name::fetch(&mut $name.0, _entity, _table_row)),
 | 
			
		||||
                )*)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -1608,7 +1477,7 @@ unsafe impl<Q: WorldQuery> WorldQuery for NopWorldQuery<Q> {
 | 
			
		||||
        _fetch: &mut (),
 | 
			
		||||
        _state: &Q::State,
 | 
			
		||||
        _archetype: &Archetype,
 | 
			
		||||
        _tables: &Tables,
 | 
			
		||||
        _tables: &Table,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1616,15 +1485,9 @@ unsafe impl<Q: WorldQuery> WorldQuery for NopWorldQuery<Q> {
 | 
			
		||||
    unsafe fn set_table<'w>(_fetch: &mut (), _state: &Q::State, _table: &Table) {}
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _archetype_index: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
        _fetch: &mut (),
 | 
			
		||||
        _entity: Entity,
 | 
			
		||||
        _table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ use crate::{
 | 
			
		||||
    query::{
 | 
			
		||||
        debug_checked_unreachable, Access, FilteredAccess, QueryFetch, WorldQuery, WorldQueryGats,
 | 
			
		||||
    },
 | 
			
		||||
    storage::{ComponentSparseSet, Table, Tables},
 | 
			
		||||
    storage::{ComponentSparseSet, Table},
 | 
			
		||||
    world::World,
 | 
			
		||||
};
 | 
			
		||||
use bevy_ecs_macros::all_tuples;
 | 
			
		||||
@ -88,20 +88,14 @@ unsafe impl<T: Component> WorldQuery for With<T> {
 | 
			
		||||
        _fetch: &mut (),
 | 
			
		||||
        _state: &ComponentId,
 | 
			
		||||
        _archetype: &Archetype,
 | 
			
		||||
        _tables: &Tables,
 | 
			
		||||
        _table: &Table,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _archetype_index: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _entity: Entity,
 | 
			
		||||
        _table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
    }
 | 
			
		||||
@ -200,20 +194,14 @@ unsafe impl<T: Component> WorldQuery for Without<T> {
 | 
			
		||||
        _fetch: &mut (),
 | 
			
		||||
        _state: &ComponentId,
 | 
			
		||||
        _archetype: &Archetype,
 | 
			
		||||
        _tables: &Tables,
 | 
			
		||||
        _table: &Table,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch<'w>(
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _archetype_index: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch<'w>(
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch<'w>(
 | 
			
		||||
        _fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
        _entity: Entity,
 | 
			
		||||
        _table_row: usize,
 | 
			
		||||
    ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
    }
 | 
			
		||||
@ -348,37 +336,39 @@ macro_rules! impl_query_filter_tuple {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn set_archetype<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, state: &Self::State, archetype: &'w Archetype, tables: &'w Tables) {
 | 
			
		||||
            unsafe fn set_archetype<'w>(
 | 
			
		||||
                fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                state: & Self::State,
 | 
			
		||||
                archetype: &'w Archetype,
 | 
			
		||||
                table: &'w Table
 | 
			
		||||
            ) {
 | 
			
		||||
                let ($($filter,)*) = fetch;
 | 
			
		||||
                let ($($state,)*) = state;
 | 
			
		||||
                let ($($state,)*) = &state;
 | 
			
		||||
                $(
 | 
			
		||||
                    $filter.matches = $filter::matches_component_set($state, &|id| archetype.contains(id));
 | 
			
		||||
                    if $filter.matches {
 | 
			
		||||
                        $filter::set_archetype(&mut $filter.fetch, $state, archetype, tables);
 | 
			
		||||
                        $filter::set_archetype(&mut $filter.fetch, $state, archetype, table);
 | 
			
		||||
                    }
 | 
			
		||||
                )*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn table_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, table_row: usize) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
            #[inline(always)]
 | 
			
		||||
            unsafe fn fetch<'w>(
 | 
			
		||||
                fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                _entity: Entity,
 | 
			
		||||
                _table_row: usize
 | 
			
		||||
            ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
                let ($($filter,)*) = fetch;
 | 
			
		||||
                false $(|| ($filter.matches && $filter::table_filter_fetch(&mut $filter.fetch, table_row)))*
 | 
			
		||||
                false $(|| ($filter.matches && $filter::filter_fetch(&mut $filter.fetch, _entity, _table_row)))*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn archetype_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, archetype_index: usize) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
                let ($($filter,)*) = fetch;
 | 
			
		||||
                false $(|| ($filter.matches && $filter::archetype_filter_fetch(&mut $filter.fetch, archetype_index)))*
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn table_filter_fetch(fetch: &mut QueryFetch<'_, Self>, table_row: usize) -> bool {
 | 
			
		||||
                Self::table_fetch(fetch, table_row)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn archetype_filter_fetch(fetch: &mut QueryFetch<'_, Self>, archetype_index: usize) -> bool {
 | 
			
		||||
                Self::archetype_fetch(fetch, archetype_index)
 | 
			
		||||
            #[inline(always)]
 | 
			
		||||
            unsafe fn filter_fetch<'w>(
 | 
			
		||||
                fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                entity: Entity,
 | 
			
		||||
                table_row: usize
 | 
			
		||||
            ) -> bool {
 | 
			
		||||
                Self::fetch(fetch, entity, table_row)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn update_component_access(state: &Self::State, access: &mut FilteredAccess<ComponentId>) {
 | 
			
		||||
@ -450,9 +440,7 @@ macro_rules! impl_tick_filter {
 | 
			
		||||
        $(#[$fetch_meta])*
 | 
			
		||||
        pub struct $fetch_name<'w, T> {
 | 
			
		||||
            table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
 | 
			
		||||
            entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
 | 
			
		||||
            marker: PhantomData<T>,
 | 
			
		||||
            entities: Option<ThinSlicePtr<'w, Entity>>,
 | 
			
		||||
            sparse_set: Option<&'w ComponentSparseSet>,
 | 
			
		||||
            last_change_tick: u32,
 | 
			
		||||
            change_tick: u32,
 | 
			
		||||
@ -470,10 +458,13 @@ macro_rules! impl_tick_filter {
 | 
			
		||||
            unsafe fn init_fetch<'w>(world: &'w World, &id: &ComponentId, last_change_tick: u32, change_tick: u32) -> <Self as WorldQueryGats<'w>>::Fetch {
 | 
			
		||||
                QueryFetch::<'w, Self> {
 | 
			
		||||
                    table_ticks: None,
 | 
			
		||||
                    entities: None,
 | 
			
		||||
                    entity_table_rows: None,
 | 
			
		||||
                    sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
 | 
			
		||||
                        .then(|| world.storages().sparse_sets.get(id).unwrap()),
 | 
			
		||||
                        .then(|| {
 | 
			
		||||
                            world.storages()
 | 
			
		||||
                                 .sparse_sets
 | 
			
		||||
                                 .get(id)
 | 
			
		||||
                                 .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                        }),
 | 
			
		||||
                    marker: PhantomData,
 | 
			
		||||
                    last_change_tick,
 | 
			
		||||
                    change_tick,
 | 
			
		||||
@ -485,8 +476,6 @@ macro_rules! impl_tick_filter {
 | 
			
		||||
            ) -> <Self as WorldQueryGats<'w>>::Fetch {
 | 
			
		||||
                $fetch_name {
 | 
			
		||||
                    table_ticks: fetch.table_ticks,
 | 
			
		||||
                    entity_table_rows: fetch.entity_table_rows,
 | 
			
		||||
                    entities: fetch.entities,
 | 
			
		||||
                    sparse_set: fetch.sparse_set,
 | 
			
		||||
                    last_change_tick: fetch.last_change_tick,
 | 
			
		||||
                    change_tick: fetch.change_tick,
 | 
			
		||||
@ -503,53 +492,68 @@ macro_rules! impl_tick_filter {
 | 
			
		||||
 | 
			
		||||
            const IS_ARCHETYPAL:  bool = false;
 | 
			
		||||
 | 
			
		||||
            unsafe fn set_table<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, &id: &ComponentId, table: &'w Table) {
 | 
			
		||||
                fetch.table_ticks = Some(table.get_column(id).unwrap().get_ticks_slice().into());
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn set_table<'w>(
 | 
			
		||||
                fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                &component_id: &ComponentId,
 | 
			
		||||
                table: &'w Table
 | 
			
		||||
            ) {
 | 
			
		||||
                fetch.table_ticks = Some(
 | 
			
		||||
                    table.get_column(component_id)
 | 
			
		||||
                         .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                         .get_ticks_slice()
 | 
			
		||||
                         .into()
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            unsafe fn set_archetype<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, &id: &ComponentId, archetype: &'w Archetype, tables: &'w Tables) {
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn set_archetype<'w>(
 | 
			
		||||
                fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                component_id: &ComponentId,
 | 
			
		||||
                _archetype: &'w Archetype,
 | 
			
		||||
                table: &'w Table
 | 
			
		||||
            ) {
 | 
			
		||||
                if Self::IS_DENSE {
 | 
			
		||||
                    Self::set_table(fetch, component_id, table);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline(always)]
 | 
			
		||||
            unsafe fn fetch<'w>(
 | 
			
		||||
                fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
 | 
			
		||||
                entity: Entity,
 | 
			
		||||
                table_row: usize
 | 
			
		||||
            ) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
                match T::Storage::STORAGE_TYPE {
 | 
			
		||||
                    StorageType::Table => {
 | 
			
		||||
                        fetch.entity_table_rows = Some(archetype.entity_table_rows().into());
 | 
			
		||||
                        let table = &tables[archetype.table_id()];
 | 
			
		||||
                        fetch.table_ticks = Some(table.get_column(id).unwrap().get_ticks_slice().into());
 | 
			
		||||
                    }
 | 
			
		||||
                    StorageType::SparseSet => fetch.entities = Some(archetype.entities().into()),
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            unsafe fn table_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, table_row: usize) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
                $is_detected(&*(fetch.table_ticks.unwrap_or_else(|| debug_checked_unreachable()).get(table_row)).deref(), fetch.last_change_tick, fetch.change_tick)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            unsafe fn archetype_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, archetype_index: usize) -> <Self as WorldQueryGats<'w>>::Item {
 | 
			
		||||
                match T::Storage::STORAGE_TYPE {
 | 
			
		||||
                    StorageType::Table => {
 | 
			
		||||
                        let table_row = *fetch.entity_table_rows.unwrap_or_else(|| debug_checked_unreachable()).get(archetype_index);
 | 
			
		||||
                        $is_detected(&*(fetch.table_ticks.unwrap_or_else(|| debug_checked_unreachable()).get(table_row)).deref(), fetch.last_change_tick, fetch.change_tick)
 | 
			
		||||
                        $is_detected(&*(
 | 
			
		||||
                            fetch.table_ticks
 | 
			
		||||
                                 .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                                 .get(table_row))
 | 
			
		||||
                                 .deref(),
 | 
			
		||||
                            fetch.last_change_tick,
 | 
			
		||||
                            fetch.change_tick
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                    StorageType::SparseSet => {
 | 
			
		||||
                        let entity = *fetch.entities.unwrap_or_else(|| debug_checked_unreachable()).get(archetype_index);
 | 
			
		||||
                        let ticks = fetch
 | 
			
		||||
                        let ticks = &*fetch
 | 
			
		||||
                            .sparse_set
 | 
			
		||||
                            .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                            .get_ticks(entity)
 | 
			
		||||
                            .map(|ticks| &*ticks.get())
 | 
			
		||||
                            .cloned()
 | 
			
		||||
                            .unwrap();
 | 
			
		||||
                        $is_detected(&ticks, fetch.last_change_tick, fetch.change_tick)
 | 
			
		||||
                            .unwrap_or_else(|| debug_checked_unreachable())
 | 
			
		||||
                            .get();
 | 
			
		||||
                        $is_detected(ticks, fetch.last_change_tick, fetch.change_tick)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn table_filter_fetch(fetch: &mut QueryFetch<'_, Self>, table_row: usize) -> bool {
 | 
			
		||||
                Self::table_fetch(fetch, table_row)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
            unsafe fn archetype_filter_fetch(fetch: &mut QueryFetch<'_, Self>, archetype_index: usize) -> bool {
 | 
			
		||||
                Self::archetype_fetch(fetch, archetype_index)
 | 
			
		||||
            #[inline(always)]
 | 
			
		||||
            unsafe fn filter_fetch<'w>(
 | 
			
		||||
                fetch: &mut QueryFetch<'w, Self>,
 | 
			
		||||
                entity: Entity,
 | 
			
		||||
                table_row: usize
 | 
			
		||||
            ) -> bool {
 | 
			
		||||
                Self::fetch(fetch, entity, table_row)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[inline]
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    archetype::{ArchetypeId, Archetypes},
 | 
			
		||||
    archetype::{ArchetypeEntity, ArchetypeId, Archetypes},
 | 
			
		||||
    entity::{Entities, Entity},
 | 
			
		||||
    prelude::World,
 | 
			
		||||
    query::{ArchetypeFilter, QueryState, WorldQuery},
 | 
			
		||||
@ -139,7 +139,8 @@ where
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<QueryItem<'w, Q>> {
 | 
			
		||||
        for entity in self.entity_iter.by_ref() {
 | 
			
		||||
            let location = match self.entities.get(*entity.borrow()) {
 | 
			
		||||
            let entity = *entity.borrow();
 | 
			
		||||
            let location = match self.entities.get(entity) {
 | 
			
		||||
                Some(location) => location,
 | 
			
		||||
                None => continue,
 | 
			
		||||
            };
 | 
			
		||||
@ -153,6 +154,7 @@ where
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let archetype = &self.archetypes[location.archetype_id];
 | 
			
		||||
            let table = &self.tables[archetype.table_id()];
 | 
			
		||||
 | 
			
		||||
            // SAFETY: `archetype` is from the world that `fetch/filter` were created for,
 | 
			
		||||
            // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
 | 
			
		||||
@ -160,7 +162,7 @@ where
 | 
			
		||||
                &mut self.fetch,
 | 
			
		||||
                &self.query_state.fetch_state,
 | 
			
		||||
                archetype,
 | 
			
		||||
                self.tables,
 | 
			
		||||
                table,
 | 
			
		||||
            );
 | 
			
		||||
            // SAFETY: `table` is from the world that `fetch/filter` were created for,
 | 
			
		||||
            // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
 | 
			
		||||
@ -168,13 +170,15 @@ where
 | 
			
		||||
                &mut self.filter,
 | 
			
		||||
                &self.query_state.filter_state,
 | 
			
		||||
                archetype,
 | 
			
		||||
                self.tables,
 | 
			
		||||
                table,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            let table_row = archetype.entity_table_row(location.index);
 | 
			
		||||
            // SAFETY: set_archetype was called prior.
 | 
			
		||||
            // `location.index` is an archetype index row in range of the current archetype, because if it was not, the match above would have `continue`d
 | 
			
		||||
            if F::archetype_filter_fetch(&mut self.filter, location.index) {
 | 
			
		||||
            if F::filter_fetch(&mut self.filter, entity, table_row) {
 | 
			
		||||
                // SAFETY: set_archetype was called prior, `location.index` is an archetype index in range of the current archetype
 | 
			
		||||
                return Some(Q::archetype_fetch(&mut self.fetch, location.index));
 | 
			
		||||
                return Some(Q::fetch(&mut self.fetch, entity, table_row));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        None
 | 
			
		||||
@ -462,6 +466,8 @@ impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery, const K: usize> Fused
 | 
			
		||||
struct QueryIterationCursor<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> {
 | 
			
		||||
    table_id_iter: std::slice::Iter<'s, TableId>,
 | 
			
		||||
    archetype_id_iter: std::slice::Iter<'s, ArchetypeId>,
 | 
			
		||||
    table_entities: &'w [Entity],
 | 
			
		||||
    archetype_entities: &'w [ArchetypeEntity],
 | 
			
		||||
    fetch: QueryFetch<'w, Q>,
 | 
			
		||||
    filter: QueryFetch<'w, F>,
 | 
			
		||||
    // length of the table table or length of the archetype, depending on whether both `Q`'s and `F`'s fetches are dense
 | 
			
		||||
@ -482,6 +488,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
 | 
			
		||||
        Self {
 | 
			
		||||
            table_id_iter: self.table_id_iter.clone(),
 | 
			
		||||
            archetype_id_iter: self.archetype_id_iter.clone(),
 | 
			
		||||
            table_entities: self.table_entities,
 | 
			
		||||
            archetype_entities: self.archetype_entities,
 | 
			
		||||
            // SAFETY: upheld by caller invariants
 | 
			
		||||
            fetch: Q::clone_fetch(&self.fetch),
 | 
			
		||||
            filter: F::clone_fetch(&self.filter),
 | 
			
		||||
@ -529,6 +537,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
 | 
			
		||||
        QueryIterationCursor {
 | 
			
		||||
            fetch,
 | 
			
		||||
            filter,
 | 
			
		||||
            table_entities: &[],
 | 
			
		||||
            archetype_entities: &[],
 | 
			
		||||
            table_id_iter: query_state.matched_table_ids.iter(),
 | 
			
		||||
            archetype_id_iter: query_state.matched_archetype_ids.iter(),
 | 
			
		||||
            current_len: 0,
 | 
			
		||||
@ -541,10 +551,17 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn peek_last(&mut self) -> Option<QueryItem<'w, Q>> {
 | 
			
		||||
        if self.current_index > 0 {
 | 
			
		||||
            let index = self.current_index - 1;
 | 
			
		||||
            if Self::IS_DENSE {
 | 
			
		||||
                Some(Q::table_fetch(&mut self.fetch, self.current_index - 1))
 | 
			
		||||
                let entity = self.table_entities.get_unchecked(index);
 | 
			
		||||
                Some(Q::fetch(&mut self.fetch, *entity, index))
 | 
			
		||||
            } else {
 | 
			
		||||
                Some(Q::archetype_fetch(&mut self.fetch, self.current_index - 1))
 | 
			
		||||
                let archetype_entity = self.archetype_entities.get_unchecked(index);
 | 
			
		||||
                Some(Q::fetch(
 | 
			
		||||
                    &mut self.fetch,
 | 
			
		||||
                    archetype_entity.entity,
 | 
			
		||||
                    archetype_entity.table_row,
 | 
			
		||||
                ))
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            None
 | 
			
		||||
@ -574,6 +591,7 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
 | 
			
		||||
                    // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
 | 
			
		||||
                    Q::set_table(&mut self.fetch, &query_state.fetch_state, table);
 | 
			
		||||
                    F::set_table(&mut self.filter, &query_state.filter_state, table);
 | 
			
		||||
                    self.table_entities = table.entities();
 | 
			
		||||
                    self.current_len = table.entity_count();
 | 
			
		||||
                    self.current_index = 0;
 | 
			
		||||
                    continue;
 | 
			
		||||
@ -581,14 +599,15 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
 | 
			
		||||
 | 
			
		||||
                // SAFETY: set_table was called prior.
 | 
			
		||||
                // `current_index` is a table row in range of the current table, because if it was not, then the if above would have been executed.
 | 
			
		||||
                if !F::table_filter_fetch(&mut self.filter, self.current_index) {
 | 
			
		||||
                let entity = self.table_entities.get_unchecked(self.current_index);
 | 
			
		||||
                if !F::filter_fetch(&mut self.filter, *entity, self.current_index) {
 | 
			
		||||
                    self.current_index += 1;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // SAFETY: set_table was called prior.
 | 
			
		||||
                // `current_index` is a table row in range of the current table, because if it was not, then the if above would have been executed.
 | 
			
		||||
                let item = Q::table_fetch(&mut self.fetch, self.current_index);
 | 
			
		||||
                let item = Q::fetch(&mut self.fetch, *entity, self.current_index);
 | 
			
		||||
 | 
			
		||||
                self.current_index += 1;
 | 
			
		||||
                return Some(item);
 | 
			
		||||
@ -600,13 +619,15 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
 | 
			
		||||
                    let archetype = &archetypes[*archetype_id];
 | 
			
		||||
                    // SAFETY: `archetype` and `tables` are from the world that `fetch/filter` were created for,
 | 
			
		||||
                    // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
 | 
			
		||||
                    Q::set_archetype(&mut self.fetch, &query_state.fetch_state, archetype, tables);
 | 
			
		||||
                    let table = &tables[archetype.table_id()];
 | 
			
		||||
                    Q::set_archetype(&mut self.fetch, &query_state.fetch_state, archetype, table);
 | 
			
		||||
                    F::set_archetype(
 | 
			
		||||
                        &mut self.filter,
 | 
			
		||||
                        &query_state.filter_state,
 | 
			
		||||
                        archetype,
 | 
			
		||||
                        tables,
 | 
			
		||||
                        table,
 | 
			
		||||
                    );
 | 
			
		||||
                    self.archetype_entities = archetype.entities();
 | 
			
		||||
                    self.current_len = archetype.len();
 | 
			
		||||
                    self.current_index = 0;
 | 
			
		||||
                    continue;
 | 
			
		||||
@ -614,14 +635,23 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
 | 
			
		||||
 | 
			
		||||
                // SAFETY: set_archetype was called prior.
 | 
			
		||||
                // `current_index` is an archetype index row in range of the current archetype, because if it was not, then the if above would have been executed.
 | 
			
		||||
                if !F::archetype_filter_fetch(&mut self.filter, self.current_index) {
 | 
			
		||||
                let archetype_entity = self.archetype_entities.get_unchecked(self.current_index);
 | 
			
		||||
                if !F::filter_fetch(
 | 
			
		||||
                    &mut self.filter,
 | 
			
		||||
                    archetype_entity.entity,
 | 
			
		||||
                    archetype_entity.table_row,
 | 
			
		||||
                ) {
 | 
			
		||||
                    self.current_index += 1;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // SAFETY: set_archetype was called prior, `current_index` is an archetype index in range of the current archetype
 | 
			
		||||
                // `current_index` is an archetype index row in range of the current archetype, because if it was not, then the if above would have been executed.
 | 
			
		||||
                let item = Q::archetype_fetch(&mut self.fetch, self.current_index);
 | 
			
		||||
                let item = Q::fetch(
 | 
			
		||||
                    &mut self.fetch,
 | 
			
		||||
                    archetype_entity.entity,
 | 
			
		||||
                    archetype_entity.table_row,
 | 
			
		||||
                );
 | 
			
		||||
                self.current_index += 1;
 | 
			
		||||
                return Some(item);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -413,20 +413,12 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
 | 
			
		||||
        let mut fetch = Q::init_fetch(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
        let mut filter = F::init_fetch(world, &self.filter_state, last_change_tick, change_tick);
 | 
			
		||||
 | 
			
		||||
        Q::set_archetype(
 | 
			
		||||
            &mut fetch,
 | 
			
		||||
            &self.fetch_state,
 | 
			
		||||
            archetype,
 | 
			
		||||
            &world.storages().tables,
 | 
			
		||||
        );
 | 
			
		||||
        F::set_archetype(
 | 
			
		||||
            &mut filter,
 | 
			
		||||
            &self.filter_state,
 | 
			
		||||
            archetype,
 | 
			
		||||
            &world.storages().tables,
 | 
			
		||||
        );
 | 
			
		||||
        if F::archetype_filter_fetch(&mut filter, location.index) {
 | 
			
		||||
            Ok(Q::archetype_fetch(&mut fetch, location.index))
 | 
			
		||||
        let table = &world.storages().tables[archetype.table_id()];
 | 
			
		||||
        Q::set_archetype(&mut fetch, &self.fetch_state, archetype, table);
 | 
			
		||||
        F::set_archetype(&mut filter, &self.filter_state, archetype, table);
 | 
			
		||||
 | 
			
		||||
        if F::filter_fetch(&mut filter, entity, location.index) {
 | 
			
		||||
            Ok(Q::fetch(&mut fetch, entity, location.index))
 | 
			
		||||
        } else {
 | 
			
		||||
            Err(QueryEntityError::QueryDoesNotMatch(entity))
 | 
			
		||||
        }
 | 
			
		||||
@ -945,34 +937,45 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
 | 
			
		||||
        let mut fetch = Q::init_fetch(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
        let mut filter = F::init_fetch(world, &self.filter_state, last_change_tick, change_tick);
 | 
			
		||||
 | 
			
		||||
        if Q::IS_DENSE && F::IS_DENSE {
 | 
			
		||||
        let tables = &world.storages().tables;
 | 
			
		||||
        if Q::IS_DENSE && F::IS_DENSE {
 | 
			
		||||
            for table_id in &self.matched_table_ids {
 | 
			
		||||
                let table = &tables[*table_id];
 | 
			
		||||
                Q::set_table(&mut fetch, &self.fetch_state, table);
 | 
			
		||||
                F::set_table(&mut filter, &self.filter_state, table);
 | 
			
		||||
 | 
			
		||||
                for table_index in 0..table.entity_count() {
 | 
			
		||||
                    if !F::table_filter_fetch(&mut filter, table_index) {
 | 
			
		||||
                let entities = table.entities();
 | 
			
		||||
                for row in 0..table.entity_count() {
 | 
			
		||||
                    let entity = entities.get_unchecked(row);
 | 
			
		||||
                    if !F::filter_fetch(&mut filter, *entity, row) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    let item = Q::table_fetch(&mut fetch, table_index);
 | 
			
		||||
                    func(item);
 | 
			
		||||
                    func(Q::fetch(&mut fetch, *entity, row));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            let archetypes = &world.archetypes;
 | 
			
		||||
            let tables = &world.storages().tables;
 | 
			
		||||
            for archetype_id in &self.matched_archetype_ids {
 | 
			
		||||
                let archetype = &archetypes[*archetype_id];
 | 
			
		||||
                Q::set_archetype(&mut fetch, &self.fetch_state, archetype, tables);
 | 
			
		||||
                F::set_archetype(&mut filter, &self.filter_state, archetype, tables);
 | 
			
		||||
                let table = &tables[archetype.table_id()];
 | 
			
		||||
                Q::set_archetype(&mut fetch, &self.fetch_state, archetype, table);
 | 
			
		||||
                F::set_archetype(&mut filter, &self.filter_state, archetype, table);
 | 
			
		||||
 | 
			
		||||
                for archetype_index in 0..archetype.len() {
 | 
			
		||||
                    if !F::archetype_filter_fetch(&mut filter, archetype_index) {
 | 
			
		||||
                let entities = archetype.entities();
 | 
			
		||||
                for idx in 0..archetype.len() {
 | 
			
		||||
                    let archetype_entity = entities.get_unchecked(idx);
 | 
			
		||||
                    if !F::filter_fetch(
 | 
			
		||||
                        &mut filter,
 | 
			
		||||
                        archetype_entity.entity,
 | 
			
		||||
                        archetype_entity.table_row,
 | 
			
		||||
                    ) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    func(Q::archetype_fetch(&mut fetch, archetype_index));
 | 
			
		||||
                    func(Q::fetch(
 | 
			
		||||
                        &mut fetch,
 | 
			
		||||
                        archetype_entity.entity,
 | 
			
		||||
                        archetype_entity.table_row,
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -1033,14 +1036,15 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
 | 
			
		||||
                            );
 | 
			
		||||
                            let tables = &world.storages().tables;
 | 
			
		||||
                            let table = &tables[*table_id];
 | 
			
		||||
                            let entities = table.entities();
 | 
			
		||||
                            Q::set_table(&mut fetch, &self.fetch_state, table);
 | 
			
		||||
                            F::set_table(&mut filter, &self.filter_state, table);
 | 
			
		||||
                            for table_index in offset..offset + len {
 | 
			
		||||
                                if !F::table_filter_fetch(&mut filter, table_index) {
 | 
			
		||||
                            for row in offset..offset + len {
 | 
			
		||||
                                let entity = entities.get_unchecked(row);
 | 
			
		||||
                                if !F::filter_fetch(&mut filter, *entity, row) {
 | 
			
		||||
                                    continue;
 | 
			
		||||
                                }
 | 
			
		||||
                                let item = Q::table_fetch(&mut fetch, table_index);
 | 
			
		||||
                                func(item);
 | 
			
		||||
                                func(Q::fetch(&mut fetch, *entity, row));
 | 
			
		||||
                            }
 | 
			
		||||
                        };
 | 
			
		||||
                        #[cfg(feature = "trace")]
 | 
			
		||||
@ -1083,14 +1087,25 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
 | 
			
		||||
                            );
 | 
			
		||||
                            let tables = &world.storages().tables;
 | 
			
		||||
                            let archetype = &world.archetypes[*archetype_id];
 | 
			
		||||
                            Q::set_archetype(&mut fetch, &self.fetch_state, archetype, tables);
 | 
			
		||||
                            F::set_archetype(&mut filter, &self.filter_state, archetype, tables);
 | 
			
		||||
                            let table = &tables[archetype.table_id()];
 | 
			
		||||
                            Q::set_archetype(&mut fetch, &self.fetch_state, archetype, table);
 | 
			
		||||
                            F::set_archetype(&mut filter, &self.filter_state, archetype, table);
 | 
			
		||||
 | 
			
		||||
                            let entities = archetype.entities();
 | 
			
		||||
                            for archetype_index in offset..offset + len {
 | 
			
		||||
                                if !F::archetype_filter_fetch(&mut filter, archetype_index) {
 | 
			
		||||
                                let archetype_entity = entities.get_unchecked(archetype_index);
 | 
			
		||||
                                if !F::filter_fetch(
 | 
			
		||||
                                    &mut filter,
 | 
			
		||||
                                    archetype_entity.entity,
 | 
			
		||||
                                    archetype_entity.table_row,
 | 
			
		||||
                                ) {
 | 
			
		||||
                                    continue;
 | 
			
		||||
                                }
 | 
			
		||||
                                func(Q::archetype_fetch(&mut fetch, archetype_index));
 | 
			
		||||
                                func(Q::fetch(
 | 
			
		||||
                                    &mut fetch,
 | 
			
		||||
                                    archetype_entity.entity,
 | 
			
		||||
                                    archetype_entity.table_row,
 | 
			
		||||
                                ));
 | 
			
		||||
                            }
 | 
			
		||||
                        };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -327,7 +327,8 @@ impl World {
 | 
			
		||||
    pub fn iter_entities(&self) -> impl Iterator<Item = Entity> + '_ {
 | 
			
		||||
        self.archetypes
 | 
			
		||||
            .iter()
 | 
			
		||||
            .flat_map(|archetype| archetype.entities().iter().copied())
 | 
			
		||||
            .flat_map(|archetype| archetype.entities().iter())
 | 
			
		||||
            .map(|archetype_entity| archetype_entity.entity)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Retrieves an [`EntityMut`] that exposes read and write operations for the given `entity`.
 | 
			
		||||
 | 
			
		||||
@ -65,7 +65,7 @@ impl Scene {
 | 
			
		||||
            for scene_entity in archetype.entities() {
 | 
			
		||||
                let entity = *instance_info
 | 
			
		||||
                    .entity_map
 | 
			
		||||
                    .entry(*scene_entity)
 | 
			
		||||
                    .entry(scene_entity.entity())
 | 
			
		||||
                    .or_insert_with(|| world.spawn_empty().id());
 | 
			
		||||
                for component_id in archetype.components() {
 | 
			
		||||
                    let component_info = self
 | 
			
		||||
@ -86,7 +86,7 @@ impl Scene {
 | 
			
		||||
                                }
 | 
			
		||||
                            })
 | 
			
		||||
                        })?;
 | 
			
		||||
                    reflect_component.copy(&self.world, world, *scene_entity, entity);
 | 
			
		||||
                    reflect_component.copy(&self.world, world, scene_entity.entity(), entity);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user