bevy_rapier2d/dynamics/
joint.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use bevy::prelude::*;
use rapier::dynamics::{ImpulseJointHandle, MultibodyJointHandle};

pub use rapier::dynamics::{JointAxesMask, JointAxis, MotorModel};

use super::{FixedJoint, GenericJoint, PrismaticJoint, RevoluteJoint, RopeJoint, SpringJoint};

#[cfg(feature = "dim3")]
use super::SphericalJoint;

/// Wrapper enum over a specific joint.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TypedJoint {
    /// See [`FixedJoint`]
    FixedJoint(FixedJoint),
    /// See [`GenericJoint`]
    GenericJoint(GenericJoint),
    /// See [`PrismaticJoint`]
    PrismaticJoint(PrismaticJoint),
    /// See [`RevoluteJoint`]
    RevoluteJoint(RevoluteJoint),
    /// See [`RopeJoint`]
    RopeJoint(RopeJoint),
    /// See [`SphericalJoint`]
    #[cfg(feature = "dim3")]
    SphericalJoint(SphericalJoint),
    /// See [`SpringJoint`]
    SpringJoint(SpringJoint),
}

impl AsMut<GenericJoint> for TypedJoint {
    fn as_mut(&mut self) -> &mut GenericJoint {
        match self {
            TypedJoint::FixedJoint(ref mut j) => &mut j.data,
            TypedJoint::GenericJoint(ref mut j) => j,
            TypedJoint::PrismaticJoint(ref mut j) => &mut j.data,
            TypedJoint::RevoluteJoint(ref mut j) => &mut j.data,
            TypedJoint::RopeJoint(ref mut j) => &mut j.data,
            #[cfg(feature = "dim3")]
            TypedJoint::SphericalJoint(ref mut j) => &mut j.data,
            TypedJoint::SpringJoint(ref mut j) => &mut j.data,
        }
    }
}

impl AsRef<GenericJoint> for TypedJoint {
    fn as_ref(&self) -> &GenericJoint {
        match self {
            TypedJoint::FixedJoint(j) => &j.data,
            TypedJoint::GenericJoint(j) => j,
            TypedJoint::PrismaticJoint(j) => &j.data,
            TypedJoint::RevoluteJoint(j) => &j.data,
            TypedJoint::RopeJoint(j) => &j.data,
            #[cfg(feature = "dim3")]
            TypedJoint::SphericalJoint(j) => &j.data,
            TypedJoint::SpringJoint(j) => &j.data,
        }
    }
}

/// The handle of an impulse joint added to the physics scene.
#[derive(Copy, Clone, Debug, Component)]
pub struct RapierImpulseJointHandle(pub ImpulseJointHandle);

/// The handle of a multibody joint added to the physics scene.
#[derive(Copy, Clone, Debug, Component)]
pub struct RapierMultibodyJointHandle(pub MultibodyJointHandle);

/// An impulse-based joint attached to two entities.
///
/// The first end-point of the joint is the rigid-body attached to
/// `ImpulseJoint::parent`. The second endpoint of the joint is the
/// rigid-body attached to the entity (or the parent of the entity)
/// containing this `ImpulseJoint` component.
///
/// To attach multiple impulse joints to the same rigid-body, multiple
/// joints can be added in the children of the entity containing that
/// rigid-body (this is similar to the technique used to attach multiple
/// colliders to the same rigid-body).
#[derive(Copy, Clone, Debug, PartialEq, Component)]
pub struct ImpulseJoint {
    /// The entity containing the rigid-body used as the first endpoint of this joint.
    pub parent: Entity,
    /// The joint’s description.
    pub data: TypedJoint,
}

impl ImpulseJoint {
    /// Initializes an impulse-based joint from its first endpoint and the joint description.
    pub fn new(parent: Entity, data: impl Into<TypedJoint>) -> Self {
        Self {
            parent,
            data: data.into(),
        }
    }
}

/// An joint based on generalized coordinates, attached to two entities.
///
/// The first end-point of the joint is the rigid-body attached to
/// `MultibodyJoint::parent`. The second endpoint of the joint is the
/// rigid-body attached to the entity containing this `MultibodyJoint` component.
///
/// Note that a set of multibody joints cannot form closed loops (for example a necklace).
/// If a closed loop is detected, the last joint that closes the loop is ignored, and an
/// error is printed to `stderr` (using `log::error!`).
#[derive(Copy, Clone, Debug, PartialEq, Component)]
pub struct MultibodyJoint {
    /// The entity containing the rigid-body used as the first endpoint of this joint.
    pub parent: Entity,
    /// The joint’s description.
    pub data: TypedJoint,
}

impl MultibodyJoint {
    /// Initializes an joint based on reduced coordinates from its first endpoint and
    /// the joint description.
    pub fn new(parent: Entity, data: TypedJoint) -> Self {
        Self { parent, data }
    }
}