1#![allow(private_bounds)]
3
4use bevy::prelude::*;
5
6pub trait FnPluginsExt {
7 fn fn_plugins<T>(&mut self, f: impl FnPlugins<T>) -> &mut Self;
20}
21
22impl FnPluginsExt for App {
23 fn fn_plugins<T>(&mut self, f: impl FnPlugins<T>) -> &mut Self {
24 f.add_to_app(self);
25 self
26 }
27}
28
29trait FnPlugins<Marker>: sealed::FnPlugins<Marker> {}
30
31impl<Marker, T> FnPlugins<Marker> for T where T: sealed::FnPlugins<Marker> {}
32
33mod sealed {
34 use bevy::ecs::all_tuples;
35 use bevy::prelude::*;
36
37 pub struct SingleFnMarker;
38 pub struct TupleFnMarker;
39
40 pub trait FnPlugins<Marker> {
41 fn add_to_app(self, app: &mut App);
42 }
43
44 impl<P: FnOnce(&mut App)> FnPlugins<SingleFnMarker> for P {
45 fn add_to_app(self, app: &mut App) {
46 self(app);
47 }
48 }
49
50 macro_rules! impl_fn_plugins {
51 ($(($param: ident, $plugins: ident)),*) => {
52 impl<$($param, $plugins),*> FnPlugins<(TupleFnMarker, $($param,)*)> for ($($plugins,)*)
53 where
54 $($plugins: FnPlugins<$param>),*
55 {
56 #[allow(non_snake_case, unused_variables)]
57 fn add_to_app(self, app: &mut App) {
58 let ($($plugins,)*) = self;
59 $($plugins.add_to_app(app);)*
60 }
61 }
62 }
63 }
64
65 all_tuples!(impl_fn_plugins, 0, 15, P, S);
66}