bevy_rapier3d/dynamics/
joint.rs

1use bevy::prelude::*;
2use rapier::dynamics::{ImpulseJointHandle, MultibodyJointHandle};
3
4pub use rapier::dynamics::{JointAxesMask, JointAxis, MotorModel};
5
6use super::{FixedJoint, GenericJoint, PrismaticJoint, RevoluteJoint, RopeJoint, SpringJoint};
7
8#[cfg(feature = "dim3")]
9use super::SphericalJoint;
10
11/// Wrapper enum over a specific joint.
12#[derive(Clone, Copy, Debug, PartialEq)]
13pub enum TypedJoint {
14    /// See [`FixedJoint`]
15    FixedJoint(FixedJoint),
16    /// See [`GenericJoint`]
17    GenericJoint(GenericJoint),
18    /// See [`PrismaticJoint`]
19    PrismaticJoint(PrismaticJoint),
20    /// See [`RevoluteJoint`]
21    RevoluteJoint(RevoluteJoint),
22    /// See [`RopeJoint`]
23    RopeJoint(RopeJoint),
24    /// See [`SphericalJoint`]
25    #[cfg(feature = "dim3")]
26    SphericalJoint(SphericalJoint),
27    /// See [`SpringJoint`]
28    SpringJoint(SpringJoint),
29}
30
31impl AsMut<GenericJoint> for TypedJoint {
32    fn as_mut(&mut self) -> &mut GenericJoint {
33        match self {
34            TypedJoint::FixedJoint(ref mut j) => &mut j.data,
35            TypedJoint::GenericJoint(ref mut j) => j,
36            TypedJoint::PrismaticJoint(ref mut j) => &mut j.data,
37            TypedJoint::RevoluteJoint(ref mut j) => &mut j.data,
38            TypedJoint::RopeJoint(ref mut j) => &mut j.data,
39            #[cfg(feature = "dim3")]
40            TypedJoint::SphericalJoint(ref mut j) => &mut j.data,
41            TypedJoint::SpringJoint(ref mut j) => &mut j.data,
42        }
43    }
44}
45
46impl AsRef<GenericJoint> for TypedJoint {
47    fn as_ref(&self) -> &GenericJoint {
48        match self {
49            TypedJoint::FixedJoint(j) => &j.data,
50            TypedJoint::GenericJoint(j) => j,
51            TypedJoint::PrismaticJoint(j) => &j.data,
52            TypedJoint::RevoluteJoint(j) => &j.data,
53            TypedJoint::RopeJoint(j) => &j.data,
54            #[cfg(feature = "dim3")]
55            TypedJoint::SphericalJoint(j) => &j.data,
56            TypedJoint::SpringJoint(j) => &j.data,
57        }
58    }
59}
60
61/// The handle of an impulse joint added to the physics scene.
62#[derive(Copy, Clone, Debug, Component)]
63pub struct RapierImpulseJointHandle(pub ImpulseJointHandle);
64
65/// The handle of a multibody joint added to the physics scene.
66#[derive(Copy, Clone, Debug, Component)]
67pub struct RapierMultibodyJointHandle(pub MultibodyJointHandle);
68
69/// An impulse-based joint attached to two entities.
70///
71/// The first end-point of the joint is the rigid-body attached to
72/// `ImpulseJoint::parent`. The second endpoint of the joint is the
73/// rigid-body attached to the entity (or the parent of the entity)
74/// containing this `ImpulseJoint` component.
75///
76/// To attach multiple impulse joints to the same rigid-body, multiple
77/// joints can be added in the children of the entity containing that
78/// rigid-body (this is similar to the technique used to attach multiple
79/// colliders to the same rigid-body).
80#[derive(Copy, Clone, Debug, PartialEq, Component)]
81pub struct ImpulseJoint {
82    /// The entity containing the rigid-body used as the first endpoint of this joint.
83    pub parent: Entity,
84    /// The joint’s description.
85    pub data: TypedJoint,
86}
87
88impl ImpulseJoint {
89    /// Initializes an impulse-based joint from its first endpoint and the joint description.
90    pub fn new(parent: Entity, data: impl Into<TypedJoint>) -> Self {
91        Self {
92            parent,
93            data: data.into(),
94        }
95    }
96}
97
98/// An joint based on generalized coordinates, attached to two entities.
99///
100/// The first end-point of the joint is the rigid-body attached to
101/// `MultibodyJoint::parent`. The second endpoint of the joint is the
102/// rigid-body attached to the entity containing this `MultibodyJoint` component.
103///
104/// Note that a set of multibody joints cannot form closed loops (for example a necklace).
105/// If a closed loop is detected, the last joint that closes the loop is ignored, and an
106/// error is printed to `stderr` (using `log::error!`).
107#[derive(Copy, Clone, Debug, PartialEq, Component)]
108pub struct MultibodyJoint {
109    /// The entity containing the rigid-body used as the first endpoint of this joint.
110    pub parent: Entity,
111    /// The joint’s description.
112    pub data: TypedJoint,
113}
114
115impl MultibodyJoint {
116    /// Initializes an joint based on reduced coordinates from its first endpoint and
117    /// the joint description.
118    pub fn new(parent: Entity, data: TypedJoint) -> Self {
119        Self { parent, data }
120    }
121}