use bevy::prelude::*;
use derive_more::From;
use crate::prelude::*;
#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
#[cfg_attr(feature = "2d", doc = " LockedAxes::ROTATION_LOCKED,")]
#[cfg_attr(feature = "3d", doc = " LockedAxes::new().lock_rotation_z(),")]
#[derive(Component, Reflect, Clone, Copy, Debug, Default, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default)]
pub struct LockedAxes(u8);
impl LockedAxes {
pub const TRANSLATION_LOCKED: Self = Self(0b111_000);
pub const ROTATION_LOCKED: Self = Self(0b000_111);
pub const ALL_LOCKED: Self = Self(0b111_111);
pub const fn new() -> Self {
Self(0)
}
pub const fn from_bits(bits: u8) -> Self {
Self(bits)
}
pub const fn to_bits(&self) -> u8 {
self.0
}
#[must_use]
pub const fn lock_translation_x(mut self) -> Self {
self.0 |= 0b100_000;
self
}
#[must_use]
pub const fn lock_translation_y(mut self) -> Self {
self.0 |= 0b010_000;
self
}
#[cfg(feature = "3d")]
#[must_use]
pub const fn lock_translation_z(mut self) -> Self {
self.0 |= 0b001_000;
self
}
#[cfg(feature = "3d")]
pub const fn lock_rotation_x(mut self) -> Self {
self.0 |= 0b000_100;
self
}
#[cfg(feature = "3d")]
#[must_use]
pub const fn lock_rotation_y(mut self) -> Self {
self.0 |= 0b000_010;
self
}
#[cfg(feature = "3d")]
#[must_use]
pub const fn lock_rotation_z(mut self) -> Self {
self.0 |= 0b000_001;
self
}
#[cfg(feature = "2d")]
#[must_use]
pub const fn lock_rotation(mut self) -> Self {
self.0 |= 0b000_001;
self
}
#[must_use]
pub const fn unlock_translation_x(mut self) -> Self {
self.0 &= !0b100_000;
self
}
#[must_use]
pub const fn unlock_translation_y(mut self) -> Self {
self.0 &= !0b010_000;
self
}
#[cfg(feature = "3d")]
#[must_use]
pub const fn unlock_translation_z(mut self) -> Self {
self.0 &= !0b001_000;
self
}
#[cfg(feature = "3d")]
#[must_use]
pub const fn unlock_rotation_x(mut self) -> Self {
self.0 &= !0b000_100;
self
}
#[cfg(feature = "3d")]
#[must_use]
pub const fn unlock_rotation_y(mut self) -> Self {
self.0 &= !0b000_010;
self
}
#[cfg(feature = "3d")]
#[must_use]
pub const fn unlock_rotation_z(mut self) -> Self {
self.0 &= !0b000_001;
self
}
#[cfg(feature = "2d")]
#[must_use]
pub const fn unlock_rotation(mut self) -> Self {
self.0 &= !0b000_001;
self
}
pub const fn is_translation_x_locked(&self) -> bool {
(self.0 & 0b100_000) != 0
}
pub const fn is_translation_y_locked(&self) -> bool {
(self.0 & 0b010_000) != 0
}
#[cfg(feature = "3d")]
pub const fn is_translation_z_locked(&self) -> bool {
(self.0 & 0b001_000) != 0
}
#[cfg(feature = "2d")]
pub const fn is_translation_locked(&self) -> bool {
(self.0 & 0b110_000) == 0b110_000
}
#[cfg(feature = "3d")]
pub const fn is_translation_locked(&self) -> bool {
(self.0 & 0b111_000) == 0b111_000
}
#[cfg(feature = "3d")]
pub const fn is_rotation_x_locked(&self) -> bool {
(self.0 & 0b000_100) != 0
}
#[cfg(feature = "3d")]
pub const fn is_rotation_y_locked(&self) -> bool {
(self.0 & 0b000_010) != 0
}
#[cfg(feature = "3d")]
pub const fn is_rotation_z_locked(&self) -> bool {
(self.0 & 0b000_001) != 0
}
#[cfg(feature = "2d")]
pub const fn is_rotation_locked(&self) -> bool {
(self.0 & 0b000_001) != 0
}
#[cfg(feature = "3d")]
pub const fn is_rotation_locked(&self) -> bool {
(self.0 & 0b000_111) == 0b000_111
}
pub(crate) fn apply_to_vec(&self, mut vector: Vector) -> Vector {
if self.is_translation_x_locked() {
vector.x = 0.0;
}
if self.is_translation_y_locked() {
vector.y = 0.0;
}
#[cfg(feature = "3d")]
if self.is_translation_z_locked() {
vector.z = 0.0;
}
vector
}
#[cfg(feature = "2d")]
pub(crate) fn apply_to_angular_inertia(
&self,
angular_inertia: impl Into<ComputedAngularInertia>,
) -> ComputedAngularInertia {
let mut angular_inertia = angular_inertia.into();
let angular_inertia_mut = angular_inertia.inverse_mut();
if self.is_rotation_locked() {
*angular_inertia_mut = 0.0;
}
angular_inertia
}
#[cfg(feature = "3d")]
pub(crate) fn apply_to_angular_inertia(
&self,
angular_inertia: impl Into<ComputedAngularInertia>,
) -> ComputedAngularInertia {
let mut angular_inertia = angular_inertia.into();
let angular_inertia_mut = angular_inertia.inverse_mut();
if self.is_rotation_x_locked() {
angular_inertia_mut.m00 = 0.0;
angular_inertia_mut.m01 = 0.0;
angular_inertia_mut.m02 = 0.0;
}
if self.is_rotation_y_locked() {
angular_inertia_mut.m11 = 0.0;
angular_inertia_mut.m01 = 0.0;
angular_inertia_mut.m12 = 0.0;
}
if self.is_rotation_z_locked() {
angular_inertia_mut.m22 = 0.0;
angular_inertia_mut.m02 = 0.0;
angular_inertia_mut.m12 = 0.0;
}
angular_inertia
}
#[cfg(feature = "2d")]
pub(crate) fn apply_to_angular_velocity(&self, mut angular_velocity: Scalar) -> Scalar {
if self.is_rotation_locked() {
angular_velocity = 0.0;
}
angular_velocity
}
#[cfg(feature = "3d")]
pub(crate) fn apply_to_angular_velocity(&self, mut angular_velocity: Vector) -> Vector {
if self.is_rotation_x_locked() {
angular_velocity.x = 0.0;
}
if self.is_rotation_y_locked() {
angular_velocity.y = 0.0;
}
if self.is_rotation_z_locked() {
angular_velocity.z = 0.0;
}
angular_velocity
}
}