use bevy::prelude::*;
pub trait PhysicsLayer: Sized {
fn to_bits(&self) -> u32;
fn all_bits() -> u32;
}
impl<L: PhysicsLayer> PhysicsLayer for &L {
fn to_bits(&self) -> u32 {
L::to_bits(self)
}
fn all_bits() -> u32 {
L::all_bits()
}
}
#[cfg_attr(feature = "2d", doc = "use bevy_xpbd_2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use bevy_xpbd_3d::prelude::*;")]
#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq)]
#[reflect(Component)]
pub struct CollisionLayers {
groups: u32,
masks: u32,
}
impl CollisionLayers {
pub fn new<L: PhysicsLayer>(
groups: impl IntoIterator<Item = L>,
masks: impl IntoIterator<Item = L>,
) -> Self {
Self::none().add_groups(groups).add_masks(masks)
}
pub fn all<L: PhysicsLayer>() -> Self {
Self::from_bits(L::all_bits(), L::all_bits())
}
pub fn all_groups<L: PhysicsLayer>() -> Self {
Self::from_bits(L::all_bits(), 0)
}
pub fn all_masks<L: PhysicsLayer>() -> Self {
Self::from_bits(0, L::all_bits())
}
pub const fn none() -> Self {
Self::from_bits(0, 0)
}
pub const fn from_bits(groups: u32, masks: u32) -> Self {
Self { groups, masks }
}
pub fn interacts_with(self, other: Self) -> bool {
(self.groups & other.masks) != 0 && (other.groups & self.masks) != 0
}
pub fn contains_group(self, layer: impl PhysicsLayer) -> bool {
(self.groups & layer.to_bits()) != 0
}
pub fn add_group(mut self, layer: impl PhysicsLayer) -> Self {
self.groups |= layer.to_bits();
self
}
pub fn add_groups(mut self, layers: impl IntoIterator<Item = impl PhysicsLayer>) -> Self {
for layer in layers.into_iter().map(|l| l.to_bits()) {
self.groups |= layer;
}
self
}
pub fn remove_group(mut self, layer: impl PhysicsLayer) -> Self {
self.groups &= !layer.to_bits();
self
}
pub fn remove_groups(mut self, layers: impl IntoIterator<Item = impl PhysicsLayer>) -> Self {
for layer in layers.into_iter().map(|l| l.to_bits()) {
self.groups &= !layer;
}
self
}
pub fn contains_mask(self, layer: impl PhysicsLayer) -> bool {
(self.masks & layer.to_bits()) != 0
}
pub fn add_mask(mut self, layer: impl PhysicsLayer) -> Self {
self.masks |= layer.to_bits();
self
}
pub fn add_masks(mut self, layers: impl IntoIterator<Item = impl PhysicsLayer>) -> Self {
for layer in layers.into_iter().map(|l| l.to_bits()) {
self.masks |= layer;
}
self
}
pub fn remove_mask(mut self, layer: impl PhysicsLayer) -> Self {
self.masks &= !layer.to_bits();
self
}
pub fn remove_masks(mut self, layers: impl IntoIterator<Item = impl PhysicsLayer>) -> Self {
for layer in layers.into_iter().map(|l| l.to_bits()) {
self.masks &= !layer;
}
self
}
pub fn groups_bits(self) -> u32 {
self.groups
}
pub fn masks_bits(self) -> u32 {
self.masks
}
}
impl Default for CollisionLayers {
fn default() -> Self {
Self {
groups: 0xffff_ffff,
masks: 0xffff_ffff,
}
}
}