use std::any::{Any, TypeId};
use std::borrow::Cow;
use std::marker::PhantomData;
use std::mem::transmute;
use std::ops::{Deref, DerefMut};
use pi_share::Share;
use crate::archetype::Flags;
use crate::system::SystemMeta;
use crate::system_params::SystemParam;
use crate::world::*;
pub struct MultiRes<'w, T: 'static> {
pub(crate) vec: &'w Vec<Share<dyn Any>>,
_p: PhantomData<T>,
}
unsafe impl<T> Send for MultiRes<'_, T> {}
unsafe impl<T> Sync for MultiRes<'_, T> {}
impl<T> MultiRes<'_, T> {
pub fn len(&self) -> usize {
self.vec.len()
}
pub fn get(&self, index: usize) -> Option<&T> {
self.vec
.get(index)
.map(|r| unsafe { r.downcast_ref_unchecked::<T>() })
}
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
unsafe { self.vec.get_unchecked(index).downcast_ref_unchecked::<T>() }
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.vec
.iter()
.map(|r| unsafe { r.downcast_ref_unchecked::<T>() })
}
}
impl<T: 'static> SystemParam for MultiRes<'_, T> {
type State = MultiResource;
type Item<'w> = MultiRes<'w, T>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
let tid = TypeId::of::<T>();
let name = std::any::type_name::<T>().into();
system_meta.res_read(tid, name);
world.system_read_multi_res(&tid).unwrap()
}
fn res_depend(
_world: &World,
_system_meta: &SystemMeta,
_state: &Self::State,
res_tid: &TypeId,
_res_name: &Cow<'static, str>,
single: bool,
result: &mut Flags,
) {
if (!single) && &TypeId::of::<T>() == res_tid {
result.set(Flags::READ, true)
}
}
#[inline]
fn get_param<'world>(
_world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self::Item<'world> {
MultiRes {
vec: state.vec(),
_p: PhantomData,
}
}
#[inline]
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state)) }
}
}
pub struct MultiResMut<'w, T: Default + 'static> {
pub(crate) value: &'w mut T,
}
unsafe impl<T: Default> Send for MultiResMut<'_, T> {}
unsafe impl<T: Default> Sync for MultiResMut<'_, T> {}
impl<T: Default + 'static> SystemParam for MultiResMut<'_, T> {
type State = SingleResource;
type Item<'w> = MultiResMut<'w, T>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
let tid = TypeId::of::<T>();
let name = std::any::type_name::<T>().into();
system_meta.res_write(tid, name);
world.system_init_write_multi_res(T::default).unwrap()
}
fn res_depend(
_world: &World,
_system_meta: &SystemMeta,
_state: &Self::State,
res_tid: &TypeId,
_res_name: &Cow<'static, str>,
single: bool,
result: &mut Flags,
) {
if (!single) && &TypeId::of::<T>() == res_tid {
result.set(Flags::SHARE_WRITE, true)
}
}
#[inline]
fn get_param<'world>(
_world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self::Item<'world> {
MultiResMut {
value: unsafe { &mut *state.downcast::<T>() },
}
}
#[inline]
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state)) }
}
}
impl<'w, T: Default + Sync + Send + 'static> Deref for MultiResMut<'w, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'w, T: Default + Sync + Send + 'static> DerefMut for MultiResMut<'w, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.value
}
}
impl<T: 'static> SystemParam for Option<MultiRes<'_, T>> {
type State = Option<MultiResource>;
type Item<'w> = Option<MultiRes<'w, T>>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
let tid = TypeId::of::<T>();
let name = std::any::type_name::<T>().into();
system_meta.res_read(tid, name);
world.system_read_multi_res(&tid)
}
fn res_depend(
_world: &World,
_system_meta: &SystemMeta,
_state: &Self::State,
res_tid: &TypeId,
_res_name: &Cow<'static, str>,
single: bool,
result: &mut Flags,
) {
if (!single) && &TypeId::of::<T>() == res_tid {
result.set(Flags::READ, true)
}
}
#[inline]
fn get_param<'world>(
_world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self::Item<'world> {
match state {
Some(s) => Some(MultiRes {
vec: s.vec(),
_p: PhantomData,
}),
None => None,
}
}
#[inline]
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state)) }
}
}
impl<T: Default + 'static> SystemParam for Option<MultiResMut<'_, T>> {
type State = Option<SingleResource>;
type Item<'w> = Option<MultiResMut<'w, T>>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
let tid = TypeId::of::<T>();
let name = std::any::type_name::<T>().into();
system_meta.res_write(tid, name);
world.system_init_write_multi_res(T::default)
}
fn res_depend(
_world: &World,
_system_meta: &SystemMeta,
_state: &Self::State,
res_tid: &TypeId,
_res_name: &Cow<'static, str>,
single: bool,
result: &mut Flags,
) {
if (!single) && &TypeId::of::<T>() == res_tid {
result.set(Flags::WRITE, true)
}
}
#[inline]
fn get_param<'world>(
_world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self::Item<'world> {
match state {
Some(s) => Some(MultiResMut {
value: unsafe { &mut *s.downcast::<T>() },
}),
None => None,
}
}
#[inline]
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state)) }
}
}