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::{BaseSceneGraph, 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 lin_vel(&self) -> Vector2<f32> {
235 *self.lin_vel
236 }
237
238 pub fn set_ang_vel(&mut self, ang_vel: f32) -> f32 {
241 self.ang_vel.set_value_and_mark_modified(ang_vel)
242 }
243
244 pub fn ang_vel(&self) -> f32 {
246 *self.ang_vel
247 }
248
249 pub fn set_mass(&mut self, mass: f32) -> f32 {
252 self.mass.set_value_and_mark_modified(mass)
253 }
254
255 pub fn mass(&self) -> f32 {
257 *self.mass
258 }
259
260 pub fn set_ang_damping(&mut self, damping: f32) -> f32 {
263 self.ang_damping.set_value_and_mark_modified(damping)
264 }
265
266 pub fn ang_damping(&self) -> f32 {
268 *self.ang_damping
269 }
270
271 pub fn set_lin_damping(&mut self, damping: f32) -> f32 {
274 self.lin_damping.set_value_and_mark_modified(damping)
275 }
276
277 pub fn lin_damping(&self) -> f32 {
279 *self.lin_damping
280 }
281
282 pub fn lock_rotations(&mut self, state: bool) -> bool {
284 self.rotation_locked.set_value_and_mark_modified(state)
285 }
286
287 pub fn is_rotation_locked(&self) -> bool {
289 *self.rotation_locked
290 }
291
292 pub fn lock_translation(&mut self, state: bool) -> bool {
294 self.translation_locked.set_value_and_mark_modified(state)
295 }
296
297 pub fn is_translation_locked(&self) -> bool {
299 *self.translation_locked
300 }
301
302 pub fn set_body_type(&mut self, body_type: RigidBodyType) -> RigidBodyType {
304 self.body_type.set_value_and_mark_modified(body_type)
305 }
306
307 pub fn body_type(&self) -> RigidBodyType {
309 *self.body_type
310 }
311
312 pub fn is_sleeping(&self) -> bool {
315 self.sleeping
316 }
317
318 pub fn is_ccd_enabled(&self) -> bool {
320 *self.ccd_enabled
321 }
322
323 pub fn enable_ccd(&mut self, enable: bool) -> bool {
326 self.ccd_enabled.set_value_and_mark_modified(enable)
327 }
328
329 pub fn set_gravity_scale(&mut self, scale: f32) -> f32 {
331 self.gravity_scale.set_value_and_mark_modified(scale)
332 }
333
334 pub fn gravity_scale(&self) -> f32 {
336 *self.gravity_scale
337 }
338
339 pub fn set_dominance(&mut self, dominance: i8) -> i8 {
344 self.dominance.set_value_and_mark_modified(dominance)
345 }
346
347 pub fn dominance(&self) -> i8 {
349 *self.dominance
350 }
351
352 pub fn apply_force(&mut self, force: Vector2<f32>) {
355 self.actions.get_mut().push_back(ApplyAction::Force(force))
356 }
357
358 pub fn apply_torque(&mut self, torque: f32) {
361 self.actions
362 .get_mut()
363 .push_back(ApplyAction::Torque(torque))
364 }
365
366 pub fn apply_force_at_point(&mut self, force: Vector2<f32>, point: Vector2<f32>) {
369 self.actions
370 .get_mut()
371 .push_back(ApplyAction::ForceAtPoint { force, point })
372 }
373
374 pub fn apply_impulse(&mut self, impulse: Vector2<f32>) {
377 self.actions
378 .get_mut()
379 .push_back(ApplyAction::Impulse(impulse))
380 }
381
382 pub fn apply_torque_impulse(&mut self, torque_impulse: f32) {
385 self.actions
386 .get_mut()
387 .push_back(ApplyAction::TorqueImpulse(torque_impulse))
388 }
389
390 pub fn apply_impulse_at_point(&mut self, impulse: Vector2<f32>, point: Vector2<f32>) {
394 self.actions
395 .get_mut()
396 .push_back(ApplyAction::ImpulseAtPoint { impulse, point })
397 }
398
399 pub fn set_next_kinematic_translation(&mut self, translation: Vector2<f32>) {
402 self.actions
403 .get_mut()
404 .push_back(ApplyAction::NextTranslation(translation));
405 }
406
407 pub fn set_next_kinematic_rotation(&mut self, rotation: UnitComplex<f32>) {
410 self.actions
411 .get_mut()
412 .push_back(ApplyAction::NextRotation(rotation));
413 }
414
415 pub fn set_next_kinematic_position(&mut self, position: Isometry2<f32>) {
418 self.actions
419 .get_mut()
420 .push_back(ApplyAction::NextPosition(position));
421 }
422
423 pub fn set_can_sleep(&mut self, can_sleep: bool) -> bool {
426 self.can_sleep.set_value_and_mark_modified(can_sleep)
427 }
428
429 pub fn is_can_sleep(&self) -> bool {
431 *self.can_sleep
432 }
433
434 pub fn wake_up(&mut self) {
436 self.actions.get_mut().push_back(ApplyAction::WakeUp)
437 }
438
439 pub(crate) fn need_sync_model(&self) -> bool {
440 self.lin_vel.need_sync()
441 || self.ang_vel.need_sync()
442 || self.lin_damping.need_sync()
443 || self.ang_damping.need_sync()
444 || self.body_type.need_sync()
445 || self.mass.need_sync()
446 || self.rotation_locked.need_sync()
447 || self.translation_locked.need_sync()
448 || self.ccd_enabled.need_sync()
449 || self.can_sleep.need_sync()
450 || self.dominance.need_sync()
451 || self.gravity_scale.need_sync()
452 || self.reset_forces.get()
453 }
454}
455
456impl ConstructorProvider<Node, Graph> for RigidBody {
457 fn constructor() -> NodeConstructor {
458 NodeConstructor::new::<Self>()
459 .with_variant("Rigid Body", |_| {
460 RigidBodyBuilder::new(BaseBuilder::new().with_name("Rigid Body 2D"))
461 .build_node()
462 .into()
463 })
464 .with_group("Physics 2D")
465 }
466}
467
468impl NodeTrait for RigidBody {
469 fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
470 self.base.local_bounding_box()
471 }
472
473 fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
474 self.base.world_bounding_box()
475 }
476
477 fn id(&self) -> Uuid {
478 Self::type_uuid()
479 }
480
481 fn on_removed_from_graph(&mut self, graph: &mut Graph) {
482 graph.physics2d.remove_body(self.native.get());
483 self.native.set(RigidBodyHandle::invalid());
484
485 Log::info(format!(
486 "Native rigid body was removed for node: {}",
487 self.name()
488 ));
489 }
490
491 fn sync_native(&self, self_handle: Handle<Node>, context: &mut SyncContext) {
492 context.physics2d.sync_to_rigid_body_node(self_handle, self);
493 }
494
495 fn on_global_transform_changed(
496 &self,
497 new_global_transform: &Matrix4<f32>,
498 context: &mut SyncContext,
499 ) {
500 if !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
501 context
502 .physics2d
503 .set_rigid_body_position(self, new_global_transform);
504 }
505 }
506
507 fn update(&mut self, context: &mut UpdateContext) {
508 context.physics2d.sync_rigid_body_node(
509 self,
510 context
512 .nodes
513 .try_borrow(self.parent)
514 .map(|p| p.global_transform())
515 .unwrap_or_else(Matrix4::identity),
516 );
517 }
518
519 fn validate(&self, scene: &Scene) -> Result<(), String> {
520 for &child in self.children() {
521 if scene.graph.try_get_of_type::<Collider>(child).is_some() {
522 return Ok(());
523 }
524 }
525
526 Err("The 2D rigid body must have at least one 2D collider as a \
527 direct child node to work correctly!"
528 .to_string())
529 }
530}
531
532pub struct RigidBodyBuilder {
534 base_builder: BaseBuilder,
535 lin_vel: Vector2<f32>,
536 ang_vel: f32,
537 lin_damping: f32,
538 ang_damping: f32,
539 sleeping: bool,
540 body_type: RigidBodyType,
541 mass: f32,
542 rotation_locked: bool,
543 translation_locked: bool,
544 ccd_enabled: bool,
545 can_sleep: bool,
546 dominance: i8,
547 gravity_scale: f32,
548}
549
550impl RigidBodyBuilder {
551 pub fn new(base_builder: BaseBuilder) -> Self {
553 Self {
554 base_builder,
555 lin_vel: Default::default(),
556 ang_vel: Default::default(),
557 lin_damping: 0.0,
558 ang_damping: 0.0,
559 sleeping: false,
560 body_type: RigidBodyType::Dynamic,
561 mass: 1.0,
562 rotation_locked: false,
563 translation_locked: false,
564 ccd_enabled: false,
565 can_sleep: true,
566 dominance: 0,
567 gravity_scale: 1.0,
568 }
569 }
570
571 pub fn with_body_type(mut self, body_type: RigidBodyType) -> Self {
573 self.body_type = body_type;
574 self
575 }
576
577 pub fn with_mass(mut self, mass: f32) -> Self {
579 self.mass = mass;
580 self
581 }
582
583 pub fn with_ccd_enabled(mut self, enabled: bool) -> Self {
585 self.ccd_enabled = enabled;
586 self
587 }
588
589 pub fn with_lin_vel(mut self, lin_vel: Vector2<f32>) -> Self {
591 self.lin_vel = lin_vel;
592 self
593 }
594
595 pub fn with_ang_vel(mut self, ang_vel: f32) -> Self {
597 self.ang_vel = ang_vel;
598 self
599 }
600
601 pub fn with_ang_damping(mut self, ang_damping: f32) -> Self {
603 self.ang_damping = ang_damping;
604 self
605 }
606
607 pub fn with_lin_damping(mut self, lin_damping: f32) -> Self {
609 self.lin_damping = lin_damping;
610 self
611 }
612
613 pub fn with_rotation_locked(mut self, rotation_locked: bool) -> Self {
615 self.rotation_locked = rotation_locked;
616 self
617 }
618
619 pub fn with_translation_locked(mut self, translation_locked: bool) -> Self {
621 self.translation_locked = translation_locked;
622 self
623 }
624
625 pub fn with_dominance(mut self, dominance: i8) -> Self {
627 self.dominance = dominance;
628 self
629 }
630
631 pub fn with_gravity_scale(mut self, gravity_scale: f32) -> Self {
633 self.gravity_scale = gravity_scale;
634 self
635 }
636
637 pub fn with_sleeping(mut self, sleeping: bool) -> Self {
639 self.sleeping = sleeping;
640 self
641 }
642
643 pub fn with_can_sleep(mut self, can_sleep: bool) -> Self {
645 self.can_sleep = can_sleep;
646 self
647 }
648
649 pub fn build_rigid_body(self) -> RigidBody {
651 RigidBody {
652 base: self.base_builder.build_base(),
653 lin_vel: self.lin_vel.into(),
654 ang_vel: self.ang_vel.into(),
655 lin_damping: self.lin_damping.into(),
656 ang_damping: self.ang_damping.into(),
657 sleeping: self.sleeping,
658 body_type: self.body_type.into(),
659 mass: self.mass.into(),
660 rotation_locked: self.rotation_locked.into(),
661 translation_locked: self.translation_locked.into(),
662 ccd_enabled: self.ccd_enabled.into(),
663 can_sleep: self.can_sleep.into(),
664 dominance: self.dominance.into(),
665 gravity_scale: self.gravity_scale.into(),
666 native: Cell::new(RigidBodyHandle::invalid()),
667 actions: Default::default(),
668 reset_forces: Default::default(),
669 }
670 }
671
672 pub fn build_node(self) -> Node {
674 Node::new(self.build_rigid_body())
675 }
676
677 pub fn build(self, graph: &mut Graph) -> Handle<Node> {
679 graph.add_node(self.build_node())
680 }
681}