use crate::{
archetype::{Archetype, ArchetypeComponentId},
change_detection::Ticks,
component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
entity::Entity,
query::{Access, DebugCheckedUnwrap, FilteredAccess},
storage::{ComponentSparseSet, Table},
world::{Mut, World},
};
use bevy_ecs_macros::all_tuples;
pub use bevy_ecs_macros::WorldQuery;
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
use std::{cell::UnsafeCell, marker::PhantomData};
pub unsafe trait WorldQuery {
type Item<'a>;
type Fetch<'a>;
type ReadOnly: ReadOnlyWorldQuery<State = Self::State>;
type State: Send + Sync + Sized;
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort>;
unsafe fn init_fetch<'w>(
world: &'w World,
state: &Self::State,
last_change_tick: u32,
change_tick: u32,
) -> Self::Fetch<'w>;
unsafe fn clone_fetch<'w>(fetch: &Self::Fetch<'w>) -> Self::Fetch<'w>;
const IS_DENSE: bool;
const IS_ARCHETYPAL: bool;
unsafe fn set_archetype<'w>(
fetch: &mut Self::Fetch<'w>,
state: &Self::State,
archetype: &'w Archetype,
table: &'w Table,
);
unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table);
unsafe fn fetch<'w>(
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: usize,
) -> Self::Item<'w>;
#[allow(unused_variables)]
#[inline(always)]
unsafe fn filter_fetch(fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: usize) -> bool {
true
}
fn update_component_access(state: &Self::State, access: &mut FilteredAccess<ComponentId>);
fn update_archetype_component_access(
state: &Self::State,
archetype: &Archetype,
access: &mut Access<ArchetypeComponentId>,
);
fn init_state(world: &mut World) -> Self::State;
fn matches_component_set(
state: &Self::State,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool;
}
pub unsafe trait ReadOnlyWorldQuery: WorldQuery<ReadOnly = Self> {}
pub type QueryFetch<'w, Q> = <Q as WorldQuery>::Fetch<'w>;
pub type QueryItem<'w, Q> = <Q as WorldQuery>::Item<'w>;
pub type ROQueryFetch<'w, Q> = QueryFetch<'w, <Q as WorldQuery>::ReadOnly>;
pub type ROQueryItem<'w, Q> = QueryItem<'w, <Q as WorldQuery>::ReadOnly>;
unsafe impl WorldQuery for Entity {
type Fetch<'w> = ();
type Item<'w> = Entity;
type ReadOnly = Self;
type State = ();
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
item
}
const IS_DENSE: bool = true;
const IS_ARCHETYPAL: bool = true;
unsafe fn init_fetch<'w>(
_world: &'w World,
_state: &Self::State,
_last_change_tick: u32,
_change_tick: u32,
) -> Self::Fetch<'w> {
}
unsafe fn clone_fetch<'w>(_fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> {}
#[inline]
unsafe fn set_archetype<'w>(
_fetch: &mut Self::Fetch<'w>,
_state: &Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) {
}
#[inline(always)]
unsafe fn fetch<'w>(
_fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: usize,
) -> Self::Item<'w> {
entity
}
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {}
fn update_archetype_component_access(
_state: &Self::State,
_archetype: &Archetype,
_access: &mut Access<ArchetypeComponentId>,
) {
}
fn init_state(_world: &mut World) {}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl ReadOnlyWorldQuery for Entity {}
#[doc(hidden)]
pub struct ReadFetch<'w, T> {
table_components: Option<ThinSlicePtr<'w, UnsafeCell<T>>>,
sparse_set: Option<&'w ComponentSparseSet>,
}
unsafe impl<T: Component> WorldQuery for &T {
type Fetch<'w> = ReadFetch<'w, T>;
type Item<'w> = &'w T;
type ReadOnly = Self;
type State = ComponentId;
fn shrink<'wlong: 'wshort, 'wshort>(item: &'wlong T) -> &'wshort T {
item
}
const IS_DENSE: bool = {
match T::Storage::STORAGE_TYPE {
StorageType::Table => true,
StorageType::SparseSet => false,
}
};
const IS_ARCHETYPAL: bool = true;
unsafe fn init_fetch<'w>(
world: &'w World,
&component_id: &ComponentId,
_last_change_tick: u32,
_change_tick: u32,
) -> ReadFetch<'w, T> {
ReadFetch {
table_components: None,
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
world
.storages()
.sparse_sets
.get(component_id)
.debug_checked_unwrap()
}),
}
}
unsafe fn clone_fetch<'w>(fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> {
ReadFetch {
table_components: fetch.table_components,
sparse_set: fetch.sparse_set,
}
}
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut ReadFetch<'w, T>,
component_id: &ComponentId,
_archetype: &'w Archetype,
table: &'w Table,
) {
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)
.debug_checked_unwrap()
.get_data_slice()
.into(),
);
}
#[inline(always)]
unsafe fn fetch<'w>(
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: usize,
) -> Self::Item<'w> {
match T::Storage::STORAGE_TYPE {
StorageType::Table => fetch
.table_components
.debug_checked_unwrap()
.get(table_row)
.deref(),
StorageType::SparseSet => fetch
.sparse_set
.debug_checked_unwrap()
.get(entity)
.debug_checked_unwrap()
.deref(),
}
}
fn update_component_access(
&component_id: &ComponentId,
access: &mut FilteredAccess<ComponentId>,
) {
assert!(
!access.access().has_write(component_id),
"&{} conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
std::any::type_name::<T>(),
);
access.add_read(component_id);
}
fn update_archetype_component_access(
&component_id: &ComponentId,
archetype: &Archetype,
access: &mut Access<ArchetypeComponentId>,
) {
if let Some(archetype_component_id) = archetype.get_archetype_component_id(component_id) {
access.add_read(archetype_component_id);
}
}
fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
}
fn matches_component_set(
&state: &ComponentId,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
set_contains_id(state)
}
}
unsafe impl<T: Component> ReadOnlyWorldQuery for &T {}
#[doc(hidden)]
pub struct WriteFetch<'w, T> {
table_data: Option<(
ThinSlicePtr<'w, UnsafeCell<T>>,
ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>,
)>,
sparse_set: Option<&'w ComponentSparseSet>,
last_change_tick: u32,
change_tick: u32,
}
unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
type Fetch<'w> = WriteFetch<'w, T>;
type Item<'w> = Mut<'w, T>;
type ReadOnly = &'__w T;
type State = ComponentId;
fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> {
item
}
const IS_DENSE: bool = {
match T::Storage::STORAGE_TYPE {
StorageType::Table => true,
StorageType::SparseSet => false,
}
};
const IS_ARCHETYPAL: bool = true;
unsafe fn init_fetch<'w>(
world: &'w World,
&component_id: &ComponentId,
last_change_tick: u32,
change_tick: u32,
) -> WriteFetch<'w, T> {
WriteFetch {
table_data: None,
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
world
.storages()
.sparse_sets
.get(component_id)
.debug_checked_unwrap()
}),
last_change_tick,
change_tick,
}
}
unsafe fn clone_fetch<'w>(fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> {
WriteFetch {
table_data: fetch.table_data,
sparse_set: fetch.sparse_set,
last_change_tick: fetch.last_change_tick,
change_tick: fetch.change_tick,
}
}
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut WriteFetch<'w, T>,
component_id: &ComponentId,
_archetype: &'w Archetype,
table: &'w Table,
) {
if Self::IS_DENSE {
Self::set_table(fetch, component_id, table);
}
}
#[inline]
unsafe fn set_table<'w>(
fetch: &mut WriteFetch<'w, T>,
&component_id: &ComponentId,
table: &'w Table,
) {
let column = table.get_column(component_id).debug_checked_unwrap();
fetch.table_data = Some((
column.get_data_slice().into(),
column.get_ticks_slice().into(),
));
}
#[inline(always)]
unsafe fn fetch<'w>(
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: usize,
) -> Self::Item<'w> {
match T::Storage::STORAGE_TYPE {
StorageType::Table => {
let (table_components, table_ticks) = fetch.table_data.debug_checked_unwrap();
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,
},
}
}
StorageType::SparseSet => {
let (component, component_ticks) = fetch
.sparse_set
.debug_checked_unwrap()
.get_with_ticks(entity)
.debug_checked_unwrap();
Mut {
value: component.assert_unique().deref_mut(),
ticks: Ticks {
component_ticks: component_ticks.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>,
) {
assert!(
!access.access().has_read(component_id),
"&mut {} conflicts with a previous access in this query. Mutable component access must be unique.",
std::any::type_name::<T>(),
);
access.add_write(component_id);
}
fn update_archetype_component_access(
&component_id: &ComponentId,
archetype: &Archetype,
access: &mut Access<ArchetypeComponentId>,
) {
if let Some(archetype_component_id) = archetype.get_archetype_component_id(component_id) {
access.add_write(archetype_component_id);
}
}
fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
}
fn matches_component_set(
&state: &ComponentId,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
set_contains_id(state)
}
}
#[doc(hidden)]
pub struct OptionFetch<'w, T: WorldQuery> {
fetch: T::Fetch<'w>,
matches: bool,
}
unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
type Fetch<'w> = OptionFetch<'w, T>;
type Item<'w> = Option<T::Item<'w>>;
type ReadOnly = Option<T::ReadOnly>;
type State = T::State;
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
item.map(T::shrink)
}
const IS_DENSE: bool = T::IS_DENSE;
const IS_ARCHETYPAL: bool = T::IS_ARCHETYPAL;
unsafe fn init_fetch<'w>(
world: &'w World,
state: &T::State,
last_change_tick: u32,
change_tick: u32,
) -> OptionFetch<'w, T> {
OptionFetch {
fetch: T::init_fetch(world, state, last_change_tick, change_tick),
matches: false,
}
}
unsafe fn clone_fetch<'w>(fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> {
OptionFetch {
fetch: T::clone_fetch(&fetch.fetch),
matches: fetch.matches,
}
}
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut OptionFetch<'w, T>,
state: &T::State,
archetype: &'w Archetype,
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, table);
}
}
#[inline]
unsafe fn set_table<'w>(fetch: &mut OptionFetch<'w, T>, state: &T::State, table: &'w Table) {
fetch.matches = T::matches_component_set(state, &|id| table.has_column(id));
if fetch.matches {
T::set_table(&mut fetch.fetch, state, table);
}
}
#[inline(always)]
unsafe fn fetch<'w>(
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: usize,
) -> Self::Item<'w> {
fetch
.matches
.then(|| T::fetch(&mut fetch.fetch, entity, table_row))
}
fn update_component_access(state: &T::State, access: &mut FilteredAccess<ComponentId>) {
let mut intermediate = access.clone();
T::update_component_access(state, &mut intermediate);
access.extend_access(&intermediate);
}
fn update_archetype_component_access(
state: &T::State,
archetype: &Archetype,
access: &mut Access<ArchetypeComponentId>,
) {
if T::matches_component_set(state, &|id| archetype.contains(id)) {
T::update_archetype_component_access(state, archetype, access);
}
}
fn init_state(world: &mut World) -> T::State {
T::init_state(world)
}
fn matches_component_set(
_state: &T::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<T: ReadOnlyWorldQuery> ReadOnlyWorldQuery for Option<T> {}
pub struct ChangeTrackers<T: Component> {
pub(crate) component_ticks: ComponentTicks,
pub(crate) last_change_tick: u32,
pub(crate) change_tick: u32,
marker: PhantomData<T>,
}
impl<T: Component> Clone for ChangeTrackers<T> {
fn clone(&self) -> Self {
Self {
component_ticks: self.component_ticks,
last_change_tick: self.last_change_tick,
change_tick: self.change_tick,
marker: PhantomData,
}
}
}
impl<T: Component> Copy for ChangeTrackers<T> {}
impl<T: Component> std::fmt::Debug for ChangeTrackers<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ChangeTrackers")
.field("component_ticks", &self.component_ticks)
.field("last_change_tick", &self.last_change_tick)
.field("change_tick", &self.change_tick)
.finish()
}
}
impl<T: Component> ChangeTrackers<T> {
pub fn is_added(&self) -> bool {
self.component_ticks
.is_added(self.last_change_tick, self.change_tick)
}
pub fn is_changed(&self) -> bool {
self.component_ticks
.is_changed(self.last_change_tick, self.change_tick)
}
}
#[doc(hidden)]
pub struct ChangeTrackersFetch<'w, T> {
table_ticks: Option<ThinSlicePtr<'w, UnsafeCell<ComponentTicks>>>,
sparse_set: Option<&'w ComponentSparseSet>,
marker: PhantomData<T>,
last_change_tick: u32,
change_tick: u32,
}
unsafe impl<T: Component> WorldQuery for ChangeTrackers<T> {
type Fetch<'w> = ChangeTrackersFetch<'w, T>;
type Item<'w> = ChangeTrackers<T>;
type ReadOnly = Self;
type State = ComponentId;
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
item
}
const IS_DENSE: bool = {
match T::Storage::STORAGE_TYPE {
StorageType::Table => true,
StorageType::SparseSet => false,
}
};
const IS_ARCHETYPAL: bool = true;
unsafe fn init_fetch<'w>(
world: &'w World,
&component_id: &ComponentId,
last_change_tick: u32,
change_tick: u32,
) -> ChangeTrackersFetch<'w, T> {
ChangeTrackersFetch {
table_ticks: None,
sparse_set: (T::Storage::STORAGE_TYPE == StorageType::SparseSet).then(|| {
world
.storages()
.sparse_sets
.get(component_id)
.debug_checked_unwrap()
}),
marker: PhantomData,
last_change_tick,
change_tick,
}
}
unsafe fn clone_fetch<'w>(fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> {
ChangeTrackersFetch {
table_ticks: fetch.table_ticks,
sparse_set: fetch.sparse_set,
marker: fetch.marker,
last_change_tick: fetch.last_change_tick,
change_tick: fetch.change_tick,
}
}
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut ChangeTrackersFetch<'w, T>,
component_id: &ComponentId,
_archetype: &'w Archetype,
table: &'w Table,
) {
if Self::IS_DENSE {
Self::set_table(fetch, component_id, table);
}
}
#[inline]
unsafe fn set_table<'w>(
fetch: &mut ChangeTrackersFetch<'w, T>,
&id: &ComponentId,
table: &'w Table,
) {
fetch.table_ticks = Some(
table
.get_column(id)
.debug_checked_unwrap()
.get_ticks_slice()
.into(),
);
}
#[inline(always)]
unsafe fn fetch<'w>(
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: usize,
) -> Self::Item<'w> {
match T::Storage::STORAGE_TYPE {
StorageType::Table => ChangeTrackers {
component_ticks: {
let table_ticks = fetch.table_ticks.debug_checked_unwrap();
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
.debug_checked_unwrap()
.get_ticks(entity)
.debug_checked_unwrap()
.get(),
marker: PhantomData,
last_change_tick: fetch.last_change_tick,
change_tick: fetch.change_tick,
},
}
}
fn update_component_access(&id: &ComponentId, access: &mut FilteredAccess<ComponentId>) {
assert!(
!access.access().has_write(id),
"ChangeTrackers<{}> conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
std::any::type_name::<T>()
);
access.add_read(id);
}
fn update_archetype_component_access(
&id: &ComponentId,
archetype: &Archetype,
access: &mut Access<ArchetypeComponentId>,
) {
if let Some(archetype_component_id) = archetype.get_archetype_component_id(id) {
access.add_read(archetype_component_id);
}
}
fn init_state(world: &mut World) -> ComponentId {
world.init_component::<T>()
}
fn matches_component_set(
&id: &ComponentId,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
set_contains_id(id)
}
}
unsafe impl<T: Component> ReadOnlyWorldQuery for ChangeTrackers<T> {}
macro_rules! impl_tuple_fetch {
($(($name: ident, $state: ident)),*) => {
#[allow(non_snake_case)]
#[allow(clippy::unused_unit)]
unsafe impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) {
type Fetch<'w> = ($($name::Fetch<'w>,)*);
type Item<'w> = ($($name::Item<'w>,)*);
type ReadOnly = ($($name::ReadOnly,)*);
type State = ($($name::State,)*);
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
let ($($name,)*) = item;
($(
$name::shrink($name),
)*)
}
#[allow(clippy::unused_unit)]
unsafe fn init_fetch<'w>(_world: &'w World, state: &Self::State, _last_change_tick: u32, _change_tick: u32) -> Self::Fetch<'w> {
let ($($name,)*) = state;
($($name::init_fetch(_world, $name, _last_change_tick, _change_tick),)*)
}
unsafe fn clone_fetch<'w>(
fetch: &Self::Fetch<'w>,
) -> Self::Fetch<'w> {
let ($($name,)*) = &fetch;
($($name::clone_fetch($name),)*)
}
const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;
const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
#[inline]
unsafe fn set_archetype<'w>(
_fetch: &mut Self::Fetch<'w>,
_state: &Self::State,
_archetype: &'w Archetype,
_table: &'w Table
) {
let ($($name,)*) = _fetch;
let ($($state,)*) = _state;
$($name::set_archetype($name, $state, _archetype, _table);)*
}
#[inline]
unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) {
let ($($name,)*) = _fetch;
let ($($state,)*) = _state;
$($name::set_table($name, $state, _table);)*
}
#[inline(always)]
#[allow(clippy::unused_unit)]
unsafe fn fetch<'w>(
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: usize
) -> Self::Item<'w> {
let ($($name,)*) = _fetch;
($($name::fetch($name, _entity, _table_row),)*)
}
#[inline(always)]
unsafe fn filter_fetch<'w>(
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: usize
) -> bool {
let ($($name,)*) = _fetch;
true $(&& $name::filter_fetch($name, _entity, _table_row))*
}
fn update_component_access(state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {
let ($($name,)*) = state;
$($name::update_component_access($name, _access);)*
}
fn update_archetype_component_access(state: &Self::State, _archetype: &Archetype, _access: &mut Access<ArchetypeComponentId>) {
let ($($name,)*) = state;
$($name::update_archetype_component_access($name, _archetype, _access);)*
}
fn init_state(_world: &mut World) -> Self::State {
($($name::init_state(_world),)*)
}
fn matches_component_set(state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
let ($($name,)*) = state;
true $(&& $name::matches_component_set($name, _set_contains_id))*
}
}
unsafe impl<$($name: ReadOnlyWorldQuery),*> ReadOnlyWorldQuery for ($($name,)*) {}
};
}
pub struct AnyOf<T>(PhantomData<T>);
macro_rules! impl_anytuple_fetch {
($(($name: ident, $state: ident)),*) => {
#[allow(non_snake_case)]
#[allow(clippy::unused_unit)]
unsafe impl<$($name: WorldQuery),*> WorldQuery for AnyOf<($($name,)*)> {
type Fetch<'w> = ($(($name::Fetch<'w>, bool),)*);
type Item<'w> = ($(Option<$name::Item<'w>>,)*);
type ReadOnly = AnyOf<($($name::ReadOnly,)*)>;
type State = ($($name::State,)*);
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
let ($($name,)*) = item;
($(
$name.map($name::shrink),
)*)
}
#[allow(clippy::unused_unit)]
unsafe fn init_fetch<'w>(_world: &'w World, state: &Self::State, _last_change_tick: u32, _change_tick: u32) -> Self::Fetch<'w> {
let ($($name,)*) = state;
($(($name::init_fetch(_world, $name, _last_change_tick, _change_tick), false),)*)
}
unsafe fn clone_fetch<'w>(
fetch: &Self::Fetch<'w>,
) -> Self::Fetch<'w> {
let ($($name,)*) = &fetch;
($(($name::clone_fetch(& $name.0), $name.1),)*)
}
const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;
const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
#[inline]
unsafe fn set_archetype<'w>(
_fetch: &mut Self::Fetch<'w>,
_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, _table);
}
)*
}
#[inline]
unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) {
let ($($name,)*) = _fetch;
let ($($state,)*) = _state;
$(
$name.1 = $name::matches_component_set($state, &|id| _table.has_column(id));
if $name.1 {
$name::set_table(&mut $name.0, $state, _table);
}
)*
}
#[inline(always)]
#[allow(clippy::unused_unit)]
unsafe fn fetch<'w>(
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: usize
) -> Self::Item<'w> {
let ($($name,)*) = _fetch;
($(
$name.1.then(|| $name::fetch(&mut $name.0, _entity, _table_row)),
)*)
}
fn update_component_access(state: &Self::State, _access: &mut FilteredAccess<ComponentId>) {
let ($($name,)*) = state;
let mut _intersected_access = _access.clone();
let mut _not_first = false;
$(
if _not_first {
let mut intermediate = _access.clone();
$name::update_component_access($name, &mut intermediate);
_intersected_access.extend_intersect_filter(&intermediate);
_intersected_access.extend_access(&intermediate);
} else {
$name::update_component_access($name, &mut _intersected_access);
_not_first = true;
}
)*
*_access = _intersected_access;
}
fn update_archetype_component_access(state: &Self::State, _archetype: &Archetype, _access: &mut Access<ArchetypeComponentId>) {
let ($($name,)*) = state;
$(
if $name::matches_component_set($name, &|id| _archetype.contains(id)) {
$name::update_archetype_component_access($name, _archetype, _access);
}
)*
}
fn init_state(_world: &mut World) -> Self::State {
($($name::init_state(_world),)*)
}
fn matches_component_set(_state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
let ($($name,)*) = _state;
false $(|| $name::matches_component_set($name, _set_contains_id))*
}
}
unsafe impl<$($name: ReadOnlyWorldQuery),*> ReadOnlyWorldQuery for AnyOf<($($name,)*)> {}
};
}
all_tuples!(impl_tuple_fetch, 0, 15, F, S);
all_tuples!(impl_anytuple_fetch, 0, 15, F, S);
pub struct NopWorldQuery<Q: WorldQuery>(PhantomData<Q>);
unsafe impl<Q: WorldQuery> WorldQuery for NopWorldQuery<Q> {
type Fetch<'w> = ();
type Item<'w> = ();
type ReadOnly = Self;
type State = Q::State;
fn shrink<'wlong: 'wshort, 'wshort>(_: ()) {}
const IS_DENSE: bool = Q::IS_DENSE;
const IS_ARCHETYPAL: bool = true;
#[inline(always)]
unsafe fn init_fetch(
_world: &World,
_state: &Q::State,
_last_change_tick: u32,
_change_tick: u32,
) {
}
unsafe fn clone_fetch<'w>(_fetch: &Self::Fetch<'w>) -> Self::Fetch<'w> {}
#[inline(always)]
unsafe fn set_archetype(
_fetch: &mut (),
_state: &Q::State,
_archetype: &Archetype,
_tables: &Table,
) {
}
#[inline(always)]
unsafe fn set_table<'w>(_fetch: &mut (), _state: &Q::State, _table: &Table) {}
#[inline(always)]
unsafe fn fetch<'w>(
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: usize,
) -> Self::Item<'w> {
}
fn update_component_access(_state: &Q::State, _access: &mut FilteredAccess<ComponentId>) {}
fn update_archetype_component_access(
_state: &Q::State,
_archetype: &Archetype,
_access: &mut Access<ArchetypeComponentId>,
) {
}
fn init_state(world: &mut World) -> Self::State {
Q::init_state(world)
}
fn matches_component_set(
state: &Self::State,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
Q::matches_component_set(state, set_contains_id)
}
}
unsafe impl<Q: WorldQuery> ReadOnlyWorldQuery for NopWorldQuery<Q> {}