use std::marker::PhantomData; use crate::{ComponentColumn, Tick, DynTypeId, world::World}; use super::{Query, Fetch, AsQuery}; #[derive(Clone, Copy, Debug, Default)] pub struct TickOf { tick: Tick, _phantom: PhantomData, } impl std::ops::Deref for TickOf { type Target = Tick; fn deref(&self) -> &Self::Target { &self.tick } } /// Fetcher for borrowing components from archetypes. pub struct FetchTickOf<'a, T> { col: &'a ComponentColumn, _phantom: PhantomData<&'a T> } impl<'a, T> Fetch<'a> for FetchTickOf<'a, T> where T: 'a, { type Item = Tick; fn dangling() -> Self { unreachable!() } unsafe fn get_item(&mut self, entity: crate::world::ArchetypeEntityId) -> Self::Item { self.col.entity_ticks[entity.0 as usize] } } /// A Query for borrowing components from archetypes. /// /// Since [`AsQuery`] is implemented for `&T`, you can use this query like this: /// ```nobuild /// for ts in world.view::<&T>() { /// println!("Got a &T!"); /// } /// ``` pub struct QueryTickOf { type_id: DynTypeId, _phantom: PhantomData } // manually implemented to avoid a Copy bound on T impl Copy for QueryTickOf {} // manually implemented to avoid a Clone bound on T impl Clone for QueryTickOf { fn clone(&self) -> Self { *self } } impl QueryTickOf { pub fn new() -> Self { Self { type_id: DynTypeId::of::(), _phantom: PhantomData, } } } impl Query for QueryTickOf where T: 'static { type Item<'a> = Tick; type Fetch<'a> = FetchTickOf<'a, T>; fn new() -> Self { QueryTickOf::::new() } fn can_visit_archetype(&self, archetype: &crate::archetype::Archetype) -> bool { archetype.columns.iter().any(|c| c.info.type_id == self.type_id) } unsafe fn fetch<'a>(&self, _world: &'a World, archetype: &'a crate::archetype::Archetype, _tick: crate::Tick) -> Self::Fetch<'a> { let col = archetype.columns.iter().find(|c| c.info.type_id == self.type_id) .expect("You ignored 'can_visit_archetype'!"); FetchTickOf { col, _phantom: PhantomData, } } } impl AsQuery for QueryTickOf { type Query = Self; } impl AsQuery for TickOf { type Query = QueryTickOf; }