use std::{any::type_name, marker::PhantomData};
use crate::{
Component, ComponentId, Entity, FilteredAccess, ReadOnlyWorldQuery, Storage, StorageSet, World,
WorldQuery,
};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct With<T> {
_marker: PhantomData<T>,
}
unsafe impl<T: Component> WorldQuery for With<T> {
type Item<'w> = ();
type Fetch<'w> = ();
type State = ComponentId;
type ReadOnly = Self;
unsafe fn init_fetch<'w>(
_world: &'w World,
_state: &Self::State,
_last_change_tick: u32,
_change_tick: u32,
) -> Self::Fetch<'w> {
}
unsafe fn fetch<'w>(_fetch: &mut Self::Fetch<'w>, _entity: Entity) -> Self::Item<'w> {}
fn init_state(world: &mut World) -> Self::State {
world.init_component::<T>()
}
fn update_component_access(&state: &Self::State, access: &mut FilteredAccess<ComponentId>) {
access.add_with(state);
}
}
unsafe impl<T: Component> ReadOnlyWorldQuery for With<T> {}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Without<T> {
_marker: PhantomData<T>,
}
unsafe impl<T: Component> WorldQuery for Without<T> {
type Item<'w> = ();
type Fetch<'w> = ();
type State = ComponentId;
type ReadOnly = Self;
unsafe fn init_fetch<'w>(
_world: &'w World,
_state: &Self::State,
_last_change_tick: u32,
_change_tick: u32,
) -> Self::Fetch<'w> {
}
unsafe fn fetch<'w>(_fetch: &mut Self::Fetch<'w>, _entity: Entity) -> Self::Item<'w> {}
fn init_state(world: &mut World) -> Self::State {
world.init_component::<T>()
}
fn update_component_access(&state: &Self::State, access: &mut FilteredAccess<ComponentId>) {
access.add_without(state);
}
}
unsafe impl<T: Component> ReadOnlyWorldQuery for Without<T> {}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Added<T> {
_marker: PhantomData<T>,
}
pub struct AddedFetch<'w, T: Component> {
storage: &'w T::Storage,
last_change_tick: u32,
change_tick: u32,
}
unsafe impl<T: Component> WorldQuery for Added<T> {
type Item<'w> = bool;
type Fetch<'w> = AddedFetch<'w, T>;
type State = ComponentId;
type ReadOnly = Self;
unsafe fn init_fetch<'w>(
world: &'w World,
&state: &Self::State,
last_change_tick: u32,
change_tick: u32,
) -> Self::Fetch<'w> {
let storage_sets = <T::Storage as Storage>::get(&world.storage);
let storage = unsafe { storage_sets.get_unchecked(state) };
AddedFetch {
storage,
last_change_tick,
change_tick,
}
}
unsafe fn fetch<'w>(fetch: &mut Self::Fetch<'w>, entity: Entity) -> Self::Item<'w> {
let ticks = unsafe { fetch.storage.get_ticks_unchecked(entity) };
let ticks = unsafe { &*ticks.get() };
ticks.is_changed(fetch.last_change_tick, fetch.change_tick)
}
unsafe fn filter_fetch<'w>(fetch: &mut Self::Fetch<'w>, entity: Entity) -> bool {
unsafe { Self::fetch(fetch, entity) }
}
fn init_state(world: &mut World) -> Self::State {
world.init_component::<T>()
}
fn update_component_access(&state: &Self::State, access: &mut FilteredAccess<ComponentId>) {
assert!(
!access.has_write(state),
"&{} conflicts with previous access in this query. Shared access cannot coexist with exclusive access.",
type_name::<T>(),
);
access.add_read(state);
}
}
unsafe impl<T: Component> ReadOnlyWorldQuery for Added<T> {}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Changed<T> {
_marker: PhantomData<T>,
}
pub struct ChangedFetch<'w, T: Component> {
storage: &'w T::Storage,
last_change_tick: u32,
change_tick: u32,
}
unsafe impl<T: Component> WorldQuery for Changed<T> {
type Item<'w> = bool;
type Fetch<'w> = ChangedFetch<'w, T>;
type State = ComponentId;
type ReadOnly = Self;
unsafe fn init_fetch<'w>(
world: &'w World,
&state: &Self::State,
last_change_tick: u32,
change_tick: u32,
) -> Self::Fetch<'w> {
let storage_sets = <T::Storage as Storage>::get(&world.storage);
let storage = unsafe { storage_sets.get_unchecked(state) };
ChangedFetch {
storage,
last_change_tick,
change_tick,
}
}
unsafe fn fetch<'w>(fetch: &mut Self::Fetch<'w>, entity: Entity) -> Self::Item<'w> {
let ticks = unsafe { fetch.storage.get_ticks_unchecked(entity) };
let ticks = unsafe { &*ticks.get() };
ticks.is_changed(fetch.last_change_tick, fetch.change_tick)
}
unsafe fn filter_fetch<'w>(fetch: &mut Self::Fetch<'w>, entity: Entity) -> bool {
unsafe { Self::fetch(fetch, entity) }
}
fn init_state(world: &mut World) -> Self::State {
world.init_component::<T>()
}
fn update_component_access(&state: &Self::State, access: &mut FilteredAccess<ComponentId>) {
assert!(
!access.has_write(state),
"&{} conflicts with previous access in this query. Shared access cannot coexist with exclusive access.",
type_name::<T>(),
);
access.add_read(state);
}
}
unsafe impl<T: Component> ReadOnlyWorldQuery for Changed<T> {}