1use crate::scene::node::constructor::NodeConstructor;
32use crate::{
33 core::{
34 algebra::{Isometry2, Matrix4, UnitComplex, Vector2},
35 log::Log,
36 math::{aabb::AxisAlignedBoundingBox, m4x4_approx_eq},
37 parking_lot::Mutex,
38 pool::Handle,
39 reflect::prelude::*,
40 type_traits::prelude::*,
41 uuid::{uuid, Uuid},
42 variable::InheritableVariable,
43 visitor::prelude::*,
44 },
45 scene::{
46 base::{Base, BaseBuilder},
47 dim2::collider::Collider,
48 graph::Graph,
49 node::{Node, NodeTrait, SyncContext, UpdateContext},
50 rigidbody::RigidBodyType,
51 Scene,
52 },
53};
54
55use fyrox_graph::constructor::ConstructorProvider;
56use fyrox_graph::SceneGraph;
57use rapier2d::prelude::RigidBodyHandle;
58use std::{
59 cell::Cell,
60 collections::VecDeque,
61 fmt::{Debug, Formatter},
62 ops::{Deref, DerefMut},
63};
64
65#[derive(Debug)]
66pub(crate) enum ApplyAction {
67 Force(Vector2<f32>),
68 Torque(f32),
69 ForceAtPoint {
70 force: Vector2<f32>,
71 point: Vector2<f32>,
72 },
73 Impulse(Vector2<f32>),
74 TorqueImpulse(f32),
75 ImpulseAtPoint {
76 impulse: Vector2<f32>,
77 point: Vector2<f32>,
78 },
79 WakeUp,
80 NextTranslation(Vector2<f32>),
81 NextRotation(UnitComplex<f32>),
82 NextPosition(Isometry2<f32>),
83}
84
85#[derive(Visit, Reflect, ComponentProvider)]
93#[reflect(derived_type = "Node")]
94pub struct RigidBody {
95 base: Base,
96
97 #[reflect(setter = "set_lin_vel")]
98 pub(crate) lin_vel: InheritableVariable<Vector2<f32>>,
99
100 #[reflect(setter = "set_ang_vel")]
101 pub(crate) ang_vel: InheritableVariable<f32>,
102
103 #[reflect(setter = "set_lin_damping")]
104 pub(crate) lin_damping: InheritableVariable<f32>,
105
106 #[reflect(setter = "set_ang_damping")]
107 pub(crate) ang_damping: InheritableVariable<f32>,
108
109 #[reflect(setter = "set_body_type")]
110 pub(crate) body_type: InheritableVariable<RigidBodyType>,
111
112 #[reflect(min_value = 0.0, step = 0.05)]
113 #[reflect(setter = "set_mass")]
114 pub(crate) mass: InheritableVariable<f32>,
115
116 #[reflect(setter = "lock_rotations")]
117 pub(crate) rotation_locked: InheritableVariable<bool>,
118
119 #[reflect(setter = "lock_translation")]
120 pub(crate) translation_locked: InheritableVariable<bool>,
121
122 #[reflect(setter = "enable_ccd")]
123 pub(crate) ccd_enabled: InheritableVariable<bool>,
124
125 #[reflect(setter = "set_can_sleep")]
126 pub(crate) can_sleep: InheritableVariable<bool>,
127
128 #[reflect(setter = "set_dominance")]
129 pub(crate) dominance: InheritableVariable<i8>,
130
131 #[reflect(setter = "set_gravity_scale")]
132 pub(crate) gravity_scale: InheritableVariable<f32>,
133
134 #[visit(skip)]
135 #[reflect(hidden)]
136 pub(crate) sleeping: bool,
137
138 #[visit(skip)]
139 #[reflect(hidden)]
140 pub(crate) reset_forces: Cell<bool>,
141
142 #[visit(skip)]
143 #[reflect(hidden)]
144 pub(crate) native: Cell<RigidBodyHandle>,
145
146 #[visit(skip)]
147 #[reflect(hidden)]
148 pub(crate) actions: Mutex<VecDeque<ApplyAction>>,
149}
150
151impl Debug for RigidBody {
152 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
153 write!(f, "RigidBody")
154 }
155}
156
157impl Default for RigidBody {
158 fn default() -> Self {
159 Self {
160 base: Default::default(),
161 lin_vel: Default::default(),
162 ang_vel: Default::default(),
163 lin_damping: Default::default(),
164 ang_damping: Default::default(),
165 sleeping: Default::default(),
166 body_type: InheritableVariable::new_modified(RigidBodyType::Dynamic),
167 mass: InheritableVariable::new_modified(1.0),
168 rotation_locked: Default::default(),
169 translation_locked: Default::default(),
170 ccd_enabled: Default::default(),
171 can_sleep: InheritableVariable::new_modified(true),
172 dominance: Default::default(),
173 gravity_scale: InheritableVariable::new_modified(1.0),
174 native: Cell::new(RigidBodyHandle::invalid()),
175 actions: Default::default(),
176 reset_forces: Default::default(),
177 }
178 }
179}
180
181impl Deref for RigidBody {
182 type Target = Base;
183
184 fn deref(&self) -> &Self::Target {
185 &self.base
186 }
187}
188
189impl DerefMut for RigidBody {
190 fn deref_mut(&mut self) -> &mut Self::Target {
191 &mut self.base
192 }
193}
194
195impl Clone for RigidBody {
196 fn clone(&self) -> Self {
197 Self {
198 base: self.base.clone(),
199 lin_vel: self.lin_vel.clone(),
200 ang_vel: self.ang_vel.clone(),
201 lin_damping: self.lin_damping.clone(),
202 ang_damping: self.ang_damping.clone(),
203 sleeping: self.sleeping,
204 body_type: self.body_type.clone(),
205 mass: self.mass.clone(),
206 rotation_locked: self.rotation_locked.clone(),
207 translation_locked: self.translation_locked.clone(),
208 ccd_enabled: self.ccd_enabled.clone(),
209 can_sleep: self.can_sleep.clone(),
210 dominance: self.dominance.clone(),
211 gravity_scale: self.gravity_scale.clone(),
212 native: Cell::new(RigidBodyHandle::invalid()),
214 actions: Default::default(),
215 reset_forces: self.reset_forces.clone(),
216 }
217 }
218}
219
220impl TypeUuidProvider for RigidBody {
221 fn type_uuid() -> Uuid {
222 uuid!("0b242335-75a4-4c65-9685-3e82a8979047")
223 }
224}
225
226impl RigidBody {
227 pub fn set_lin_vel(&mut self, lin_vel: Vector2<f32>) -> Vector2<f32> {
230 self.lin_vel.set_value_and_mark_modified(lin_vel)
231 }
232
233 pub fn set_lin_vel_x(&mut self, x_vel: f32) {
236 self.lin_vel.x = x_vel;
237 }
238
239 pub fn set_lin_vel_y(&mut self, y_vel: f32) {
242 self.lin_vel.y = y_vel;
243 }
244
245 pub fn lin_vel(&self) -> Vector2<f32> {
247 *self.lin_vel
248 }
249
250 pub fn set_ang_vel(&mut self, ang_vel: f32) -> f32 {
253 self.ang_vel.set_value_and_mark_modified(ang_vel)
254 }
255
256 pub fn ang_vel(&self) -> f32 {
258 *self.ang_vel
259 }
260
261 pub fn set_mass(&mut self, mass: f32) -> f32 {
264 self.mass.set_value_and_mark_modified(mass)
265 }
266
267 pub fn mass(&self) -> f32 {
269 *self.mass
270 }
271
272 pub fn set_ang_damping(&mut self, damping: f32) -> f32 {
275 self.ang_damping.set_value_and_mark_modified(damping)
276 }
277
278 pub fn ang_damping(&self) -> f32 {
280 *self.ang_damping
281 }
282
283 pub fn set_lin_damping(&mut self, damping: f32) -> f32 {
286 self.lin_damping.set_value_and_mark_modified(damping)
287 }
288
289 pub fn lin_damping(&self) -> f32 {
291 *self.lin_damping
292 }
293
294 pub fn lock_rotations(&mut self, state: bool) -> bool {
296 self.rotation_locked.set_value_and_mark_modified(state)
297 }
298
299 pub fn is_rotation_locked(&self) -> bool {
301 *self.rotation_locked
302 }
303
304 pub fn lock_translation(&mut self, state: bool) -> bool {
306 self.translation_locked.set_value_and_mark_modified(state)
307 }
308
309 pub fn is_translation_locked(&self) -> bool {
311 *self.translation_locked
312 }
313
314 pub fn set_body_type(&mut self, body_type: RigidBodyType) -> RigidBodyType {
316 self.body_type.set_value_and_mark_modified(body_type)
317 }
318
319 pub fn body_type(&self) -> RigidBodyType {
321 *self.body_type
322 }
323
324 pub fn is_sleeping(&self) -> bool {
327 self.sleeping
328 }
329
330 pub fn is_ccd_enabled(&self) -> bool {
332 *self.ccd_enabled
333 }
334
335 pub fn enable_ccd(&mut self, enable: bool) -> bool {
338 self.ccd_enabled.set_value_and_mark_modified(enable)
339 }
340
341 pub fn set_gravity_scale(&mut self, scale: f32) -> f32 {
343 self.gravity_scale.set_value_and_mark_modified(scale)
344 }
345
346 pub fn gravity_scale(&self) -> f32 {
348 *self.gravity_scale
349 }
350
351 pub fn set_dominance(&mut self, dominance: i8) -> i8 {
356 self.dominance.set_value_and_mark_modified(dominance)
357 }
358
359 pub fn dominance(&self) -> i8 {
361 *self.dominance
362 }
363
364 pub fn apply_force(&mut self, force: Vector2<f32>) {
367 self.actions.get_mut().push_back(ApplyAction::Force(force))
368 }
369
370 pub fn apply_torque(&mut self, torque: f32) {
373 self.actions
374 .get_mut()
375 .push_back(ApplyAction::Torque(torque))
376 }
377
378 pub fn apply_force_at_point(&mut self, force: Vector2<f32>, point: Vector2<f32>) {
381 self.actions
382 .get_mut()
383 .push_back(ApplyAction::ForceAtPoint { force, point })
384 }
385
386 pub fn apply_impulse(&mut self, impulse: Vector2<f32>) {
389 self.actions
390 .get_mut()
391 .push_back(ApplyAction::Impulse(impulse))
392 }
393
394 pub fn apply_torque_impulse(&mut self, torque_impulse: f32) {
397 self.actions
398 .get_mut()
399 .push_back(ApplyAction::TorqueImpulse(torque_impulse))
400 }
401
402 pub fn apply_impulse_at_point(&mut self, impulse: Vector2<f32>, point: Vector2<f32>) {
406 self.actions
407 .get_mut()
408 .push_back(ApplyAction::ImpulseAtPoint { impulse, point })
409 }
410
411 pub fn set_next_kinematic_translation(&mut self, translation: Vector2<f32>) {
414 self.actions
415 .get_mut()
416 .push_back(ApplyAction::NextTranslation(translation));
417 }
418
419 pub fn set_next_kinematic_rotation(&mut self, rotation: UnitComplex<f32>) {
422 self.actions
423 .get_mut()
424 .push_back(ApplyAction::NextRotation(rotation));
425 }
426
427 pub fn set_next_kinematic_position(&mut self, position: Isometry2<f32>) {
430 self.actions
431 .get_mut()
432 .push_back(ApplyAction::NextPosition(position));
433 }
434
435 pub fn set_can_sleep(&mut self, can_sleep: bool) -> bool {
438 self.can_sleep.set_value_and_mark_modified(can_sleep)
439 }
440
441 pub fn is_can_sleep(&self) -> bool {
443 *self.can_sleep
444 }
445
446 pub fn wake_up(&mut self) {
448 self.actions.get_mut().push_back(ApplyAction::WakeUp)
449 }
450
451 pub(crate) fn need_sync_model(&self) -> bool {
452 self.lin_vel.need_sync()
453 || self.ang_vel.need_sync()
454 || self.lin_damping.need_sync()
455 || self.ang_damping.need_sync()
456 || self.body_type.need_sync()
457 || self.mass.need_sync()
458 || self.rotation_locked.need_sync()
459 || self.translation_locked.need_sync()
460 || self.ccd_enabled.need_sync()
461 || self.can_sleep.need_sync()
462 || self.dominance.need_sync()
463 || self.gravity_scale.need_sync()
464 || self.reset_forces.get()
465 }
466}
467
468impl ConstructorProvider<Node, Graph> for RigidBody {
469 fn constructor() -> NodeConstructor {
470 NodeConstructor::new::<Self>()
471 .with_variant("Rigid Body", |_| {
472 RigidBodyBuilder::new(BaseBuilder::new().with_name("Rigid Body 2D"))
473 .build_node()
474 .into()
475 })
476 .with_group("Physics 2D")
477 }
478}
479
480impl NodeTrait for RigidBody {
481 fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
482 self.base.local_bounding_box()
483 }
484
485 fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
486 self.base.world_bounding_box()
487 }
488
489 fn id(&self) -> Uuid {
490 Self::type_uuid()
491 }
492
493 fn on_removed_from_graph(&mut self, graph: &mut Graph) {
494 graph.physics2d.remove_body(self.native.get());
495 self.native.set(RigidBodyHandle::invalid());
496
497 Log::info(format!(
498 "Native rigid body was removed for node: {}",
499 self.name()
500 ));
501 }
502
503 fn sync_native(&self, self_handle: Handle<Node>, context: &mut SyncContext) {
504 context.physics2d.sync_to_rigid_body_node(self_handle, self);
505 }
506
507 fn on_global_transform_changed(
508 &self,
509 new_global_transform: &Matrix4<f32>,
510 context: &mut SyncContext,
511 ) {
512 if !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
513 context
514 .physics2d
515 .set_rigid_body_position(self, new_global_transform);
516 }
517 }
518
519 fn update(&mut self, context: &mut UpdateContext) {
520 context.physics2d.sync_rigid_body_node(
521 self,
522 context
524 .nodes
525 .try_borrow(self.parent)
526 .ok()
527 .map(|p| p.global_transform())
528 .unwrap_or_else(Matrix4::identity),
529 );
530 }
531
532 fn validate(&self, scene: &Scene) -> Result<(), String> {
533 for &child in self.children() {
534 if scene.graph.try_get_of_type::<Collider>(child).is_ok() {
535 return Ok(());
536 }
537 }
538
539 Err("The 2D rigid body must have at least one 2D collider as a \
540 direct child node to work correctly!"
541 .to_string())
542 }
543}
544
545pub struct RigidBodyBuilder {
547 base_builder: BaseBuilder,
548 lin_vel: Vector2<f32>,
549 ang_vel: f32,
550 lin_damping: f32,
551 ang_damping: f32,
552 sleeping: bool,
553 body_type: RigidBodyType,
554 mass: f32,
555 rotation_locked: bool,
556 translation_locked: bool,
557 ccd_enabled: bool,
558 can_sleep: bool,
559 dominance: i8,
560 gravity_scale: f32,
561}
562
563impl RigidBodyBuilder {
564 pub fn new(base_builder: BaseBuilder) -> Self {
566 Self {
567 base_builder,
568 lin_vel: Default::default(),
569 ang_vel: Default::default(),
570 lin_damping: 0.0,
571 ang_damping: 0.0,
572 sleeping: false,
573 body_type: RigidBodyType::Dynamic,
574 mass: 1.0,
575 rotation_locked: false,
576 translation_locked: false,
577 ccd_enabled: false,
578 can_sleep: true,
579 dominance: 0,
580 gravity_scale: 1.0,
581 }
582 }
583
584 pub fn with_body_type(mut self, body_type: RigidBodyType) -> Self {
586 self.body_type = body_type;
587 self
588 }
589
590 pub fn with_mass(mut self, mass: f32) -> Self {
592 self.mass = mass;
593 self
594 }
595
596 pub fn with_ccd_enabled(mut self, enabled: bool) -> Self {
598 self.ccd_enabled = enabled;
599 self
600 }
601
602 pub fn with_lin_vel(mut self, lin_vel: Vector2<f32>) -> Self {
604 self.lin_vel = lin_vel;
605 self
606 }
607
608 pub fn with_ang_vel(mut self, ang_vel: f32) -> Self {
610 self.ang_vel = ang_vel;
611 self
612 }
613
614 pub fn with_ang_damping(mut self, ang_damping: f32) -> Self {
616 self.ang_damping = ang_damping;
617 self
618 }
619
620 pub fn with_lin_damping(mut self, lin_damping: f32) -> Self {
622 self.lin_damping = lin_damping;
623 self
624 }
625
626 pub fn with_rotation_locked(mut self, rotation_locked: bool) -> Self {
628 self.rotation_locked = rotation_locked;
629 self
630 }
631
632 pub fn with_translation_locked(mut self, translation_locked: bool) -> Self {
634 self.translation_locked = translation_locked;
635 self
636 }
637
638 pub fn with_dominance(mut self, dominance: i8) -> Self {
640 self.dominance = dominance;
641 self
642 }
643
644 pub fn with_gravity_scale(mut self, gravity_scale: f32) -> Self {
646 self.gravity_scale = gravity_scale;
647 self
648 }
649
650 pub fn with_sleeping(mut self, sleeping: bool) -> Self {
652 self.sleeping = sleeping;
653 self
654 }
655
656 pub fn with_can_sleep(mut self, can_sleep: bool) -> Self {
658 self.can_sleep = can_sleep;
659 self
660 }
661
662 pub fn build_rigid_body(self) -> RigidBody {
664 RigidBody {
665 base: self.base_builder.build_base(),
666 lin_vel: self.lin_vel.into(),
667 ang_vel: self.ang_vel.into(),
668 lin_damping: self.lin_damping.into(),
669 ang_damping: self.ang_damping.into(),
670 sleeping: self.sleeping,
671 body_type: self.body_type.into(),
672 mass: self.mass.into(),
673 rotation_locked: self.rotation_locked.into(),
674 translation_locked: self.translation_locked.into(),
675 ccd_enabled: self.ccd_enabled.into(),
676 can_sleep: self.can_sleep.into(),
677 dominance: self.dominance.into(),
678 gravity_scale: self.gravity_scale.into(),
679 native: Cell::new(RigidBodyHandle::invalid()),
680 actions: Default::default(),
681 reset_forces: Default::default(),
682 }
683 }
684
685 pub fn build_node(self) -> Node {
687 Node::new(self.build_rigid_body())
688 }
689
690 pub fn build(self, graph: &mut Graph) -> Handle<RigidBody> {
692 graph.add_node(self.build_node()).to_variant()
693 }
694}