1use crate::scene::collider::ColliderShape;
32use crate::scene::node::constructor::NodeConstructor;
33use crate::{
34 core::{
35 algebra::{Isometry3, Matrix4, UnitQuaternion, Vector3},
36 log::Log,
37 math::{aabb::AxisAlignedBoundingBox, m4x4_approx_eq},
38 parking_lot::Mutex,
39 pool::Handle,
40 reflect::prelude::*,
41 type_traits::prelude::*,
42 uuid::{uuid, Uuid},
43 variable::InheritableVariable,
44 visitor::prelude::*,
45 },
46 scene::{
47 base::{Base, BaseBuilder},
48 collider::Collider,
49 graph::Graph,
50 node::{Node, NodeTrait, SyncContext, UpdateContext},
51 Scene,
52 },
53};
54use fyrox_core::uuid_provider;
55use fyrox_graph::constructor::ConstructorProvider;
56use fyrox_graph::SceneGraph;
57use rapier3d::{dynamics, prelude::RigidBodyHandle};
58use std::{
59 cell::Cell,
60 collections::VecDeque,
61 fmt::{Debug, Formatter},
62 ops::{Deref, DerefMut},
63};
64use strum_macros::{AsRefStr, EnumString, VariantNames};
65
66#[derive(
68 Copy, Clone, Debug, Reflect, Visit, PartialEq, Eq, Hash, AsRefStr, EnumString, VariantNames,
69)]
70#[repr(u32)]
71#[derive(Default)]
72pub enum RigidBodyType {
73 #[default]
75 Dynamic = 0,
76 Static = 1,
78 KinematicPositionBased = 2,
81 KinematicVelocityBased = 3,
84}
85
86uuid_provider!(RigidBodyType = "562d2907-1b41-483a-8ca2-12eebaff7f5d");
87
88impl From<dynamics::RigidBodyType> for RigidBodyType {
89 fn from(s: dynamics::RigidBodyType) -> Self {
90 match s {
91 dynamics::RigidBodyType::Dynamic => Self::Dynamic,
92 dynamics::RigidBodyType::Fixed => Self::Static,
93 dynamics::RigidBodyType::KinematicPositionBased => Self::KinematicPositionBased,
94 dynamics::RigidBodyType::KinematicVelocityBased => Self::KinematicVelocityBased,
95 }
96 }
97}
98
99impl From<RigidBodyType> for rapier3d::dynamics::RigidBodyType {
100 fn from(v: RigidBodyType) -> Self {
101 match v {
102 RigidBodyType::Dynamic => rapier3d::dynamics::RigidBodyType::Dynamic,
103 RigidBodyType::Static => rapier3d::dynamics::RigidBodyType::Fixed,
104 RigidBodyType::KinematicPositionBased => {
105 rapier3d::dynamics::RigidBodyType::KinematicPositionBased
106 }
107 RigidBodyType::KinematicVelocityBased => {
108 rapier3d::dynamics::RigidBodyType::KinematicVelocityBased
109 }
110 }
111 }
112}
113
114impl From<RigidBodyType> for rapier2d::dynamics::RigidBodyType {
115 fn from(v: RigidBodyType) -> Self {
116 match v {
117 RigidBodyType::Dynamic => rapier2d::dynamics::RigidBodyType::Dynamic,
118 RigidBodyType::Static => rapier2d::dynamics::RigidBodyType::Fixed,
119 RigidBodyType::KinematicPositionBased => {
120 rapier2d::dynamics::RigidBodyType::KinematicPositionBased
121 }
122 RigidBodyType::KinematicVelocityBased => {
123 rapier2d::dynamics::RigidBodyType::KinematicVelocityBased
124 }
125 }
126 }
127}
128
129#[derive(Debug)]
130pub(crate) enum ApplyAction {
131 Force(Vector3<f32>),
132 Torque(Vector3<f32>),
133 ForceAtPoint {
134 force: Vector3<f32>,
135 point: Vector3<f32>,
136 },
137 Impulse(Vector3<f32>),
138 TorqueImpulse(Vector3<f32>),
139 ImpulseAtPoint {
140 impulse: Vector3<f32>,
141 point: Vector3<f32>,
142 },
143 WakeUp,
144 NextTranslation(Vector3<f32>),
145 NextRotation(UnitQuaternion<f32>),
146 NextPosition(Isometry3<f32>),
147}
148
149#[derive(Copy, Clone, Debug, Reflect, Visit, PartialEq, AsRefStr, EnumString, VariantNames)]
150pub enum RigidBodyMassPropertiesType {
152 Default,
154 Additional {
156 center_of_mass: Vector3<f32>,
158 principal_inertia: Vector3<f32>,
160 },
161}
162uuid_provider!(RigidBodyMassPropertiesType = "663b6a92-9c0f-4f47-b66a-6b4293312a5d");
163
164#[derive(Visit, Reflect, ComponentProvider)]
172#[reflect(derived_type = "Node")]
173pub struct RigidBody {
174 base: Base,
175
176 #[reflect(setter = "set_lin_vel")]
177 pub(crate) lin_vel: InheritableVariable<Vector3<f32>>,
178
179 #[reflect(setter = "set_ang_vel")]
180 pub(crate) ang_vel: InheritableVariable<Vector3<f32>>,
181
182 #[reflect(setter = "set_lin_damping")]
183 pub(crate) lin_damping: InheritableVariable<f32>,
184
185 #[reflect(setter = "set_ang_damping")]
186 pub(crate) ang_damping: InheritableVariable<f32>,
187
188 #[reflect(setter = "set_body_type")]
189 pub(crate) body_type: InheritableVariable<RigidBodyType>,
190
191 #[reflect(min_value = 0.0, step = 0.05)]
192 #[reflect(setter = "set_mass")]
193 pub(crate) mass: InheritableVariable<f32>,
194
195 #[reflect(setter = "lock_x_rotations")]
196 pub(crate) x_rotation_locked: InheritableVariable<bool>,
197
198 #[reflect(setter = "lock_y_rotations")]
199 pub(crate) y_rotation_locked: InheritableVariable<bool>,
200
201 #[reflect(setter = "lock_z_rotations")]
202 pub(crate) z_rotation_locked: InheritableVariable<bool>,
203
204 #[reflect(setter = "lock_translation")]
205 pub(crate) translation_locked: InheritableVariable<bool>,
206
207 #[reflect(setter = "enable_ccd")]
208 pub(crate) ccd_enabled: InheritableVariable<bool>,
209
210 #[reflect(setter = "set_can_sleep")]
211 pub(crate) can_sleep: InheritableVariable<bool>,
212
213 #[reflect(setter = "set_dominance")]
214 pub(crate) dominance: InheritableVariable<i8>,
215
216 #[reflect(setter = "set_gravity_scale")]
217 pub(crate) gravity_scale: InheritableVariable<f32>,
218
219 #[visit(optional)]
220 #[reflect(setter = "set_mass_properties_type")]
221 pub(crate) mass_properties_type: InheritableVariable<RigidBodyMassPropertiesType>,
222
223 #[visit(skip)]
224 #[reflect(hidden)]
225 pub(crate) sleeping: bool,
226 #[visit(skip)]
227 #[reflect(hidden)]
228 pub(crate) reset_forces: Cell<bool>,
229 #[visit(skip)]
230 #[reflect(hidden)]
231 pub(crate) native: Cell<RigidBodyHandle>,
232 #[visit(skip)]
233 #[reflect(hidden)]
234 pub(crate) actions: Mutex<VecDeque<ApplyAction>>,
235}
236
237impl Debug for RigidBody {
238 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
239 write!(f, "RigidBody")
240 }
241}
242
243impl Default for RigidBody {
244 fn default() -> Self {
245 Self {
246 base: Default::default(),
247 lin_vel: Default::default(),
248 ang_vel: Default::default(),
249 lin_damping: Default::default(),
250 ang_damping: Default::default(),
251 sleeping: Default::default(),
252 body_type: InheritableVariable::new_modified(RigidBodyType::Dynamic),
253 mass: InheritableVariable::new_modified(1.0),
254 x_rotation_locked: Default::default(),
255 y_rotation_locked: Default::default(),
256 z_rotation_locked: Default::default(),
257 translation_locked: Default::default(),
258 ccd_enabled: Default::default(),
259 can_sleep: InheritableVariable::new_modified(true),
260 dominance: Default::default(),
261 gravity_scale: InheritableVariable::new_modified(1.0),
262 native: Cell::new(RigidBodyHandle::invalid()),
263 actions: Default::default(),
264 reset_forces: Default::default(),
265 mass_properties_type: InheritableVariable::new_modified(
266 RigidBodyMassPropertiesType::Default,
267 ),
268 }
269 }
270}
271
272impl Deref for RigidBody {
273 type Target = Base;
274
275 fn deref(&self) -> &Self::Target {
276 &self.base
277 }
278}
279
280impl DerefMut for RigidBody {
281 fn deref_mut(&mut self) -> &mut Self::Target {
282 &mut self.base
283 }
284}
285
286impl Clone for RigidBody {
287 fn clone(&self) -> Self {
288 Self {
289 base: self.base.clone(),
290 lin_vel: self.lin_vel.clone(),
291 ang_vel: self.ang_vel.clone(),
292 lin_damping: self.lin_damping.clone(),
293 ang_damping: self.ang_damping.clone(),
294 sleeping: self.sleeping,
295 body_type: self.body_type.clone(),
296 mass: self.mass.clone(),
297 x_rotation_locked: self.x_rotation_locked.clone(),
298 y_rotation_locked: self.y_rotation_locked.clone(),
299 z_rotation_locked: self.z_rotation_locked.clone(),
300 translation_locked: self.translation_locked.clone(),
301 ccd_enabled: self.ccd_enabled.clone(),
302 can_sleep: self.can_sleep.clone(),
303 dominance: self.dominance.clone(),
304 gravity_scale: self.gravity_scale.clone(),
305 native: Cell::new(RigidBodyHandle::invalid()),
307 actions: Default::default(),
308 reset_forces: self.reset_forces.clone(),
309 mass_properties_type: self.mass_properties_type.clone(),
310 }
311 }
312}
313
314impl TypeUuidProvider for RigidBody {
315 fn type_uuid() -> Uuid {
316 uuid!("4be15a7c-3566-49c4-bba8-2f4ccc57ffed")
317 }
318}
319
320impl RigidBody {
321 pub fn set_lin_vel(&mut self, lin_vel: Vector3<f32>) -> Vector3<f32> {
324 self.lin_vel.set_value_and_mark_modified(lin_vel)
325 }
326
327 pub fn set_lin_vel_x(&mut self, x_vel: f32) {
330 self.lin_vel.x = x_vel;
331 }
332
333 pub fn set_lin_vel_y(&mut self, y_vel: f32) {
336 self.lin_vel.y = y_vel;
337 }
338
339 pub fn set_lin_vel_z(&mut self, z_vel: f32) {
342 self.lin_vel.z = z_vel;
343 }
344
345 pub fn lin_vel(&self) -> Vector3<f32> {
347 *self.lin_vel
348 }
349
350 pub fn set_ang_vel(&mut self, ang_vel: Vector3<f32>) -> Vector3<f32> {
353 self.ang_vel.set_value_and_mark_modified(ang_vel)
354 }
355
356 pub fn ang_vel(&self) -> Vector3<f32> {
358 *self.ang_vel
359 }
360
361 pub fn set_mass(&mut self, mass: f32) -> f32 {
364 self.mass.set_value_and_mark_modified(mass)
365 }
366
367 pub fn mass(&self) -> f32 {
369 *self.mass
370 }
371
372 pub fn set_ang_damping(&mut self, damping: f32) -> f32 {
375 self.ang_damping.set_value_and_mark_modified(damping)
376 }
377
378 pub fn ang_damping(&self) -> f32 {
380 *self.ang_damping
381 }
382
383 pub fn set_lin_damping(&mut self, damping: f32) -> f32 {
386 self.lin_damping.set_value_and_mark_modified(damping)
387 }
388
389 pub fn lin_damping(&self) -> f32 {
391 *self.lin_damping
392 }
393
394 pub fn lock_x_rotations(&mut self, state: bool) -> bool {
396 self.x_rotation_locked.set_value_and_mark_modified(state)
397 }
398
399 pub fn is_x_rotation_locked(&self) -> bool {
401 *self.x_rotation_locked
402 }
403
404 pub fn lock_y_rotations(&mut self, state: bool) -> bool {
406 self.y_rotation_locked.set_value_and_mark_modified(state)
407 }
408
409 pub fn is_y_rotation_locked(&self) -> bool {
411 *self.y_rotation_locked
412 }
413
414 pub fn lock_z_rotations(&mut self, state: bool) -> bool {
416 self.z_rotation_locked.set_value_and_mark_modified(state)
417 }
418
419 pub fn is_z_rotation_locked(&self) -> bool {
421 *self.z_rotation_locked
422 }
423
424 pub fn lock_rotations(&mut self, locked: bool) {
426 self.x_rotation_locked.set_value_and_mark_modified(locked);
427 self.y_rotation_locked.set_value_and_mark_modified(locked);
428 self.z_rotation_locked.set_value_and_mark_modified(locked);
429 }
430
431 pub fn lock_translation(&mut self, state: bool) -> bool {
433 self.translation_locked.set_value_and_mark_modified(state)
434 }
435
436 pub fn is_translation_locked(&self) -> bool {
438 *self.translation_locked
439 }
440
441 pub fn set_body_type(&mut self, body_type: RigidBodyType) -> RigidBodyType {
443 self.body_type.set_value_and_mark_modified(body_type)
444 }
445
446 pub fn body_type(&self) -> RigidBodyType {
448 *self.body_type
449 }
450
451 pub fn is_sleeping(&self) -> bool {
454 self.sleeping
455 }
456
457 pub fn is_ccd_enabled(&self) -> bool {
459 *self.ccd_enabled
460 }
461
462 pub fn enable_ccd(&mut self, enable: bool) -> bool {
465 self.ccd_enabled.set_value_and_mark_modified(enable)
466 }
467
468 pub fn set_gravity_scale(&mut self, scale: f32) -> f32 {
470 self.gravity_scale.set_value_and_mark_modified(scale)
471 }
472
473 pub fn set_mass_properties_type(
475 &mut self,
476 mass_properties_type: RigidBodyMassPropertiesType,
477 ) -> RigidBodyMassPropertiesType {
478 self.mass_properties_type
479 .set_value_and_mark_modified(mass_properties_type)
480 }
481
482 pub fn mass_properties_type(&self) -> RigidBodyMassPropertiesType {
484 *self.mass_properties_type
485 }
486
487 pub fn gravity_scale(&self) -> f32 {
489 *self.gravity_scale
490 }
491
492 pub fn set_dominance(&mut self, dominance: i8) -> i8 {
497 self.dominance.set_value_and_mark_modified(dominance)
498 }
499
500 pub fn dominance(&self) -> i8 {
502 *self.dominance
503 }
504
505 pub fn apply_force(&mut self, force: Vector3<f32>) {
508 self.actions.get_mut().push_back(ApplyAction::Force(force))
509 }
510
511 pub fn apply_torque(&mut self, torque: Vector3<f32>) {
514 self.actions
515 .get_mut()
516 .push_back(ApplyAction::Torque(torque))
517 }
518
519 pub fn apply_force_at_point(&mut self, force: Vector3<f32>, point: Vector3<f32>) {
522 self.actions
523 .get_mut()
524 .push_back(ApplyAction::ForceAtPoint { force, point })
525 }
526
527 pub fn apply_impulse(&mut self, impulse: Vector3<f32>) {
530 self.actions
531 .get_mut()
532 .push_back(ApplyAction::Impulse(impulse))
533 }
534
535 pub fn apply_torque_impulse(&mut self, torque_impulse: Vector3<f32>) {
538 self.actions
539 .get_mut()
540 .push_back(ApplyAction::TorqueImpulse(torque_impulse))
541 }
542
543 pub fn apply_impulse_at_point(&mut self, impulse: Vector3<f32>, point: Vector3<f32>) {
547 self.actions
548 .get_mut()
549 .push_back(ApplyAction::ImpulseAtPoint { impulse, point })
550 }
551
552 pub fn set_next_kinematic_translation(&mut self, translation: Vector3<f32>) {
555 self.actions
556 .get_mut()
557 .push_back(ApplyAction::NextTranslation(translation));
558 }
559
560 pub fn set_next_kinematic_rotation(&mut self, rotation: UnitQuaternion<f32>) {
563 self.actions
564 .get_mut()
565 .push_back(ApplyAction::NextRotation(rotation));
566 }
567
568 pub fn set_next_kinematic_position(&mut self, position: Isometry3<f32>) {
571 self.actions
572 .get_mut()
573 .push_back(ApplyAction::NextPosition(position));
574 }
575
576 pub fn set_can_sleep(&mut self, can_sleep: bool) -> bool {
579 self.can_sleep.set_value_and_mark_modified(can_sleep)
580 }
581
582 pub fn is_can_sleep(&self) -> bool {
584 *self.can_sleep
585 }
586
587 pub fn wake_up(&mut self) {
589 self.actions.get_mut().push_back(ApplyAction::WakeUp)
590 }
591
592 pub(crate) fn need_sync_model(&self) -> bool {
593 self.lin_vel.need_sync()
594 || self.ang_vel.need_sync()
595 || self.lin_damping.need_sync()
596 || self.ang_damping.need_sync()
597 || self.body_type.need_sync()
598 || self.mass.need_sync()
599 || self.x_rotation_locked.need_sync()
600 || self.y_rotation_locked.need_sync()
601 || self.z_rotation_locked.need_sync()
602 || self.translation_locked.need_sync()
603 || self.ccd_enabled.need_sync()
604 || self.can_sleep.need_sync()
605 || self.dominance.need_sync()
606 || self.gravity_scale.need_sync()
607 || self.reset_forces.get()
608 }
609}
610
611impl ConstructorProvider<Node, Graph> for RigidBody {
612 fn constructor() -> NodeConstructor {
613 NodeConstructor::new::<Self>()
614 .with_variant("Rigid Body", |_| {
615 RigidBodyBuilder::new(BaseBuilder::new().with_name("Rigid Body"))
616 .build_node()
617 .into()
618 })
619 .with_group("Physics")
620 }
621}
622
623impl NodeTrait for RigidBody {
624 fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
625 self.base.local_bounding_box()
626 }
627
628 fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
629 self.base.world_bounding_box()
630 }
631
632 fn id(&self) -> Uuid {
633 Self::type_uuid()
634 }
635
636 fn on_removed_from_graph(&mut self, graph: &mut Graph) {
637 graph.physics.remove_body(self.native.get());
638 self.native.set(RigidBodyHandle::invalid());
639
640 Log::info(format!(
641 "Native rigid body was removed for node: {}",
642 self.name()
643 ));
644 }
645
646 fn sync_native(&self, self_handle: Handle<Node>, context: &mut SyncContext) {
647 context.physics.sync_to_rigid_body_node(self_handle, self);
648 }
649
650 fn on_global_transform_changed(
651 &self,
652 new_global_transform: &Matrix4<f32>,
653 context: &mut SyncContext,
654 ) {
655 if !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
656 context
657 .physics
658 .set_rigid_body_position(self, new_global_transform);
659 }
660 }
661
662 fn update(&mut self, context: &mut UpdateContext) {
663 context.physics.sync_rigid_body_node(
664 self,
665 context
667 .nodes
668 .try_borrow(self.parent)
669 .ok()
670 .map(|p| p.global_transform())
671 .unwrap_or_else(Matrix4::identity),
672 );
673 }
674
675 fn validate(&self, scene: &Scene) -> Result<(), String> {
676 for &child in self.children() {
677 if let Ok(collider) = scene.graph.try_get_of_type::<Collider>(child) {
678 match collider.shape() {
679 ColliderShape::Trimesh(_) | ColliderShape::Heightfield(_)
680 if *self.body_type == RigidBodyType::Dynamic =>
681 {
682 return Err(
683 "The 3D rigid body is marked as dynamic, but uses the collider \
684 that cannot be dynamic. Consider making the rigid body static."
685 .to_string(),
686 )
687 }
688 _ => (),
689 }
690
691 return Ok(());
692 }
693 }
694
695 Err("The 3D rigid body must have at least one 3D collider as a \
696 direct child node to work correctly!"
697 .to_string())
698 }
699}
700
701pub struct RigidBodyBuilder {
703 base_builder: BaseBuilder,
704 lin_vel: Vector3<f32>,
705 ang_vel: Vector3<f32>,
706 lin_damping: f32,
707 ang_damping: f32,
708 sleeping: bool,
709 body_type: RigidBodyType,
710 mass: f32,
711 x_rotation_locked: bool,
712 y_rotation_locked: bool,
713 z_rotation_locked: bool,
714 translation_locked: bool,
715 ccd_enabled: bool,
716 can_sleep: bool,
717 dominance: i8,
718 gravity_scale: f32,
719 mass_properties_type: RigidBodyMassPropertiesType,
720}
721
722impl RigidBodyBuilder {
723 pub fn new(base_builder: BaseBuilder) -> Self {
725 Self {
726 base_builder,
727 lin_vel: Default::default(),
728 ang_vel: Default::default(),
729 lin_damping: 0.0,
730 ang_damping: 0.0,
731 sleeping: false,
732 body_type: RigidBodyType::Dynamic,
733 mass: 1.0,
734 x_rotation_locked: false,
735 y_rotation_locked: false,
736 z_rotation_locked: false,
737 translation_locked: false,
738 ccd_enabled: false,
739 can_sleep: true,
740 dominance: 0,
741 gravity_scale: 1.0,
742 mass_properties_type: RigidBodyMassPropertiesType::Default,
743 }
744 }
745
746 pub fn with_body_type(mut self, body_type: RigidBodyType) -> Self {
748 self.body_type = body_type;
749 self
750 }
751
752 pub fn with_mass(mut self, mass: f32) -> Self {
754 self.mass = mass;
755 self
756 }
757
758 pub fn with_ccd_enabled(mut self, enabled: bool) -> Self {
760 self.ccd_enabled = enabled;
761 self
762 }
763
764 pub fn with_lin_vel(mut self, lin_vel: Vector3<f32>) -> Self {
766 self.lin_vel = lin_vel;
767 self
768 }
769
770 pub fn with_ang_vel(mut self, ang_vel: Vector3<f32>) -> Self {
772 self.ang_vel = ang_vel;
773 self
774 }
775
776 pub fn with_ang_damping(mut self, ang_damping: f32) -> Self {
778 self.ang_damping = ang_damping;
779 self
780 }
781
782 pub fn with_lin_damping(mut self, lin_damping: f32) -> Self {
784 self.lin_damping = lin_damping;
785 self
786 }
787
788 pub fn with_x_rotation_locked(mut self, x_rotation_locked: bool) -> Self {
790 self.x_rotation_locked = x_rotation_locked;
791 self
792 }
793
794 pub fn with_y_rotation_locked(mut self, y_rotation_locked: bool) -> Self {
796 self.y_rotation_locked = y_rotation_locked;
797 self
798 }
799
800 pub fn with_z_rotation_locked(mut self, z_rotation_locked: bool) -> Self {
802 self.z_rotation_locked = z_rotation_locked;
803 self
804 }
805
806 pub fn with_translation_locked(mut self, translation_locked: bool) -> Self {
808 self.translation_locked = translation_locked;
809 self
810 }
811
812 pub fn with_locked_rotations(mut self, locked: bool) -> Self {
814 self.x_rotation_locked = locked;
815 self.y_rotation_locked = locked;
816 self.z_rotation_locked = locked;
817 self
818 }
819
820 pub fn with_sleeping(mut self, sleeping: bool) -> Self {
822 self.sleeping = sleeping;
823 self
824 }
825
826 pub fn with_can_sleep(mut self, can_sleep: bool) -> Self {
828 self.can_sleep = can_sleep;
829 self
830 }
831
832 pub fn with_dominance(mut self, dominance: i8) -> Self {
834 self.dominance = dominance;
835 self
836 }
837
838 pub fn with_gravity_scale(mut self, gravity_scale: f32) -> Self {
840 self.gravity_scale = gravity_scale;
841 self
842 }
843
844 pub fn with_mass_properties_type(
846 mut self,
847 mass_properties_type: RigidBodyMassPropertiesType,
848 ) -> Self {
849 self.mass_properties_type = mass_properties_type;
850 self
851 }
852
853 pub fn build_rigid_body(self) -> RigidBody {
855 RigidBody {
856 base: self.base_builder.build_base(),
857 lin_vel: self.lin_vel.into(),
858 ang_vel: self.ang_vel.into(),
859 lin_damping: self.lin_damping.into(),
860 ang_damping: self.ang_damping.into(),
861 sleeping: self.sleeping,
862 body_type: self.body_type.into(),
863 mass: self.mass.into(),
864 x_rotation_locked: self.x_rotation_locked.into(),
865 y_rotation_locked: self.y_rotation_locked.into(),
866 z_rotation_locked: self.z_rotation_locked.into(),
867 translation_locked: self.translation_locked.into(),
868 ccd_enabled: self.ccd_enabled.into(),
869 can_sleep: self.can_sleep.into(),
870 dominance: self.dominance.into(),
871 gravity_scale: self.gravity_scale.into(),
872 native: Cell::new(RigidBodyHandle::invalid()),
873 actions: Default::default(),
874 reset_forces: Default::default(),
875 mass_properties_type: self.mass_properties_type.into(),
876 }
877 }
878
879 pub fn build_node(self) -> Node {
881 Node::new(self.build_rigid_body())
882 }
883
884 pub fn build(self, graph: &mut Graph) -> Handle<RigidBody> {
886 graph.add_node(self.build_node()).to_variant()
887 }
888}