1use crate::dynamics::{FixedJoint, PrismaticJoint, RevoluteJoint, RopeJoint};
2use crate::math::{Real, Rot, Vect};
3use rapier::dynamics::{
4 GenericJoint as RapierGenericJoint, JointAxesMask, JointAxis, JointLimits, JointMotor,
5 MotorModel,
6};
7
8#[cfg(feature = "dim3")]
9use crate::dynamics::SphericalJoint;
10
11#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
13#[derive(Copy, Clone, Debug, PartialEq, Default)]
14#[repr(transparent)]
15pub struct GenericJoint {
16 pub raw: RapierGenericJoint,
18}
19
20impl GenericJoint {
21 pub fn into_rapier(self) -> RapierGenericJoint {
23 self.raw
24 }
25}
26
27impl GenericJoint {
33 #[must_use]
35 pub fn new(locked_axes: JointAxesMask) -> Self {
36 Self {
37 raw: RapierGenericJoint::new(locked_axes),
38 }
39 }
40
41 pub fn locked_axes(&self) -> JointAxesMask {
43 self.raw.locked_axes
44 }
45
46 pub fn lock_axes(&mut self, axes: JointAxesMask) -> &mut Self {
48 self.raw.lock_axes(axes);
49 self
50 }
51
52 #[must_use]
54 pub fn local_basis1(&self) -> Rot {
55 #[cfg(feature = "dim2")]
56 return self.raw.local_frame1.rotation.angle();
57 #[cfg(feature = "dim3")]
58 return self.raw.local_frame1.rotation.into();
59 }
60
61 pub fn set_local_basis1(&mut self, local_basis: Rot) -> &mut Self {
63 #[cfg(feature = "dim2")]
64 {
65 self.raw.local_frame1.rotation = na::UnitComplex::new(local_basis);
66 }
67 #[cfg(feature = "dim3")]
68 {
69 self.raw.local_frame1.rotation = local_basis.into();
70 }
71 self
72 }
73
74 #[must_use]
76 pub fn local_basis2(&self) -> Rot {
77 #[cfg(feature = "dim2")]
78 return self.raw.local_frame2.rotation.angle();
79 #[cfg(feature = "dim3")]
80 return self.raw.local_frame2.rotation.into();
81 }
82
83 pub fn set_local_basis2(&mut self, local_basis: Rot) -> &mut Self {
85 #[cfg(feature = "dim2")]
86 {
87 self.raw.local_frame2.rotation = na::UnitComplex::new(local_basis);
88 }
89 #[cfg(feature = "dim3")]
90 {
91 self.raw.local_frame2.rotation = local_basis.into();
92 }
93 self
94 }
95
96 #[must_use]
98 pub fn local_axis1(&self) -> Vect {
99 (*self.raw.local_axis1()).into()
100 }
101
102 pub fn set_local_axis1(&mut self, local_axis: Vect) -> &mut Self {
104 self.raw.set_local_axis1(local_axis.try_into().unwrap());
105 self
106 }
107
108 #[must_use]
110 pub fn local_axis2(&self) -> Vect {
111 (*self.raw.local_axis2()).into()
112 }
113
114 pub fn set_local_axis2(&mut self, local_axis: Vect) -> &mut Self {
116 self.raw.set_local_axis2(local_axis.try_into().unwrap());
117 self
118 }
119
120 #[must_use]
122 pub fn local_anchor1(&self) -> Vect {
123 self.raw.local_anchor1().into()
124 }
125
126 pub fn set_local_anchor1(&mut self, anchor1: Vect) -> &mut Self {
128 self.raw.set_local_anchor1(anchor1.into());
129 self
130 }
131
132 #[must_use]
134 pub fn local_anchor2(&self) -> Vect {
135 self.raw.local_anchor2().into()
136 }
137
138 pub fn set_local_anchor2(&mut self, anchor2: Vect) -> &mut Self {
140 self.raw.set_local_anchor2(anchor2.into());
141 self
142 }
143
144 pub fn contacts_enabled(&self) -> bool {
146 self.raw.contacts_enabled
147 }
148
149 pub fn set_contacts_enabled(&mut self, enabled: bool) -> &mut Self {
151 self.raw.set_contacts_enabled(enabled);
152 self
153 }
154
155 #[must_use]
157 pub fn limits(&self, axis: JointAxis) -> Option<&JointLimits<Real>> {
158 self.raw.limits(axis)
159 }
160
161 pub fn set_limits(&mut self, axis: JointAxis, limits: [Real; 2]) -> &mut Self {
163 self.raw.set_limits(axis, limits);
164 self
165 }
166
167 pub fn set_coupled_axes(&mut self, axes: JointAxesMask) -> &mut Self {
169 self.raw.coupled_axes = axes;
170 self
171 }
172
173 #[must_use]
175 pub fn motor_model(&self, axis: JointAxis) -> Option<MotorModel> {
176 self.raw.motor_model(axis)
177 }
178
179 pub fn set_motor_model(&mut self, axis: JointAxis, model: MotorModel) -> &mut Self {
181 self.raw.set_motor_model(axis, model);
182 self
183 }
184
185 pub fn set_motor_velocity(
187 &mut self,
188 axis: JointAxis,
189 target_vel: Real,
190 factor: Real,
191 ) -> &mut Self {
192 self.raw.set_motor_velocity(axis, target_vel, factor);
193 self
194 }
195
196 pub fn set_motor_position(
198 &mut self,
199 axis: JointAxis,
200 target_pos: Real,
201 stiffness: Real,
202 damping: Real,
203 ) -> &mut Self {
204 self.raw
205 .set_motor_position(axis, target_pos, stiffness, damping);
206 self
207 }
208
209 pub fn set_motor_max_force(&mut self, axis: JointAxis, max_force: Real) -> &mut Self {
211 self.raw.set_motor_max_force(axis, max_force);
212 self
213 }
214
215 #[must_use]
217 pub fn motor(&self, axis: JointAxis) -> Option<&JointMotor> {
218 self.raw.motor(axis)
219 }
220
221 pub fn set_motor(
223 &mut self,
224 axis: JointAxis,
225 target_pos: Real,
226 target_vel: Real,
227 stiffness: Real,
228 damping: Real,
229 ) -> &mut Self {
230 self.raw
231 .set_motor(axis, target_pos, target_vel, stiffness, damping);
232 self
233 }
234}
235
236macro_rules! joint_conversion_methods(
237 ($as_joint: ident, $as_joint_mut: ident, $Joint: ty, $axes: expr) => {
238 #[must_use]
240 pub fn $as_joint(&self) -> Option<&$Joint> {
241 if self.locked_axes() == $axes {
242 Some(unsafe { std::mem::transmute::<&Self, &$Joint>(self) })
245 } else {
246 None
247 }
248 }
249
250 #[must_use]
252 pub fn $as_joint_mut(&mut self) -> Option<&mut $Joint> {
253 if self.locked_axes() == $axes {
254 Some(unsafe { std::mem::transmute::<&mut Self, &mut $Joint>(self) })
257 } else {
258 None
259 }
260 }
261 }
262);
263
264impl GenericJoint {
265 joint_conversion_methods!(
266 as_revolute,
267 as_revolute_mut,
268 RevoluteJoint,
269 JointAxesMask::LOCKED_REVOLUTE_AXES
270 );
271 joint_conversion_methods!(
272 as_fixed,
273 as_fixed_mut,
274 FixedJoint,
275 JointAxesMask::LOCKED_FIXED_AXES
276 );
277 joint_conversion_methods!(
278 as_prismatic,
279 as_prismatic_mut,
280 PrismaticJoint,
281 JointAxesMask::LOCKED_PRISMATIC_AXES
282 );
283 joint_conversion_methods!(
284 as_rope,
285 as_rope_mut,
286 RopeJoint,
287 JointAxesMask::FREE_FIXED_AXES
288 );
289
290 #[cfg(feature = "dim3")]
291 joint_conversion_methods!(
292 as_spherical,
293 as_spherical_mut,
294 SphericalJoint,
295 JointAxesMask::LOCKED_SPHERICAL_AXES
296 );
297}
298
299#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
301#[derive(Copy, Clone, Debug)]
302pub struct GenericJointBuilder(GenericJoint);
303
304impl GenericJointBuilder {
305 #[must_use]
307 pub fn new(locked_axes: JointAxesMask) -> Self {
308 Self(GenericJoint::new(locked_axes))
309 }
310
311 #[must_use]
313 pub fn locked_axes(mut self, axes: JointAxesMask) -> Self {
314 self.0.lock_axes(axes);
315 self
316 }
317
318 #[must_use]
320 pub fn local_basis1(mut self, local_basis: Rot) -> Self {
321 self.0.set_local_basis1(local_basis);
322 self
323 }
324
325 #[must_use]
327 pub fn local_basis2(mut self, local_basis: Rot) -> Self {
328 self.0.set_local_basis2(local_basis);
329 self
330 }
331
332 #[must_use]
334 pub fn local_axis1(mut self, local_axis: Vect) -> Self {
335 self.0.set_local_axis1(local_axis);
336 self
337 }
338
339 #[must_use]
341 pub fn local_axis2(mut self, local_axis: Vect) -> Self {
342 self.0.set_local_axis2(local_axis);
343 self
344 }
345
346 #[must_use]
348 pub fn local_anchor1(mut self, anchor1: Vect) -> Self {
349 self.0.set_local_anchor1(anchor1);
350 self
351 }
352
353 #[must_use]
355 pub fn local_anchor2(mut self, anchor2: Vect) -> Self {
356 self.0.set_local_anchor2(anchor2);
357 self
358 }
359
360 #[must_use]
362 pub fn limits(mut self, axis: JointAxis, limits: [Real; 2]) -> Self {
363 self.0.set_limits(axis, limits);
364 self
365 }
366
367 #[must_use]
369 pub fn coupled_axes(mut self, axes: JointAxesMask) -> Self {
370 self.0.set_coupled_axes(axes);
371 self
372 }
373
374 #[must_use]
376 pub fn motor_model(mut self, axis: JointAxis, model: MotorModel) -> Self {
377 self.0.set_motor_model(axis, model);
378 self
379 }
380
381 #[must_use]
383 pub fn motor_velocity(mut self, axis: JointAxis, target_vel: Real, factor: Real) -> Self {
384 self.0.set_motor_velocity(axis, target_vel, factor);
385 self
386 }
387
388 #[must_use]
390 pub fn motor_position(
391 mut self,
392 axis: JointAxis,
393 target_pos: Real,
394 stiffness: Real,
395 damping: Real,
396 ) -> Self {
397 self.0
398 .set_motor_position(axis, target_pos, stiffness, damping);
399 self
400 }
401
402 #[must_use]
404 pub fn set_motor(
405 mut self,
406 axis: JointAxis,
407 target_pos: Real,
408 target_vel: Real,
409 stiffness: Real,
410 damping: Real,
411 ) -> Self {
412 self.0
413 .set_motor(axis, target_pos, target_vel, stiffness, damping);
414 self
415 }
416
417 #[must_use]
419 pub fn motor_max_force(mut self, axis: JointAxis, max_force: Real) -> Self {
420 self.0.set_motor_max_force(axis, max_force);
421 self
422 }
423
424 #[must_use]
426 pub fn build(self) -> GenericJoint {
427 self.0
428 }
429}
430
431impl From<GenericJointBuilder> for GenericJoint {
432 fn from(joint: GenericJointBuilder) -> GenericJoint {
433 joint.0
434 }
435}