use crate::{
archetype::{Archetype, Archetypes},
bundle::Bundle,
change_detection::{
ComponentTicksMut, ComponentTicksRef, ContiguousComponentTicksMut,
ContiguousComponentTicksRef, ContiguousMut, ContiguousRef, MaybeLocation, Tick,
},
component::{Component, ComponentId, Components, Mutable, StorageType},
entity::{Entities, Entity, EntityLocation},
query::{
access_iter::{EcsAccessLevel, EcsAccessType},
Access, DebugCheckedUnwrap, FilteredAccess, WorldQuery,
},
storage::{ComponentSparseSet, Table, TableRow},
world::{
unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityMutExcept, EntityRef, EntityRefExcept,
FilteredEntityMut, FilteredEntityRef, Mut, Ref, World,
},
};
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
use bevy_utils::prelude::DebugName;
use core::{cell::UnsafeCell, iter, marker::PhantomData, panic::Location};
use variadics_please::all_tuples;
#[diagnostic::on_unimplemented(
message = "`{Self}` is not valid to request as data in a `Query`",
label = "invalid `Query` data",
note = "if `{Self}` is a component type, try using `&{Self}` or `&mut {Self}`"
)]
pub unsafe trait QueryData: WorldQuery {
const IS_READ_ONLY: bool;
const IS_ARCHETYPAL: bool;
type ReadOnly: ReadOnlyQueryData<State = <Self as WorldQuery>::State>;
type Item<'w, 's>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's>;
fn provide_extra_access(
_state: &mut Self::State,
_access: &mut Access,
_available_access: &Access,
) {
}
unsafe fn fetch<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>>;
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>>;
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be iterated contiguously",
label = "invalid contiguous `Query` data",
note = "if `{Self}` is a custom query type, using `QueryData` derive macro, ensure that the `#[query_data(contiguous(target))]` attribute is added"
)]
pub trait ContiguousQueryData: ArchetypeQueryData {
type Contiguous<'w, 's>;
unsafe fn fetch_contiguous<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's>;
}
pub unsafe trait ReadOnlyQueryData: QueryData<ReadOnly = Self> {}
pub type QueryItem<'w, 's, Q> = <Q as QueryData>::Item<'w, 's>;
pub type ROQueryItem<'w, 's, D> = QueryItem<'w, 's, <D as QueryData>::ReadOnly>;
pub trait ReleaseStateQueryData: QueryData {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static>;
}
pub trait ArchetypeQueryData: QueryData {}
unsafe impl WorldQuery for Entity {
type Fetch<'w> = ();
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {}
unsafe fn init_fetch<'w, 's>(
_world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
_last_run: Tick,
_this_run: Tick,
) -> Self::Fetch<'w> {
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {}
fn init_state(_world: &mut World) {}
fn get_state(_components: &Components) -> Option<()> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl QueryData for Entity {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = Entity;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
_fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(entity)
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl ReadOnlyQueryData for Entity {}
impl ReleaseStateQueryData for Entity {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl ArchetypeQueryData for Entity {}
impl ContiguousQueryData for Entity {
type Contiguous<'w, 's> = &'w [Entity];
unsafe fn fetch_contiguous<'w, 's>(
_state: &'s Self::State,
_fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
entities
}
}
unsafe impl WorldQuery for EntityLocation {
type Fetch<'w> = &'w Entities;
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
_last_run: Tick,
_this_run: Tick,
) -> Self::Fetch<'w> {
world.entities()
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {}
fn init_state(_world: &mut World) {}
fn get_state(_components: &Components) -> Option<()> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl QueryData for EntityLocation {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = EntityLocation;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(unsafe { fetch.get_spawned(entity).debug_checked_unwrap() })
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl ReadOnlyQueryData for EntityLocation {}
impl ReleaseStateQueryData for EntityLocation {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl ArchetypeQueryData for EntityLocation {}
#[derive(Clone, Copy, Debug)]
pub struct SpawnDetails {
spawned_by: MaybeLocation,
spawn_tick: Tick,
last_run: Tick,
this_run: Tick,
}
impl SpawnDetails {
pub fn is_spawned(self) -> bool {
self.spawn_tick.is_newer_than(self.last_run, self.this_run)
}
pub fn spawn_tick(self) -> Tick {
self.spawn_tick
}
pub fn spawned_by(self) -> MaybeLocation {
self.spawned_by
}
}
#[doc(hidden)]
#[derive(Clone)]
pub struct SpawnDetailsFetch<'w> {
entities: &'w Entities,
last_run: Tick,
this_run: Tick,
}
unsafe impl WorldQuery for SpawnDetails {
type Fetch<'w> = SpawnDetailsFetch<'w>;
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
SpawnDetailsFetch {
entities: world.entities(),
last_run,
this_run,
}
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &'w Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {}
fn init_state(_world: &mut World) {}
fn get_state(_components: &Components) -> Option<()> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl QueryData for SpawnDetails {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = Self;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
let (spawned_by, spawn_tick) = unsafe {
fetch
.entities
.entity_get_spawned_or_despawned_unchecked(entity)
};
Some(Self {
spawned_by,
spawn_tick,
last_run: fetch.last_run,
this_run: fetch.this_run,
})
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl ReadOnlyQueryData for SpawnDetails {}
impl ReleaseStateQueryData for SpawnDetails {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl ArchetypeQueryData for SpawnDetails {}
#[derive(Copy, Clone)]
#[doc(hidden)]
pub struct EntityFetch<'w> {
world: UnsafeWorldCell<'w>,
last_run: Tick,
this_run: Tick,
}
unsafe impl<'a> WorldQuery for EntityRef<'a> {
type Fetch<'w> = EntityFetch<'w>;
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
EntityFetch {
world,
last_run,
this_run,
}
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, access: &mut FilteredAccess) {
assert!(
!access.access().has_any_component_write(),
"EntityRef conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
);
access.read_all_components();
}
fn init_state(_world: &mut World) {}
fn get_state(_components: &Components) -> Option<()> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<'a> QueryData for EntityRef<'a> {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = EntityRef<'w>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
let cell = unsafe {
fetch
.world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.debug_checked_unwrap()
};
Some(unsafe { EntityRef::new(cell) })
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Component(EcsAccessLevel::ReadAll))
}
}
unsafe impl ReadOnlyQueryData for EntityRef<'_> {}
impl ReleaseStateQueryData for EntityRef<'_> {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl ArchetypeQueryData for EntityRef<'_> {}
unsafe impl<'a> WorldQuery for EntityMut<'a> {
type Fetch<'w> = EntityFetch<'w>;
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
EntityFetch {
world,
last_run,
this_run,
}
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, access: &mut FilteredAccess) {
assert!(
!access.access().has_any_component_read(),
"EntityMut conflicts with a previous access in this query. Exclusive access cannot coincide with any other accesses.",
);
access.write_all_components();
}
fn init_state(_world: &mut World) {}
fn get_state(_components: &Components) -> Option<()> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<'a> QueryData for EntityMut<'a> {
const IS_READ_ONLY: bool = false;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = EntityRef<'a>;
type Item<'w, 's> = EntityMut<'w>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
let cell = unsafe {
fetch
.world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.debug_checked_unwrap()
};
Some(unsafe { EntityMut::new(cell) })
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Component(EcsAccessLevel::WriteAll))
}
}
impl ReleaseStateQueryData for EntityMut<'_> {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl ArchetypeQueryData for EntityMut<'_> {}
unsafe impl WorldQuery for FilteredEntityRef<'_, '_> {
type Fetch<'w> = EntityFetch<'w>;
type State = Access;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
const IS_DENSE: bool = true;
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
EntityFetch {
world,
last_run,
this_run,
}
}
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_: &'w Table,
) {
}
fn update_component_access(state: &Self::State, filtered_access: &mut FilteredAccess) {
assert!(
filtered_access.access().is_compatible(state),
"FilteredEntityRef conflicts with a previous access in this query. Exclusive access cannot coincide with any other accesses.",
);
filtered_access.access.extend(state);
}
fn init_state(_world: &mut World) -> Self::State {
Access::default()
}
fn get_state(_components: &Components) -> Option<Self::State> {
Some(Access::default())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<'a, 'b> QueryData for FilteredEntityRef<'a, 'b> {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = FilteredEntityRef<'w, 's>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline]
fn provide_extra_access(
state: &mut Self::State,
access: &mut Access,
available_access: &Access,
) {
state.clone_from(available_access);
state.clear_writes();
state.remove_conflicting_access(access);
access.extend(state);
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
access: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
let cell = unsafe {
fetch
.world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.debug_checked_unwrap()
};
Some(unsafe { FilteredEntityRef::new(cell, access) })
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Access(state))
}
}
unsafe impl ReadOnlyQueryData for FilteredEntityRef<'_, '_> {}
impl ArchetypeQueryData for FilteredEntityRef<'_, '_> {}
unsafe impl WorldQuery for FilteredEntityMut<'_, '_> {
type Fetch<'w> = EntityFetch<'w>;
type State = Access;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
const IS_DENSE: bool = true;
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
EntityFetch {
world,
last_run,
this_run,
}
}
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_: &'w Table,
) {
}
fn update_component_access(state: &Self::State, filtered_access: &mut FilteredAccess) {
assert!(
filtered_access.access().is_compatible(state),
"FilteredEntityMut conflicts with a previous access in this query. Exclusive access cannot coincide with any other accesses.",
);
filtered_access.access.extend(state);
}
fn init_state(_world: &mut World) -> Self::State {
Access::default()
}
fn get_state(_components: &Components) -> Option<Self::State> {
Some(Access::default())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<'a, 'b> QueryData for FilteredEntityMut<'a, 'b> {
const IS_READ_ONLY: bool = false;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = FilteredEntityRef<'a, 'b>;
type Item<'w, 's> = FilteredEntityMut<'w, 's>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline]
fn provide_extra_access(
state: &mut Self::State,
access: &mut Access,
available_access: &Access,
) {
state.clone_from(available_access);
state.remove_conflicting_access(access);
access.extend(state);
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
access: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
let cell = unsafe {
fetch
.world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.debug_checked_unwrap()
};
Some(unsafe { FilteredEntityMut::new(cell, access) })
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Access(state))
}
}
impl ArchetypeQueryData for FilteredEntityMut<'_, '_> {}
unsafe impl<'a, 'b, B> WorldQuery for EntityRefExcept<'a, 'b, B>
where
B: Bundle,
{
type Fetch<'w> = EntityFetch<'w>;
type State = Access;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
EntityFetch {
world,
last_run,
this_run,
}
}
const IS_DENSE: bool = true;
unsafe fn set_archetype<'w, 's>(
_: &mut Self::Fetch<'w>,
_: &'s Self::State,
_: &'w Archetype,
_: &'w Table,
) {
}
unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {}
fn update_component_access(state: &Self::State, filtered_access: &mut FilteredAccess) {
let access = filtered_access.access_mut();
assert!(
access.is_compatible(state),
"`EntityRefExcept<{}>` conflicts with a previous access in this query.",
DebugName::type_name::<B>(),
);
access.extend(state);
}
fn init_state(world: &mut World) -> Self::State {
let mut access = Access::new();
access.read_all_components();
for id in B::component_ids(&mut world.components_registrator()) {
access.remove_component_read(id);
}
access
}
fn get_state(components: &Components) -> Option<Self::State> {
let mut access = Access::new();
access.read_all_components();
for id in B::get_component_ids(components).flatten() {
access.remove_component_read(id);
}
Some(access)
}
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
true
}
}
unsafe impl<'a, 'b, B> QueryData for EntityRefExcept<'a, 'b, B>
where
B: Bundle,
{
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = EntityRefExcept<'w, 's, B>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
unsafe fn fetch<'w, 's>(
access: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_: TableRow,
) -> Option<Self::Item<'w, 's>> {
let cell = fetch
.world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.unwrap();
Some(EntityRefExcept::new(cell, access))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Access(state))
}
}
unsafe impl<B> ReadOnlyQueryData for EntityRefExcept<'_, '_, B> where B: Bundle {}
impl<B: Bundle> ArchetypeQueryData for EntityRefExcept<'_, '_, B> {}
unsafe impl<'a, 'b, B> WorldQuery for EntityMutExcept<'a, 'b, B>
where
B: Bundle,
{
type Fetch<'w> = EntityFetch<'w>;
type State = Access;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_: &'s Self::State,
last_run: Tick,
this_run: Tick,
) -> Self::Fetch<'w> {
EntityFetch {
world,
last_run,
this_run,
}
}
const IS_DENSE: bool = true;
unsafe fn set_archetype<'w, 's>(
_: &mut Self::Fetch<'w>,
_: &'s Self::State,
_: &'w Archetype,
_: &'w Table,
) {
}
unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {}
fn update_component_access(state: &Self::State, filtered_access: &mut FilteredAccess) {
let access = filtered_access.access_mut();
assert!(
access.is_compatible(state),
"`EntityMutExcept<{}>` conflicts with a previous access in this query.",
DebugName::type_name::<B>()
);
access.extend(state);
}
fn init_state(world: &mut World) -> Self::State {
let mut access = Access::new();
access.write_all_components();
for id in B::component_ids(&mut world.components_registrator()) {
access.remove_component_read(id);
}
access
}
fn get_state(components: &Components) -> Option<Self::State> {
let mut access = Access::new();
access.write_all_components();
for id in B::get_component_ids(components).flatten() {
access.remove_component_read(id);
}
Some(access)
}
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
true
}
}
unsafe impl<'a, 'b, B> QueryData for EntityMutExcept<'a, 'b, B>
where
B: Bundle,
{
const IS_READ_ONLY: bool = false;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = EntityRefExcept<'a, 'b, B>;
type Item<'w, 's> = EntityMutExcept<'w, 's, B>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
unsafe fn fetch<'w, 's>(
access: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_: TableRow,
) -> Option<Self::Item<'w, 's>> {
let cell = fetch
.world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.unwrap();
Some(EntityMutExcept::new(cell, access))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Access(state))
}
}
impl<B: Bundle> ArchetypeQueryData for EntityMutExcept<'_, '_, B> {}
unsafe impl WorldQuery for &Archetype {
type Fetch<'w> = (&'w Entities, &'w Archetypes);
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
_last_run: Tick,
_this_run: Tick,
) -> Self::Fetch<'w> {
(world.entities(), world.archetypes())
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {}
fn init_state(_world: &mut World) {}
fn get_state(_components: &Components) -> Option<()> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl QueryData for &Archetype {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = &'w Archetype;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
let (entities, archetypes) = *fetch;
let location = unsafe { entities.get_spawned(entity).debug_checked_unwrap() };
Some(unsafe { archetypes.get(location.archetype_id).debug_checked_unwrap() })
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl ReadOnlyQueryData for &Archetype {}
impl ReleaseStateQueryData for &Archetype {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl ArchetypeQueryData for &Archetype {}
pub struct ReadFetch<'w, T: Component> {
components: StorageSwitch<
T,
Option<ThinSlicePtr<'w, UnsafeCell<T>>>,
Option<&'w ComponentSparseSet>,
>,
}
impl<T: Component> Clone for ReadFetch<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Component> Copy for ReadFetch<'_, T> {}
unsafe impl<T: Component> WorldQuery for &T {
type Fetch<'w> = ReadFetch<'w, T>;
type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
#[inline]
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
&component_id: &ComponentId,
_last_run: Tick,
_this_run: Tick,
) -> ReadFetch<'w, T> {
ReadFetch {
components: StorageSwitch::new(
|| None,
|| {
unsafe { world.storages().sparse_sets.get(component_id) }
},
),
}
}
const IS_DENSE: bool = {
match T::STORAGE_TYPE {
StorageType::Table => true,
StorageType::SparseSet => false,
}
};
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut ReadFetch<'w, T>,
component_id: &ComponentId,
_archetype: &'w Archetype,
table: &'w Table,
) {
if Self::IS_DENSE {
unsafe {
Self::set_table(fetch, component_id, table);
}
}
}
#[inline]
unsafe fn set_table<'w>(
fetch: &mut ReadFetch<'w, T>,
&component_id: &ComponentId,
table: &'w Table,
) {
let table_data = Some(
table
.get_data_slice_for(component_id)
.debug_checked_unwrap()
.into(),
);
unsafe { fetch.components.set_table(table_data) };
}
fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
assert!(
!access.access().has_component_write(component_id),
"&{} conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
DebugName::type_name::<T>(),
);
access.add_component_read(component_id);
}
fn init_state(world: &mut World) -> ComponentId {
world.register_component::<T>()
}
fn get_state(components: &Components) -> Option<Self::State> {
components.component_id::<T>()
}
fn matches_component_set(
&state: &ComponentId,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
set_contains_id(state)
}
}
unsafe impl<T: Component> QueryData for &T {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = &'w T;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(fetch.components.extract(
|table| {
let table = unsafe { table.debug_checked_unwrap() };
let item = unsafe { table.get_unchecked(table_row.index()) };
item.deref()
},
|sparse_set| {
let item = unsafe {
sparse_set
.debug_checked_unwrap()
.get(entity)
.debug_checked_unwrap()
};
item.deref()
},
))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Component(EcsAccessLevel::Read(*state)))
}
}
impl<T: Component> ContiguousQueryData for &T {
type Contiguous<'w, 's> = &'w [T];
unsafe fn fetch_contiguous<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
fetch.components.extract(
|table| {
let table = unsafe { table.debug_checked_unwrap() };
unsafe { table.cast().as_slice_unchecked(entities.len()) }
},
|_| {
#[cfg(debug_assertions)]
unreachable!();
#[cfg(not(debug_assertions))]
core::hint::unreachable_unchecked();
},
)
}
}
unsafe impl<T: Component> ReadOnlyQueryData for &T {}
impl<T: Component> ReleaseStateQueryData for &T {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl<T: Component> ArchetypeQueryData for &T {}
#[doc(hidden)]
pub struct RefFetch<'w, T: Component> {
components: StorageSwitch<
T,
Option<(
ThinSlicePtr<'w, UnsafeCell<T>>,
ThinSlicePtr<'w, UnsafeCell<Tick>>,
ThinSlicePtr<'w, UnsafeCell<Tick>>,
MaybeLocation<ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>>,
)>,
Option<&'w ComponentSparseSet>,
>,
last_run: Tick,
this_run: Tick,
}
impl<T: Component> Clone for RefFetch<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Component> Copy for RefFetch<'_, T> {}
unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
type Fetch<'w> = RefFetch<'w, T>;
type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
#[inline]
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
&component_id: &ComponentId,
last_run: Tick,
this_run: Tick,
) -> RefFetch<'w, T> {
RefFetch {
components: StorageSwitch::new(
|| None,
|| {
unsafe { world.storages().sparse_sets.get(component_id) }
},
),
last_run,
this_run,
}
}
const IS_DENSE: bool = {
match T::STORAGE_TYPE {
StorageType::Table => true,
StorageType::SparseSet => false,
}
};
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut RefFetch<'w, T>,
component_id: &ComponentId,
_archetype: &'w Archetype,
table: &'w Table,
) {
if Self::IS_DENSE {
unsafe {
Self::set_table(fetch, component_id, table);
}
}
}
#[inline]
unsafe fn set_table<'w>(
fetch: &mut RefFetch<'w, T>,
&component_id: &ComponentId,
table: &'w Table,
) {
let column = table.get_column(component_id).debug_checked_unwrap();
let table_data = Some((
column.get_data_slice(table.entity_count() as usize).into(),
column
.get_added_ticks_slice(table.entity_count() as usize)
.into(),
column
.get_changed_ticks_slice(table.entity_count() as usize)
.into(),
column
.get_changed_by_slice(table.entity_count() as usize)
.map(Into::into),
));
unsafe { fetch.components.set_table(table_data) };
}
fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
assert!(
!access.access().has_component_write(component_id),
"&{} conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
DebugName::type_name::<T>(),
);
access.add_component_read(component_id);
}
fn init_state(world: &mut World) -> ComponentId {
world.register_component::<T>()
}
fn get_state(components: &Components) -> Option<Self::State> {
components.component_id::<T>()
}
fn matches_component_set(
&state: &ComponentId,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
set_contains_id(state)
}
}
unsafe impl<'__w, T: Component> QueryData for Ref<'__w, T> {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = Ref<'w, T>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(fetch.components.extract(
|table| {
let (table_components, added_ticks, changed_ticks, callers) =
unsafe { table.debug_checked_unwrap() };
let component = unsafe { table_components.get_unchecked(table_row.index()) };
let added = unsafe { added_ticks.get_unchecked(table_row.index()) };
let changed = unsafe { changed_ticks.get_unchecked(table_row.index()) };
let caller =
callers.map(|callers| unsafe { callers.get_unchecked(table_row.index()) });
Ref {
value: component.deref(),
ticks: ComponentTicksRef {
added: added.deref(),
changed: changed.deref(),
changed_by: caller.map(|caller| caller.deref()),
this_run: fetch.this_run,
last_run: fetch.last_run,
},
}
},
|sparse_set| {
let (component, ticks) = unsafe {
sparse_set
.debug_checked_unwrap()
.get_with_ticks(entity)
.debug_checked_unwrap()
};
Ref {
value: component.deref(),
ticks: ComponentTicksRef::from_tick_cells(
ticks,
fetch.last_run,
fetch.this_run,
),
}
},
))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Component(EcsAccessLevel::Read(*state)))
}
}
unsafe impl<'__w, T: Component> ReadOnlyQueryData for Ref<'__w, T> {}
impl<T: Component> ReleaseStateQueryData for Ref<'_, T> {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl<T: Component> ArchetypeQueryData for Ref<'_, T> {}
impl<T: Component> ContiguousQueryData for Ref<'_, T> {
type Contiguous<'w, 's> = ContiguousRef<'w, T>;
unsafe fn fetch_contiguous<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
fetch.components.extract(
|table| {
let (table_components, added_ticks, changed_ticks, callers) =
unsafe { table.debug_checked_unwrap() };
ContiguousRef {
value: unsafe { table_components.cast().as_slice_unchecked(entities.len()) },
ticks: unsafe {
ContiguousComponentTicksRef::from_slice_ptrs(
added_ticks,
changed_ticks,
callers,
entities.len(),
fetch.this_run,
fetch.last_run,
)
},
}
},
|_| {
#[cfg(debug_assertions)]
unreachable!();
#[cfg(not(debug_assertions))]
core::hint::unreachable_unchecked();
},
)
}
}
pub struct WriteFetch<'w, T: Component> {
components: StorageSwitch<
T,
Option<(
ThinSlicePtr<'w, UnsafeCell<T>>,
ThinSlicePtr<'w, UnsafeCell<Tick>>,
ThinSlicePtr<'w, UnsafeCell<Tick>>,
MaybeLocation<ThinSlicePtr<'w, UnsafeCell<&'static Location<'static>>>>,
)>,
Option<&'w ComponentSparseSet>,
>,
last_run: Tick,
this_run: Tick,
}
impl<T: Component> Clone for WriteFetch<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T: Component> Copy for WriteFetch<'_, T> {}
unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
type Fetch<'w> = WriteFetch<'w, T>;
type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
#[inline]
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
&component_id: &ComponentId,
last_run: Tick,
this_run: Tick,
) -> WriteFetch<'w, T> {
WriteFetch {
components: StorageSwitch::new(
|| None,
|| {
unsafe { world.storages().sparse_sets.get(component_id) }
},
),
last_run,
this_run,
}
}
const IS_DENSE: bool = {
match T::STORAGE_TYPE {
StorageType::Table => true,
StorageType::SparseSet => false,
}
};
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut WriteFetch<'w, T>,
component_id: &ComponentId,
_archetype: &'w Archetype,
table: &'w Table,
) {
if Self::IS_DENSE {
unsafe {
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();
let table_data = Some((
column.get_data_slice(table.entity_count() as usize).into(),
column
.get_added_ticks_slice(table.entity_count() as usize)
.into(),
column
.get_changed_ticks_slice(table.entity_count() as usize)
.into(),
column
.get_changed_by_slice(table.entity_count() as usize)
.map(Into::into),
));
unsafe { fetch.components.set_table(table_data) };
}
fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
assert!(
!access.access().has_component_read(component_id),
"&mut {} conflicts with a previous access in this query. Mutable component access must be unique.",
DebugName::type_name::<T>(),
);
access.add_component_write(component_id);
}
fn init_state(world: &mut World) -> ComponentId {
world.register_component::<T>()
}
fn get_state(components: &Components) -> Option<Self::State> {
components.component_id::<T>()
}
fn matches_component_set(
&state: &ComponentId,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
set_contains_id(state)
}
}
unsafe impl<'__w, T: Component<Mutability = Mutable>> QueryData for &'__w mut T {
const IS_READ_ONLY: bool = false;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = &'__w T;
type Item<'w, 's> = Mut<'w, T>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(fetch.components.extract(
|table| {
let (table_components, added_ticks, changed_ticks, callers) =
unsafe { table.debug_checked_unwrap() };
let component = unsafe { table_components.get_unchecked(table_row.index()) };
let added = unsafe { added_ticks.get_unchecked(table_row.index()) };
let changed = unsafe { changed_ticks.get_unchecked(table_row.index()) };
let caller =
callers.map(|callers| unsafe { callers.get_unchecked(table_row.index()) });
Mut {
value: component.deref_mut(),
ticks: ComponentTicksMut {
added: added.deref_mut(),
changed: changed.deref_mut(),
changed_by: caller.map(|caller| caller.deref_mut()),
this_run: fetch.this_run,
last_run: fetch.last_run,
},
}
},
|sparse_set| {
let (component, ticks) = unsafe {
sparse_set
.debug_checked_unwrap()
.get_with_ticks(entity)
.debug_checked_unwrap()
};
Mut {
value: component.assert_unique().deref_mut(),
ticks: ComponentTicksMut::from_tick_cells(
ticks,
fetch.last_run,
fetch.this_run,
),
}
},
))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Component(EcsAccessLevel::Write(*state)))
}
}
impl<T: Component<Mutability = Mutable>> ReleaseStateQueryData for &mut T {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl<T: Component<Mutability = Mutable>> ArchetypeQueryData for &mut T {}
impl<T: Component<Mutability = Mutable>> ContiguousQueryData for &mut T {
type Contiguous<'w, 's> = ContiguousMut<'w, T>;
unsafe fn fetch_contiguous<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
fetch.components.extract(
|table| {
let (table_components, added_ticks, changed_ticks, callers) =
unsafe { table.debug_checked_unwrap() };
ContiguousMut {
value: unsafe { table_components.as_mut_slice_unchecked(entities.len()) },
ticks: unsafe {
ContiguousComponentTicksMut::from_slice_ptrs(
added_ticks,
changed_ticks,
callers,
entities.len(),
fetch.this_run,
fetch.last_run,
)
},
}
},
|_| {
#[cfg(debug_assertions)]
unreachable!();
#[cfg(not(debug_assertions))]
core::hint::unreachable_unchecked();
},
)
}
}
unsafe impl<'__w, T: Component> WorldQuery for Mut<'__w, T> {
type Fetch<'w> = WriteFetch<'w, T>;
type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
#[inline]
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
state: &ComponentId,
last_run: Tick,
this_run: Tick,
) -> WriteFetch<'w, T> {
<&mut T as WorldQuery>::init_fetch(world, state, last_run, this_run)
}
const IS_DENSE: bool = <&mut T as WorldQuery>::IS_DENSE;
#[inline]
unsafe fn set_archetype<'w>(
fetch: &mut WriteFetch<'w, T>,
state: &ComponentId,
archetype: &'w Archetype,
table: &'w Table,
) {
<&mut T as WorldQuery>::set_archetype(fetch, state, archetype, table);
}
#[inline]
unsafe fn set_table<'w>(fetch: &mut WriteFetch<'w, T>, state: &ComponentId, table: &'w Table) {
<&mut T as WorldQuery>::set_table(fetch, state, table);
}
fn update_component_access(&component_id: &ComponentId, access: &mut FilteredAccess) {
assert!(
!access.access().has_component_read(component_id),
"Mut<{}> conflicts with a previous access in this query. Mutable component access mut be unique.",
DebugName::type_name::<T>(),
);
access.add_component_write(component_id);
}
fn init_state(world: &mut World) -> ComponentId {
<&mut T as WorldQuery>::init_state(world)
}
fn get_state(components: &Components) -> Option<ComponentId> {
<&mut T as WorldQuery>::get_state(components)
}
fn matches_component_set(
state: &ComponentId,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
<&mut T as WorldQuery>::matches_component_set(state, set_contains_id)
}
}
unsafe impl<'__w, T: Component<Mutability = Mutable>> QueryData for Mut<'__w, T> {
const IS_READ_ONLY: bool = false;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Ref<'__w, T>;
type Item<'w, 's> = Mut<'w, T>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
<&mut T as QueryData>::shrink(item)
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
<&mut T as QueryData>::fetch(state, fetch, entity, table_row)
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::once(EcsAccessType::Component(EcsAccessLevel::Write(*state)))
}
}
impl<T: Component<Mutability = Mutable>> ReleaseStateQueryData for Mut<'_, T> {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl<T: Component<Mutability = Mutable>> ArchetypeQueryData for Mut<'_, T> {}
impl<'__w, T: Component<Mutability = Mutable>> ContiguousQueryData for Mut<'__w, T> {
type Contiguous<'w, 's> = ContiguousMut<'w, T>;
unsafe fn fetch_contiguous<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
<&mut T as ContiguousQueryData>::fetch_contiguous(state, fetch, entities)
}
}
#[doc(hidden)]
pub struct OptionFetch<'w, T: WorldQuery> {
fetch: T::Fetch<'w>,
matches: bool,
}
impl<T: WorldQuery> Clone for OptionFetch<'_, T> {
fn clone(&self) -> Self {
Self {
fetch: self.fetch.clone(),
matches: self.matches,
}
}
}
unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
type Fetch<'w> = OptionFetch<'w, T>;
type State = T::State;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
OptionFetch {
fetch: T::shrink_fetch(fetch.fetch),
matches: fetch.matches,
}
}
#[inline]
unsafe fn init_fetch<'w, 's>(
world: UnsafeWorldCell<'w>,
state: &'s T::State,
last_run: Tick,
this_run: Tick,
) -> OptionFetch<'w, T> {
OptionFetch {
fetch: unsafe { T::init_fetch(world, state, last_run, this_run) },
matches: false,
}
}
const IS_DENSE: bool = T::IS_DENSE;
#[inline]
unsafe fn set_archetype<'w, 's>(
fetch: &mut OptionFetch<'w, T>,
state: &'s T::State,
archetype: &'w Archetype,
table: &'w Table,
) {
fetch.matches = T::matches_component_set(state, &|id| archetype.contains(id));
if fetch.matches {
unsafe {
T::set_archetype(&mut fetch.fetch, state, archetype, table);
}
}
}
#[inline]
unsafe fn set_table<'w, 's>(
fetch: &mut OptionFetch<'w, T>,
state: &'s T::State,
table: &'w Table,
) {
fetch.matches = T::matches_component_set(state, &|id| table.has_column(id));
if fetch.matches {
unsafe {
T::set_table(&mut fetch.fetch, state, table);
}
}
}
fn update_component_access(state: &T::State, access: &mut FilteredAccess) {
let mut intermediate = access.clone();
T::update_component_access(state, &mut intermediate);
access.extend_access(&intermediate);
}
fn init_state(world: &mut World) -> T::State {
T::init_state(world)
}
fn get_state(components: &Components) -> Option<Self::State> {
T::get_state(components)
}
fn matches_component_set(
_state: &T::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<T: QueryData> QueryData for Option<T> {
const IS_READ_ONLY: bool = T::IS_READ_ONLY;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Option<T::ReadOnly>;
type Item<'w, 's> = Option<T::Item<'w, 's>>;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item.map(T::shrink)
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(
fetch
.matches
.then(|| unsafe { T::fetch(state, &mut fetch.fetch, entity, table_row) })
.flatten(),
)
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
T::iter_access(state)
}
}
unsafe impl<T: ReadOnlyQueryData> ReadOnlyQueryData for Option<T> {}
impl<T: ReleaseStateQueryData> ReleaseStateQueryData for Option<T> {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item.map(T::release_state)
}
}
impl<T: QueryData> ArchetypeQueryData for Option<T> {}
impl<T: ContiguousQueryData> ContiguousQueryData for Option<T> {
type Contiguous<'w, 's> = Option<T::Contiguous<'w, 's>>;
unsafe fn fetch_contiguous<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
fetch
.matches
.then(|| unsafe { T::fetch_contiguous(state, &mut fetch.fetch, entities) })
}
}
pub struct Has<T>(PhantomData<T>);
impl<T> core::fmt::Debug for Has<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "Has<{}>", DebugName::type_name::<T>())
}
}
unsafe impl<T: Component> WorldQuery for Has<T> {
type Fetch<'w> = bool;
type State = ComponentId;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch
}
#[inline]
unsafe fn init_fetch<'w, 's>(
_world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
_last_run: Tick,
_this_run: Tick,
) -> Self::Fetch<'w> {
false
}
const IS_DENSE: bool = {
match T::STORAGE_TYPE {
StorageType::Table => true,
StorageType::SparseSet => false,
}
};
#[inline]
unsafe fn set_archetype<'w, 's>(
fetch: &mut Self::Fetch<'w>,
state: &'s Self::State,
archetype: &'w Archetype,
_table: &Table,
) {
*fetch = archetype.contains(*state);
}
#[inline]
unsafe fn set_table<'w, 's>(
fetch: &mut Self::Fetch<'w>,
state: &'s Self::State,
table: &'w Table,
) {
*fetch = table.has_column(*state);
}
fn update_component_access(&component_id: &Self::State, access: &mut FilteredAccess) {
access.access_mut().add_archetypal(component_id);
}
fn init_state(world: &mut World) -> ComponentId {
world.register_component::<T>()
}
fn get_state(components: &Components) -> Option<Self::State> {
components.component_id::<T>()
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<T: Component> QueryData for Has<T> {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = bool;
fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
item
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(*fetch)
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl<T: Component> ReadOnlyQueryData for Has<T> {}
impl<T: Component> ReleaseStateQueryData for Has<T> {
fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
item
}
}
impl<T: Component> ArchetypeQueryData for Has<T> {}
impl<T: Component> ContiguousQueryData for Has<T> {
type Contiguous<'w, 's> = bool;
unsafe fn fetch_contiguous<'w, 's>(
_state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
_entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
*fetch
}
}
pub struct AnyOf<T>(PhantomData<T>);
macro_rules! impl_tuple_query_data {
($(#[$meta:meta])* $(($name: ident, $item: ident, $state: ident)),*) => {
#[expect(
clippy::allow_attributes,
reason = "This is a tuple-related macro; as such the lints below may not always apply."
)]
#[allow(
non_snake_case,
reason = "The names of some variables are provided by the macro's caller, not by us."
)]
#[allow(
unused_variables,
reason = "Zero-length tuples won't use any of the parameters."
)]
#[allow(
clippy::unused_unit,
reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
)]
$(#[$meta])*
unsafe impl<$($name: QueryData),*> QueryData for ($($name,)*) {
const IS_READ_ONLY: bool = true $(&& $name::IS_READ_ONLY)*;
const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
type ReadOnly = ($($name::ReadOnly,)*);
type Item<'w, 's> = ($($name::Item<'w, 's>,)*);
fn shrink<'wlong: 'wshort, 'wshort, 's>(item: Self::Item<'wlong, 's>) -> Self::Item<'wshort, 's> {
let ($($name,)*) = item;
($(
$name::shrink($name),
)*)
}
#[inline]
fn provide_extra_access(
state: &mut Self::State,
access: &mut Access,
available_access: &Access,
) {
let ($($name,)*) = state;
$($name::provide_extra_access($name, access, available_access);)*
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entity: Entity,
table_row: TableRow
) -> Option<Self::Item<'w, 's>> {
let ($($state,)*) = state;
let ($($name,)*) = fetch;
Some(($(unsafe { $name::fetch($state, $name, entity, table_row) }?,)*))
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
let ($($name,)*) = state;
iter::empty()$(.chain($name::iter_access($name)))*
}
}
$(#[$meta])*
unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for ($($name,)*) {}
#[expect(
clippy::allow_attributes,
reason = "This is a tuple-related macro; as such the lints below may not always apply."
)]
#[allow(
clippy::unused_unit,
reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
)]
$(#[$meta])*
impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for ($($name,)*) {
fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
($($name::release_state($item),)*)
}
}
$(#[$meta])*
impl<$($name: ArchetypeQueryData),*> ArchetypeQueryData for ($($name,)*) {}
#[expect(
clippy::allow_attributes,
reason = "This is a tuple-related macro; as such the lints below may not always apply."
)]
#[allow(
non_snake_case,
reason = "The names of some variables are provided by the macro's caller, not by us."
)]
#[allow(
unused_variables,
reason = "Zero-length tuples won't use any of the parameters."
)]
#[allow(
clippy::unused_unit,
reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
)]
$(#[$meta])*
impl<$($name: ContiguousQueryData),*> ContiguousQueryData for ($($name,)*) {
type Contiguous<'w, 's> = ($($name::Contiguous::<'w, 's>,)*);
unsafe fn fetch_contiguous<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
let ($($state,)*) = state;
let ($($name,)*) = fetch;
($(unsafe {$name::fetch_contiguous($state, $name, entities)},)*)
}
}
};
}
macro_rules! impl_anytuple_fetch {
($(#[$meta:meta])* $(($name: ident, $state: ident, $item: ident)),*) => {
$(#[$meta])*
#[expect(
clippy::allow_attributes,
reason = "This is a tuple-related macro; as such the lints below may not always apply."
)]
#[allow(
non_snake_case,
reason = "The names of some variables are provided by the macro's caller, not by us."
)]
#[allow(
unused_variables,
reason = "Zero-length tuples won't use any of the parameters."
)]
#[allow(
clippy::unused_unit,
reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
)]
unsafe impl<$($name: WorldQuery),*> WorldQuery for AnyOf<($($name,)*)> {
type Fetch<'w> = ($(($name::Fetch<'w>, bool),)*);
type State = ($($name::State,)*);
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
let ($($name,)*) = fetch;
($(
($name::shrink_fetch($name.0), $name.1),
)*)
}
#[inline]
unsafe fn init_fetch<'w, 's>(_world: UnsafeWorldCell<'w>, state: &'s Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w> {
let ($($name,)*) = state;
($(( unsafe { $name::init_fetch(_world, $name, _last_run, _this_run) }, false),)*)
}
const IS_DENSE: bool = true $(&& $name::IS_DENSE)*;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s 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 {
unsafe { $name::set_archetype(&mut $name.0, $state, _archetype, _table); }
}
)*
}
#[inline]
unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w>, _state: &'s 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 {
unsafe { $name::set_table(&mut $name.0, $state, _table); }
}
)*
}
fn update_component_access(state: &Self::State, access: &mut FilteredAccess) {
let ($($name,)*) = state;
let mut _new_access = FilteredAccess::matches_nothing();
$(
let mut intermediate = access.clone();
$name::update_component_access($name, &mut intermediate);
_new_access.append_or(&intermediate);
)*
access.filter_sets = _new_access.filter_sets;
<($(Option<$name>,)*)>::update_component_access(state, access);
}
fn init_state(world: &mut World) -> Self::State {
($($name::init_state(world),)*)
}
fn get_state(components: &Components) -> Option<Self::State> {
Some(($($name::get_state(components)?,)*))
}
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))*
}
}
#[expect(
clippy::allow_attributes,
reason = "This is a tuple-related macro; as such the lints below may not always apply."
)]
#[allow(
non_snake_case,
reason = "The names of some variables are provided by the macro's caller, not by us."
)]
#[allow(
unused_variables,
reason = "Zero-length tuples won't use any of the parameters."
)]
#[allow(
clippy::unused_unit,
reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
)]
$(#[$meta])*
unsafe impl<$($name: QueryData),*> QueryData for AnyOf<($($name,)*)> {
const IS_READ_ONLY: bool = true $(&& $name::IS_READ_ONLY)*;
const IS_ARCHETYPAL: bool = true $(&& $name::IS_ARCHETYPAL)*;
type ReadOnly = AnyOf<($($name::ReadOnly,)*)>;
type Item<'w, 's> = ($(Option<$name::Item<'w, 's>>,)*);
fn shrink<'wlong: 'wshort, 'wshort, 's>(item: Self::Item<'wlong, 's>) -> Self::Item<'wshort, 's> {
let ($($name,)*) = item;
($(
$name.map($name::shrink),
)*)
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: TableRow
) -> Option<Self::Item<'w, 's>> {
let ($($name,)*) = _fetch;
let ($($state,)*) = _state;
let result = ($(
$name.1.then(|| unsafe { $name::fetch($state, &mut $name.0, _entity, _table_row) }).flatten(),
)*);
(Self::IS_ARCHETYPAL
|| !matches!(result, ($(Option::<QueryItem<$name>>::None,)*))
|| !(false $(|| $name.1)*))
.then_some(result)
}
fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
let ($($name,)*) = state;
iter::empty()$(.chain($name::iter_access($name)))*
}
}
$(#[$meta])*
unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for AnyOf<($($name,)*)> {}
#[expect(
clippy::allow_attributes,
reason = "This is a tuple-related macro; as such the lints below may not always apply."
)]
#[allow(
clippy::unused_unit,
reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
)]
impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for AnyOf<($($name,)*)> {
fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> {
($($item.map(|$item| $name::release_state($item)),)*)
}
}
$(#[$meta])*
impl<$($name: ArchetypeQueryData),*> ArchetypeQueryData for AnyOf<($($name,)*)> {}
#[expect(
clippy::allow_attributes,
reason = "This is a tuple-related macro; as such the lints below may not always apply."
)]
#[allow(
non_snake_case,
reason = "The names of some variables are provided by the macro's caller, not by us."
)]
#[allow(
unused_variables,
reason = "Zero-length tuples won't use any of the parameters."
)]
#[allow(
clippy::unused_unit,
reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
)]
$(#[$meta])*
impl<$($name: ContiguousQueryData),*> ContiguousQueryData for AnyOf<($($name,)*)> {
type Contiguous<'w, 's> = ($(Option<$name::Contiguous<'w,'s>>,)*);
unsafe fn fetch_contiguous<'w, 's>(
state: &'s Self::State,
fetch: &mut Self::Fetch<'w>,
entities: &'w [Entity],
) -> Self::Contiguous<'w, 's> {
let ($($name,)*) = fetch;
let ($($state,)*) = state;
($(
$name.1.then(|| unsafe { $name::fetch_contiguous($state, &mut $name.0, entities) }),
)*)
}
}
};
}
all_tuples!(
#[doc(fake_variadic)]
impl_tuple_query_data,
0,
15,
F,
i,
s
);
all_tuples!(
#[doc(fake_variadic)]
impl_anytuple_fetch,
0,
15,
F,
S,
i
);
pub(crate) struct NopWorldQuery<D: QueryData>(PhantomData<D>);
unsafe impl<D: QueryData> WorldQuery for NopWorldQuery<D> {
type Fetch<'w> = ();
type State = D::State;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
}
#[inline(always)]
unsafe fn init_fetch(
_world: UnsafeWorldCell,
_state: &D::State,
_last_run: Tick,
_this_run: Tick,
) {
}
const IS_DENSE: bool = D::IS_DENSE;
#[inline(always)]
unsafe fn set_archetype(
_fetch: &mut (),
_state: &D::State,
_archetype: &Archetype,
_tables: &Table,
) {
}
#[inline(always)]
unsafe fn set_table<'w>(_fetch: &mut (), _state: &D::State, _table: &Table) {}
fn update_component_access(_state: &D::State, _access: &mut FilteredAccess) {}
fn init_state(world: &mut World) -> Self::State {
D::init_state(world)
}
fn get_state(components: &Components) -> Option<Self::State> {
D::get_state(components)
}
fn matches_component_set(
state: &Self::State,
set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
D::matches_component_set(state, set_contains_id)
}
}
unsafe impl<D: QueryData> QueryData for NopWorldQuery<D> {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = ();
fn shrink<'wlong: 'wshort, 'wshort, 's>(
_item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(())
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl<D: QueryData> ReadOnlyQueryData for NopWorldQuery<D> {}
impl<D: QueryData> ReleaseStateQueryData for NopWorldQuery<D> {
fn release_state<'w>(_item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {}
}
impl<D: QueryData> ArchetypeQueryData for NopWorldQuery<D> {}
unsafe impl<T: ?Sized> WorldQuery for PhantomData<T> {
type Fetch<'w> = ();
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(_fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
}
unsafe fn init_fetch<'w, 's>(
_world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
_last_run: Tick,
_this_run: Tick,
) -> Self::Fetch<'w> {
}
const IS_DENSE: bool = true;
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &'w Table,
) {
}
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {}
fn init_state(_world: &mut World) -> Self::State {}
fn get_state(_components: &Components) -> Option<Self::State> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl<T: ?Sized> QueryData for PhantomData<T> {
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type ReadOnly = Self;
type Item<'w, 's> = ();
fn shrink<'wlong: 'wshort, 'wshort, 's>(
_item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
}
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(())
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl<T: ?Sized> ReadOnlyQueryData for PhantomData<T> {}
impl<T: ?Sized> ReleaseStateQueryData for PhantomData<T> {
fn release_state<'w>(_item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {}
}
impl<T: ?Sized> ArchetypeQueryData for PhantomData<T> {}
pub(super) union StorageSwitch<C: Component, T: Copy, S: Copy> {
table: T,
sparse_set: S,
_marker: PhantomData<C>,
}
impl<C: Component, T: Copy, S: Copy> StorageSwitch<C, T, S> {
pub fn new(table: impl FnOnce() -> T, sparse_set: impl FnOnce() -> S) -> Self {
match C::STORAGE_TYPE {
StorageType::Table => Self { table: table() },
StorageType::SparseSet => Self {
sparse_set: sparse_set(),
},
}
}
#[inline]
pub unsafe fn set_table(&mut self, table: T) {
match C::STORAGE_TYPE {
StorageType::Table => self.table = table,
_ => {
#[cfg(debug_assertions)]
unreachable!();
#[cfg(not(debug_assertions))]
core::hint::unreachable_unchecked()
}
}
}
pub fn extract<R>(&self, table: impl FnOnce(T) -> R, sparse_set: impl FnOnce(S) -> R) -> R {
match C::STORAGE_TYPE {
StorageType::Table => table(
unsafe { self.table },
),
StorageType::SparseSet => sparse_set(
unsafe { self.sparse_set },
),
}
}
}
impl<C: Component, T: Copy, S: Copy> Clone for StorageSwitch<C, T, S> {
fn clone(&self) -> Self {
*self
}
}
impl<C: Component, T: Copy, S: Copy> Copy for StorageSwitch<C, T, S> {}
#[cfg(test)]
mod tests {
use super::*;
use crate::change_detection::DetectChanges;
use crate::query::Without;
use crate::system::{assert_is_system, Query};
use bevy_ecs::prelude::Schedule;
use bevy_ecs_macros::QueryData;
#[derive(Component)]
pub struct A;
#[derive(Component)]
pub struct B;
#[test]
fn world_query_struct_variants() {
#[derive(QueryData)]
pub struct NamedQuery {
id: Entity,
a: &'static A,
}
#[derive(QueryData)]
pub struct TupleQuery(&'static A, &'static B);
#[derive(QueryData)]
pub struct UnitQuery;
fn my_system(_: Query<(NamedQuery, TupleQuery, UnitQuery)>) {}
assert_is_system(my_system);
}
#[test]
fn world_query_phantom_data() {
#[derive(QueryData)]
pub struct IgnoredQuery<Marker> {
id: Entity,
_marker: PhantomData<Marker>,
}
fn ignored_system(_: Query<IgnoredQuery<()>>) {}
assert_is_system(ignored_system);
}
#[test]
fn derive_release_state() {
struct NonReleaseQueryData;
unsafe impl WorldQuery for NonReleaseQueryData {
type Fetch<'w> = ();
type State = ();
fn shrink_fetch<'wlong: 'wshort, 'wshort>(
_: Self::Fetch<'wlong>,
) -> Self::Fetch<'wshort> {
}
unsafe fn init_fetch<'w, 's>(
_world: UnsafeWorldCell<'w>,
_state: &'s Self::State,
_last_run: Tick,
_this_run: Tick,
) -> Self::Fetch<'w> {
}
const IS_DENSE: bool = true;
#[inline]
unsafe fn set_archetype<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_archetype: &'w Archetype,
_table: &Table,
) {
}
#[inline]
unsafe fn set_table<'w, 's>(
_fetch: &mut Self::Fetch<'w>,
_state: &'s Self::State,
_table: &'w Table,
) {
}
fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {}
fn init_state(_world: &mut World) {}
fn get_state(_components: &Components) -> Option<()> {
Some(())
}
fn matches_component_set(
_state: &Self::State,
_set_contains_id: &impl Fn(ComponentId) -> bool,
) -> bool {
true
}
}
unsafe impl QueryData for NonReleaseQueryData {
type ReadOnly = Self;
const IS_READ_ONLY: bool = true;
const IS_ARCHETYPAL: bool = true;
type Item<'w, 's> = ();
fn shrink<'wlong: 'wshort, 'wshort, 's>(
_item: Self::Item<'wlong, 's>,
) -> Self::Item<'wshort, 's> {
}
#[inline(always)]
unsafe fn fetch<'w, 's>(
_state: &'s Self::State,
_fetch: &mut Self::Fetch<'w>,
_entity: Entity,
_table_row: TableRow,
) -> Option<Self::Item<'w, 's>> {
Some(())
}
fn iter_access(_state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
iter::empty()
}
}
unsafe impl ReadOnlyQueryData for NonReleaseQueryData {}
impl ArchetypeQueryData for NonReleaseQueryData {}
#[derive(QueryData)]
pub struct DerivedNonReleaseRead {
non_release: NonReleaseQueryData,
a: &'static A,
}
#[derive(QueryData)]
#[query_data(mutable)]
pub struct DerivedNonReleaseMutable {
non_release: NonReleaseQueryData,
a: &'static mut A,
}
#[derive(QueryData)]
pub struct DerivedReleaseRead {
a: &'static A,
}
#[derive(QueryData)]
#[query_data(mutable)]
pub struct DerivedReleaseMutable {
a: &'static mut A,
}
fn assert_is_release_state<Q: ReleaseStateQueryData>() {}
assert_is_release_state::<DerivedReleaseRead>();
assert_is_release_state::<DerivedReleaseMutable>();
}
#[test]
fn read_only_field_visibility() {
mod private {
use super::*;
#[derive(QueryData)]
#[query_data(mutable)]
pub struct D {
pub a: &'static mut A,
}
}
let _ = private::DReadOnly { a: &A };
fn my_system(query: Query<private::D>) {
for q in &query {
let _ = &q.a;
}
}
assert_is_system(my_system);
}
#[test]
fn world_query_metadata_collision() {
#[derive(QueryData)]
pub struct Client<S: ClientState> {
pub state: &'static S,
pub fetch: &'static ClientFetch,
}
pub trait ClientState: Component {}
#[derive(Component)]
pub struct ClientFetch;
#[derive(Component)]
pub struct C;
impl ClientState for C {}
fn client_system(_: Query<Client<C>>) {}
assert_is_system(client_system);
}
#[test]
fn test_entity_ref_query_with_ticks() {
#[derive(Component)]
pub struct C;
fn system(query: Query<EntityRef>) {
for entity_ref in &query {
if let Some(c) = entity_ref.get_ref::<C>()
&& !c.is_added()
{
panic!("Expected C to be added");
}
}
}
let mut world = World::new();
let mut schedule = Schedule::default();
schedule.add_systems(system);
world.spawn(C);
world.clear_trackers();
schedule.run(&mut world);
}
#[test]
fn test_contiguous_query_data() {
#[derive(Component, PartialEq, Eq, Debug)]
pub struct C(i32);
#[derive(Component, PartialEq, Eq, Debug)]
pub struct D(bool);
let mut world = World::new();
world.spawn((C(0), D(true)));
world.spawn((C(1), D(false)));
world.spawn(C(2));
let mut query = world.query::<(&C, &D)>();
let mut iter = query.contiguous_iter(&world).unwrap();
let c = iter.next().unwrap();
assert_eq!(c.0, [C(0), C(1)].as_slice());
assert_eq!(c.1, [D(true), D(false)].as_slice());
assert!(iter.next().is_none());
let mut query = world.query::<&C>();
let mut iter = query.contiguous_iter(&world).unwrap();
let mut present = [false; 3];
let mut len = 0;
for _ in 0..2 {
let c = iter.next().unwrap();
for c in c {
present[c.0 as usize] = true;
len += 1;
}
}
assert!(iter.next().is_none());
assert_eq!(len, 3);
assert_eq!(present, [true; 3]);
let mut query = world.query::<&mut C>();
let mut iter = query.contiguous_iter_mut(&mut world).unwrap();
for _ in 0..2 {
let c = iter.next().unwrap();
for c in c {
c.0 *= 2;
}
}
assert!(iter.next().is_none());
let mut iter = query.contiguous_iter(&world).unwrap();
let mut present = [false; 6];
let mut len = 0;
for _ in 0..2 {
let c = iter.next().unwrap();
for c in c {
present[c.0 as usize] = true;
len += 1;
}
}
assert_eq!(present, [true, false, true, false, true, false]);
assert_eq!(len, 3);
let mut query = world.query_filtered::<&C, Without<D>>();
let mut iter = query.contiguous_iter(&world).unwrap();
assert_eq!(iter.next().unwrap(), &[C(4)]);
assert!(iter.next().is_none());
}
#[test]
fn sparse_set_contiguous_query() {
#[derive(Component, Debug, PartialEq, Eq)]
#[component(storage = "SparseSet")]
pub struct S(i32);
let mut world = World::new();
world.spawn(S(0));
let mut query = world.query::<&mut S>();
let iter = query.contiguous_iter_mut(&mut world);
assert!(iter.is_none());
}
#[test]
fn any_of_contiguous_test() {
#[derive(Component, Debug, Clone, Copy)]
pub struct C(i32);
#[derive(Component, Debug, Clone, Copy)]
pub struct D(i32);
let mut world = World::new();
world.spawn((C(0), D(1)));
world.spawn(C(2));
world.spawn(D(3));
world.spawn(());
let mut query = world.query::<AnyOf<(&C, &D)>>();
let iter = query.contiguous_iter(&world).unwrap();
let mut present = [false; 4];
for (c, d) in iter {
assert!(c.is_some() || d.is_some());
let c = c.unwrap_or_default();
let d = d.unwrap_or_default();
for i in 0..c.len().max(d.len()) {
let c = c.get(i).cloned();
let d = d.get(i).cloned();
if let Some(C(c)) = c {
assert!(!present[c as usize]);
present[c as usize] = true;
}
if let Some(D(d)) = d {
assert!(!present[d as usize]);
present[d as usize] = true;
}
}
}
assert_eq!(present, [true; 4]);
}
#[test]
fn option_contiguous_test() {
#[derive(Component, Clone, Copy)]
struct C(i32);
#[derive(Component, Clone, Copy)]
struct D(i32);
let mut world = World::new();
world.spawn((C(0), D(1)));
world.spawn(D(2));
world.spawn(C(3));
let mut query = world.query::<(Option<&C>, &D)>();
let iter = query.contiguous_iter(&world).unwrap();
let mut present = [false; 3];
for (c, d) in iter {
let c = c.unwrap_or_default();
for i in 0..d.len() {
let c = c.get(i).cloned();
let D(d) = d[i];
if let Some(C(c)) = c {
assert!(!present[c as usize]);
present[c as usize] = true;
}
assert!(!present[d as usize]);
present[d as usize] = true;
}
}
assert_eq!(present, [true; 3]);
}
}