use crate::math::Vect;
use bevy::{prelude::*, reflect::FromReflect};
use rapier::prelude::{
Isometry, LockedAxes as RapierLockedAxes, RigidBodyActivation, RigidBodyHandle, RigidBodyType,
};
use std::ops::{Add, AddAssign, Sub, SubAssign};
#[derive(Copy, Clone, Debug, Component)]
pub struct RapierRigidBodyHandle(pub RigidBodyHandle);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Component, Reflect, FromReflect)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[reflect(Component, PartialEq)]
pub enum RigidBody {
Dynamic,
Fixed,
KinematicPositionBased,
KinematicVelocityBased,
}
impl Default for RigidBody {
fn default() -> Self {
RigidBody::Dynamic
}
}
impl From<RigidBody> for RigidBodyType {
fn from(rigid_body: RigidBody) -> RigidBodyType {
match rigid_body {
RigidBody::Dynamic => RigidBodyType::Dynamic,
RigidBody::Fixed => RigidBodyType::Fixed,
RigidBody::KinematicPositionBased => RigidBodyType::KinematicPositionBased,
RigidBody::KinematicVelocityBased => RigidBodyType::KinematicVelocityBased,
}
}
}
impl From<RigidBodyType> for RigidBody {
fn from(rigid_body: RigidBodyType) -> RigidBody {
match rigid_body {
RigidBodyType::Dynamic => RigidBody::Dynamic,
RigidBodyType::Fixed => RigidBody::Fixed,
RigidBodyType::KinematicPositionBased => RigidBody::KinematicPositionBased,
RigidBodyType::KinematicVelocityBased => RigidBody::KinematicVelocityBased,
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Component, Reflect, FromReflect)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[reflect(Component, PartialEq)]
pub struct Velocity {
pub linvel: Vect,
#[cfg(feature = "dim2")]
pub angvel: f32,
#[cfg(feature = "dim3")]
pub angvel: Vect,
}
impl Velocity {
pub const fn zero() -> Self {
Self {
linvel: Vect::ZERO,
#[cfg(feature = "dim2")]
angvel: 0.0,
#[cfg(feature = "dim3")]
angvel: Vect::ZERO,
}
}
pub const fn linear(linvel: Vect) -> Self {
Self {
linvel,
#[cfg(feature = "dim2")]
angvel: 0.0,
#[cfg(feature = "dim3")]
angvel: Vect::ZERO,
}
}
#[cfg(feature = "dim2")]
pub const fn angular(angvel: f32) -> Self {
Self {
linvel: Vect::ZERO,
angvel,
}
}
#[cfg(feature = "dim3")]
pub const fn angular(angvel: Vect) -> Self {
Self {
linvel: Vect::ZERO,
angvel,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub enum AdditionalMassProperties {
Mass(f32),
MassProperties(MassProperties),
}
impl Default for AdditionalMassProperties {
fn default() -> Self {
Self::MassProperties(MassProperties::default())
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct ReadMassProperties(pub MassProperties);
#[derive(Copy, Clone, Debug, Default, PartialEq, Reflect, FromReflect)]
#[reflect(PartialEq)]
pub struct MassProperties {
pub local_center_of_mass: Vect,
pub mass: f32,
#[cfg(feature = "dim2")]
pub principal_inertia: f32,
#[cfg(feature = "dim3")]
pub principal_inertia_local_frame: crate::math::Rot,
#[cfg(feature = "dim3")]
pub principal_inertia: Vect,
}
impl MassProperties {
#[cfg(feature = "dim2")]
pub fn into_rapier(self, physics_scale: f32) -> rapier::dynamics::MassProperties {
rapier::dynamics::MassProperties::new(
(self.local_center_of_mass / physics_scale).into(),
self.mass,
#[allow(clippy::useless_conversion)] (self.principal_inertia / (physics_scale * physics_scale)).into(),
)
}
#[cfg(feature = "dim3")]
pub fn into_rapier(self, physics_scale: f32) -> rapier::dynamics::MassProperties {
rapier::dynamics::MassProperties::with_principal_inertia_frame(
(self.local_center_of_mass / physics_scale).into(),
self.mass,
(self.principal_inertia / (physics_scale * physics_scale)).into(),
self.principal_inertia_local_frame.into(),
)
}
pub fn from_rapier(mprops: rapier::dynamics::MassProperties, physics_scale: f32) -> Self {
#[allow(clippy::useless_conversion)] Self {
mass: mprops.mass(),
local_center_of_mass: (mprops.local_com * physics_scale).into(),
principal_inertia: (mprops.principal_inertia() * (physics_scale * physics_scale))
.into(),
#[cfg(feature = "dim3")]
principal_inertia_local_frame: mprops.principal_inertia_local_frame.into(),
}
}
}
bitflags::bitflags! {
#[derive(Default, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct LockedAxes: u8 {
const TRANSLATION_LOCKED_X = 1 << 0;
const TRANSLATION_LOCKED_Y = 1 << 1;
const TRANSLATION_LOCKED_Z = 1 << 2;
const TRANSLATION_LOCKED = Self::TRANSLATION_LOCKED_X.bits | Self::TRANSLATION_LOCKED_Y.bits | Self::TRANSLATION_LOCKED_Z.bits;
const ROTATION_LOCKED_X = 1 << 3;
const ROTATION_LOCKED_Y = 1 << 4;
const ROTATION_LOCKED_Z = 1 << 5;
const ROTATION_LOCKED = Self::ROTATION_LOCKED_X.bits | Self::ROTATION_LOCKED_Y.bits | Self::ROTATION_LOCKED_Z.bits;
}
}
impl From<LockedAxes> for RapierLockedAxes {
fn from(locked_axes: LockedAxes) -> RapierLockedAxes {
RapierLockedAxes::from_bits(locked_axes.bits()).expect("Internal conversion error.")
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct ExternalForce {
pub force: Vect,
#[cfg(feature = "dim2")]
pub torque: f32,
#[cfg(feature = "dim3")]
pub torque: Vect,
}
impl ExternalForce {
pub fn at_point(force: Vect, point: Vect, center_of_mass: Vect) -> Self {
Self {
force,
#[cfg(feature = "dim2")]
torque: (point - center_of_mass).perp_dot(force),
#[cfg(feature = "dim3")]
torque: (point - center_of_mass).cross(force),
}
}
}
impl Add for ExternalForce {
type Output = Self;
#[inline]
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl Sub for ExternalForce {
type Output = Self;
#[inline]
fn sub(mut self, rhs: Self) -> Self::Output {
self -= rhs;
self
}
}
impl AddAssign for ExternalForce {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.force += rhs.force;
self.torque += rhs.torque;
}
}
impl SubAssign for ExternalForce {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
self.force -= rhs.force;
self.torque -= rhs.torque;
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct ExternalImpulse {
pub impulse: Vect,
#[cfg(feature = "dim2")]
pub torque_impulse: f32,
#[cfg(feature = "dim3")]
pub torque_impulse: Vect,
}
impl ExternalImpulse {
pub fn at_point(impulse: Vect, point: Vect, center_of_mass: Vect) -> Self {
Self {
impulse,
#[cfg(feature = "dim2")]
torque_impulse: (point - center_of_mass).perp_dot(impulse),
#[cfg(feature = "dim3")]
torque_impulse: (point - center_of_mass).cross(impulse),
}
}
pub fn reset(&mut self) {
*self = Default::default();
}
}
impl Add for ExternalImpulse {
type Output = Self;
#[inline]
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl Sub for ExternalImpulse {
type Output = Self;
#[inline]
fn sub(mut self, rhs: Self) -> Self::Output {
self -= rhs;
self
}
}
impl AddAssign for ExternalImpulse {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.impulse += rhs.impulse;
self.torque_impulse += rhs.torque_impulse;
}
}
impl SubAssign for ExternalImpulse {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
self.impulse -= rhs.impulse;
self.torque_impulse -= rhs.torque_impulse;
}
}
#[derive(Copy, Clone, Debug, PartialEq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct GravityScale(pub f32);
impl Default for GravityScale {
fn default() -> Self {
Self(1.0)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct Ccd {
pub enabled: bool,
}
impl Ccd {
pub fn enabled() -> Self {
Self { enabled: true }
}
pub fn disabled() -> Self {
Self { enabled: false }
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct Dominance {
pub groups: i8,
}
impl Dominance {
pub fn group(group: i8) -> Self {
Self { groups: group }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct Sleeping {
pub linear_threshold: f32,
pub angular_threshold: f32,
pub sleeping: bool,
}
impl Sleeping {
pub fn disabled() -> Self {
Self {
linear_threshold: -1.0,
angular_threshold: -1.0,
sleeping: false,
}
}
}
impl Default for Sleeping {
fn default() -> Self {
Self {
linear_threshold: RigidBodyActivation::default_linear_threshold(),
angular_threshold: RigidBodyActivation::default_angular_threshold(),
sleeping: false,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct Damping {
pub linear_damping: f32,
pub angular_damping: f32,
}
impl Default for Damping {
fn default() -> Self {
Self {
linear_damping: 0.0,
angular_damping: 0.0,
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Component)]
pub struct TransformInterpolation {
pub start: Option<Isometry<f32>>,
pub end: Option<Isometry<f32>>,
}
impl TransformInterpolation {
pub fn lerp_slerp(&self, t: f32) -> Option<Isometry<f32>> {
if let (Some(start), Some(end)) = (self.start, self.end) {
Some(start.lerp_slerp(&end, t))
} else {
None
}
}
}
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, Component, Reflect, FromReflect)]
#[reflect(Component, PartialEq)]
pub struct RigidBodyDisabled;