Skip to main content

concinnity_core/physics/layers/
mask.rs

1// The membership/filter bit pair a collider or query carries. Layer *names*
2// belong to the authored world, so resolving them is the driver's job; by the
3// time a mask reaches the simulation it is two words of bits.
4
5/// Membership and filter bits applied to a collider or query.
6///
7/// Two colliders interact only when each one's memberships intersect the
8/// other's filter, so a one-way filter still blocks the pair.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct LayerMask {
11    /// Layers this collider or query belongs to.
12    pub memberships: u32,
13    /// Layers this collider or query interacts with.
14    pub filter: u32,
15}
16
17impl LayerMask {
18    /// Member of every layer, interacting with everything.
19    pub const ALL: LayerMask = LayerMask {
20        memberships: u32::MAX,
21        filter: u32::MAX,
22    };
23
24    /// Whether two masks admit each other. The same rule governs a query
25    /// against a collider, with the query carrying one of the two masks.
26    pub(crate) const fn interacts_with(self, other: LayerMask) -> bool {
27        (self.memberships & other.filter) != 0 && (other.memberships & self.filter) != 0
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn everything_admits_everything() {
37        assert!(LayerMask::ALL.interacts_with(LayerMask::ALL));
38    }
39
40    #[test]
41    fn a_one_way_filter_blocks_the_pair_from_both_sides() {
42        let open = LayerMask::ALL;
43        let closed = LayerMask {
44            memberships: u32::MAX,
45            filter: 0,
46        };
47        assert!(!open.interacts_with(closed));
48        assert!(!closed.interacts_with(open));
49    }
50
51    #[test]
52    fn disjoint_layers_never_meet() {
53        let first = LayerMask {
54            memberships: 0b01,
55            filter: 0b01,
56        };
57        let second = LayerMask {
58            memberships: 0b10,
59            filter: 0b10,
60        };
61        assert!(!first.interacts_with(second));
62        assert!(first.interacts_with(first));
63    }
64}