2023-12-28 03:53:58 +00:00
|
|
|
use std::{marker::PhantomData, cell::{Ref, RefMut}};
|
2023-12-01 04:05:06 +00:00
|
|
|
|
|
|
|
use crate::{world::World, resource::ResourceObject};
|
|
|
|
|
2023-12-04 04:14:27 +00:00
|
|
|
use super::{Query, Fetch, AsQuery};
|
2023-12-01 04:05:06 +00:00
|
|
|
|
|
|
|
pub struct FetchResource<'a, T> {
|
|
|
|
world: Option<&'a World>,
|
|
|
|
_phantom: PhantomData<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: 'a + 'static> Fetch<'a> for FetchResource<'a, T> {
|
2024-01-05 01:49:27 +00:00
|
|
|
type Item = Res<'a, T>;
|
2023-12-01 04:05:06 +00:00
|
|
|
|
|
|
|
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();
|
2024-01-05 01:49:27 +00:00
|
|
|
Res(w.get_resource::<T>())
|
2023-12-01 04:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-12-06 04:22:48 +00:00
|
|
|
/// A query type for borrowing Resources.
|
2023-12-04 04:14:27 +00:00
|
|
|
pub struct QueryResource<T: ResourceObject> {
|
2023-12-01 04:05:06 +00:00
|
|
|
_phantom: PhantomData<T>
|
|
|
|
}
|
2024-01-05 01:49:27 +00:00
|
|
|
//pub type Resource<T> = QueryResource<T>;
|
2023-12-01 04:05:06 +00:00
|
|
|
|
2023-12-04 04:14:27 +00:00
|
|
|
impl<T: ResourceObject> Copy for QueryResource<T> {}
|
|
|
|
|
|
|
|
impl<T: ResourceObject> Clone for QueryResource<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ResourceObject + 'static> Query for QueryResource<T> {
|
2024-01-05 01:49:27 +00:00
|
|
|
type Item<'a> = Res<'a, T>;
|
2023-12-01 04:05:06 +00:00
|
|
|
|
|
|
|
type Fetch<'a> = FetchResource<'a, T>;
|
|
|
|
|
|
|
|
const ALWAYS_FETCHES: bool = true;
|
|
|
|
|
2023-12-04 04:14:27 +00:00
|
|
|
fn new() -> Self {
|
|
|
|
QueryResource::<T> {
|
|
|
|
_phantom: PhantomData
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-01 04:05:06 +00:00
|
|
|
fn can_visit_archetype(&self, _archetype: &crate::archetype::Archetype) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2023-12-26 19:12:53 +00:00
|
|
|
unsafe fn fetch<'a>(&self, world: &'a World, _archetype: &'a crate::archetype::Archetype, tick: crate::Tick) -> Self::Fetch<'a> {
|
2023-12-28 03:53:58 +00:00
|
|
|
let _ = tick;
|
2023-12-01 04:05:06 +00:00
|
|
|
self.fetch_world(world).unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn fetch_world<'a>(&self, world: &'a World) -> Option<Self::Fetch<'a>> {
|
|
|
|
Some(FetchResource {
|
|
|
|
world: Some(world),
|
|
|
|
_phantom: PhantomData,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R: ResourceObject> AsQuery for QueryResource<R> {
|
|
|
|
type Query = QueryResource<R>;
|
|
|
|
}
|
2023-12-06 04:22:48 +00:00
|
|
|
|
2024-01-05 01:49:27 +00:00
|
|
|
/// A struct used for querying resources from the World.
|
2024-01-07 02:38:21 +00:00
|
|
|
pub struct Res<'a, T>(pub(crate) Ref<'a, T>);
|
2024-01-05 01:49:27 +00:00
|
|
|
|
|
|
|
impl<'a, T: ResourceObject> std::ops::Deref for Res<'a, T> {
|
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
self.0.deref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: ResourceObject> AsQuery for Res<'a, T> {
|
|
|
|
type Query = QueryResource<T>;
|
|
|
|
}
|
|
|
|
|
2023-12-06 04:22:48 +00:00
|
|
|
pub struct FetchResourceMut<'a, T> {
|
|
|
|
world: Option<&'a World>,
|
|
|
|
_phantom: PhantomData<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: 'a + 'static> Fetch<'a> for FetchResourceMut<'a, T> {
|
2024-01-05 01:49:27 +00:00
|
|
|
type Item = ResMut<'a, T>;
|
2023-12-06 04:22:48 +00:00
|
|
|
|
|
|
|
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();
|
2024-01-05 01:49:27 +00:00
|
|
|
ResMut(w.get_resource_mut::<T>())
|
2023-12-06 04:22:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A query type for borrowing Resources mutably.
|
|
|
|
pub struct QueryResourceMut<T: ResourceObject> {
|
|
|
|
_phantom: PhantomData<T>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ResourceObject> Copy for QueryResourceMut<T> {}
|
|
|
|
|
|
|
|
impl<T: ResourceObject> Clone for QueryResourceMut<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
*self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ResourceObject + 'static> Query for QueryResourceMut<T> {
|
2024-01-05 01:49:27 +00:00
|
|
|
type Item<'a> = ResMut<'a, T>;
|
2023-12-06 04:22:48 +00:00
|
|
|
|
|
|
|
type Fetch<'a> = FetchResourceMut<'a, T>;
|
|
|
|
|
|
|
|
const ALWAYS_FETCHES: bool = true;
|
|
|
|
|
|
|
|
fn new() -> Self {
|
|
|
|
QueryResourceMut::<T> {
|
|
|
|
_phantom: PhantomData
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn can_visit_archetype(&self, _archetype: &crate::archetype::Archetype) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
2023-12-26 19:12:53 +00:00
|
|
|
unsafe fn fetch<'a>(&self, world: &'a World, _archetype: &'a crate::archetype::Archetype, tick: crate::Tick) -> Self::Fetch<'a> {
|
2023-12-28 03:53:58 +00:00
|
|
|
let _ = tick;
|
2023-12-06 04:22:48 +00:00
|
|
|
self.fetch_world(world).unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn fetch_world<'a>(&self, world: &'a World) -> Option<Self::Fetch<'a>> {
|
|
|
|
Some(FetchResourceMut {
|
|
|
|
world: Some(world),
|
|
|
|
_phantom: PhantomData,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R: ResourceObject> AsQuery for QueryResourceMut<R> {
|
|
|
|
type Query = QueryResourceMut<R>;
|
|
|
|
}
|
2024-01-05 01:49:27 +00:00
|
|
|
|
|
|
|
/// A struct used for querying resources from the World.
|
2024-01-07 02:38:21 +00:00
|
|
|
pub struct ResMut<'a, T>(pub(crate) RefMut<'a, T>);
|
2024-01-05 01:49:27 +00:00
|
|
|
|
|
|
|
impl<'a, T: ResourceObject> std::ops::Deref for ResMut<'a, T> {
|
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
self.0.deref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: ResourceObject> std::ops::DerefMut for ResMut<'a, T> {
|
|
|
|
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
self.0.deref_mut()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T: ResourceObject> AsQuery for ResMut<'a, T> {
|
|
|
|
type Query = QueryResourceMut<T>;
|
|
|
|
}
|
|
|
|
|
2023-12-01 04:05:06 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2024-01-05 01:49:27 +00:00
|
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
|
2024-03-03 02:20:19 +00:00
|
|
|
use crate::{query::{Res, ResMut}, tests::{Vec2, Vec3}, world::World};
|
2023-12-01 04:05:06 +00:00
|
|
|
|
|
|
|
struct SomeCounter(u32);
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn simple_query() {
|
|
|
|
let mut world = World::new();
|
|
|
|
{
|
|
|
|
let counter = SomeCounter(0);
|
|
|
|
world.add_resource(counter);
|
|
|
|
println!("Added resource");
|
|
|
|
}
|
|
|
|
|
2024-03-03 02:20:19 +00:00
|
|
|
let mut res_iter = world.view_iter::<Res<SomeCounter>>();
|
2023-12-01 04:05:06 +00:00
|
|
|
let res = res_iter.next().unwrap();
|
2024-01-05 01:49:27 +00:00
|
|
|
let res = res.deref();
|
2023-12-01 04:05:06 +00:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2024-03-03 02:20:19 +00:00
|
|
|
let i = world.view_iter::<(Res<SomeCounter>, &Vec2)>();
|
2023-12-01 04:05:06 +00:00
|
|
|
assert_eq!(i.count(), 3);
|
2024-03-03 02:20:19 +00:00
|
|
|
let i = world.view_iter::<(&Vec2, Res<SomeCounter>)>();
|
2023-12-01 04:05:06 +00:00
|
|
|
assert_eq!(i.count(), 3);
|
|
|
|
|
2024-03-03 02:20:19 +00:00
|
|
|
for (res, e) in world.view_iter::<(Res<SomeCounter>, &Vec2)>() {
|
2024-01-05 01:49:27 +00:00
|
|
|
println!("Got res {}! and entity at {:?}", res.deref().0, e);
|
2023-12-01 04:05:06 +00:00
|
|
|
}
|
|
|
|
|
2024-03-03 02:20:19 +00:00
|
|
|
let i = world.view_iter::<Res<SomeCounter>>();
|
2023-12-01 04:05:06 +00:00
|
|
|
assert_eq!(i.count(), 1);
|
|
|
|
}
|
2023-12-06 04:22:48 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn mutate_query() {
|
|
|
|
let mut world = World::new();
|
|
|
|
{
|
|
|
|
let counter = SomeCounter(0);
|
|
|
|
world.add_resource(counter);
|
|
|
|
println!("Added resource");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2024-03-03 02:20:19 +00:00
|
|
|
let mut resmut_iter = world.view_iter::<ResMut<SomeCounter>>();
|
2023-12-06 04:22:48 +00:00
|
|
|
let mut resmut = resmut_iter.next().unwrap();
|
2024-01-05 01:49:27 +00:00
|
|
|
let resmut = resmut.deref_mut();
|
2023-12-06 04:22:48 +00:00
|
|
|
assert_eq!(resmut.0, 0);
|
|
|
|
resmut.0 += 20;
|
|
|
|
}
|
|
|
|
|
2024-03-03 02:20:19 +00:00
|
|
|
let mut res_iter = world.view_iter::<Res<SomeCounter>>();
|
2023-12-06 04:22:48 +00:00
|
|
|
let res = res_iter.next().unwrap();
|
2024-01-05 01:49:27 +00:00
|
|
|
let res = res.deref();
|
2023-12-06 04:22:48 +00:00
|
|
|
assert_eq!(res.0, 20);
|
|
|
|
}
|
2023-12-01 04:05:06 +00:00
|
|
|
}
|