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