avian3d/collision/collider/layers.rs
1use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
2
3use bevy::prelude::*;
4
5/// A layer used for determining which entities should interact with each other.
6/// Physics layers are used heavily by [`CollisionLayers`].
7///
8/// This trait can be derived for enums with `#[derive(PhysicsLayer)]`.
9pub trait PhysicsLayer: Sized + Default {
10 /// Converts the layer to a bitmask.
11 fn to_bits(&self) -> u32;
12 /// Creates a layer bitmask with all bits set to 1.
13 fn all_bits() -> u32;
14}
15
16impl<'a, L: PhysicsLayer> PhysicsLayer for &'a L
17where
18 &'a L: Default,
19{
20 fn to_bits(&self) -> u32 {
21 L::to_bits(self)
22 }
23
24 fn all_bits() -> u32 {
25 L::all_bits()
26 }
27}
28
29/// A bitmask for layers.
30///
31/// A [`LayerMask`] can be constructed from bits directly, or from types implementing [`PhysicsLayer`].
32/// The first bit `0b0001` is reserved for the default layer, which all entities belong to by default.
33///
34/// ```
35#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
36#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
37/// #
38/// #[derive(PhysicsLayer, Clone, Copy, Debug, Default)]
39/// enum GameLayer {
40/// #[default]
41/// Default, // Layer 0 - the default layer that objects are assigned to
42/// Player, // Layer 1
43/// Enemy, // Layer 2
44/// Ground, // Layer 3
45/// }
46///
47/// // The first bit is reserved for the default layer.
48/// assert_eq!(GameLayer::default().to_bits(), 1 << 0);
49///
50/// // The `GameLayer::Ground` layer is the fourth layer, so its bit value is `1 << 3`.
51/// assert_eq!(GameLayer::Ground.to_bits(), 1 << 3);
52///
53/// // Here, `GameLayer::Enemy` is automatically converted to a `LayerMask` for the comparison.
54/// assert_eq!(LayerMask(0b00100), GameLayer::Enemy);
55/// ```
56///
57/// Bitwise operations can be used to modify and combine masks:
58///
59/// ```
60#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
61#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
62/// let mask1 = LayerMask(0b0001);
63/// let mask2 = LayerMask(0b0010);
64/// assert_eq!(mask1 | mask2, LayerMask(0b0011));
65///
66/// // You can also add layers from `u32` bitmasks and compare against them directly.
67/// assert_eq!(mask1 | 0b0010, 0b0011);
68/// ```
69///
70/// Another way to use [`LayerMask`] is to define layers as constants:
71///
72/// ```
73#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
74#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
75/// // `1 << n` is bitshifting: the first layer shifted by `n` layers.
76/// pub const FIRST_LAYER: LayerMask = LayerMask(1 << 0);
77/// pub const LAST_LAYER: LayerMask = LayerMask(1 << 31);
78///
79/// // Bitwise operations for `LayerMask` unfortunately can't be const, so we need to access the `u32` values.
80/// pub const COMBINED: LayerMask = LayerMask(FIRST_LAYER.0 | LAST_LAYER.0);
81/// ```
82#[derive(Reflect, Clone, Copy, Debug, Deref, DerefMut, Eq, PartialOrd, Ord)]
83#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
84#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
85#[reflect(Debug, PartialEq)]
86pub struct LayerMask(pub u32);
87
88impl From<u32> for LayerMask {
89 fn from(layer: u32) -> Self {
90 Self(layer)
91 }
92}
93
94impl<L: PhysicsLayer> From<L> for LayerMask {
95 fn from(layer: L) -> Self {
96 LayerMask(layer.to_bits())
97 }
98}
99
100impl<L: Into<LayerMask>, const N: usize> From<[L; N]> for LayerMask {
101 fn from(value: [L; N]) -> Self {
102 let mut bits = 0;
103
104 for layer in value.into_iter().map(|l| {
105 let layers: LayerMask = l.into();
106 layers
107 }) {
108 bits |= layer.0;
109 }
110
111 LayerMask(bits)
112 }
113}
114
115impl LayerMask {
116 /// Contains all layers.
117 pub const ALL: Self = Self(0xffff_ffff);
118 /// Contains no layers.
119 pub const NONE: Self = Self(0);
120 /// Contains the default layer.
121 pub const DEFAULT: Self = Self(1);
122
123 /// Adds the given `layers` to `self`.
124 ///
125 /// # Example
126 ///
127 /// ```
128 #[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
129 #[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
130 /// let mut layers = LayerMask(0b1010);
131 ///
132 /// // These are equivalent
133 /// layers.add(0b0001);
134 /// layers |= 0b0001;
135 ///
136 /// assert_eq!(layers, 0b1011);
137 /// ```
138 pub fn add(&mut self, layers: impl Into<Self>) {
139 let layers: LayerMask = layers.into();
140 *self |= layers;
141 }
142
143 /// Removes the given `layers` from `self`.
144 ///
145 /// # Example
146 ///
147 /// ```
148 #[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
149 #[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
150 /// let mut layers = LayerMask(0b1010);
151 ///
152 /// // These are equivalent
153 /// layers.remove(0b0010);
154 /// layers &= !0b0010;
155 ///
156 /// assert_eq!(layers, 0b1000);
157 /// ```
158 pub fn remove(&mut self, layers: impl Into<Self>) {
159 let layers: LayerMask = layers.into();
160 *self &= !layers;
161 }
162
163 /// Returns `true` if `self` contains all of the given `layers`.
164 ///
165 /// # Example
166 ///
167 /// ```
168 #[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
169 #[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
170 /// let mut layers = LayerMask(0b1010);
171 ///
172 /// // These are equivalent
173 /// assert!(layers.has_all(0b1010));
174 /// assert!((layers & 0b1010) != 0);
175 ///
176 /// assert!(!layers.has_all(0b0100));
177 /// assert!((layers & 0b0100) == 0);
178 /// ```
179 #[doc(alias = "contains_all")]
180 pub fn has_all(self, layers: impl Into<Self>) -> bool {
181 let layers: LayerMask = layers.into();
182 (self & layers) != 0
183 }
184}
185
186impl<L: Into<LayerMask> + Copy> PartialEq<L> for LayerMask {
187 fn eq(&self, other: &L) -> bool {
188 let other: Self = (*other).into();
189 self.0 == other.0
190 }
191}
192
193impl<L: Into<LayerMask>> BitAnd<L> for LayerMask {
194 type Output = Self;
195
196 fn bitand(self, rhs: L) -> Self::Output {
197 Self(self.0 & rhs.into().0)
198 }
199}
200
201impl<L: Into<LayerMask>> BitAndAssign<L> for LayerMask {
202 fn bitand_assign(&mut self, rhs: L) {
203 self.0 = self.0 & rhs.into().0;
204 }
205}
206
207impl<L: Into<LayerMask>> BitOr<L> for LayerMask {
208 type Output = Self;
209
210 fn bitor(self, rhs: L) -> Self::Output {
211 Self(self.0 | rhs.into().0)
212 }
213}
214
215impl<L: Into<LayerMask>> BitOrAssign<L> for LayerMask {
216 fn bitor_assign(&mut self, rhs: L) {
217 self.0 = self.0 | rhs.into().0;
218 }
219}
220
221impl<L: Into<LayerMask>> BitXor<L> for LayerMask {
222 type Output = Self;
223
224 fn bitxor(self, rhs: L) -> Self::Output {
225 Self(self.0 ^ rhs.into().0)
226 }
227}
228
229impl<L: Into<LayerMask>> BitXorAssign<L> for LayerMask {
230 fn bitxor_assign(&mut self, rhs: L) {
231 self.0 = self.0 ^ rhs.into().0;
232 }
233}
234
235impl Not for LayerMask {
236 type Output = Self;
237
238 fn not(self) -> Self::Output {
239 Self(!self.0)
240 }
241}
242
243/// Defines the collision layers of a collider using *memberships* and *filters*.
244///
245/// **Memberships** indicate what layers the collider is a part of.\
246/// **Filters** indicate what layers the collider can interact with.
247///
248/// Two colliders `A` and `B` can interact if and only if:
249///
250/// - The memberships of `A` contain a layer that is also in the filters of `B`
251/// - The memberships of `B` contain a layer that is also in the filters of `A`
252///
253/// The memberships and filters are stored as [`LayerMask`]s, which represent [bitmasks] for layers.
254/// The first bit `0b0001` is reserved for the default layer, which all entities belong to by default.
255///
256/// By default, colliders have all filters and can interact with any layer.
257///
258/// [bitmasks]: https://en.wikipedia.org/wiki/Mask_(computing)
259///
260/// # Creation
261///
262/// Collision layers store memberships and filters using [`LayerMask`]s. A [`LayerMask`] can be created using
263/// bitmasks, or by creating an enum that implements [`PhysicsLayer`].
264///
265/// Many [`CollisionLayers`] methods can take any type that implements `Into<LayerMask>`.
266/// For example, you can use bitmasks with [`CollisionLayers::new`]:
267///
268/// ```
269#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
270#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
271/// #
272/// // Belongs to the second layer and interacts with colliders
273/// // on the first, second, and third layer.
274/// let layers = CollisionLayers::new(0b00010, 0b0111);
275/// ```
276///
277/// You can also use an enum that implements [`PhysicsLayer`]:
278///
279/// ```
280#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
281#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
282/// #
283/// #[derive(PhysicsLayer, Default)]
284/// enum GameLayer {
285/// #[default]
286/// Default, // Layer 0 - the default layer that objects are assigned to
287/// Player, // Layer 1
288/// Enemy, // Layer 2
289/// Ground, // Layer 3
290/// }
291///
292/// // Player collides with enemies and the ground, but not with other players
293/// let layers = CollisionLayers::new(
294/// GameLayer::Player,
295/// [GameLayer::Default, GameLayer::Enemy, GameLayer::Ground],
296/// );
297/// ```
298///
299/// You can also use [`LayerMask`] directly:
300///
301/// ```
302#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
303#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
304/// #
305/// // Belongs to the first layer and interacts with all layers.
306/// let layers = CollisionLayers::new(LayerMask(0b0001), LayerMask::ALL);
307/// ```
308///
309/// Layers can also be defined using constants and bitwise operations:
310///
311/// ```
312#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
313#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
314/// # use bevy::prelude::Commands;
315/// #
316/// // `1 << n` is bitshifting: the first layer shifted by `n` layers.
317/// pub const FIRST_LAYER: u32 = 1 << 0; // Note: this is the default layer.
318/// pub const SECOND_LAYER: u32 = 1 << 1;
319/// pub const LAST_LAYER: u32 = 1 << 31;
320///
321/// fn spawn(mut commands: Commands) {
322/// // This collider belongs to the first two layers and can interact with the last layer.
323/// commands.spawn((
324#[cfg_attr(feature = "2d", doc = " Collider::circle(0.5),")]
325#[cfg_attr(feature = "3d", doc = " Collider::sphere(0.5),")]
326/// CollisionLayers::from_bits(FIRST_LAYER | SECOND_LAYER, LAST_LAYER),
327/// ));
328/// }
329/// ```
330///
331/// # Modifying Layers
332///
333/// Existing [`CollisionLayers`] can be modified by simply accessing the `memberships` and `filters`
334/// and changing their [`LayerMask`]s.
335///
336/// ```
337#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
338#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
339/// let mut layers = CollisionLayers::new(0b0010, 0b1011);
340///
341/// // Add memberships (these are equivalent)
342/// layers.memberships.add(0b0001);
343/// layers.memberships |= 0b0001;
344///
345/// assert_eq!(layers.memberships, 0b0011);
346///
347/// // Remove filters
348/// layers.filters.remove(0b0001);
349/// layers.filters &= !0b0001;
350///
351/// assert_eq!(layers.filters, 0b1010);
352///
353/// // Check if layers are contained
354/// assert!(layers.memberships.has_all(0b0011));
355/// assert!((layers.memberships & 0b0011) != 0);
356/// ```
357#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq, Eq)]
358#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
359#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
360#[reflect(Debug, Component, PartialEq)]
361pub struct CollisionLayers {
362 /// The layers that an entity belongs to.
363 #[doc(alias = "groups", alias = "layers")]
364 pub memberships: LayerMask,
365 /// The layers that an entity can interact with.
366 #[doc(alias = "masks", alias = "layer_mask")]
367 pub filters: LayerMask,
368}
369
370impl CollisionLayers {
371 /// Contains the default layer and all filters.
372 pub const DEFAULT: Self = Self {
373 memberships: LayerMask::DEFAULT,
374 filters: LayerMask::ALL,
375 };
376
377 /// Contains all memberships and filters.
378 pub const ALL: Self = Self {
379 memberships: LayerMask::ALL,
380 filters: LayerMask::ALL,
381 };
382
383 /// Contains no memberships and no filters.
384 pub const NONE: Self = Self {
385 memberships: LayerMask::NONE,
386 filters: LayerMask::NONE,
387 };
388
389 /// Contains all memberships but no filters.
390 pub const ALL_MEMBERSHIPS: Self = Self {
391 memberships: LayerMask::ALL,
392 filters: LayerMask::NONE,
393 };
394
395 /// Contains all filters but no memberships.
396 pub const ALL_FILTERS: Self = Self {
397 memberships: LayerMask::NONE,
398 filters: LayerMask::ALL,
399 };
400
401 /// Creates a new [`CollisionLayers`] configuration with the given collision memberships and filters.
402 pub fn new(memberships: impl Into<LayerMask>, filters: impl Into<LayerMask>) -> Self {
403 Self {
404 memberships: memberships.into(),
405 filters: filters.into(),
406 }
407 }
408
409 /// Creates a new [`CollisionLayers`] configuration using bits.
410 ///
411 /// There is one bit per group and mask, so there are a total of 32 layers.
412 /// For example, if an entity is a part of the layers `[0, 1, 3]` and can interact with the layers `[1, 2]`,
413 /// the memberships in bits would be `0b01011` while the filters would be `0b00110`.
414 pub const fn from_bits(memberships: u32, filters: u32) -> Self {
415 Self {
416 memberships: LayerMask(memberships),
417 filters: LayerMask(filters),
418 }
419 }
420
421 /// Returns true if an entity with this [`CollisionLayers`] configuration
422 /// can interact with an entity with the `other` [`CollisionLayers`] configuration.
423 pub fn interacts_with(self, other: Self) -> bool {
424 (self.memberships & other.filters) != LayerMask::NONE
425 && (other.memberships & self.filters) != LayerMask::NONE
426 }
427}
428
429impl Default for CollisionLayers {
430 fn default() -> Self {
431 CollisionLayers::DEFAULT
432 }
433}
434
435#[cfg(test)]
436mod tests {
437 use crate::prelude::*;
438
439 #[derive(PhysicsLayer, Default)]
440 enum GameLayer {
441 #[default]
442 Default,
443 Player,
444 Enemy,
445 Ground,
446 }
447
448 #[test]
449 fn creation() {
450 let with_bitmask = CollisionLayers::new(0b00100, 0b01011);
451 let with_enum = CollisionLayers::new(
452 GameLayer::Enemy,
453 [GameLayer::Default, GameLayer::Player, GameLayer::Ground],
454 );
455 let with_layers =
456 CollisionLayers::new(LayerMask::from(GameLayer::Enemy), LayerMask(0b01011));
457
458 assert_eq!(with_bitmask, with_enum);
459 assert_eq!(with_bitmask, with_layers);
460
461 assert!(with_bitmask.memberships.has_all(GameLayer::Enemy));
462 assert!(!with_bitmask.memberships.has_all(GameLayer::Player));
463
464 assert!(with_bitmask
465 .filters
466 .has_all([GameLayer::Player, GameLayer::Ground]));
467 assert!(!with_bitmask.filters.has_all(GameLayer::Enemy));
468 }
469}