use std::any::TypeId;
use std::borrow::Cow;
use std::mem::transmute;
use std::ops::{Deref, DerefMut};
use crate::archetype::{Archetype, ArchetypeDependResult, Flags};
use crate::system::SystemMeta;
use crate::system_params::SystemParam;
use crate::world::*;
use pi_proc_macros::all_tuples;
pub trait ParamSetElement: SystemParam {
fn init_set_state(world: &World, system_meta: &mut SystemMeta) -> Self::State;
}
pub struct ParamSet<'w, T: 'static + ParamSetElement>(<T as SystemParam>::Item<'w>);
impl<'w, T: ParamSetElement + 'static> Deref for ParamSet<'w, T> {
type Target = <T as SystemParam>::Item<'w>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'w, T: ParamSetElement + 'static> DerefMut for ParamSet<'w, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: 'static + ParamSetElement> SystemParam for ParamSet<'_, T> {
type State = <T as SystemParam>::State;
type Item<'w> = ParamSet<'w, T>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
let s = T::init_set_state(world, system_meta);
system_meta.param_set_ok();
s
}
#[inline]
fn archetype_depend(
world: &World,
system_meta: &SystemMeta,
state: &Self::State,
archetype: &Archetype,
result: &mut ArchetypeDependResult,
) {
<T as SystemParam>::archetype_depend(world, system_meta, state, archetype, result)
}
#[inline]
fn res_depend(
world: &World,
system_meta: &SystemMeta,
state: &Self::State,
res_tid: &TypeId,
res_name: &Cow<'static, str>,
single: bool,
result: &mut Flags,
) {
<T as SystemParam>::res_depend(world, system_meta, state, res_tid, res_name, single, result)
}
#[inline]
fn align(world: &World, system_meta: &SystemMeta, state: &mut Self::State) {
<T as SystemParam>::align(world, system_meta, state)
}
fn get_param<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
) -> Self::Item<'world> {
ParamSet(<T as SystemParam>::get_param(world, system_meta, state))
}
#[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)) }
}
}
macro_rules! impl_param_set_tuple_fetch {
($($param: ident),*) => {
#[allow(non_snake_case)]
#[allow(clippy::unused_unit)]
impl<$($param: ParamSetElement),*> ParamSetElement for ($($param,)*) {
fn init_set_state(_world: &World, _system_meta: &mut SystemMeta) -> Self::State{
(($($param::init_set_state(_world, _system_meta),)*))
}
}
};
}
all_tuples!(impl_param_set_tuple_fetch, 1, 15, F);