use std::{marker::PhantomData, any::TypeId, ptr::NonNull, cell::Ref}; use crate::{world::World, resource::ResourceObject}; use super::{Query, Fetch, AsQuery}; pub struct FetchResource<'a, T> { world: Option<&'a World>, _phantom: PhantomData, } impl<'a, T: 'a + 'static> Fetch<'a> for FetchResource<'a, T> { type Item = Ref<'a, T>; fn dangling() -> Self { Self { world: None, _phantom: PhantomData, } } fn can_visit_item(&mut self, _entity: crate::world::ArchetypeEntityId) -> bool { true } unsafe fn get_item(&mut self, _entity: crate::world::ArchetypeEntityId) -> Self::Item { let w = self.world.unwrap(); w.get_resource::() } } /// A query type for getting Resources /// /// Resources are stored in an archetype with the id of [`world::RESOURCE_ARCHETYPE_ID`]. There is only one instance of a type of resource. /// The resources are stored in that archetype in the first entity in the column. pub struct QueryResource { _phantom: PhantomData } impl Copy for QueryResource {} impl Clone for QueryResource { fn clone(&self) -> Self { *self } } pub type Resource = QueryResource; impl Query for QueryResource { type Item<'a> = Ref<'a, T>; type Fetch<'a> = FetchResource<'a, T>; const ALWAYS_FETCHES: bool = true; fn new() -> Self { QueryResource:: { _phantom: PhantomData } } fn can_visit_archetype(&self, _archetype: &crate::archetype::Archetype) -> bool { true } unsafe fn fetch<'a>(&self, world: &'a World, _arch_id: crate::archetype::ArchetypeId, _archetype: &'a crate::archetype::Archetype) -> Self::Fetch<'a> { self.fetch_world(world).unwrap() } unsafe fn fetch_world<'a>(&self, world: &'a World) -> Option> { Some(FetchResource { world: Some(world), _phantom: PhantomData, }) } } impl AsQuery for QueryResource { type Query = QueryResource; } #[cfg(test)] mod tests { use crate::{world::World, tests::{Vec2, Vec3}}; use super::QueryResource; struct SomeCounter(u32); #[test] fn simple_query() { let mut world = World::new(); { let counter = SomeCounter(0); world.add_resource(counter); println!("Added resource"); } let mut res_iter = world.view::>(); let res = res_iter.next().unwrap(); assert_eq!(res.0, 0); } #[test] fn complex_query() { let mut world = World::new(); { let counter = SomeCounter(0); world.spawn((Vec2::rand(),)); world.spawn((Vec2::rand(),)); world.spawn((Vec2::rand(),)); world.spawn((Vec3::rand(),)); world.add_resource(counter); println!("Added resource"); } let i = world.view::<(QueryResource, &Vec2)>(); assert_eq!(i.count(), 3); let i = world.view::<(&Vec2, QueryResource)>(); assert_eq!(i.count(), 3); for (res, e) in world.view::<(QueryResource, &Vec2)>() { println!("Got res {}! and entity at {:?}", res.0, e); } let i = world.view::>(); assert_eq!(i.count(), 1); } }