avian3d/dynamics/rigid_body/
locked_axes.rs1use bevy::prelude::*;
2use derive_more::From;
3
4use crate::prelude::*;
5
6#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
16#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
17#[cfg_attr(feature = "2d", doc = " LockedAxes::ROTATION_LOCKED,")]
24#[cfg_attr(feature = "3d", doc = " LockedAxes::new().lock_rotation_z(),")]
25#[derive(Component, Reflect, Clone, Copy, Debug, Default, From)]
29#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
30#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
31#[reflect(Debug, Component, Default)]
32pub struct LockedAxes(u8);
33
34impl LockedAxes {
35 pub const TRANSLATION_LOCKED: Self = Self(0b111_000);
37 pub const ROTATION_LOCKED: Self = Self(0b000_111);
39 pub const ALL_LOCKED: Self = Self(0b111_111);
41
42 pub const fn new() -> Self {
44 Self(0)
45 }
46
47 pub const fn from_bits(bits: u8) -> Self {
52 Self(bits)
53 }
54
55 pub const fn to_bits(&self) -> u8 {
61 self.0
62 }
63
64 #[must_use]
66 pub const fn lock_translation_x(mut self) -> Self {
67 self.0 |= 0b100_000;
68 self
69 }
70
71 #[must_use]
73 pub const fn lock_translation_y(mut self) -> Self {
74 self.0 |= 0b010_000;
75 self
76 }
77
78 #[cfg(feature = "3d")]
80 #[must_use]
81 pub const fn lock_translation_z(mut self) -> Self {
82 self.0 |= 0b001_000;
83 self
84 }
85
86 #[cfg(feature = "3d")]
88 pub const fn lock_rotation_x(mut self) -> Self {
89 self.0 |= 0b000_100;
90 self
91 }
92
93 #[cfg(feature = "3d")]
95 #[must_use]
96 pub const fn lock_rotation_y(mut self) -> Self {
97 self.0 |= 0b000_010;
98 self
99 }
100
101 #[cfg(feature = "3d")]
103 #[must_use]
104 pub const fn lock_rotation_z(mut self) -> Self {
105 self.0 |= 0b000_001;
106 self
107 }
108
109 #[cfg(feature = "2d")]
111 #[must_use]
112 pub const fn lock_rotation(mut self) -> Self {
113 self.0 |= 0b000_001;
114 self
115 }
116
117 #[must_use]
119 pub const fn unlock_translation_x(mut self) -> Self {
120 self.0 &= !0b100_000;
121 self
122 }
123
124 #[must_use]
126 pub const fn unlock_translation_y(mut self) -> Self {
127 self.0 &= !0b010_000;
128 self
129 }
130
131 #[cfg(feature = "3d")]
133 #[must_use]
134 pub const fn unlock_translation_z(mut self) -> Self {
135 self.0 &= !0b001_000;
136 self
137 }
138
139 #[cfg(feature = "3d")]
141 #[must_use]
142 pub const fn unlock_rotation_x(mut self) -> Self {
143 self.0 &= !0b000_100;
144 self
145 }
146
147 #[cfg(feature = "3d")]
149 #[must_use]
150 pub const fn unlock_rotation_y(mut self) -> Self {
151 self.0 &= !0b000_010;
152 self
153 }
154
155 #[cfg(feature = "3d")]
157 #[must_use]
158 pub const fn unlock_rotation_z(mut self) -> Self {
159 self.0 &= !0b000_001;
160 self
161 }
162
163 #[cfg(feature = "2d")]
165 #[must_use]
166 pub const fn unlock_rotation(mut self) -> Self {
167 self.0 &= !0b000_001;
168 self
169 }
170
171 pub const fn is_translation_x_locked(&self) -> bool {
173 (self.0 & 0b100_000) != 0
174 }
175
176 pub const fn is_translation_y_locked(&self) -> bool {
178 (self.0 & 0b010_000) != 0
179 }
180
181 #[cfg(feature = "3d")]
183 pub const fn is_translation_z_locked(&self) -> bool {
184 (self.0 & 0b001_000) != 0
185 }
186
187 #[cfg(feature = "3d")]
189 pub const fn is_rotation_x_locked(&self) -> bool {
190 (self.0 & 0b000_100) != 0
191 }
192
193 #[cfg(feature = "3d")]
195 pub const fn is_rotation_y_locked(&self) -> bool {
196 (self.0 & 0b000_010) != 0
197 }
198
199 #[cfg(feature = "3d")]
201 pub const fn is_rotation_z_locked(&self) -> bool {
202 (self.0 & 0b000_001) != 0
203 }
204
205 #[cfg(feature = "2d")]
207 pub const fn is_rotation_locked(&self) -> bool {
208 (self.0 & 0b000_001) != 0
209 }
210
211 pub(crate) fn apply_to_vec(&self, mut vector: Vector) -> Vector {
213 if self.is_translation_x_locked() {
214 vector.x = 0.0;
215 }
216 if self.is_translation_y_locked() {
217 vector.y = 0.0;
218 }
219 #[cfg(feature = "3d")]
220 if self.is_translation_z_locked() {
221 vector.z = 0.0;
222 }
223 vector
224 }
225
226 #[cfg(feature = "2d")]
228 pub(crate) fn apply_to_angular_inertia(
229 &self,
230 angular_inertia: impl Into<ComputedAngularInertia>,
231 ) -> ComputedAngularInertia {
232 let mut angular_inertia = angular_inertia.into();
233
234 if self.is_rotation_locked() {
235 *angular_inertia.inverse_mut() = 0.0;
236 }
237
238 angular_inertia
239 }
240
241 #[cfg(feature = "3d")]
243 pub(crate) fn apply_to_angular_inertia(
244 &self,
245 angular_inertia: impl Into<ComputedAngularInertia>,
246 ) -> ComputedAngularInertia {
247 let mut angular_inertia = angular_inertia.into();
248
249 if self.is_rotation_x_locked() {
250 angular_inertia.inverse_mut().x_axis = Vector::ZERO;
251 }
252 if self.is_rotation_y_locked() {
253 angular_inertia.inverse_mut().y_axis = Vector::ZERO;
254 }
255 if self.is_rotation_z_locked() {
256 angular_inertia.inverse_mut().z_axis = Vector::ZERO;
257 }
258
259 angular_inertia
260 }
261
262 #[cfg(feature = "2d")]
264 pub(crate) fn apply_to_angular_velocity(&self, mut angular_velocity: Scalar) -> Scalar {
265 if self.is_rotation_locked() {
266 angular_velocity = 0.0;
267 }
268 angular_velocity
269 }
270
271 #[cfg(feature = "3d")]
273 pub(crate) fn apply_to_angular_velocity(&self, mut angular_velocity: Vector) -> Vector {
274 if self.is_rotation_x_locked() {
275 angular_velocity.x = 0.0;
276 }
277 if self.is_rotation_y_locked() {
278 angular_velocity.y = 0.0;
279 }
280 if self.is_rotation_z_locked() {
281 angular_velocity.z = 0.0;
282 }
283 angular_velocity
284 }
285}