kaige_ecs/internals/query/filter/
maybe_changed.rs1use 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#[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}