wecs_core/system/
function_system.rs

1use std::marker::PhantomData;
2
3use crate::world::UnsafeWorldCell;
4
5use super::{IntoSystem, System, SystemParam, SystemParamItem};
6
7pub struct FunctionSystem<Marker, F> {
8    name: &'static str,
9    func: F,
10    marker: PhantomData<Marker>,
11}
12
13impl<Marker, F> System for FunctionSystem<Marker, F>
14where
15    Marker: 'static,
16    F: SystemParamFunction<Marker>,
17{
18    fn run(&mut self, world: &mut crate::world::World) {
19        let unsafe_world_cell = UnsafeWorldCell::new(world);
20        let params = F::Param::get_param(unsafe_world_cell);
21        self.func.run(params)
22    }
23}
24
25impl<Marker, F> IntoSystem<Marker> for F
26where
27    Marker: 'static,
28    F: SystemParamFunction<Marker>,
29{
30    type System = FunctionSystem<Marker, F>;
31
32    fn into_system(self) -> Self::System {
33        FunctionSystem {
34            name: std::any::type_name::<F>(),
35            func: self,
36            marker: PhantomData,
37        }
38    }
39}
40
41pub trait SystemParamFunction<Marker>: 'static {
42    type Param: SystemParam;
43
44    fn run(&mut self, param_value: SystemParamItem<Self::Param>);
45}
46
47impl<F> SystemParamFunction<fn()> for F
48where
49    F: 'static,
50    for<'a> &'a mut F: FnMut(),
51{
52    type Param = ();
53
54    fn run(&mut self, param_value: SystemParamItem<Self::Param>) {
55        fn call_inner(mut f: impl FnMut()) {
56            f()
57        }
58
59        call_inner(self)
60    }
61}
62
63macro_rules! impl_spf_from {
64    ( $($n:ident),* ) => {
65        #[allow(non_snake_case)]
66        impl<F, $($n,)*> SystemParamFunction<fn($($n,)*)> for F
67        where
68            F: 'static,
69            for<'a> &'a mut F: FnMut($($n,)*) + FnMut($(SystemParamItem<$n>,)*),
70            $($n: SystemParam,)*
71        {
72            type Param = ($($n,)*);
73
74            fn run(&mut self, param_value: SystemParamItem<Self::Param>) {
75                fn call_inner<$($n,)*>(mut f: impl FnMut($($n,)*), $($n: $n,)*) {
76                    f($($n,)*)
77                }
78                let ($($n,)*) = param_value;
79                call_inner(self, $($n,)*)
80            }
81        }
82    };
83}
84
85impl_spf_from!(T1);
86impl_spf_from!(T1, T2);
87impl_spf_from!(T1, T2, T3);
88impl_spf_from!(T1, T2, T3, T4);
89impl_spf_from!(T1, T2, T3, T4, T5);
90impl_spf_from!(T1, T2, T3, T4, T5, T6);
91impl_spf_from!(T1, T2, T3, T4, T5, T6, T7);
92impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8);
93impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
94impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
95impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
96impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
97impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
98impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
99impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
100impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);