summaryrefslogtreecommitdiff
path: root/ecs/src/component.rs
blob: 4829050adc2c6414c638c77bc68b69c77b1687ab (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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::any::{Any, TypeId};
use std::fmt::Debug;

use seq_macro::seq;

pub trait Component: Any
{
    #[doc(hidden)]
    fn as_any_mut(&mut self) -> &mut dyn Any;

    #[doc(hidden)]
    fn as_any(&self) -> &dyn Any;
}

impl<Value: Any> Component for Value
{
    fn as_any_mut(&mut self) -> &mut dyn Any
    {
        self
    }

    fn as_any(&self) -> &dyn Any
    {
        self
    }
}

impl dyn Component
{
    pub fn downcast_mut<Real: 'static>(&mut self) -> Option<&mut Real>
    {
        self.as_any_mut().downcast_mut()
    }

    pub fn is<Other: 'static>(&self) -> bool
    {
        self.as_any().is::<Other>()
    }
}

impl Debug for dyn Component
{
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
    {
        formatter.debug_struct("Component").finish_non_exhaustive()
    }
}

/// A sequence of components.
pub trait Sequence
{
    type MutRefs<'component>
    where
        Self: 'component;

    fn into_vec(self) -> Vec<Box<dyn Component>>;

    fn type_ids() -> Vec<TypeId>;

    fn from_components<'components>(
        components: &'components mut [Box<dyn Component>],
    ) -> Self::MutRefs<'components>;
}

macro_rules! inner {
    ($c: tt) => {
        seq!(I in 0..=$c {
            impl<#(Comp~I: Component,)*> Sequence for (#(Comp~I,)*) {
                type MutRefs<'component> = (#(&'component mut Comp~I,)*)
                    where Self: 'component;

                fn into_vec(self) -> Vec<Box<dyn Component>> {
                    Vec::from_iter([#(Box::new(self.I) as Box<dyn Component>,)*])
                }

                fn type_ids() -> Vec<TypeId> {
                    vec![
                        #(
                            TypeId::of::<Comp~I>(),
                        )*
                    ]
                }

                fn from_components<'components>(
                    components: &'components mut [Box<dyn Component>],
                ) -> Self::MutRefs<'components>
                {
                    #(
                        let mut comp_~I = None;
                    )*

                    for comp in components.iter_mut() {
                        #(
                            if comp.is::<Comp~I>() {
                                comp_~I = Some(comp);
                                continue;
                            }

                        )*
                    }


                    (#(
                        comp_~I.unwrap().downcast_mut::<Comp~I>().unwrap(),
                    )*)
                }
            }
        });
    };
}

seq!(C in 0..=64 {
    inner!(C);
});