avian2d/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 = "2d")]
189 pub const fn is_translation_locked(&self) -> bool {
190 (self.0 & 0b110_000) == 0b110_000
191 }
192
193 #[cfg(feature = "3d")]
195 pub const fn is_translation_locked(&self) -> bool {
196 (self.0 & 0b111_000) == 0b111_000
197 }
198
199 #[cfg(feature = "3d")]
201 pub const fn is_rotation_x_locked(&self) -> bool {
202 (self.0 & 0b000_100) != 0
203 }
204
205 #[cfg(feature = "3d")]
207 pub const fn is_rotation_y_locked(&self) -> bool {
208 (self.0 & 0b000_010) != 0
209 }
210
211 #[cfg(feature = "3d")]
213 pub const fn is_rotation_z_locked(&self) -> bool {
214 (self.0 & 0b000_001) != 0
215 }
216
217 #[cfg(feature = "2d")]
219 pub const fn is_rotation_locked(&self) -> bool {
220 (self.0 & 0b000_001) != 0
221 }
222
223 #[cfg(feature = "3d")]
225 pub const fn is_rotation_locked(&self) -> bool {
226 (self.0 & 0b000_111) == 0b000_111
227 }
228
229 pub(crate) fn apply_to_vec(&self, mut vector: Vector) -> Vector {
231 if self.is_translation_x_locked() {
232 vector.x = 0.0;
233 }
234 if self.is_translation_y_locked() {
235 vector.y = 0.0;
236 }
237 #[cfg(feature = "3d")]
238 if self.is_translation_z_locked() {
239 vector.z = 0.0;
240 }
241 vector
242 }
243
244 #[cfg(feature = "2d")]
246 pub(crate) fn apply_to_angular_inertia(
247 &self,
248 angular_inertia: impl Into<ComputedAngularInertia>,
249 ) -> ComputedAngularInertia {
250 let mut angular_inertia = angular_inertia.into();
251 let angular_inertia_mut = angular_inertia.inverse_mut();
252 if self.is_rotation_locked() {
253 *angular_inertia_mut = 0.0;
254 }
255 angular_inertia
256 }
257
258 #[cfg(feature = "3d")]
260 pub(crate) fn apply_to_angular_inertia(
261 &self,
262 angular_inertia: impl Into<ComputedAngularInertia>,
263 ) -> ComputedAngularInertia {
264 let mut angular_inertia = angular_inertia.into();
265 let angular_inertia_mut = angular_inertia.inverse_mut();
266 if self.is_rotation_x_locked() {
267 angular_inertia_mut.m00 = 0.0;
268 angular_inertia_mut.m01 = 0.0;
269 angular_inertia_mut.m02 = 0.0;
270 }
271 if self.is_rotation_y_locked() {
272 angular_inertia_mut.m11 = 0.0;
273 angular_inertia_mut.m01 = 0.0;
274 angular_inertia_mut.m12 = 0.0;
275 }
276 if self.is_rotation_z_locked() {
277 angular_inertia_mut.m22 = 0.0;
278 angular_inertia_mut.m02 = 0.0;
279 angular_inertia_mut.m12 = 0.0;
280 }
281 angular_inertia
282 }
283
284 #[cfg(feature = "2d")]
286 pub(crate) fn apply_to_angular_velocity(&self, mut angular_velocity: Scalar) -> Scalar {
287 if self.is_rotation_locked() {
288 angular_velocity = 0.0;
289 }
290 angular_velocity
291 }
292
293 #[cfg(feature = "3d")]
295 pub(crate) fn apply_to_angular_velocity(&self, mut angular_velocity: Vector) -> Vector {
296 if self.is_rotation_x_locked() {
297 angular_velocity.x = 0.0;
298 }
299 if self.is_rotation_y_locked() {
300 angular_velocity.y = 0.0;
301 }
302 if self.is_rotation_z_locked() {
303 angular_velocity.z = 0.0;
304 }
305 angular_velocity
306 }
307}