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
use std::{collections::HashMap, marker::PhantomData};

use super::{
    and::And, not::Not, or::Or, passthrough::Passthrough, ActiveFilter, DynamicFilter, FilterResult,
};
use crate::internals::{query::view::Fetch, storage::component::Component, world::WorldId};

/// A filter which performs coarse-grained change detection.
///
/// This filter will reject _most_ components which have not
/// been changed, but not all.
#[derive(Debug)]
pub struct ComponentChangedFilter<T: Component> {
    _phantom: PhantomData<T>,
    history: HashMap<WorldId, u64>,
    world: Option<WorldId>,
    threshold: u64,
    maximum: u64,
}

impl<T: Component> Default for ComponentChangedFilter<T> {
    fn default() -> Self {
        Self {
            _phantom: PhantomData,
            history: Default::default(),
            world: None,
            threshold: 0,
            maximum: 0,
        }
    }
}

impl<T: Component> Clone for ComponentChangedFilter<T> {
    fn clone(&self) -> Self {
        Self {
            _phantom: PhantomData,
            history: self.history.clone(),
            world: None,
            threshold: 0,
            maximum: 0,
        }
    }
}

impl<T: Component> ActiveFilter for ComponentChangedFilter<T> {}

impl<T: Component> DynamicFilter for ComponentChangedFilter<T> {
    fn prepare(&mut self, world: WorldId) {
        if let Some(world) = self.world {
            self.history.insert(world, self.maximum);
        }

        self.world = Some(world);
        self.threshold = *self.history.entry(world).or_insert(0);
        self.maximum = self.threshold;
    }

    fn matches_archetype<Fet: Fetch>(&mut self, fetch: &Fet) -> FilterResult {
        if let Some(version) = fetch.version::<T>() {
            if version > self.maximum {
                self.maximum = version;
            }
            FilterResult::Match(version > self.threshold)
        } else {
            FilterResult::Defer
        }
    }
}

impl<T: Component> std::ops::Not for ComponentChangedFilter<T> {
    type Output = Not<Self>;

    #[inline]
    fn not(self) -> Self::Output {
        Not { filter: self }
    }
}

impl<'a, T: Component, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for ComponentChangedFilter<T> {
    type Output = And<(Self, Rhs)>;

    #[inline]
    fn bitand(self, rhs: Rhs) -> Self::Output {
        And {
            filters: (self, rhs),
        }
    }
}

impl<'a, T: Component> std::ops::BitAnd<Passthrough> for ComponentChangedFilter<T> {
    type Output = Self;

    #[inline]
    fn bitand(self, _: Passthrough) -> Self::Output {
        self
    }
}

impl<'a, T: Component, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for ComponentChangedFilter<T> {
    type Output = Or<(Self, Rhs)>;

    #[inline]
    fn bitor(self, rhs: Rhs) -> Self::Output {
        Or {
            filters: (self, rhs),
        }
    }
}

impl<'a, T: Component> std::ops::BitOr<Passthrough> for ComponentChangedFilter<T> {
    type Output = Self;

    #[inline]
    fn bitor(self, _: Passthrough) -> Self::Output {
        self
    }
}