1use crate::dynamics::{FixedJoint, PrismaticJoint, RevoluteJoint, RopeJoint, TypedJoint};
2use crate::math::{Real, Rot, Vect};
3use rapier::dynamics::{
4 GenericJoint as RapierGenericJoint, JointAxesMask, JointAxis, JointLimits, JointMotor,
5 MotorModel, SpringCoefficients,
6};
7use rapier::math::Pose;
8
9#[cfg(feature = "dim2")]
10use crate::dynamics::PinSlotJoint;
11
12#[cfg(feature = "dim3")]
13use crate::dynamics::SphericalJoint;
14
15#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
17#[derive(Copy, Clone, Debug, PartialEq, Default)]
18#[repr(transparent)]
19pub struct GenericJoint {
20 pub raw: RapierGenericJoint,
22}
23
24impl GenericJoint {
25 pub fn into_rapier(self) -> RapierGenericJoint {
27 self.raw
28 }
29}
30
31impl GenericJoint {
37 #[must_use]
39 pub fn new(locked_axes: JointAxesMask) -> Self {
40 Self {
41 raw: RapierGenericJoint::new(locked_axes),
42 }
43 }
44
45 pub fn locked_axes(&self) -> JointAxesMask {
47 self.raw.locked_axes
48 }
49
50 pub fn lock_axes(&mut self, axes: JointAxesMask) -> &mut Self {
52 self.raw.lock_axes(axes);
53 self
54 }
55
56 #[must_use]
58 pub fn local_basis1(&self) -> Rot {
59 #[cfg(feature = "dim2")]
60 return self.raw.local_frame1.rotation.angle();
61 #[cfg(feature = "dim3")]
62 return self.raw.local_frame1.rotation;
63 }
64
65 pub fn set_local_basis1(&mut self, local_basis: Rot) -> &mut Self {
67 #[cfg(feature = "dim2")]
68 {
69 self.raw.local_frame1.rotation = rapier::math::Rot2::new(local_basis);
70 }
71 #[cfg(feature = "dim3")]
72 {
73 self.raw.local_frame1.rotation = local_basis;
74 }
75 self
76 }
77
78 #[must_use]
80 pub fn local_basis2(&self) -> Rot {
81 #[cfg(feature = "dim2")]
82 return self.raw.local_frame2.rotation.angle();
83 #[cfg(feature = "dim3")]
84 return self.raw.local_frame2.rotation;
85 }
86
87 pub fn set_local_basis2(&mut self, local_basis: Rot) -> &mut Self {
89 #[cfg(feature = "dim2")]
90 {
91 self.raw.local_frame2.rotation = rapier::math::Rot2::new(local_basis);
92 }
93 #[cfg(feature = "dim3")]
94 {
95 self.raw.local_frame2.rotation = local_basis;
96 }
97 self
98 }
99
100 #[must_use]
102 pub fn local_axis1(&self) -> Vect {
103 self.raw.local_axis1()
104 }
105
106 pub fn set_local_axis1(&mut self, local_axis: Vect) -> &mut Self {
108 self.raw.set_local_axis1(local_axis.normalize());
109 self
110 }
111
112 #[must_use]
114 pub fn local_axis2(&self) -> Vect {
115 self.raw.local_axis2()
116 }
117
118 pub fn set_local_axis2(&mut self, local_axis: Vect) -> &mut Self {
120 self.raw.set_local_axis2(local_axis.normalize());
121 self
122 }
123
124 #[must_use]
126 pub fn local_anchor1(&self) -> Vect {
127 self.raw.local_anchor1()
128 }
129
130 pub fn set_local_anchor1(&mut self, anchor1: Vect) -> &mut Self {
132 self.raw.set_local_anchor1(anchor1);
133 self
134 }
135
136 #[must_use]
138 pub fn local_anchor2(&self) -> Vect {
139 self.raw.local_anchor2()
140 }
141
142 pub fn set_local_anchor2(&mut self, anchor2: Vect) -> &mut Self {
144 self.raw.set_local_anchor2(anchor2);
145 self
146 }
147
148 #[must_use]
150 pub fn local_frame1(&self) -> Pose {
151 self.raw.local_frame1
152 }
153
154 pub fn set_local_frame1(&mut self, local_frame: Pose) -> &mut Self {
156 self.raw.set_local_frame1(local_frame);
157 self
158 }
159
160 #[must_use]
162 pub fn local_frame2(&self) -> Pose {
163 self.raw.local_frame2
164 }
165
166 pub fn set_local_frame2(&mut self, local_frame: Pose) -> &mut Self {
168 self.raw.set_local_frame2(local_frame);
169 self
170 }
171
172 pub fn contacts_enabled(&self) -> bool {
174 self.raw.contacts_enabled
175 }
176
177 pub fn set_contacts_enabled(&mut self, enabled: bool) -> &mut Self {
179 self.raw.set_contacts_enabled(enabled);
180 self
181 }
182
183 pub fn is_enabled(&self) -> bool {
189 self.raw.is_enabled()
190 }
191
192 pub fn set_enabled(&mut self, enabled: bool) -> &mut Self {
197 self.raw.set_enabled(enabled);
198 self
199 }
200
201 #[must_use]
203 pub fn softness(&self) -> SpringCoefficients<Real> {
204 self.raw.softness
205 }
206
207 pub fn set_softness(&mut self, softness: SpringCoefficients<Real>) -> &mut Self {
209 self.raw.softness = softness;
210 self
211 }
212
213 pub fn flip(&mut self) -> &mut Self {
217 self.raw.flip();
218 self
219 }
220
221 #[must_use]
223 pub fn limits(&self, axis: JointAxis) -> Option<&JointLimits<Real>> {
224 self.raw.limits(axis)
225 }
226
227 pub fn set_limits(&mut self, axis: JointAxis, limits: [Real; 2]) -> &mut Self {
229 self.raw.set_limits(axis, limits);
230 self
231 }
232
233 pub fn set_coupled_axes(&mut self, axes: JointAxesMask) -> &mut Self {
235 self.raw.coupled_axes = axes;
236 self
237 }
238
239 #[must_use]
241 pub fn motor_model(&self, axis: JointAxis) -> Option<MotorModel> {
242 self.raw.motor_model(axis)
243 }
244
245 pub fn set_motor_model(&mut self, axis: JointAxis, model: MotorModel) -> &mut Self {
247 self.raw.set_motor_model(axis, model);
248 self
249 }
250
251 pub fn set_motor_velocity(
253 &mut self,
254 axis: JointAxis,
255 target_vel: Real,
256 factor: Real,
257 ) -> &mut Self {
258 self.raw.set_motor_velocity(axis, target_vel, factor);
259 self
260 }
261
262 pub fn set_motor_position(
264 &mut self,
265 axis: JointAxis,
266 target_pos: Real,
267 stiffness: Real,
268 damping: Real,
269 ) -> &mut Self {
270 self.raw
271 .set_motor_position(axis, target_pos, stiffness, damping);
272 self
273 }
274
275 pub fn set_motor_max_force(&mut self, axis: JointAxis, max_force: Real) -> &mut Self {
277 self.raw.set_motor_max_force(axis, max_force);
278 self
279 }
280
281 #[must_use]
283 pub fn motor(&self, axis: JointAxis) -> Option<&JointMotor> {
284 self.raw.motor(axis)
285 }
286
287 pub fn set_motor(
289 &mut self,
290 axis: JointAxis,
291 target_pos: Real,
292 target_vel: Real,
293 stiffness: Real,
294 damping: Real,
295 ) -> &mut Self {
296 self.raw
297 .set_motor(axis, target_pos, target_vel, stiffness, damping);
298 self
299 }
300}
301
302macro_rules! joint_conversion_methods(
303 ($as_joint: ident, $as_joint_mut: ident, $Joint: ty, $axes: expr) => {
304 #[must_use]
306 pub fn $as_joint(&self) -> Option<&$Joint> {
307 if self.locked_axes() == $axes {
308 Some(unsafe { std::mem::transmute::<&Self, &$Joint>(self) })
311 } else {
312 None
313 }
314 }
315
316 #[must_use]
318 pub fn $as_joint_mut(&mut self) -> Option<&mut $Joint> {
319 if self.locked_axes() == $axes {
320 Some(unsafe { std::mem::transmute::<&mut Self, &mut $Joint>(self) })
323 } else {
324 None
325 }
326 }
327 }
328);
329
330impl GenericJoint {
331 joint_conversion_methods!(
332 as_revolute,
333 as_revolute_mut,
334 RevoluteJoint,
335 JointAxesMask::LOCKED_REVOLUTE_AXES
336 );
337 joint_conversion_methods!(
338 as_fixed,
339 as_fixed_mut,
340 FixedJoint,
341 JointAxesMask::LOCKED_FIXED_AXES
342 );
343 joint_conversion_methods!(
344 as_prismatic,
345 as_prismatic_mut,
346 PrismaticJoint,
347 JointAxesMask::LOCKED_PRISMATIC_AXES
348 );
349 joint_conversion_methods!(
350 as_rope,
351 as_rope_mut,
352 RopeJoint,
353 JointAxesMask::FREE_FIXED_AXES
354 );
355
356 #[cfg(feature = "dim3")]
357 joint_conversion_methods!(
358 as_spherical,
359 as_spherical_mut,
360 SphericalJoint,
361 JointAxesMask::LOCKED_SPHERICAL_AXES
362 );
363
364 #[cfg(feature = "dim2")]
365 joint_conversion_methods!(
366 as_pin_slot,
367 as_pin_slot_mut,
368 PinSlotJoint,
369 JointAxesMask::LOCKED_PIN_SLOT_AXES
370 );
371}
372
373#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
375#[derive(Copy, Clone, Debug)]
376pub struct GenericJointBuilder(GenericJoint);
377
378impl GenericJointBuilder {
379 #[must_use]
381 pub fn new(locked_axes: JointAxesMask) -> Self {
382 Self(GenericJoint::new(locked_axes))
383 }
384
385 #[must_use]
387 pub fn locked_axes(mut self, axes: JointAxesMask) -> Self {
388 self.0.lock_axes(axes);
389 self
390 }
391
392 #[must_use]
394 pub fn local_basis1(mut self, local_basis: Rot) -> Self {
395 self.0.set_local_basis1(local_basis);
396 self
397 }
398
399 #[must_use]
401 pub fn local_basis2(mut self, local_basis: Rot) -> Self {
402 self.0.set_local_basis2(local_basis);
403 self
404 }
405
406 #[must_use]
408 pub fn local_axis1(mut self, local_axis: Vect) -> Self {
409 self.0.set_local_axis1(local_axis);
410 self
411 }
412
413 #[must_use]
415 pub fn local_axis2(mut self, local_axis: Vect) -> Self {
416 self.0.set_local_axis2(local_axis);
417 self
418 }
419
420 #[must_use]
422 pub fn local_anchor1(mut self, anchor1: Vect) -> Self {
423 self.0.set_local_anchor1(anchor1);
424 self
425 }
426
427 #[must_use]
429 pub fn local_anchor2(mut self, anchor2: Vect) -> Self {
430 self.0.set_local_anchor2(anchor2);
431 self
432 }
433
434 #[must_use]
436 pub fn local_frame1(mut self, local_frame: Pose) -> Self {
437 self.0.set_local_frame1(local_frame);
438 self
439 }
440
441 #[must_use]
443 pub fn local_frame2(mut self, local_frame: Pose) -> Self {
444 self.0.set_local_frame2(local_frame);
445 self
446 }
447
448 #[must_use]
450 pub fn contacts_enabled(mut self, enabled: bool) -> Self {
451 self.0.set_contacts_enabled(enabled);
452 self
453 }
454
455 #[must_use]
457 pub fn enabled(mut self, enabled: bool) -> Self {
458 self.0.set_enabled(enabled);
459 self
460 }
461
462 #[must_use]
464 pub fn softness(mut self, softness: SpringCoefficients<Real>) -> Self {
465 self.0.set_softness(softness);
466 self
467 }
468
469 #[must_use]
471 pub fn limits(mut self, axis: JointAxis, limits: [Real; 2]) -> Self {
472 self.0.set_limits(axis, limits);
473 self
474 }
475
476 #[must_use]
478 pub fn coupled_axes(mut self, axes: JointAxesMask) -> Self {
479 self.0.set_coupled_axes(axes);
480 self
481 }
482
483 #[must_use]
485 pub fn motor_model(mut self, axis: JointAxis, model: MotorModel) -> Self {
486 self.0.set_motor_model(axis, model);
487 self
488 }
489
490 #[must_use]
492 pub fn motor_velocity(mut self, axis: JointAxis, target_vel: Real, factor: Real) -> Self {
493 self.0.set_motor_velocity(axis, target_vel, factor);
494 self
495 }
496
497 #[must_use]
499 pub fn motor_position(
500 mut self,
501 axis: JointAxis,
502 target_pos: Real,
503 stiffness: Real,
504 damping: Real,
505 ) -> Self {
506 self.0
507 .set_motor_position(axis, target_pos, stiffness, damping);
508 self
509 }
510
511 #[must_use]
513 pub fn set_motor(
514 mut self,
515 axis: JointAxis,
516 target_pos: Real,
517 target_vel: Real,
518 stiffness: Real,
519 damping: Real,
520 ) -> Self {
521 self.0
522 .set_motor(axis, target_pos, target_vel, stiffness, damping);
523 self
524 }
525
526 #[must_use]
528 pub fn motor_max_force(mut self, axis: JointAxis, max_force: Real) -> Self {
529 self.0.set_motor_max_force(axis, max_force);
530 self
531 }
532
533 #[must_use]
535 pub fn build(self) -> GenericJoint {
536 self.0
537 }
538}
539
540impl From<GenericJointBuilder> for GenericJoint {
541 fn from(joint: GenericJointBuilder) -> GenericJoint {
542 joint.0
543 }
544}
545
546impl From<GenericJointBuilder> for TypedJoint {
547 fn from(joint: GenericJointBuilder) -> TypedJoint {
548 joint.0.into()
549 }
550}
551
552impl From<GenericJoint> for TypedJoint {
553 fn from(joint: GenericJoint) -> TypedJoint {
554 TypedJoint::GenericJoint(joint)
555 }
556}