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,
|
_fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
|
||||||
_state: &Self::State,
|
_state: &Self::State,
|
||||||
_archetype: &'__w #path::archetype::Archetype,
|
_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`
|
/// 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);)*
|
#(<#field_types>::set_table(&mut _fetch.#field_idents, &_state.#field_idents, _table);)*
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SAFETY: we call `table_fetch` for each member that implements `Fetch`.
|
/// SAFETY: we call `fetch` for each member that implements `Fetch`.
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
unsafe fn table_fetch<'__w>(
|
unsafe fn fetch<'__w>(
|
||||||
_fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
|
_fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
|
||||||
|
_entity: Entity,
|
||||||
_table_row: usize
|
_table_row: usize
|
||||||
) -> <Self as #path::query::WorldQueryGats<'__w>>::Item {
|
) -> <Self as #path::query::WorldQueryGats<'__w>>::Item {
|
||||||
Self::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(),)*
|
#(#ignored_field_idents: Default::default(),)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SAFETY: we call `archetype_fetch` for each member that implements `Fetch`.
|
#[allow(unused_variables)]
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
unsafe fn archetype_fetch<'__w>(
|
unsafe fn filter_fetch<'__w>(
|
||||||
_fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
|
_fetch: &mut <Self as #path::query::WorldQueryGats<'__w>>::Fetch,
|
||||||
_archetype_index: usize
|
_entity: Entity,
|
||||||
) -> <Self as #path::query::WorldQueryGats<'__w>>::Item {
|
_table_row: usize
|
||||||
Self::Item {
|
) -> bool {
|
||||||
#(#field_idents: <#field_types>::archetype_fetch(&mut _fetch.#field_idents, _archetype_index),)*
|
true #(&& <#field_types>::filter_fetch(&mut _fetch.#field_idents, _entity, _table_row))*
|
||||||
#(#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))*
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_component_access(state: &Self::State, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
|
fn update_component_access(state: &Self::State, _access: &mut #path::query::FilteredAccess<#path::component::ComponentId>) {
|
||||||
|
|||||||
@ -121,9 +121,19 @@ impl Edges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TableInfo {
|
pub struct ArchetypeEntity {
|
||||||
id: TableId,
|
pub(crate) entity: Entity,
|
||||||
entity_rows: Vec<usize>,
|
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 {
|
pub(crate) struct ArchetypeSwapRemoveResult {
|
||||||
@ -138,9 +148,9 @@ pub(crate) struct ArchetypeComponentInfo {
|
|||||||
|
|
||||||
pub struct Archetype {
|
pub struct Archetype {
|
||||||
id: ArchetypeId,
|
id: ArchetypeId,
|
||||||
entities: Vec<Entity>,
|
table_id: TableId,
|
||||||
edges: Edges,
|
edges: Edges,
|
||||||
table_info: TableInfo,
|
entities: Vec<ArchetypeEntity>,
|
||||||
table_components: Box<[ComponentId]>,
|
table_components: Box<[ComponentId]>,
|
||||||
sparse_set_components: Box<[ComponentId]>,
|
sparse_set_components: Box<[ComponentId]>,
|
||||||
components: SparseSet<ComponentId, ArchetypeComponentInfo>,
|
components: SparseSet<ComponentId, ArchetypeComponentInfo>,
|
||||||
@ -183,14 +193,11 @@ impl Archetype {
|
|||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
table_info: TableInfo {
|
table_id,
|
||||||
id: table_id,
|
entities: Vec::new(),
|
||||||
entity_rows: Default::default(),
|
|
||||||
},
|
|
||||||
components,
|
components,
|
||||||
table_components,
|
table_components,
|
||||||
sparse_set_components,
|
sparse_set_components,
|
||||||
entities: Default::default(),
|
|
||||||
edges: Default::default(),
|
edges: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,19 +209,14 @@ impl Archetype {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn table_id(&self) -> TableId {
|
pub fn table_id(&self) -> TableId {
|
||||||
self.table_info.id
|
self.table_id
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn entities(&self) -> &[Entity] {
|
pub fn entities(&self) -> &[ArchetypeEntity] {
|
||||||
&self.entities
|
&self.entities
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn entity_table_rows(&self) -> &[usize] {
|
|
||||||
&self.table_info.entity_rows
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn table_components(&self) -> &[ComponentId] {
|
pub fn table_components(&self) -> &[ComponentId] {
|
||||||
&self.table_components
|
&self.table_components
|
||||||
@ -242,20 +244,19 @@ impl Archetype {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn entity_table_row(&self, index: usize) -> usize {
|
pub fn entity_table_row(&self, index: usize) -> usize {
|
||||||
self.table_info.entity_rows[index]
|
self.entities[index].table_row
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn set_entity_table_row(&mut self, index: usize, table_row: usize) {
|
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
|
/// # Safety
|
||||||
/// valid component values must be immediately written to the relevant storages
|
/// valid component values must be immediately written to the relevant storages
|
||||||
/// `table_row` must be valid
|
/// `table_row` must be valid
|
||||||
pub(crate) unsafe fn allocate(&mut self, entity: Entity, table_row: usize) -> EntityLocation {
|
pub(crate) unsafe fn allocate(&mut self, entity: Entity, table_row: usize) -> EntityLocation {
|
||||||
self.entities.push(entity);
|
self.entities.push(ArchetypeEntity { entity, table_row });
|
||||||
self.table_info.entity_rows.push(table_row);
|
|
||||||
|
|
||||||
EntityLocation {
|
EntityLocation {
|
||||||
archetype_id: self.id,
|
archetype_id: self.id,
|
||||||
@ -265,21 +266,20 @@ impl Archetype {
|
|||||||
|
|
||||||
pub(crate) fn reserve(&mut self, additional: usize) {
|
pub(crate) fn reserve(&mut self, additional: usize) {
|
||||||
self.entities.reserve(additional);
|
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
|
/// Removes the entity at `index` by swapping it out. Returns the table row the entity is stored
|
||||||
/// in.
|
/// in.
|
||||||
pub(crate) fn swap_remove(&mut self, index: usize) -> ArchetypeSwapRemoveResult {
|
pub(crate) fn swap_remove(&mut self, index: usize) -> ArchetypeSwapRemoveResult {
|
||||||
let is_last = index == self.entities.len() - 1;
|
let is_last = index == self.entities.len() - 1;
|
||||||
self.entities.swap_remove(index);
|
let entity = self.entities.swap_remove(index);
|
||||||
ArchetypeSwapRemoveResult {
|
ArchetypeSwapRemoveResult {
|
||||||
swapped_entity: if is_last {
|
swapped_entity: if is_last {
|
||||||
None
|
None
|
||||||
} else {
|
} 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) {
|
pub(crate) fn clear_entities(&mut self) {
|
||||||
self.entities.clear();
|
self.entities.clear();
|
||||||
self.table_info.entity_rows.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -540,8 +540,8 @@ mod tests {
|
|||||||
let f = world
|
let f = world
|
||||||
.spawn((TableStored("def"), A(456), SparseStored(1)))
|
.spawn((TableStored("def"), A(456), SparseStored(1)))
|
||||||
.id();
|
.id();
|
||||||
// // this should be skipped
|
// this should be skipped
|
||||||
// SparseStored(1).spawn("abc");
|
// world.spawn(SparseStored(1));
|
||||||
let ents = world
|
let ents = world
|
||||||
.query::<(Entity, Option<&SparseStored>, &A)>()
|
.query::<(Entity, Option<&SparseStored>, &A)>()
|
||||||
.iter(&world)
|
.iter(&world)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use crate::{
|
|||||||
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
query::{debug_checked_unreachable, Access, FilteredAccess},
|
query::{debug_checked_unreachable, Access, FilteredAccess},
|
||||||
storage::{ComponentSparseSet, Table, Tables},
|
storage::{ComponentSparseSet, Table},
|
||||||
world::{Mut, World},
|
world::{Mut, World},
|
||||||
};
|
};
|
||||||
use bevy_ecs_macros::all_tuples;
|
use bevy_ecs_macros::all_tuples;
|
||||||
@ -285,11 +285,10 @@ use std::{cell::UnsafeCell, marker::PhantomData};
|
|||||||
/// exactly reflects the results of the following methods:
|
/// exactly reflects the results of the following methods:
|
||||||
///
|
///
|
||||||
/// - [`matches_component_set`]
|
/// - [`matches_component_set`]
|
||||||
/// - [`archetype_fetch`]
|
/// - [`fetch`]
|
||||||
/// - [`table_fetch`]
|
|
||||||
///
|
///
|
||||||
/// [`Added`]: crate::query::Added
|
/// [`Added`]: crate::query::Added
|
||||||
/// [`archetype_fetch`]: Self::archetype_fetch
|
/// [`fetch`]: Self::fetch
|
||||||
/// [`Changed`]: crate::query::Changed
|
/// [`Changed`]: crate::query::Changed
|
||||||
/// [`Fetch`]: crate::query::WorldQueryGats::Fetch
|
/// [`Fetch`]: crate::query::WorldQueryGats::Fetch
|
||||||
/// [`matches_component_set`]: Self::matches_component_set
|
/// [`matches_component_set`]: Self::matches_component_set
|
||||||
@ -297,7 +296,6 @@ use std::{cell::UnsafeCell, marker::PhantomData};
|
|||||||
/// [`Query`]: crate::system::Query
|
/// [`Query`]: crate::system::Query
|
||||||
/// [`ReadOnly`]: Self::ReadOnly
|
/// [`ReadOnly`]: Self::ReadOnly
|
||||||
/// [`State`]: Self::State
|
/// [`State`]: Self::State
|
||||||
/// [`table_fetch`]: Self::table_fetch
|
|
||||||
/// [`update_archetype_component_access`]: Self::update_archetype_component_access
|
/// [`update_archetype_component_access`]: Self::update_archetype_component_access
|
||||||
/// [`update_component_access`]: Self::update_component_access
|
/// [`update_component_access`]: Self::update_component_access
|
||||||
/// [`With`]: crate::query::With
|
/// [`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
|
/// 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"
|
/// 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`]
|
/// for "dense" queries. If this returns true, [`WorldQuery::set_table`] must be used before
|
||||||
/// will be called for iterators. If this returns false, [`WorldQuery::set_archetype`] and
|
/// [`WorldQuery::fetch`] can be called for iterators. If this returns false,
|
||||||
/// [`WorldQuery::archetype_fetch`] will be called for iterators.
|
/// [`WorldQuery::set_archetype`] must be used before [`WorldQuery::fetch`] can be called for
|
||||||
|
/// iterators.
|
||||||
const IS_DENSE: bool;
|
const IS_DENSE: bool;
|
||||||
|
|
||||||
/// Returns true if (and only if) this Fetch relies strictly on archetypes to limit which
|
/// 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,
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
state: &Self::State,
|
state: &Self::State,
|
||||||
archetype: &'w Archetype,
|
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
|
/// 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,
|
table: &'w Table,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Fetch [`Self::Item`](`WorldQueryGats::Item`) for the given `archetype_index` in the current [`Archetype`]. This must
|
/// Fetch [`Self::Item`](`WorldQueryGats::Item`) for either the given `entity` in the current [`Table`],
|
||||||
/// always be called after [`WorldQuery::set_archetype`] with an `archetype_index` in the range of
|
/// or for the given `entity` in the current [`Archetype`]. This must always be called after
|
||||||
/// the current [`Archetype`]
|
/// [`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_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`]
|
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Must always be called _after_ [`WorldQuery::set_table`]. `table_row` must be in the range of the
|
/// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and
|
||||||
/// current table
|
/// `table_row` must be in the range of the current table and archetype.
|
||||||
unsafe fn table_fetch<'w>(
|
unsafe fn fetch<'w>(
|
||||||
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
entity: Entity,
|
||||||
table_row: usize,
|
table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item;
|
) -> <Self as WorldQueryGats<'w>>::Item;
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Must always be called _after_ [`WorldQuery::set_archetype`]. `archetype_index` must be in the range
|
/// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and
|
||||||
/// of the current archetype.
|
/// `table_row` must be in the range of the current table and archetype.
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
unsafe fn archetype_filter_fetch(
|
unsafe fn 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(
|
|
||||||
fetch: &mut <Self as WorldQueryGats<'_>>::Fetch,
|
fetch: &mut <Self as WorldQueryGats<'_>>::Fetch,
|
||||||
|
entity: Entity,
|
||||||
table_row: usize,
|
table_row: usize,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
true
|
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
|
/// 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>;
|
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
|
/// SAFETY: no component or archetype access
|
||||||
unsafe impl WorldQuery for Entity {
|
unsafe impl WorldQuery for Entity {
|
||||||
type ReadOnly = Self;
|
type ReadOnly = Self;
|
||||||
@ -490,56 +463,41 @@ unsafe impl WorldQuery for Entity {
|
|||||||
|
|
||||||
unsafe fn init_fetch<'w>(
|
unsafe fn init_fetch<'w>(
|
||||||
_world: &'w World,
|
_world: &'w World,
|
||||||
_state: &(),
|
_state: &Self::State,
|
||||||
_last_change_tick: u32,
|
_last_change_tick: u32,
|
||||||
_change_tick: u32,
|
_change_tick: u32,
|
||||||
) -> EntityFetch<'w> {
|
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
||||||
EntityFetch { entities: None }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn clone_fetch<'w>(
|
unsafe fn clone_fetch<'w>(
|
||||||
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
|
_fetch: &<Self as WorldQueryGats<'w>>::Fetch,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
||||||
EntityFetch {
|
|
||||||
entities: fetch.entities,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_archetype<'w>(
|
unsafe fn set_archetype<'w>(
|
||||||
fetch: &mut EntityFetch<'w>,
|
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
_state: &(),
|
_state: &Self::State,
|
||||||
archetype: &'w Archetype,
|
_archetype: &'w Archetype,
|
||||||
_tables: &Tables,
|
_table: &Table,
|
||||||
) {
|
) {
|
||||||
fetch.entities = Some(archetype.entities().into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_table<'w>(fetch: &mut EntityFetch<'w>, _state: &(), table: &'w Table) {
|
unsafe fn set_table<'w>(
|
||||||
fetch.entities = Some(table.entities().into());
|
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
_state: &Self::State,
|
||||||
|
_table: &'w Table,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
unsafe fn table_fetch<'w>(
|
unsafe fn fetch<'w>(
|
||||||
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
table_row: usize,
|
entity: Entity,
|
||||||
) -> QueryItem<'w, Self> {
|
_table_row: usize,
|
||||||
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,
|
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
let entities = fetch
|
entity
|
||||||
.entities
|
|
||||||
.unwrap_or_else(|| debug_checked_unreachable());
|
|
||||||
*entities.get(archetype_index)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {}
|
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 {
|
impl<'w> WorldQueryGats<'w> for Entity {
|
||||||
type Fetch = EntityFetch<'w>;
|
type Fetch = ();
|
||||||
type Item = Entity;
|
type Item = Entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -573,9 +531,7 @@ unsafe impl ReadOnlyWorldQuery for Entity {}
|
|||||||
pub struct ReadFetch<'w, T> {
|
pub struct ReadFetch<'w, T> {
|
||||||
// T::Storage = TableStorage
|
// T::Storage = TableStorage
|
||||||
table_components: Option<ThinSlicePtr<'w, UnsafeCell<T>>>,
|
table_components: Option<ThinSlicePtr<'w, UnsafeCell<T>>>,
|
||||||
entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
|
|
||||||
// T::Storage = SparseStorage
|
// T::Storage = SparseStorage
|
||||||
entities: Option<ThinSlicePtr<'w, Entity>>,
|
|
||||||
sparse_set: Option<&'w ComponentSparseSet>,
|
sparse_set: Option<&'w ComponentSparseSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,10 +561,13 @@ unsafe impl<T: Component> WorldQuery for &T {
|
|||||||
) -> ReadFetch<'w, T> {
|
) -> ReadFetch<'w, T> {
|
||||||
ReadFetch {
|
ReadFetch {
|
||||||
table_components: None,
|
table_components: None,
|
||||||
entity_table_rows: None,
|
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
|
||||||
entities: None,
|
world
|
||||||
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
|
.storages()
|
||||||
.then(|| world.storages().sparse_sets.get(component_id).unwrap()),
|
.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 {
|
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
||||||
ReadFetch {
|
ReadFetch {
|
||||||
table_components: fetch.table_components,
|
table_components: fetch.table_components,
|
||||||
entity_table_rows: fetch.entity_table_rows,
|
|
||||||
entities: fetch.entities,
|
|
||||||
sparse_set: fetch.sparse_set,
|
sparse_set: fetch.sparse_set,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -626,64 +583,49 @@ unsafe impl<T: Component> WorldQuery for &T {
|
|||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_archetype<'w>(
|
unsafe fn set_archetype<'w>(
|
||||||
fetch: &mut ReadFetch<'w, T>,
|
fetch: &mut ReadFetch<'w, T>,
|
||||||
&component_id: &ComponentId,
|
component_id: &ComponentId,
|
||||||
archetype: &'w Archetype,
|
_archetype: &'w Archetype,
|
||||||
tables: &'w Tables,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
match T::Storage::STORAGE_TYPE {
|
if Self::IS_DENSE {
|
||||||
StorageType::Table => {
|
Self::set_table(fetch, component_id, 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());
|
|
||||||
}
|
|
||||||
StorageType::SparseSet => fetch.entities = Some(archetype.entities().into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_table<'w>(fetch: &mut ReadFetch<'w, T>, &id: &ComponentId, table: &'w Table) {
|
unsafe fn set_table<'w>(
|
||||||
fetch.table_components = Some(table.get_column(id).unwrap().get_data_slice().into());
|
fetch: &mut ReadFetch<'w, T>,
|
||||||
|
&component_id: &ComponentId,
|
||||||
|
table: &'w Table,
|
||||||
|
) {
|
||||||
|
fetch.table_components = Some(
|
||||||
|
table
|
||||||
|
.get_column(component_id)
|
||||||
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
|
.get_data_slice()
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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 {
|
|
||||||
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>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn table_fetch<'w>(
|
|
||||||
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
entity: Entity,
|
||||||
table_row: usize,
|
table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
let components = fetch
|
match T::Storage::STORAGE_TYPE {
|
||||||
.table_components
|
StorageType::Table => fetch
|
||||||
.unwrap_or_else(|| debug_checked_unreachable());
|
.table_components
|
||||||
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(
|
fn update_component_access(
|
||||||
@ -731,11 +673,11 @@ impl<'w, T: Component> WorldQueryGats<'w> for &T {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct WriteFetch<'w, T> {
|
pub struct WriteFetch<'w, T> {
|
||||||
// T::Storage = TableStorage
|
// T::Storage = TableStorage
|
||||||
table_components: Option<ThinSlicePtr<'w, UnsafeCell<T>>>,
|
table_data: Option<(
|
||||||
table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
|
ThinSlicePtr<'w, UnsafeCell<T>>,
|
||||||
entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
|
ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>,
|
||||||
|
)>,
|
||||||
// T::Storage = SparseStorage
|
// T::Storage = SparseStorage
|
||||||
entities: Option<ThinSlicePtr<'w, Entity>>,
|
|
||||||
sparse_set: Option<&'w ComponentSparseSet>,
|
sparse_set: Option<&'w ComponentSparseSet>,
|
||||||
|
|
||||||
last_change_tick: u32,
|
last_change_tick: u32,
|
||||||
@ -767,12 +709,14 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
|
|||||||
change_tick: u32,
|
change_tick: u32,
|
||||||
) -> WriteFetch<'w, T> {
|
) -> WriteFetch<'w, T> {
|
||||||
WriteFetch {
|
WriteFetch {
|
||||||
table_components: None,
|
table_data: None,
|
||||||
entities: None,
|
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
|
||||||
entity_table_rows: None,
|
world
|
||||||
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
|
.storages()
|
||||||
.then(|| world.storages().sparse_sets.get(component_id).unwrap()),
|
.sparse_sets
|
||||||
table_ticks: None,
|
.get(component_id)
|
||||||
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
|
}),
|
||||||
last_change_tick,
|
last_change_tick,
|
||||||
change_tick,
|
change_tick,
|
||||||
}
|
}
|
||||||
@ -782,10 +726,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
|
|||||||
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
|
fetch: &<Self as WorldQueryGats<'w>>::Fetch,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
||||||
WriteFetch {
|
WriteFetch {
|
||||||
table_components: fetch.table_components,
|
table_data: fetch.table_data,
|
||||||
table_ticks: fetch.table_ticks,
|
|
||||||
entities: fetch.entities,
|
|
||||||
entity_table_rows: fetch.entity_table_rows,
|
|
||||||
sparse_set: fetch.sparse_set,
|
sparse_set: fetch.sparse_set,
|
||||||
last_change_tick: fetch.last_change_tick,
|
last_change_tick: fetch.last_change_tick,
|
||||||
change_tick: fetch.change_tick,
|
change_tick: fetch.change_tick,
|
||||||
@ -795,20 +736,12 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
|
|||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_archetype<'w>(
|
unsafe fn set_archetype<'w>(
|
||||||
fetch: &mut WriteFetch<'w, T>,
|
fetch: &mut WriteFetch<'w, T>,
|
||||||
&component_id: &ComponentId,
|
component_id: &ComponentId,
|
||||||
archetype: &'w Archetype,
|
_archetype: &'w Archetype,
|
||||||
tables: &'w Tables,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
match T::Storage::STORAGE_TYPE {
|
if Self::IS_DENSE {
|
||||||
StorageType::Table => {
|
Self::set_table(fetch, component_id, 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()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,23 +751,26 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
|
|||||||
&component_id: &ComponentId,
|
&component_id: &ComponentId,
|
||||||
table: &'w Table,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
let column = table.get_column(component_id).unwrap();
|
let column = table
|
||||||
fetch.table_components = Some(column.get_data_slice().into());
|
.get_column(component_id)
|
||||||
fetch.table_ticks = Some(column.get_ticks_slice().into());
|
.unwrap_or_else(|| debug_checked_unreachable());
|
||||||
|
fetch.table_data = Some((
|
||||||
|
column.get_data_slice().into(),
|
||||||
|
column.get_ticks_slice().into(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
unsafe fn archetype_fetch<'w>(
|
unsafe fn fetch<'w>(
|
||||||
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
archetype_index: usize,
|
entity: Entity,
|
||||||
|
table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
match T::Storage::STORAGE_TYPE {
|
match T::Storage::STORAGE_TYPE {
|
||||||
StorageType::Table => {
|
StorageType::Table => {
|
||||||
let (entity_table_rows, (table_components, table_ticks)) = fetch
|
let (table_components, table_ticks) = fetch
|
||||||
.entity_table_rows
|
.table_data
|
||||||
.zip(fetch.table_components.zip(fetch.table_ticks))
|
|
||||||
.unwrap_or_else(|| debug_checked_unreachable());
|
.unwrap_or_else(|| debug_checked_unreachable());
|
||||||
let table_row = *entity_table_rows.get(archetype_index);
|
|
||||||
Mut {
|
Mut {
|
||||||
value: table_components.get(table_row).deref_mut(),
|
value: table_components.get(table_row).deref_mut(),
|
||||||
ticks: Ticks {
|
ticks: Ticks {
|
||||||
@ -845,12 +781,9 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
StorageType::SparseSet => {
|
StorageType::SparseSet => {
|
||||||
let (entities, sparse_set) = fetch
|
let (component, component_ticks) = fetch
|
||||||
.entities
|
.sparse_set
|
||||||
.zip(fetch.sparse_set)
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
.unwrap_or_else(|| debug_checked_unreachable());
|
|
||||||
let entity = *entities.get(archetype_index);
|
|
||||||
let (component, component_ticks) = sparse_set
|
|
||||||
.get_with_ticks(entity)
|
.get_with_ticks(entity)
|
||||||
.unwrap_or_else(|| debug_checked_unreachable());
|
.unwrap_or_else(|| debug_checked_unreachable());
|
||||||
Mut {
|
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(
|
fn update_component_access(
|
||||||
&component_id: &ComponentId,
|
&component_id: &ComponentId,
|
||||||
access: &mut FilteredAccess<ComponentId>,
|
access: &mut FilteredAccess<ComponentId>,
|
||||||
@ -968,11 +882,11 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
|
|||||||
fetch: &mut OptionFetch<'w, T>,
|
fetch: &mut OptionFetch<'w, T>,
|
||||||
state: &T::State,
|
state: &T::State,
|
||||||
archetype: &'w Archetype,
|
archetype: &'w Archetype,
|
||||||
tables: &'w Tables,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
fetch.matches = T::matches_component_set(state, &|id| archetype.contains(id));
|
fetch.matches = T::matches_component_set(state, &|id| archetype.contains(id));
|
||||||
if fetch.matches {
|
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]
|
#[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 {
|
|
||||||
if fetch.matches {
|
|
||||||
Some(T::archetype_fetch(&mut fetch.fetch, archetype_index))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn table_fetch<'w>(
|
|
||||||
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
entity: Entity,
|
||||||
table_row: usize,
|
table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
if fetch.matches {
|
fetch
|
||||||
Some(T::table_fetch(&mut fetch.fetch, table_row))
|
.matches
|
||||||
} else {
|
.then(|| T::fetch(&mut fetch.fetch, entity, table_row))
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_component_access(state: &T::State, access: &mut FilteredAccess<ComponentId>) {
|
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> {
|
pub struct ChangeTrackersFetch<'w, T> {
|
||||||
// T::Storage = TableStorage
|
// T::Storage = TableStorage
|
||||||
table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
|
table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
|
||||||
entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
|
|
||||||
// T::Storage = SparseStorage
|
// T::Storage = SparseStorage
|
||||||
entities: Option<ThinSlicePtr<'w, Entity>>,
|
|
||||||
sparse_set: Option<&'w ComponentSparseSet>,
|
sparse_set: Option<&'w ComponentSparseSet>,
|
||||||
|
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
@ -1157,16 +1056,19 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
|
|||||||
|
|
||||||
unsafe fn init_fetch<'w>(
|
unsafe fn init_fetch<'w>(
|
||||||
world: &'w World,
|
world: &'w World,
|
||||||
&id: &ComponentId,
|
&component_id: &ComponentId,
|
||||||
last_change_tick: u32,
|
last_change_tick: u32,
|
||||||
change_tick: u32,
|
change_tick: u32,
|
||||||
) -> ChangeTrackersFetch<'w, T> {
|
) -> ChangeTrackersFetch<'w, T> {
|
||||||
ChangeTrackersFetch {
|
ChangeTrackersFetch {
|
||||||
table_ticks: None,
|
table_ticks: None,
|
||||||
entities: None,
|
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
|
||||||
entity_table_rows: None,
|
world
|
||||||
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
|
.storages()
|
||||||
.then(|| world.storages().sparse_sets.get(id).unwrap()),
|
.sparse_sets
|
||||||
|
.get(component_id)
|
||||||
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
|
}),
|
||||||
marker: PhantomData,
|
marker: PhantomData,
|
||||||
last_change_tick,
|
last_change_tick,
|
||||||
change_tick,
|
change_tick,
|
||||||
@ -1178,8 +1080,6 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
|
|||||||
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
||||||
ChangeTrackersFetch {
|
ChangeTrackersFetch {
|
||||||
table_ticks: fetch.table_ticks,
|
table_ticks: fetch.table_ticks,
|
||||||
entity_table_rows: fetch.entity_table_rows,
|
|
||||||
entities: fetch.entities,
|
|
||||||
sparse_set: fetch.sparse_set,
|
sparse_set: fetch.sparse_set,
|
||||||
marker: fetch.marker,
|
marker: fetch.marker,
|
||||||
last_change_tick: fetch.last_change_tick,
|
last_change_tick: fetch.last_change_tick,
|
||||||
@ -1190,17 +1090,12 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn set_archetype<'w>(
|
unsafe fn set_archetype<'w>(
|
||||||
fetch: &mut ChangeTrackersFetch<'w, T>,
|
fetch: &mut ChangeTrackersFetch<'w, T>,
|
||||||
&id: &ComponentId,
|
component_id: &ComponentId,
|
||||||
archetype: &'w Archetype,
|
_archetype: &'w Archetype,
|
||||||
tables: &'w Tables,
|
table: &'w Table,
|
||||||
) {
|
) {
|
||||||
match T::Storage::STORAGE_TYPE {
|
if Self::IS_DENSE {
|
||||||
StorageType::Table => {
|
Self::set_table(fetch, component_id, 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()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,68 +1105,44 @@ unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
|
|||||||
&id: &ComponentId,
|
&id: &ComponentId,
|
||||||
table: &'w Table,
|
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]
|
#[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 {
|
|
||||||
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 {
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StorageType::SparseSet => {
|
|
||||||
let entities = fetch
|
|
||||||
.entities
|
|
||||||
.unwrap_or_else(|| debug_checked_unreachable());
|
|
||||||
let entity = *entities.get(archetype_index);
|
|
||||||
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()),
|
|
||||||
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,
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
entity: Entity,
|
||||||
table_row: usize,
|
table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
ChangeTrackers {
|
match T::Storage::STORAGE_TYPE {
|
||||||
component_ticks: {
|
StorageType::Table => ChangeTrackers {
|
||||||
let table_ticks = fetch
|
component_ticks: {
|
||||||
.table_ticks
|
let table_ticks = fetch
|
||||||
.unwrap_or_else(|| debug_checked_unreachable());
|
.table_ticks
|
||||||
table_ticks.get(table_row).read()
|
.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,
|
||||||
|
},
|
||||||
|
StorageType::SparseSet => ChangeTrackers {
|
||||||
|
component_ticks: *fetch
|
||||||
|
.sparse_set
|
||||||
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
|
.get_ticks(entity)
|
||||||
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
|
.get(),
|
||||||
|
marker: PhantomData,
|
||||||
|
last_change_tick: fetch.last_change_tick,
|
||||||
|
change_tick: fetch.change_tick,
|
||||||
},
|
},
|
||||||
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)*;
|
const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
|
||||||
|
|
||||||
#[inline]
|
#[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 ($($name,)*) = _fetch;
|
||||||
let ($($state,)*) = _state;
|
let ($($state,)*) = _state;
|
||||||
$($name::set_archetype($name, $state, _archetype, _tables);)*
|
$($name::set_archetype($name, $state, _archetype, _table);)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1368,32 +1244,25 @@ macro_rules! impl_tuple_fetch {
|
|||||||
$($name::set_table($name, $state, _table);)*
|
$($name::set_table($name, $state, _table);)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
#[allow(clippy::unused_unit)]
|
#[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;
|
let ($($name,)*) = _fetch;
|
||||||
($($name::table_fetch($name, _table_row),)*)
|
($($name::fetch($name, _entity, _table_row),)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
#[allow(clippy::unused_unit)]
|
unsafe fn filter_fetch<'w>(
|
||||||
unsafe fn archetype_fetch<'w>(_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, _archetype_index: usize) -> QueryItem<'w, Self> {
|
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
_entity: Entity,
|
||||||
|
_table_row: usize
|
||||||
|
) -> bool {
|
||||||
let ($($name,)*) = _fetch;
|
let ($($name,)*) = _fetch;
|
||||||
($($name::archetype_fetch($name, _archetype_index),)*)
|
true $(&& $name::filter_fetch($name, _entity, _table_row))*
|
||||||
}
|
|
||||||
|
|
||||||
#[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))*
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_component_access(state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {
|
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)*;
|
const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
|
||||||
|
|
||||||
#[inline]
|
#[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 ($($name,)*) = _fetch;
|
||||||
let ($($state,)*) = _state;
|
let ($($state,)*) = _state;
|
||||||
$(
|
$(
|
||||||
$name.1 = $name::matches_component_set($state, &|id| _archetype.contains(id));
|
$name.1 = $name::matches_component_set($state, &|id| _archetype.contains(id));
|
||||||
if $name.1 {
|
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)]
|
#[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;
|
let ($($name,)*) = _fetch;
|
||||||
($(
|
($(
|
||||||
$name.1.then(|| $name::table_fetch(&mut $name.0, _table_row)),
|
$name.1.then(|| $name::fetch(&mut $name.0, _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> {
|
|
||||||
let ($($name,)*) = _fetch;
|
|
||||||
($(
|
|
||||||
$name.1.then(|| $name::archetype_fetch(&mut $name.0, _archetype_index)),
|
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1608,7 +1477,7 @@ unsafe impl<Q: WorldQuery> WorldQuery for NopWorldQuery<Q> {
|
|||||||
_fetch: &mut (),
|
_fetch: &mut (),
|
||||||
_state: &Q::State,
|
_state: &Q::State,
|
||||||
_archetype: &Archetype,
|
_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) {}
|
unsafe fn set_table<'w>(_fetch: &mut (), _state: &Q::State, _table: &Table) {}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn archetype_fetch<'w>(
|
unsafe fn fetch<'w>(
|
||||||
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
_archetype_index: usize,
|
_entity: Entity,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
unsafe fn table_fetch<'w>(
|
|
||||||
_fetch: &mut (),
|
|
||||||
_table_row: usize,
|
_table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use crate::{
|
|||||||
query::{
|
query::{
|
||||||
debug_checked_unreachable, Access, FilteredAccess, QueryFetch, WorldQuery, WorldQueryGats,
|
debug_checked_unreachable, Access, FilteredAccess, QueryFetch, WorldQuery, WorldQueryGats,
|
||||||
},
|
},
|
||||||
storage::{ComponentSparseSet, Table, Tables},
|
storage::{ComponentSparseSet, Table},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
use bevy_ecs_macros::all_tuples;
|
use bevy_ecs_macros::all_tuples;
|
||||||
@ -88,20 +88,14 @@ unsafe impl<T: Component> WorldQuery for With<T> {
|
|||||||
_fetch: &mut (),
|
_fetch: &mut (),
|
||||||
_state: &ComponentId,
|
_state: &ComponentId,
|
||||||
_archetype: &Archetype,
|
_archetype: &Archetype,
|
||||||
_tables: &Tables,
|
_table: &Table,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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]
|
|
||||||
unsafe fn table_fetch<'w>(
|
|
||||||
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
_entity: Entity,
|
||||||
_table_row: usize,
|
_table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
}
|
}
|
||||||
@ -200,20 +194,14 @@ unsafe impl<T: Component> WorldQuery for Without<T> {
|
|||||||
_fetch: &mut (),
|
_fetch: &mut (),
|
||||||
_state: &ComponentId,
|
_state: &ComponentId,
|
||||||
_archetype: &Archetype,
|
_archetype: &Archetype,
|
||||||
_tables: &Tables,
|
_table: &Table,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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]
|
|
||||||
unsafe fn table_fetch<'w>(
|
|
||||||
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
_fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
_entity: Entity,
|
||||||
_table_row: usize,
|
_table_row: usize,
|
||||||
) -> <Self as WorldQueryGats<'w>>::Item {
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
}
|
}
|
||||||
@ -348,37 +336,39 @@ macro_rules! impl_query_filter_tuple {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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 ($($filter,)*) = fetch;
|
||||||
let ($($state,)*) = state;
|
let ($($state,)*) = &state;
|
||||||
$(
|
$(
|
||||||
$filter.matches = $filter::matches_component_set($state, &|id| archetype.contains(id));
|
$filter.matches = $filter::matches_component_set($state, &|id| archetype.contains(id));
|
||||||
if $filter.matches {
|
if $filter.matches {
|
||||||
$filter::set_archetype(&mut $filter.fetch, $state, archetype, tables);
|
$filter::set_archetype(&mut $filter.fetch, $state, archetype, table);
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
unsafe fn table_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, table_row: usize) -> <Self as WorldQueryGats<'w>>::Item {
|
unsafe fn fetch<'w>(
|
||||||
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
_entity: Entity,
|
||||||
|
_table_row: usize
|
||||||
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
let ($($filter,)*) = fetch;
|
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]
|
#[inline(always)]
|
||||||
unsafe fn archetype_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, archetype_index: usize) -> <Self as WorldQueryGats<'w>>::Item {
|
unsafe fn filter_fetch<'w>(
|
||||||
let ($($filter,)*) = fetch;
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
false $(|| ($filter.matches && $filter::archetype_filter_fetch(&mut $filter.fetch, archetype_index)))*
|
entity: Entity,
|
||||||
}
|
table_row: usize
|
||||||
|
) -> bool {
|
||||||
#[inline]
|
Self::fetch(fetch, entity, table_row)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_component_access(state: &Self::State, access: &mut FilteredAccess<ComponentId>) {
|
fn update_component_access(state: &Self::State, access: &mut FilteredAccess<ComponentId>) {
|
||||||
@ -450,9 +440,7 @@ macro_rules! impl_tick_filter {
|
|||||||
$(#[$fetch_meta])*
|
$(#[$fetch_meta])*
|
||||||
pub struct $fetch_name<'w, T> {
|
pub struct $fetch_name<'w, T> {
|
||||||
table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
|
table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
|
||||||
entity_table_rows: Option<ThinSlicePtr<'w, usize>>,
|
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
entities: Option<ThinSlicePtr<'w, Entity>>,
|
|
||||||
sparse_set: Option<&'w ComponentSparseSet>,
|
sparse_set: Option<&'w ComponentSparseSet>,
|
||||||
last_change_tick: u32,
|
last_change_tick: u32,
|
||||||
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 {
|
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> {
|
QueryFetch::<'w, Self> {
|
||||||
table_ticks: None,
|
table_ticks: None,
|
||||||
entities: None,
|
|
||||||
entity_table_rows: None,
|
|
||||||
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet)
|
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,
|
marker: PhantomData,
|
||||||
last_change_tick,
|
last_change_tick,
|
||||||
change_tick,
|
change_tick,
|
||||||
@ -485,8 +476,6 @@ macro_rules! impl_tick_filter {
|
|||||||
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
) -> <Self as WorldQueryGats<'w>>::Fetch {
|
||||||
$fetch_name {
|
$fetch_name {
|
||||||
table_ticks: fetch.table_ticks,
|
table_ticks: fetch.table_ticks,
|
||||||
entity_table_rows: fetch.entity_table_rows,
|
|
||||||
entities: fetch.entities,
|
|
||||||
sparse_set: fetch.sparse_set,
|
sparse_set: fetch.sparse_set,
|
||||||
last_change_tick: fetch.last_change_tick,
|
last_change_tick: fetch.last_change_tick,
|
||||||
change_tick: fetch.change_tick,
|
change_tick: fetch.change_tick,
|
||||||
@ -503,53 +492,68 @@ macro_rules! impl_tick_filter {
|
|||||||
|
|
||||||
const IS_ARCHETYPAL: bool = false;
|
const IS_ARCHETYPAL: bool = false;
|
||||||
|
|
||||||
unsafe fn set_table<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, &id: &ComponentId, table: &'w Table) {
|
#[inline]
|
||||||
fetch.table_ticks = Some(table.get_column(id).unwrap().get_ticks_slice().into());
|
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]
|
||||||
match T::Storage::STORAGE_TYPE {
|
unsafe fn set_archetype<'w>(
|
||||||
StorageType::Table => {
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
fetch.entity_table_rows = Some(archetype.entity_table_rows().into());
|
component_id: &ComponentId,
|
||||||
let table = &tables[archetype.table_id()];
|
_archetype: &'w Archetype,
|
||||||
fetch.table_ticks = Some(table.get_column(id).unwrap().get_ticks_slice().into());
|
table: &'w Table
|
||||||
}
|
) {
|
||||||
StorageType::SparseSet => fetch.entities = Some(archetype.entities().into()),
|
if Self::IS_DENSE {
|
||||||
|
Self::set_table(fetch, component_id, table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn table_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, table_row: usize) -> <Self as WorldQueryGats<'w>>::Item {
|
#[inline(always)]
|
||||||
$is_detected(&*(fetch.table_ticks.unwrap_or_else(|| debug_checked_unreachable()).get(table_row)).deref(), fetch.last_change_tick, fetch.change_tick)
|
unsafe fn fetch<'w>(
|
||||||
}
|
fetch: &mut <Self as WorldQueryGats<'w>>::Fetch,
|
||||||
|
entity: Entity,
|
||||||
unsafe fn archetype_fetch<'w>(fetch: &mut <Self as WorldQueryGats<'w>>::Fetch, archetype_index: usize) -> <Self as WorldQueryGats<'w>>::Item {
|
table_row: usize
|
||||||
|
) -> <Self as WorldQueryGats<'w>>::Item {
|
||||||
match T::Storage::STORAGE_TYPE {
|
match T::Storage::STORAGE_TYPE {
|
||||||
StorageType::Table => {
|
StorageType::Table => {
|
||||||
let table_row = *fetch.entity_table_rows.unwrap_or_else(|| debug_checked_unreachable()).get(archetype_index);
|
$is_detected(&*(
|
||||||
$is_detected(&*(fetch.table_ticks.unwrap_or_else(|| debug_checked_unreachable()).get(table_row)).deref(), fetch.last_change_tick, fetch.change_tick)
|
fetch.table_ticks
|
||||||
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
|
.get(table_row))
|
||||||
|
.deref(),
|
||||||
|
fetch.last_change_tick,
|
||||||
|
fetch.change_tick
|
||||||
|
)
|
||||||
}
|
}
|
||||||
StorageType::SparseSet => {
|
StorageType::SparseSet => {
|
||||||
let entity = *fetch.entities.unwrap_or_else(|| debug_checked_unreachable()).get(archetype_index);
|
let ticks = &*fetch
|
||||||
let ticks = fetch
|
|
||||||
.sparse_set
|
.sparse_set
|
||||||
.unwrap_or_else(|| debug_checked_unreachable())
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
.get_ticks(entity)
|
.get_ticks(entity)
|
||||||
.map(|ticks| &*ticks.get())
|
.unwrap_or_else(|| debug_checked_unreachable())
|
||||||
.cloned()
|
.get();
|
||||||
.unwrap();
|
$is_detected(ticks, fetch.last_change_tick, fetch.change_tick)
|
||||||
$is_detected(&ticks, fetch.last_change_tick, fetch.change_tick)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
unsafe fn table_filter_fetch(fetch: &mut QueryFetch<'_, Self>, table_row: usize) -> bool {
|
unsafe fn filter_fetch<'w>(
|
||||||
Self::table_fetch(fetch, table_row)
|
fetch: &mut QueryFetch<'w, Self>,
|
||||||
}
|
entity: Entity,
|
||||||
|
table_row: usize
|
||||||
#[inline]
|
) -> bool {
|
||||||
unsafe fn archetype_filter_fetch(fetch: &mut QueryFetch<'_, Self>, archetype_index: usize) -> bool {
|
Self::fetch(fetch, entity, table_row)
|
||||||
Self::archetype_fetch(fetch, archetype_index)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -625,7 +629,7 @@ impl_tick_filter!(
|
|||||||
|
|
||||||
impl_tick_filter!(
|
impl_tick_filter!(
|
||||||
/// A filter on a component that only retains results added or mutably dereferenced after the system last ran.
|
/// A filter on a component that only retains results added or mutably dereferenced after the system last ran.
|
||||||
///
|
///
|
||||||
/// A common use for this filter is avoiding redundant work when values have not changed.
|
/// A common use for this filter is avoiding redundant work when values have not changed.
|
||||||
///
|
///
|
||||||
/// **Note** that simply *mutably dereferencing* a component is considered a change ([`DerefMut`](std::ops::DerefMut)).
|
/// **Note** that simply *mutably dereferencing* a component is considered a change ([`DerefMut`](std::ops::DerefMut)).
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
archetype::{ArchetypeId, Archetypes},
|
archetype::{ArchetypeEntity, ArchetypeId, Archetypes},
|
||||||
entity::{Entities, Entity},
|
entity::{Entities, Entity},
|
||||||
prelude::World,
|
prelude::World,
|
||||||
query::{ArchetypeFilter, QueryState, WorldQuery},
|
query::{ArchetypeFilter, QueryState, WorldQuery},
|
||||||
@ -139,7 +139,8 @@ where
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<QueryItem<'w, Q>> {
|
unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<QueryItem<'w, Q>> {
|
||||||
for entity in self.entity_iter.by_ref() {
|
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,
|
Some(location) => location,
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
@ -153,6 +154,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let archetype = &self.archetypes[location.archetype_id];
|
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,
|
// 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
|
// `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
|
||||||
@ -160,7 +162,7 @@ where
|
|||||||
&mut self.fetch,
|
&mut self.fetch,
|
||||||
&self.query_state.fetch_state,
|
&self.query_state.fetch_state,
|
||||||
archetype,
|
archetype,
|
||||||
self.tables,
|
table,
|
||||||
);
|
);
|
||||||
// SAFETY: `table` is from the world that `fetch/filter` were created for,
|
// 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
|
// `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
|
||||||
@ -168,13 +170,15 @@ where
|
|||||||
&mut self.filter,
|
&mut self.filter,
|
||||||
&self.query_state.filter_state,
|
&self.query_state.filter_state,
|
||||||
archetype,
|
archetype,
|
||||||
self.tables,
|
table,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let table_row = archetype.entity_table_row(location.index);
|
||||||
// SAFETY: set_archetype was called prior.
|
// 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
|
// `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
|
// 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
|
None
|
||||||
@ -462,6 +466,8 @@ impl<'w, 's, Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery, const K: usize> Fused
|
|||||||
struct QueryIterationCursor<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> {
|
struct QueryIterationCursor<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> {
|
||||||
table_id_iter: std::slice::Iter<'s, TableId>,
|
table_id_iter: std::slice::Iter<'s, TableId>,
|
||||||
archetype_id_iter: std::slice::Iter<'s, ArchetypeId>,
|
archetype_id_iter: std::slice::Iter<'s, ArchetypeId>,
|
||||||
|
table_entities: &'w [Entity],
|
||||||
|
archetype_entities: &'w [ArchetypeEntity],
|
||||||
fetch: QueryFetch<'w, Q>,
|
fetch: QueryFetch<'w, Q>,
|
||||||
filter: QueryFetch<'w, F>,
|
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
|
// 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 {
|
Self {
|
||||||
table_id_iter: self.table_id_iter.clone(),
|
table_id_iter: self.table_id_iter.clone(),
|
||||||
archetype_id_iter: self.archetype_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
|
// SAFETY: upheld by caller invariants
|
||||||
fetch: Q::clone_fetch(&self.fetch),
|
fetch: Q::clone_fetch(&self.fetch),
|
||||||
filter: F::clone_fetch(&self.filter),
|
filter: F::clone_fetch(&self.filter),
|
||||||
@ -529,6 +537,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
|
|||||||
QueryIterationCursor {
|
QueryIterationCursor {
|
||||||
fetch,
|
fetch,
|
||||||
filter,
|
filter,
|
||||||
|
table_entities: &[],
|
||||||
|
archetype_entities: &[],
|
||||||
table_id_iter: query_state.matched_table_ids.iter(),
|
table_id_iter: query_state.matched_table_ids.iter(),
|
||||||
archetype_id_iter: query_state.matched_archetype_ids.iter(),
|
archetype_id_iter: query_state.matched_archetype_ids.iter(),
|
||||||
current_len: 0,
|
current_len: 0,
|
||||||
@ -541,10 +551,17 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
|
|||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn peek_last(&mut self) -> Option<QueryItem<'w, Q>> {
|
unsafe fn peek_last(&mut self) -> Option<QueryItem<'w, Q>> {
|
||||||
if self.current_index > 0 {
|
if self.current_index > 0 {
|
||||||
|
let index = self.current_index - 1;
|
||||||
if Self::IS_DENSE {
|
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 {
|
} 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 {
|
} else {
|
||||||
None
|
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
|
// `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
|
||||||
Q::set_table(&mut self.fetch, &query_state.fetch_state, table);
|
Q::set_table(&mut self.fetch, &query_state.fetch_state, table);
|
||||||
F::set_table(&mut self.filter, &query_state.filter_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_len = table.entity_count();
|
||||||
self.current_index = 0;
|
self.current_index = 0;
|
||||||
continue;
|
continue;
|
||||||
@ -581,14 +599,15 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
|
|||||||
|
|
||||||
// SAFETY: set_table was called prior.
|
// 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.
|
// `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;
|
self.current_index += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: set_table was called prior.
|
// 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.
|
// `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;
|
self.current_index += 1;
|
||||||
return Some(item);
|
return Some(item);
|
||||||
@ -600,13 +619,15 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
|
|||||||
let archetype = &archetypes[*archetype_id];
|
let archetype = &archetypes[*archetype_id];
|
||||||
// SAFETY: `archetype` and `tables` are from the world that `fetch/filter` were created for,
|
// 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
|
// `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(
|
F::set_archetype(
|
||||||
&mut self.filter,
|
&mut self.filter,
|
||||||
&query_state.filter_state,
|
&query_state.filter_state,
|
||||||
archetype,
|
archetype,
|
||||||
tables,
|
table,
|
||||||
);
|
);
|
||||||
|
self.archetype_entities = archetype.entities();
|
||||||
self.current_len = archetype.len();
|
self.current_len = archetype.len();
|
||||||
self.current_index = 0;
|
self.current_index = 0;
|
||||||
continue;
|
continue;
|
||||||
@ -614,14 +635,23 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> QueryIterationCursor<'w, 's,
|
|||||||
|
|
||||||
// SAFETY: set_archetype was called prior.
|
// 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.
|
// `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;
|
self.current_index += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: set_archetype was called prior, `current_index` is an archetype index in range of the current archetype
|
// 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.
|
// `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;
|
self.current_index += 1;
|
||||||
return Some(item);
|
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 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);
|
let mut filter = F::init_fetch(world, &self.filter_state, last_change_tick, change_tick);
|
||||||
|
|
||||||
Q::set_archetype(
|
let table = &world.storages().tables[archetype.table_id()];
|
||||||
&mut fetch,
|
Q::set_archetype(&mut fetch, &self.fetch_state, archetype, table);
|
||||||
&self.fetch_state,
|
F::set_archetype(&mut filter, &self.filter_state, archetype, table);
|
||||||
archetype,
|
|
||||||
&world.storages().tables,
|
if F::filter_fetch(&mut filter, entity, location.index) {
|
||||||
);
|
Ok(Q::fetch(&mut fetch, entity, location.index))
|
||||||
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))
|
|
||||||
} else {
|
} else {
|
||||||
Err(QueryEntityError::QueryDoesNotMatch(entity))
|
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 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);
|
let mut filter = F::init_fetch(world, &self.filter_state, last_change_tick, change_tick);
|
||||||
|
|
||||||
|
let tables = &world.storages().tables;
|
||||||
if Q::IS_DENSE && F::IS_DENSE {
|
if Q::IS_DENSE && F::IS_DENSE {
|
||||||
let tables = &world.storages().tables;
|
|
||||||
for table_id in &self.matched_table_ids {
|
for table_id in &self.matched_table_ids {
|
||||||
let table = &tables[*table_id];
|
let table = &tables[*table_id];
|
||||||
Q::set_table(&mut fetch, &self.fetch_state, table);
|
Q::set_table(&mut fetch, &self.fetch_state, table);
|
||||||
F::set_table(&mut filter, &self.filter_state, table);
|
F::set_table(&mut filter, &self.filter_state, table);
|
||||||
|
|
||||||
for table_index in 0..table.entity_count() {
|
let entities = table.entities();
|
||||||
if !F::table_filter_fetch(&mut filter, table_index) {
|
for row in 0..table.entity_count() {
|
||||||
|
let entity = entities.get_unchecked(row);
|
||||||
|
if !F::filter_fetch(&mut filter, *entity, row) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let item = Q::table_fetch(&mut fetch, table_index);
|
func(Q::fetch(&mut fetch, *entity, row));
|
||||||
func(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let archetypes = &world.archetypes;
|
let archetypes = &world.archetypes;
|
||||||
let tables = &world.storages().tables;
|
|
||||||
for archetype_id in &self.matched_archetype_ids {
|
for archetype_id in &self.matched_archetype_ids {
|
||||||
let archetype = &archetypes[*archetype_id];
|
let archetype = &archetypes[*archetype_id];
|
||||||
Q::set_archetype(&mut fetch, &self.fetch_state, archetype, tables);
|
let table = &tables[archetype.table_id()];
|
||||||
F::set_archetype(&mut filter, &self.filter_state, archetype, tables);
|
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() {
|
let entities = archetype.entities();
|
||||||
if !F::archetype_filter_fetch(&mut filter, archetype_index) {
|
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;
|
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 tables = &world.storages().tables;
|
||||||
let table = &tables[*table_id];
|
let table = &tables[*table_id];
|
||||||
|
let entities = table.entities();
|
||||||
Q::set_table(&mut fetch, &self.fetch_state, table);
|
Q::set_table(&mut fetch, &self.fetch_state, table);
|
||||||
F::set_table(&mut filter, &self.filter_state, table);
|
F::set_table(&mut filter, &self.filter_state, table);
|
||||||
for table_index in offset..offset + len {
|
for row in offset..offset + len {
|
||||||
if !F::table_filter_fetch(&mut filter, table_index) {
|
let entity = entities.get_unchecked(row);
|
||||||
|
if !F::filter_fetch(&mut filter, *entity, row) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let item = Q::table_fetch(&mut fetch, table_index);
|
func(Q::fetch(&mut fetch, *entity, row));
|
||||||
func(item);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
@ -1083,14 +1087,25 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
|
|||||||
);
|
);
|
||||||
let tables = &world.storages().tables;
|
let tables = &world.storages().tables;
|
||||||
let archetype = &world.archetypes[*archetype_id];
|
let archetype = &world.archetypes[*archetype_id];
|
||||||
Q::set_archetype(&mut fetch, &self.fetch_state, archetype, tables);
|
let table = &tables[archetype.table_id()];
|
||||||
F::set_archetype(&mut filter, &self.filter_state, archetype, tables);
|
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 {
|
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;
|
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> + '_ {
|
pub fn iter_entities(&self) -> impl Iterator<Item = Entity> + '_ {
|
||||||
self.archetypes
|
self.archetypes
|
||||||
.iter()
|
.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`.
|
/// 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() {
|
for scene_entity in archetype.entities() {
|
||||||
let entity = *instance_info
|
let entity = *instance_info
|
||||||
.entity_map
|
.entity_map
|
||||||
.entry(*scene_entity)
|
.entry(scene_entity.entity())
|
||||||
.or_insert_with(|| world.spawn_empty().id());
|
.or_insert_with(|| world.spawn_empty().id());
|
||||||
for component_id in archetype.components() {
|
for component_id in archetype.components() {
|
||||||
let component_info = self
|
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