From 75ae38131b7a7ac404a7eb22afdc3bce897e3a05 Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Sat, 21 Sep 2024 20:35:57 -0400 Subject: [PATCH 1/4] excise: Remove rest_length field. --- src/dynamics/solver/joints/distance.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/dynamics/solver/joints/distance.rs b/src/dynamics/solver/joints/distance.rs index ce5632ad..665af1e0 100644 --- a/src/dynamics/solver/joints/distance.rs +++ b/src/dynamics/solver/joints/distance.rs @@ -25,10 +25,8 @@ pub struct DistanceJoint { pub local_anchor1: Vector, /// Attachment point on the second body. pub local_anchor2: Vector, - /// The distance the attached bodies will be kept relative to each other. - pub rest_length: Scalar, /// The extents of the allowed relative translation between the attached bodies. - pub length_limits: Option, + pub length_limits: DistanceLimit, /// Linear damping applied by the joint. pub damping_linear: Scalar, /// Angular damping applied by the joint. @@ -62,8 +60,7 @@ impl Joint for DistanceJoint { entity2, local_anchor1: Vector::ZERO, local_anchor2: Vector::ZERO, - rest_length: 0.0, - length_limits: None, + length_limits: DistanceLimit::ZERO, damping_linear: 0.0, damping_angular: 0.0, lagrange: 0.0, @@ -132,9 +129,7 @@ impl DistanceJoint { // If min and max limits aren't specified, use rest length // TODO: Remove rest length, just use min/max limits. - let limits = self - .length_limits - .unwrap_or(DistanceLimit::new(self.rest_length, self.rest_length)); + let limits = self.length_limits; // Compute the direction and magnitude of the positional correction required // to keep the bodies within a certain distance from each other. @@ -175,15 +170,16 @@ impl DistanceJoint { /// Sets the minimum and maximum distances between the attached bodies. pub fn with_limits(self, min: Scalar, max: Scalar) -> Self { Self { - length_limits: Some(DistanceLimit::new(min, max)), + length_limits: DistanceLimit::new(min, max), ..self } } - /// Sets the joint's rest length, or distance the bodies will be kept at. + /// Sets the joint's minimum and maximum length limit to `rest_length`, or + /// distance the bodies will be kept at. pub fn with_rest_length(self, rest_length: Scalar) -> Self { Self { - rest_length, + length_limits: DistanceLimit::new(rest_length, rest_length), ..self } } From 2a018cdf1e24dd19fbe8cb90c5e09c3d1ed2978b Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Sat, 21 Sep 2024 21:32:10 -0400 Subject: [PATCH 2/4] test: Fix failing doc tests. Just added a '&' where needed. --- src/spatial_query/system_param.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/spatial_query/system_param.rs b/src/spatial_query/system_param.rs index 2a9401ab..5d461f18 100644 --- a/src/spatial_query/system_param.rs +++ b/src/spatial_query/system_param.rs @@ -38,7 +38,7 @@ use bevy::{ecs::system::SystemParam, prelude::*}; /// Dir3::X, // Direction /// 100.0, // Maximum time of impact (travel distance) /// true, // Does the ray treat colliders as "solid" -/// SpatialQueryFilter::default(), // Query filter +/// &SpatialQueryFilter::default(), // Query filter /// ) { /// println!("First hit: {:?}", first_hit); /// } @@ -50,7 +50,7 @@ use bevy::{ecs::system::SystemParam, prelude::*}; /// 100.0, // Maximum time of impact (travel distance) /// 20, // Maximum number of hits /// true, // Does the ray treat colliders as "solid" -/// SpatialQueryFilter::default(), // Query filter +/// &SpatialQueryFilter::default(), // Query filter /// ); /// /// // Print hits @@ -115,7 +115,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// Dir3::X, // Direction /// 100.0, // Maximum time of impact (travel distance) /// true, // Does the ray treat colliders as "solid" - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// ) { /// println!("First hit: {:?}", first_hit); /// } @@ -167,7 +167,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// Dir3::X, // Direction /// 100.0, // Maximum time of impact (travel distance) /// true, // Does the ray treat colliders as "solid" - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// &|entity| { // Predicate /// // Skip entities with the `Invisible` component. /// !query.contains(entity) @@ -229,7 +229,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// 100.0, // Maximum time of impact (travel distance) /// 20, // Maximum number of hits /// true, // Does the ray treat colliders as "solid" - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// ); /// /// // Print hits @@ -291,7 +291,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// Dir3::X, // Direction /// 100.0, // Maximum time of impact (travel distance) /// true, // Does the ray treat colliders as "solid" - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// |hit| { // Callback function /// hits.push(hit); /// true @@ -359,7 +359,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// Dir3::X, // Direction /// 100.0, // Maximum time of impact (travel distance) /// true, // Should initial penetration at the origin be ignored - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// ) { /// println!("First hit: {:?}", first_hit); /// } @@ -424,7 +424,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// 100.0, // Maximum time of impact (travel distance) /// 20, // Max hits /// true, // Should initial penetration at the origin be ignored - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// ); /// /// // Print hits @@ -495,7 +495,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// Dir3::X, // Direction /// 100.0, // Maximum time of impact (travel distance) /// true, // Should initial penetration at the origin be ignored - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// |hit| { // Callback function /// hits.push(hit); /// true @@ -557,7 +557,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// if let Some(projection) = spatial_query.project_point( /// Vec3::ZERO, // Point /// true, // Are colliders treated as "solid" - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// ) { /// println!("Projection: {:?}", projection); /// } @@ -593,7 +593,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// # #[cfg(all(feature = "3d", feature = "f32"))] /// fn print_point_intersections(spatial_query: SpatialQuery) { /// let intersections = - /// spatial_query.point_intersections(Vec3::ZERO, SpatialQueryFilter::default()); + /// spatial_query.point_intersections(Vec3::ZERO, &SpatialQueryFilter::default()); /// /// for entity in intersections.iter() { /// println!("Entity: {:?}", entity); @@ -633,7 +633,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// /// spatial_query.point_intersections_callback( /// Vec3::ZERO, // Point - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// |entity| { // Callback function /// intersections.push(entity); /// true @@ -745,7 +745,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// &Collider::sphere(0.5), // Shape /// Vec3::ZERO, // Shape position /// Quat::default(), // Shape rotation - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// ); /// /// for entity in intersections.iter() { @@ -793,7 +793,7 @@ impl<'w, 's> SpatialQuery<'w, 's> { /// &Collider::sphere(0.5), // Shape /// Vec3::ZERO, // Shape position /// Quat::default(), // Shape rotation - /// SpatialQueryFilter::default(), // Query filter + /// &SpatialQueryFilter::default(), // Query filter /// |entity| { // Callback function /// intersections.push(entity); /// true From 93e5e6d27ed2efb5b4f6fed453645e42c3920113 Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Sat, 21 Sep 2024 21:33:02 -0400 Subject: [PATCH 3/4] feature: Add From impls for DistanceLimit. Add From and From<(Scalar, Scalar)> for DistanceLimit. --- crates/avian2d/examples/distance_joint_2d.rs | 2 +- crates/avian3d/examples/distance_joint_3d.rs | 2 +- src/dynamics/solver/joints/distance.rs | 32 +++++++++++++------- src/dynamics/solver/joints/mod.rs | 20 ++++++++++++ 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/crates/avian2d/examples/distance_joint_2d.rs b/crates/avian2d/examples/distance_joint_2d.rs index 77aa85d0..f2bde85b 100644 --- a/crates/avian2d/examples/distance_joint_2d.rs +++ b/crates/avian2d/examples/distance_joint_2d.rs @@ -51,7 +51,7 @@ fn setup(mut commands: Commands) { DistanceJoint::new(anchor, object) .with_local_anchor_1(Vector::ZERO) .with_local_anchor_2(Vector::ZERO) - .with_rest_length(100.0) + .with_length_limits(100.0) .with_linear_velocity_damping(0.1) .with_angular_velocity_damping(1.0) .with_compliance(0.00000001), diff --git a/crates/avian3d/examples/distance_joint_3d.rs b/crates/avian3d/examples/distance_joint_3d.rs index 8a617960..594654f2 100644 --- a/crates/avian3d/examples/distance_joint_3d.rs +++ b/crates/avian3d/examples/distance_joint_3d.rs @@ -52,7 +52,7 @@ fn setup( commands.spawn( DistanceJoint::new(static_cube, dynamic_cube) .with_local_anchor_2(0.5 * Vector::ONE) - .with_rest_length(1.5) + .with_length_limits(1.5) .with_compliance(1.0 / 400.0), ); diff --git a/src/dynamics/solver/joints/distance.rs b/src/dynamics/solver/joints/distance.rs index 665af1e0..4c5ad52a 100644 --- a/src/dynamics/solver/joints/distance.rs +++ b/src/dynamics/solver/joints/distance.rs @@ -167,22 +167,32 @@ impl DistanceJoint { self.compute_force(self.lagrange, dir, dt) } - /// Sets the minimum and maximum distances between the attached bodies. - pub fn with_limits(self, min: Scalar, max: Scalar) -> Self { + /// Returns self with the minimum and maximum distances between the attached + /// bodies. + /// + /// `` + /// # #[cfg(feature = "2d")] + /// # use avian2d::prelude::*; + /// # #[cfg(feature = "3d")] + /// # use avian3d::prelude::*; + /// # use bevy::perlude::*;` + /// # fn new_joint() -> DistanceJoint { DistanceJoint::new(Entity::PLACEHOLDER, Entity::PLACEHOLDER) } + /// let j: DistanceJoint = new_joint(); + /// let a = j.with_length_limits(DistanceLimit { min: 0.0, max: 1.0 }); + /// let b = j.with_length_limits((0.0, 1.0)); + /// assert_eq!(a, b); + /// + /// let c = j.with_length_limits(DistanceLimit { min: 0.5, max: 0.5 }); + /// let d = j.with_length_limits(0.5); + /// assert_eq!(c, d); + /// ``` + pub fn with_length_limits(self, limit: impl Into) -> Self { Self { - length_limits: DistanceLimit::new(min, max), + length_limits: limit.into(), ..self } } - /// Sets the joint's minimum and maximum length limit to `rest_length`, or - /// distance the bodies will be kept at. - pub fn with_rest_length(self, rest_length: Scalar) -> Self { - Self { - length_limits: DistanceLimit::new(rest_length, rest_length), - ..self - } - } } impl PositionConstraint for DistanceJoint {} diff --git a/src/dynamics/solver/joints/mod.rs b/src/dynamics/solver/joints/mod.rs index 6fa37350..b0cfb396 100644 --- a/src/dynamics/solver/joints/mod.rs +++ b/src/dynamics/solver/joints/mod.rs @@ -194,6 +194,26 @@ pub struct DistanceLimit { pub max: Scalar, } +/// Convert the `limit` into a distance limit where _min = max = limit_. +impl From for DistanceLimit { + fn from(limit: Scalar) -> DistanceLimit { + DistanceLimit { + min: limit, + max: limit + } + } +} + +/// Convert the `(min, max)` pair into a distance limit. +impl From<(Scalar, Scalar)> for DistanceLimit { + fn from((min, max): (Scalar, Scalar)) -> DistanceLimit { + DistanceLimit { + min, + max + } + } +} + impl DistanceLimit { /// A `DistanceLimit` with `min` and `max` set to zero. pub const ZERO: Self = Self { min: 0.0, max: 0.0 }; From f8f4c9c08a47827da5f620d45c57f3bf16f702c7 Mon Sep 17 00:00:00 2001 From: Shane Celis Date: Sat, 21 Sep 2024 22:53:16 -0400 Subject: [PATCH 4/4] chore: "Listen to Clippy, she's trying to help you out."--Hansel, Zoolander (2001) --- src/dynamics/solver/joints/distance.rs | 5 ++--- src/dynamics/solver/joints/mod.rs | 7 ++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/dynamics/solver/joints/distance.rs b/src/dynamics/solver/joints/distance.rs index 4c5ad52a..a85f7d2e 100644 --- a/src/dynamics/solver/joints/distance.rs +++ b/src/dynamics/solver/joints/distance.rs @@ -170,12 +170,12 @@ impl DistanceJoint { /// Returns self with the minimum and maximum distances between the attached /// bodies. /// - /// `` + /// ``` /// # #[cfg(feature = "2d")] /// # use avian2d::prelude::*; /// # #[cfg(feature = "3d")] /// # use avian3d::prelude::*; - /// # use bevy::perlude::*;` + /// # use bevy::prelude::*; /// # fn new_joint() -> DistanceJoint { DistanceJoint::new(Entity::PLACEHOLDER, Entity::PLACEHOLDER) } /// let j: DistanceJoint = new_joint(); /// let a = j.with_length_limits(DistanceLimit { min: 0.0, max: 1.0 }); @@ -192,7 +192,6 @@ impl DistanceJoint { ..self } } - } impl PositionConstraint for DistanceJoint {} diff --git a/src/dynamics/solver/joints/mod.rs b/src/dynamics/solver/joints/mod.rs index b0cfb396..5a0eacbd 100644 --- a/src/dynamics/solver/joints/mod.rs +++ b/src/dynamics/solver/joints/mod.rs @@ -199,7 +199,7 @@ impl From for DistanceLimit { fn from(limit: Scalar) -> DistanceLimit { DistanceLimit { min: limit, - max: limit + max: limit, } } } @@ -207,10 +207,7 @@ impl From for DistanceLimit { /// Convert the `(min, max)` pair into a distance limit. impl From<(Scalar, Scalar)> for DistanceLimit { fn from((min, max): (Scalar, Scalar)) -> DistanceLimit { - DistanceLimit { - min, - max - } + DistanceLimit { min, max } } }