summaryrefslogtreecommitdiff
path: root/ecs/src/component/storage.rs
blob: cdff09e56622f14852b1c268aa561bce16bf53f4 (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
use std::any::{type_name, TypeId};
use std::collections::HashSet;

use crate::component::{Component, IsOptional as ComponentIsOptional};
use crate::lock::Lock;
use crate::type_name::TypeName;
use crate::EntityComponent;

#[derive(Debug, Default)]
pub struct ComponentStorage
{
    entities: Vec<Entity>,
}

impl ComponentStorage
{
    pub fn find_entity_with_components(
        &self,
        start_index: usize,
        component_type_ids: &[(TypeId, ComponentIsOptional)],
    ) -> Option<(usize, &[EntityComponent])>
    {
        // TODO: This is a really dumb and slow way to do this. Refactor the world
        // to store components in archetypes
        self.entities
            .iter()
            .enumerate()
            .skip(start_index)
            .find(move |(_index, entity)| {
                let entity_components = entity
                    .components
                    .iter()
                    .map(|component| component.id)
                    .collect::<HashSet<_>>();

                if component_type_ids
                    .iter()
                    .filter(|(_, is_optional)| *is_optional == ComponentIsOptional::No)
                    .all(|(component_type_id, _)| {
                        entity_components.contains(component_type_id)
                    })
                {
                    return true;
                }

                false
            })
            .map(|(index, entity)| (index, &*entity.components))
    }

    pub fn push_entity(
        &mut self,
        components: impl IntoIterator<Item = Box<dyn Component>>,
    )
    {
        self.entities.push(Entity {
            components: components
                .into_iter()
                .map(|component| EntityComponent {
                    id: (*component).type_id(),
                    name: component.type_name(),
                    component: Lock::new(component),
                })
                .collect(),
        });
    }
}

impl TypeName for ComponentStorage
{
    fn type_name(&self) -> &'static str
    {
        type_name::<Self>()
    }
}

#[derive(Debug, Default)]
struct Entity
{
    components: Vec<EntityComponent>,
}