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