use crate::app::App;
use crate::assets::Assets;
use crate::builder::AppBuilder;
use crate::Graphics;
use downcast_rs::{impl_downcast, Downcast};
use indexmap::IndexMap;
use notan_core::events::Event;
use std::any::{Any, TypeId};
use std::cell::{Ref, RefCell, RefMut};
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
pub enum AppFlow {
Next = 0,
Skip = 1,
SkipFrame = 2,
}
impl Default for AppFlow {
fn default() -> AppFlow {
AppFlow::Next
}
}
trait PluginCell
where
Self: Any + Downcast,
{
fn run_init(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String>;
fn run_pre_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String>;
fn run_event(
&mut self,
app: &mut App,
assets: &mut Assets,
event: &Event,
) -> Result<AppFlow, String>;
fn run_update(&mut self, app: &mut App, assets: &mut Assets) -> Result<AppFlow, String>;
fn run_draw(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String>;
fn run_post_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String>;
}
impl<T: Plugin + 'static> PluginCell for RefCell<T> {
#[inline(always)]
fn run_init(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.borrow_mut().init(app, assets, gfx)
}
#[inline(always)]
fn run_pre_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.borrow_mut().pre_frame(app, assets, gfx)
}
#[inline(always)]
fn run_event(
&mut self,
app: &mut App,
assets: &mut Assets,
event: &Event,
) -> Result<AppFlow, String> {
self.borrow_mut().event(app, assets, event)
}
#[inline(always)]
fn run_update(&mut self, app: &mut App, assets: &mut Assets) -> Result<AppFlow, String> {
self.borrow_mut().update(app, assets)
}
#[inline(always)]
fn run_draw(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.borrow_mut().draw(app, assets, gfx)
}
#[inline(always)]
fn run_post_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.borrow_mut().post_frame(app, assets, gfx)
}
}
impl_downcast!(PluginCell);
#[derive(Default)]
pub struct Plugins {
map: IndexMap<TypeId, Box<dyn PluginCell>>,
}
impl Plugins {
pub fn add<T: Plugin + 'static>(&mut self, value: T) {
self.map
.insert(TypeId::of::<T>(), Box::new(RefCell::new(value)));
}
pub fn remove<T: Plugin + 'static>(&mut self) {
self.map.remove(&TypeId::of::<T>());
}
pub fn get<T: Plugin + 'static>(&self) -> Option<Ref<T>> {
self.map
.get(&TypeId::of::<T>())?
.downcast_ref::<RefCell<T>>()
.map(|value| value.borrow())
}
pub fn get_mut<T: Plugin + 'static>(&self) -> Option<RefMut<T>> {
self.map
.get(&TypeId::of::<T>())?
.downcast_ref::<RefCell<T>>()
.map(|value| value.borrow_mut())
}
#[inline]
pub(crate) fn init(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.map
.iter_mut()
.map(|(_, p)| p.run_init(app, assets, gfx))
.max()
.unwrap_or_else(|| Ok(Default::default()))
}
#[inline]
pub(crate) fn pre_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.map
.iter_mut()
.map(|(_, p)| p.run_pre_frame(app, assets, gfx))
.max()
.unwrap_or_else(|| Ok(Default::default()))
}
#[inline]
pub(crate) fn event(
&mut self,
app: &mut App,
assets: &mut Assets,
event: &Event,
) -> Result<AppFlow, String> {
self.map
.iter_mut()
.map(|(_, p)| p.run_event(app, assets, event))
.max()
.unwrap_or_else(|| Ok(Default::default()))
}
#[inline]
pub(crate) fn update(&mut self, app: &mut App, assets: &mut Assets) -> Result<AppFlow, String> {
self.map
.iter_mut()
.map(|(_, p)| p.run_update(app, assets))
.max()
.unwrap_or_else(|| Ok(Default::default()))
}
#[inline]
pub(crate) fn draw(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.map
.iter_mut()
.map(|(_, p)| p.run_draw(app, assets, gfx))
.max()
.unwrap_or_else(|| Ok(Default::default()))
}
#[inline]
pub(crate) fn post_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
self.map
.iter_mut()
.map(|(_, p)| p.run_post_frame(app, assets, gfx))
.max()
.unwrap_or_else(|| Ok(Default::default()))
}
}
#[allow(unused_variables)]
pub trait Plugin
where
Self: Send + Sync,
{
fn init(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
Ok(Default::default())
}
fn pre_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
Ok(Default::default())
}
fn event(
&mut self,
app: &mut App,
assets: &mut Assets,
event: &Event,
) -> Result<AppFlow, String> {
Ok(Default::default())
}
fn update(&mut self, app: &mut App, assets: &mut Assets) -> Result<AppFlow, String> {
Ok(Default::default())
}
fn draw(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
Ok(Default::default())
}
fn post_frame(
&mut self,
app: &mut App,
assets: &mut Assets,
gfx: &mut Graphics,
) -> Result<AppFlow, String> {
Ok(Default::default())
}
fn build<S, B>(&mut self, builder: &mut AppBuilder<S, B>)
where
Self: Sized,
{
}
}