kaige_ecs/internals/query/filter/
maybe_changed.rs

1use std::{collections::HashMap, marker::PhantomData};
2
3use super::{
4    and::And, not::Not, or::Or, passthrough::Passthrough, ActiveFilter, DynamicFilter, FilterResult,
5};
6use crate::internals::{query::view::Fetch, storage::component::Component, world::WorldId};
7
8/// A filter which performs coarse-grained change detection.
9///
10/// This filter will reject _most_ components which have not
11/// been changed, but not all.
12#[derive(Debug)]
13pub struct ComponentChangedFilter<T: Component> {
14    _phantom: PhantomData<T>,
15    history: HashMap<WorldId, u64>,
16    world: Option<WorldId>,
17    threshold: u64,
18    maximum: u64,
19}
20
21impl<T: Component> Default for ComponentChangedFilter<T> {
22    fn default() -> Self {
23        Self {
24            _phantom: PhantomData,
25            history: Default::default(),
26            world: None,
27            threshold: 0,
28            maximum: 0,
29        }
30    }
31}
32
33impl<T: Component> Clone for ComponentChangedFilter<T> {
34    fn clone(&self) -> Self {
35        Self {
36            _phantom: PhantomData,
37            history: self.history.clone(),
38            world: None,
39            threshold: 0,
40            maximum: 0,
41        }
42    }
43}
44
45impl<T: Component> ActiveFilter for ComponentChangedFilter<T> {}
46
47impl<T: Component> DynamicFilter for ComponentChangedFilter<T> {
48    fn prepare(&mut self, world: WorldId) {
49        if let Some(world) = self.world {
50            self.history.insert(world, self.maximum);
51        }
52
53        self.world = Some(world);
54        self.threshold = *self.history.entry(world).or_insert(0);
55        self.maximum = self.threshold;
56    }
57
58    fn matches_archetype<Fet: Fetch>(&mut self, fetch: &Fet) -> FilterResult {
59        if let Some(version) = fetch.version::<T>() {
60            if version > self.maximum {
61                self.maximum = version;
62            }
63            FilterResult::Match(version > self.threshold)
64        } else {
65            FilterResult::Defer
66        }
67    }
68}
69
70impl<T: Component> std::ops::Not for ComponentChangedFilter<T> {
71    type Output = Not<Self>;
72
73    #[inline]
74    fn not(self) -> Self::Output {
75        Not { filter: self }
76    }
77}
78
79impl<'a, T: Component, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for ComponentChangedFilter<T> {
80    type Output = And<(Self, Rhs)>;
81
82    #[inline]
83    fn bitand(self, rhs: Rhs) -> Self::Output {
84        And {
85            filters: (self, rhs),
86        }
87    }
88}
89
90impl<'a, T: Component> std::ops::BitAnd<Passthrough> for ComponentChangedFilter<T> {
91    type Output = Self;
92
93    #[inline]
94    fn bitand(self, _: Passthrough) -> Self::Output {
95        self
96    }
97}
98
99impl<'a, T: Component, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for ComponentChangedFilter<T> {
100    type Output = Or<(Self, Rhs)>;
101
102    #[inline]
103    fn bitor(self, rhs: Rhs) -> Self::Output {
104        Or {
105            filters: (self, rhs),
106        }
107    }
108}
109
110impl<'a, T: Component> std::ops::BitOr<Passthrough> for ComponentChangedFilter<T> {
111    type Output = Self;
112
113    #[inline]
114    fn bitor(self, _: Passthrough) -> Self::Output {
115        self
116    }
117}