trecs/tools/
filter.rs

1use std::{
2    any::{Any, TypeId},
3    collections::HashSet,
4    marker::PhantomData,
5};
6
7use crate::bundle::BundleMeta;
8#[allow(unused_imports)]
9use crate::{bundle::Bundle, tools::WorldFetch};
10/// 用来过滤[Bundle]
11///
12/// 作为[WorldFetch]的附属使用
13pub trait WorldFilter: Any {
14    /// 传入[Bundle]的components_ids
15    ///
16    /// + 返回true表示通过
17    /// + 返回false表示没
18    fn filter(components_ids: &'static [TypeId]) -> bool;
19
20    /// 加速版本,会从缓存读取,否则重新计算
21    ///
22    /// 主要是为了让嵌套的[WorldFilter]可以更快
23    fn filter_by_meta(meta: &mut BundleMeta) -> bool;
24}
25
26/// [Bundle]是B的子集时通过
27#[derive(Debug, Clone, Copy)]
28pub struct All<B: Bundle>(PhantomData<B>);
29
30/// [Bundle]与B有交集时通过
31#[derive(Debug, Clone, Copy)]
32pub struct AnyOf<B: Bundle>(PhantomData<B>);
33
34/// [Bundle]与B没有交集时通过
35#[derive(Debug, Clone, Copy)]
36pub struct Not<B: Bundle>(PhantomData<B>);
37
38impl<B: Bundle> WorldFilter for All<B> {
39    fn filter(components_ids: &'static [TypeId]) -> bool {
40        let set = B::components_ids()
41            .iter()
42            .copied()
43            .fold(HashSet::new(), |mut set, id| {
44                set.insert(id);
45                set
46            });
47        !components_ids.iter().any(|id| !set.contains(id))
48    }
49
50    fn filter_by_meta(meta: &mut BundleMeta) -> bool {
51        meta.filter::<Self>()
52    }
53}
54
55impl<B: Bundle> WorldFilter for AnyOf<B> {
56    fn filter(components_ids: &'static [TypeId]) -> bool {
57        let set = B::components_ids()
58            .iter()
59            .copied()
60            .fold(HashSet::new(), |mut set, id| {
61                set.insert(id);
62                set
63            });
64        components_ids.iter().any(|id| set.contains(id))
65    }
66
67    fn filter_by_meta(meta: &mut BundleMeta) -> bool {
68        meta.filter::<Self>()
69    }
70}
71
72impl<B: Bundle> WorldFilter for Not<B> {
73    fn filter(components_ids: &'static [TypeId]) -> bool {
74        let set = B::components_ids()
75            .iter()
76            .copied()
77            .fold(HashSet::new(), |mut set, id| {
78                set.insert(id);
79                set
80            });
81        !components_ids.iter().any(|id| set.contains(id))
82    }
83
84    fn filter_by_meta(meta: &mut BundleMeta) -> bool {
85        meta.filter::<Self>()
86    }
87}
88
89mod __impl {
90    use super::{BundleMeta, TypeId, WorldFilter};
91    macro_rules! impl_filter {
92        ($($t:ident),*) => {
93            impl<$($t:WorldFilter),*> WorldFilter for ($($t,)*) {
94                fn filter(components_ids : &'static [TypeId]) -> bool{
95                    $($t::filter(components_ids))&&*
96                }
97
98                fn filter_by_meta(meta: &mut BundleMeta) -> bool {
99                   $($t::filter_by_meta(meta))&&*
100                }
101            }
102        };
103    }
104
105    trecs_proc::all_tuple!(impl_filter, 16);
106
107    impl WorldFilter for () {
108        fn filter(_: &'static [TypeId]) -> bool {
109            true
110        }
111
112        fn filter_by_meta(_meta: &mut BundleMeta) -> bool {
113            true
114        }
115    }
116}