Skip to main content

gizmo_core/query/
iter.rs

1use super::WorldQuery;
2use crate::world::World;
3use std::marker::PhantomData;
4
5// =========================================================================
6// QUERY ITERATOR
7// =========================================================================
8
9pub struct QueryIter<'a, 'w, Q: WorldQuery> {
10    pub(super) world: &'a World,
11    pub(super) archetype_indices: &'a [usize],
12    pub(super) current_arch_idx: usize,
13    pub(super) current_row: usize,
14    pub(super) current_fetch: Option<Q::Fetch<'a>>,
15    pub(super) _marker: PhantomData<Q>,
16    pub(super) _marker_w: PhantomData<&'w ()>,
17}
18
19impl<'a, 'w, Q: WorldQuery> Iterator for QueryIter<'a, 'w, Q>
20where
21    'w: 'a,
22{
23    type Item = (u32, Q::Item<'a>);
24
25    fn next(&mut self) -> Option<Self::Item> {
26        loop {
27            if self.current_arch_idx >= self.archetype_indices.len() {
28                return None;
29            }
30
31            let arch_idx = self.archetype_indices[self.current_arch_idx];
32            let arch = &self.world.archetype_index.archetypes[arch_idx];
33
34            let fetch = match self.current_fetch {
35                Some(f) => f,
36                None => {
37                    match unsafe { Q::fetch_raw(self.world, arch, self.world.tick) } {
38                        Some(f) => {
39                            self.current_fetch = Some(f);
40                            self.current_row = 0;
41                            f
42                        }
43                        None => {
44                            // Bu archetype bu query'ye uymuyor, sonrakine geƧ
45                            self.current_arch_idx += 1;
46                            continue;
47                        }
48                    }
49                }
50            };
51
52            if self.current_row < arch.len() {
53                let row = self.current_row;
54                self.current_row += 1;
55                let id = arch.entities()[row];
56                if unsafe { Q::filter_row(fetch, row, id, self.world.change_ref_tick) } {
57                    let item = unsafe { Q::get_item(fetch, row, id) };
58                    return Some((id, item));
59                }
60                continue;
61            }
62
63            self.current_fetch = None;
64            self.current_arch_idx += 1;
65        }
66    }
67
68    #[inline(always)]
69    fn for_each<F>(self, mut f: F)
70    where
71        Self: Sized,
72        F: FnMut(Self::Item),
73    {
74        for &arch_idx in self.archetype_indices {
75            let arch = &self.world.archetype_index.archetypes[arch_idx];
76            let len = arch.len();
77            if len == 0 {
78                continue;
79            }
80            if let Some(fetch) = unsafe { Q::fetch_raw(self.world, arch, self.world.tick) } {
81                let entities = arch.entities();
82                for (row, &id) in entities.iter().enumerate().take(len) {
83                    if unsafe { Q::filter_row(fetch, row, id, self.world.change_ref_tick) } {
84                        let item = unsafe { Q::get_item(fetch, row, id) };
85                        f((id, item));
86                    }
87                }
88            }
89        }
90    }
91}
92
93// =========================================================================
94// QUERY CHUNKS ITERATOR
95// =========================================================================
96
97pub struct QueryChunksIter<'a, 'w, Q: WorldQuery> {
98    pub(super) world: &'a World,
99    pub(super) archetype_indices: &'a [usize],
100    pub(super) current_arch_idx: usize,
101    pub(super) _marker: PhantomData<&'w Q>,
102}
103
104impl<'a, 'w, Q: WorldQuery> Iterator for QueryChunksIter<'a, 'w, Q>
105where
106    'w: 'a,
107{
108    type Item = (&'a [u32], Q::Slice<'a>);
109
110    fn next(&mut self) -> Option<Self::Item> {
111        while self.current_arch_idx < self.archetype_indices.len() {
112            let arch_idx = self.archetype_indices[self.current_arch_idx];
113            self.current_arch_idx += 1;
114
115            let arch = &self.world.archetype_index.archetypes[arch_idx];
116            let len = arch.len();
117            if len == 0 {
118                continue;
119            }
120
121            let fetch = match unsafe { Q::fetch_raw(self.world, arch, self.world.tick) } {
122                Some(f) => f,
123                None => continue,
124            };
125
126            let ids = unsafe { std::slice::from_raw_parts(arch.entities().as_ptr(), len) };
127            let slice = unsafe { Q::get_slice(fetch, len) };
128
129            return Some((ids, slice));
130        }
131        None
132    }
133}