#![allow(private_bounds)]
use bevy::prelude::*;
pub trait FnPluginsExt {
fn fn_plugins<T>(&mut self, f: impl FnPlugins<T>) -> &mut Self;
}
impl FnPluginsExt for App {
fn fn_plugins<T>(&mut self, f: impl FnPlugins<T>) -> &mut Self {
f.add_to_app(self);
self
}
}
trait FnPlugins<Marker>: sealed::FnPlugins<Marker> {}
impl<Marker, T> FnPlugins<Marker> for T where T: sealed::FnPlugins<Marker> {}
mod sealed {
use bevy::ecs::all_tuples;
use bevy::prelude::*;
pub struct SingleFnMarker;
pub struct TupleFnMarker;
pub trait FnPlugins<Marker> {
fn add_to_app(self, app: &mut App);
}
impl<P: FnOnce(&mut App)> FnPlugins<SingleFnMarker> for P {
fn add_to_app(self, app: &mut App) {
self(app);
}
}
macro_rules! impl_fn_plugins {
($(($param: ident, $plugins: ident)),*) => {
impl<$($param, $plugins),*> FnPlugins<(TupleFnMarker, $($param,)*)> for ($($plugins,)*)
where
$($plugins: FnPlugins<$param>),*
{
#[allow(non_snake_case, unused_variables)]
fn add_to_app(self, app: &mut App) {
let ($($plugins,)*) = self;
$($plugins.add_to_app(app);)*
}
}
}
}
all_tuples!(impl_fn_plugins, 0, 15, P, S);
}