From 7937f40da4391c539e2c9d9ecb6e6a0d37625eb4 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Fri, 7 Jul 2023 13:07:31 +0300 Subject: [PATCH] Add `GravityScale` component (#57) --- src/components/mod.rs | 14 ++++++++++++-- src/lib.rs | 2 +- src/plugins/integrator.rs | 15 +++++++++++++-- src/plugins/setup.rs | 1 + src/plugins/sleeping.rs | 1 + src/resources.rs | 7 ++++--- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/components/mod.rs b/src/components/mod.rs index 2df9acc6..d757ef24 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -234,6 +234,16 @@ impl FloatZero for Scalar { #[reflect(Component)] pub struct ExternalTorque(pub Torque); +/// Controls how [gravity](Gravity) affects a specific [rigid body](RigidBody). +/// +/// A gravity scale of `0.0` will disable gravity, while `2.0` will double the gravity. +/// Using a negative value will flip the direction of the gravity. +#[derive( + Component, Reflect, Debug, Clone, Copy, PartialEq, PartialOrd, Default, Deref, DerefMut, From, +)] +#[reflect(Component)] +pub struct GravityScale(pub Scalar); + /// Determines how coefficients are combined. The default is `Average`. /// /// When combine rules clash with each other, the following priority order is used: `Max > Multiply > Min > Average`. @@ -505,7 +515,7 @@ impl From for Friction { /// /// The default linear damping coefficient is `0.0`, which corresponds to no damping. #[derive( - Component, Reflect, Debug, Clone, Copy, PartialEq, PartialOrd, Default, Deref, DerefMut, + Component, Reflect, Debug, Clone, Copy, PartialEq, PartialOrd, Default, Deref, DerefMut, From, )] #[reflect(Component)] pub struct LinearDamping(pub Scalar); @@ -515,7 +525,7 @@ pub struct LinearDamping(pub Scalar); /// /// The default angular damping coefficient is `0.0`, which corresponds to no damping. #[derive( - Component, Reflect, Debug, Clone, Copy, PartialEq, PartialOrd, Default, Deref, DerefMut, + Component, Reflect, Debug, Clone, Copy, PartialEq, PartialOrd, Default, Deref, DerefMut, From, )] #[reflect(Component)] pub struct AngularDamping(pub Scalar); diff --git a/src/lib.rs b/src/lib.rs index 13fea0d9..0ec14bb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,7 @@ //! - Material properties like [restitution](Restitution) and [friction](Friction) //! - [Linear damping](LinearDamping) and [angular damping](AngularDamping) for simulating drag //! - External [forces](ExternalForce) and [torque](ExternalTorque) -//! - [Gravity](Gravity) +//! - [Gravity] and [gravity scale](GravityScale) //! - [Joints](joints) //! - Built-in [constraints] and support for [custom constraints](constraints#custom-constraints) //! - [Spatial queries](spatial_query) diff --git a/src/plugins/integrator.rs b/src/plugins/integrator.rs index ab0a00ff..b2567874 100644 --- a/src/plugins/integrator.rs +++ b/src/plugins/integrator.rs @@ -29,6 +29,7 @@ type PosIntegrationComponents = ( &'static mut PreviousPosition, &'static mut LinearVelocity, Option<&'static LinearDamping>, + Option<&'static GravityScale>, &'static ExternalForce, &'static Mass, ); @@ -39,7 +40,17 @@ fn integrate_pos( gravity: Res, sub_dt: Res, ) { - for (rb, mut pos, mut prev_pos, mut lin_vel, lin_damping, external_force, mass) in &mut bodies { + for ( + rb, + mut pos, + mut prev_pos, + mut lin_vel, + lin_damping, + gravity_scale, + external_force, + mass, + ) in &mut bodies + { prev_pos.0 = pos.0; if rb.is_static() { @@ -53,7 +64,7 @@ fn integrate_pos( lin_vel.0 *= 1.0 / (1.0 + sub_dt.0 * damping.0); } - let gravitation_force = mass.0 * gravity.0; + let gravitation_force = mass.0 * gravity.0 * gravity_scale.map_or(1.0, |scale| scale.0); let external_forces = gravitation_force + external_force.0; lin_vel.0 += sub_dt.0 * external_forces / mass.0; } diff --git a/src/plugins/setup.rs b/src/plugins/setup.rs index 2b091f8d..0b0fb688 100644 --- a/src/plugins/setup.rs +++ b/src/plugins/setup.rs @@ -68,6 +68,7 @@ impl Plugin for PhysicsSetupPlugin { .register_type::() .register_type::() .register_type::() + .register_type::() .register_type::() .register_type::() .register_type::() diff --git a/src/plugins/sleeping.rs b/src/plugins/sleeping.rs index a85f0834..527425ec 100644 --- a/src/plugins/sleeping.rs +++ b/src/plugins/sleeping.rs @@ -88,6 +88,7 @@ type BodyWokeUpFilter = Or<( Changed, Changed, Changed, + Changed, )>; /// Removes the [`Sleeping`] component from sleeping bodies when properties like diff --git a/src/resources.rs b/src/resources.rs index fce6c497..b212311a 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -151,10 +151,11 @@ impl Default for DeactivationTime { /// A resource for the global gravitational acceleration. /// /// The default is an acceleration of 9.81 m/s^2 pointing down, which is approximate to the gravitational -/// acceleration near Earth's surface. +/// acceleration near Earth's surface. Note that if you are using pixels as length units in 2D, +/// this gravity will be tiny. You should modify the gravity to fit your application. /// -/// Note that if you are using pixels as length units in 2D, this gravity will be tiny. You should -/// modify the gravity to fit your application. +/// You can also control how gravity affects a specific [rigid body](RigidBody) using the [`GravityScale`] +/// component. The magnitude of the gravity will be multiplied by this scaling factor. /// /// ## Example ///