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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use index_pool::iter::IndexIter;
use free_ranges::Range;
use fnv::FnvHashMap;
use vec_map::VecMap;

use std::collections::hash_map::Values;
use std::collections::btree_set::Iter as BIter;

use aspect::Aspect;
use component::ComponentManager;
use entity::{Entity, EntityData, IndexedEntity};

pub struct FilteredEntityIter<'a, C>
where
    C: ComponentManager,
{
    inner: EntityIter<'a, C>,
    aspect: Aspect<C>,
    components: &'a C,
}

// Inner Entity Iterator
pub enum EntityIter<'a, C>
where
    C: ComponentManager,
{
    Map(Values<'a, Entity, IndexedEntity<C>>),
    Indexed(IndexedEntityIter<'a, C>),
    Watched(WatchedEntityIter<'a, C>),
}

impl<'a, C> Clone for EntityIter<'a, C>
where
    C: ComponentManager,
{
    fn clone(&self) -> Self {
        match *self {
            EntityIter::Map(ref map) => EntityIter::Map(map.clone()),
            EntityIter::Indexed(ref ind) => EntityIter::Indexed(ind.clone()),
            EntityIter::Watched(ref wat) => EntityIter::Watched(wat.clone()),
        }
    }
}

pub struct IndexedEntityIter<'a, C>
where
    C: ComponentManager,
{
    pub(crate) iter: IndexIter<'a>,
    pub(crate) values: &'a VecMap<IndexedEntity<C>>,
}

impl<'a, C> Clone for IndexedEntityIter<'a, C>
where
    C: ComponentManager,
{
    fn clone(&self) -> Self {
        IndexedEntityIter {
            iter: self.iter.clone(),
            values: self.values.clone(),
        }
    }
}

pub struct WatchedEntityIter<'a, C>
where
    C: ComponentManager,
{
    pub(crate) current_range: Range,
    pub(crate) indices: BIter<'a, Range>,
    pub(crate) entities: &'a FnvHashMap<usize, IndexedEntity<C>>,
}

impl<'a, C> Clone for WatchedEntityIter<'a, C>
where
    C: ComponentManager,
{
    fn clone(&self) -> Self {
        WatchedEntityIter {
            current_range: self.current_range,
            indices: self.indices.clone(),
            entities: self.entities,
        }
    }
}

impl<'a, C> EntityIter<'a, C>
where
    C: ComponentManager,
{
    pub fn filter(self, aspect: Aspect<C>, components: &'a C) -> FilteredEntityIter<'a, C> {
        FilteredEntityIter {
            inner: self,
            aspect: aspect,
            components: components,
        }
    }
}

impl<'a, C> Iterator for EntityIter<'a, C>
where
    C: ComponentManager,
{
    type Item = EntityData<'a, C>;
    fn next(&mut self) -> Option<EntityData<'a, C>> {
        match *self {
            EntityIter::Map(ref mut values) => values.next().map(|x| EntityData(x)),
            EntityIter::Indexed(ref mut iter) => iter.iter
                .next()
                .map(|i| iter.values.get(i).unwrap())
                .map(|x| EntityData(x)),
            EntityIter::Watched(ref mut iter) => {
                if iter.current_range.empty() {
                    if let Some(&range) = iter.indices.next() {
                        iter.current_range = range;
                    } else {
                        return None;
                    }
                }

                let index = iter.current_range.min;
                let data = EntityData(&iter.entities[&index]);
                iter.current_range = iter.current_range.pop_front();
                Some(data)
            }
        }
    }
}

impl<'a, C> Iterator for FilteredEntityIter<'a, C>
where
    C: ComponentManager,
{
    type Item = EntityData<'a, C>;
    fn next(&mut self) -> Option<EntityData<'a, C>> {
        for x in self.inner.by_ref() {
            if self.aspect.check(x, self.components) {
                return Some(x);
            } else {
                continue;
            }
        }
        None
    }
}