Skip to main content

concinnity_physics/
layers.rs

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