summaryrefslogtreecommitdiff
path: root/ecs/src/system/stateful.rs
blob: b641cf2bd672446e18f19b0f2d3725d9825d0c66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std::marker::PhantomData;

use crate::component::Local;
use crate::system::{System, TypeErased};
use crate::{ComponentStorage, Query};

/// A stateful system.
pub struct Stateful<Func, LocalComponent, Comps>
{
    func: Func,
    local_component: Option<LocalComponent>,
    _comps_pd: PhantomData<Comps>,
}

impl<Func: 'static, Comps: 'static, LocalComponent: 'static>
    System<fn(Query<Comps>, Local<LocalComponent>)>
    for Stateful<Func, LocalComponent, Comps>
where
    Func: Fn(Query<Comps>, Local<LocalComponent>),
{
    type Input = LocalComponent;
    type Query<'a> = Query<'a, Comps>;

    fn initialize(mut self, input: Self::Input) -> Self
    {
        self.local_component = Some(input);

        self
    }

    fn run(&mut self, component_storage: &mut ComponentStorage)
    {
        (self.func)(
            Query::new(component_storage),
            Local::new(self.local_component.as_mut().unwrap()),
        );
    }

    fn into_type_erased(self) -> TypeErased
    {
        TypeErased {
            data: Box::new(self),
            func: Box::new(move |data, component_storage| {
                let this = data.downcast_mut::<Self>().unwrap();

                this.run(component_storage);
            }),
        }
    }
}

impl<Func: 'static, Comps, LocalComponent: 'static>
    crate::system::Into<fn(Query<Comps>, Local<LocalComponent>)> for Func
where
    Func: Fn(Query<Comps>, Local<LocalComponent>),
{
    type System = Stateful<Func, LocalComponent, Comps>;

    fn into_system(self) -> Self::System
    {
        Self::System {
            func: self,
            local_component: None,
            _comps_pd: PhantomData,
        }
    }
}