use std::{any::TypeId, sync::Arc};
use bevy::{
ecs::{system::SystemId, world::Command},
prelude::*,
};
use crate::Cx;
#[derive(PartialEq, Debug)]
pub struct Callback<P = ()> {
pub(crate) id: SystemId<P, ()>,
}
pub trait AnyCallback: 'static {
fn remove(&self, world: &mut World);
fn type_id(&self) -> TypeId;
}
impl dyn AnyCallback + Send + Sync {
pub fn downcast<P: 'static>(&self) -> Callback<P> {
if TypeId::of::<P>() == self.type_id() {
unsafe { *(self as *const dyn AnyCallback as *const Callback<P>) }
} else {
panic!("downcast failed")
}
}
}
impl<P: 'static> AnyCallback for Callback<P> {
fn remove(&self, world: &mut World) {
world.remove_system(self.id).unwrap();
}
fn type_id(&self) -> TypeId {
TypeId::of::<P>()
}
}
impl<P> Copy for Callback<P> {}
impl<P> Clone for Callback<P> {
fn clone(&self) -> Self {
*self
}
}
pub trait RunCallback {
fn run_callback<P: 'static>(&mut self, callback: Callback<P>, props: P);
}
impl RunCallback for World {
fn run_callback<P: 'static>(&mut self, callback: Callback<P>, props: P) {
self.run_system_with_input(callback.id, props).unwrap();
}
}
impl<'p, 'w> RunCallback for Cx<'p, 'w> {
fn run_callback<P: 'static>(&mut self, callback: Callback<P>, props: P) {
self.world_mut().run_callback(callback, props);
}
}
pub(crate) struct UnregisterCallbackCmd(pub(crate) Arc<dyn AnyCallback + Send + Sync>);
impl Command for UnregisterCallbackCmd {
fn apply(self, world: &mut World) {
self.0.remove(world)
}
}