use std::any::Any;
use std::mem::{replace, transmute};
use std::ops::{Deref, DerefMut};
use pi_share::Share;
use crate::system::{Relation, SystemMeta, TypeInfo};
use crate::system_params::SystemParam;
use crate::world::{Downcast, Tick, TickMut, World};
#[derive(Debug, Default)]
pub struct TickRes<T> {
pub(crate) res: T,
pub(crate) changed_tick: Tick,
}
unsafe impl<T> Send for TickRes<T> {}
unsafe impl<T> Sync for TickRes<T> {}
impl<T: 'static> Downcast for TickRes<T> {
fn into_any(self: Share<Self>) -> Share<dyn Any + Send + Sync> {
self
}
fn into_box_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
impl<T: 'static> TickMut for TickRes<T> {
fn get_tick(&self) -> Tick {
self.changed_tick
}
fn set_tick(&mut self, tick: Tick) {
self.changed_tick = tick;
}
}
impl<T: 'static> TickRes<T> {
pub fn new(res: T) -> Self {
TickRes {
res,
changed_tick: Tick::default(),
}
}
}
impl<T: 'static> Deref for TickRes<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.res
}
}
impl<T: 'static> DerefMut for TickRes<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.res
}
}
#[derive(Debug)]
pub struct SingleRes<'w, T: 'static> {
pub(crate) value: &'w TickRes<T>,
pub(crate) last_run: Tick,
}
unsafe impl<T> Send for SingleRes<'_, T> {}
unsafe impl<T> Sync for SingleRes<'_, T> {}
impl<'w, T: 'static> SingleRes<'w, T> {
pub(crate) fn new(value: &'w TickRes<T>, last_run: Tick) -> Self {
SingleRes { value, last_run }
}
pub fn changed_tick(&self) -> Tick {
self.value.changed_tick
}
pub fn is_changed(&self) -> bool {
self.value.changed_tick > self.last_run
}
}
impl<T: 'static + Send + Sync> SystemParam for SingleRes<'_, T> {
type State = (Option<Share<TickRes<T>>>, usize, Tick);
type Item<'w> = SingleRes<'w, T>;
fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
init_read_state(world, meta)
}
fn get_param<'world>(
world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self::Item<'world> {
if state.0.is_none() {
init_opt_state(world, &mut state.0, state.1);
}
let r = state.0.as_ref().unwrap();
let last_run = replace(&mut state.2, tick);
SingleRes::new(&r, last_run)
}
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state, tick)) }
}
}
impl<'w, T: Sync + Send + 'static> Deref for SingleRes<'w, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value.res
}
}
#[derive(Debug)]
pub struct SingleResMut<'w, T: 'static> {
pub(crate) value: &'w mut TickRes<T>,
pub(crate) tick: Tick,
}
unsafe impl<T> Send for SingleResMut<'_, T> {}
unsafe impl<T> Sync for SingleResMut<'_, T> {}
impl<'w, T: 'static> SingleResMut<'w, T> {
pub(crate) fn new(value: &'w mut TickRes<T>, tick: Tick) -> Self {
SingleResMut { value, tick }
}
pub fn changed_tick(&self) -> Tick {
self.value.changed_tick
}
pub fn tick(&self) -> Tick {
self.tick
}
}
impl<T: 'static> SystemParam for SingleResMut<'_, T> {
type State = (Option<Share<TickRes<T>>>, usize);
type Item<'w> = SingleResMut<'w, T>;
fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
init_write_state(world, meta)
}
fn get_param<'world>(
world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self::Item<'world> {
if state.0.is_none() {
init_opt_state(world, &mut state.0, state.1);
}
let r = state.0.as_mut().unwrap();
SingleResMut::new(unsafe { Share::get_mut_unchecked(r) }, tick)
}
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state, tick)) }
}
}
impl<'w, T: Sync + Send + 'static> Deref for SingleResMut<'w, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value.res
}
}
impl<'w, T: Sync + Send + 'static> DerefMut for SingleResMut<'w, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.value.changed_tick = self.tick;
&mut self.value.res
}
}
impl<T: 'static> SystemParam for Option<SingleRes<'_, T>> {
type State = (Option<Share<TickRes<T>>>, usize, Tick);
type Item<'w> = Option<SingleRes<'w, T>>;
fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
init_read_state(world, meta)
}
fn get_param<'world>(
world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self::Item<'world> {
if state.0.is_none() {
let s = match world.index_single_res_any(state.1) {
Some(r) => r.clone(),
None => return None
};
state.0 = Some(Share::downcast::<TickRes<T>>(s.into_any()).unwrap());
}
if let Some(r) = &state.0 {
let last_run = replace(&mut state.2, tick);
Some(SingleRes::new(r.as_any().downcast_ref().unwrap(), last_run))
} else {
None
}
}
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state, tick)) }
}
}
impl<T: 'static> SystemParam for Option<SingleResMut<'_, T>> {
type State = (Option<Share<TickRes<T>>>, usize);
type Item<'w> = Option<SingleResMut<'w, T>>;
fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
init_write_state(world, meta)
}
fn get_param<'world>(
world: &'world World,
_system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self::Item<'world> {
if state.0.is_none() {
let s = match world.index_single_res_any(state.1) {
Some(r) => r.clone(),
None => return None
};
state.0 = Some(Share::downcast::<TickRes<T>>(s.into_any()).unwrap());
}
if let Some(r) = state.0.as_mut() {
Some(SingleResMut::new(
unsafe { Share::get_mut_unchecked(r) },
tick,
))
} else {
None
}
}
fn get_self<'world>(
world: &'world World,
system_meta: &'world SystemMeta,
state: &'world mut Self::State,
tick: Tick,
) -> Self {
unsafe { transmute(Self::get_param(world, system_meta, state, tick)) }
}
}
fn init_read_state<T: 'static>(
world: &mut World,
meta: &mut SystemMeta,
) -> (Option<Share<TickRes<T>>>, usize, Tick) {
let t = TypeInfo::of::<T>();
let r = Relation::Read(t.type_id);
let index = meta.add_single_res(world, t, r);
let s = world.index_single_res_any(index);
if let Some(s) = s {
(
Some(Share::downcast::<TickRes<T>>(s.clone().into_any()).unwrap()),
index,
Tick::default(),
)
} else {
(None, index, Tick::default())
}
}
fn init_write_state<T: 'static>(
world: &mut World,
meta: &mut SystemMeta,
) -> (Option<Share<TickRes<T>>>, usize) {
let t = TypeInfo::of::<T>();
let r = Relation::Write(t.type_id);
let index = meta.add_single_res(world, t, r);
let s = world.index_single_res_any(index);
if let Some(s) = s {
(
Some(Share::downcast::<TickRes<T>>(s.clone().into_any()).unwrap()),
index,
)
} else {
(None, index)
}
}
fn init_opt_state<T: 'static>(world: &World, state: &mut Option<Share<TickRes<T>>>, index: usize) {
log::error!("t==============={:?}", std::any::type_name::<T>());
let s = world.index_single_res_any(index).unwrap().clone();
*state = Some(Share::downcast::<TickRes<T>>(s.into_any()).unwrap());
}