Skip to main content

gizmo_physics/components/
collision_layer.rs

1use serde::{Deserialize, Serialize};
2
3pub const LAYER_DEFAULT: u32 = 0;
4pub const LAYER_PLAYER: u32 = 1;
5pub const LAYER_ENEMY: u32 = 2;
6pub const LAYER_TRIGGER: u32 = 3;
7
8#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
9pub struct CollisionLayer {
10    pub layer: u32, // Which layer this object is on (0-31)
11    pub mask: u32,  // Which layers this object collides with (bitfield)
12}
13
14impl Default for CollisionLayer {
15    fn default() -> Self {
16        Self {
17            layer: LAYER_DEFAULT,
18            mask: u32::MAX, // Collide with everything by default
19        }
20    }
21}
22
23impl CollisionLayer {
24    pub fn new(layer: u32) -> Self {
25        Self {
26            layer,
27            mask: u32::MAX,
28        }
29    }
30
31    pub fn from_layer(layer: u32) -> Self {
32        Self::new(layer)
33    }
34
35    pub fn with_mask(mut self, mask: u32) -> Self {
36        self.mask = mask;
37        self
38    }
39
40    pub fn mask_from_layers(layers: &[u32]) -> u32 {
41        layers
42            .iter()
43            .fold(0u32, |acc, &l| acc | (1u32.checked_shl(l).unwrap_or(0)))
44    }
45
46    #[inline]
47    pub fn can_collide_with(&self, other: &CollisionLayer) -> bool {
48        debug_assert!(
49            self.layer < 32,
50            "CollisionLayer: layer {} >= 32",
51            self.layer
52        );
53        debug_assert!(
54            other.layer < 32,
55            "CollisionLayer: layer {} >= 32",
56            other.layer
57        );
58
59        let layer_bit = 1u32.checked_shl(self.layer).unwrap_or(0);
60        let other_layer_bit = 1u32.checked_shl(other.layer).unwrap_or(0);
61        (self.mask & other_layer_bit) != 0 && (other.mask & layer_bit) != 0
62    }
63}
64
65gizmo_core::impl_component!(CollisionLayer);