From 23ca1befad3e48d7e48f11a3b02eebeed3c99e08 Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Mon, 12 Feb 2024 20:29:42 +0200 Subject: [PATCH] Fix colliders without `RigidBody` not working (#323) # Objective On the main branch, collisions between colliders without a `RigidBody` component are currently not detected. This is because some queries are overly strict and require components that only rigid bodies have. ## Solution Make some components in queries optional in order to fix non-rigidbody colliders. --- src/plugins/collision/broad_phase.rs | 13 +++++++------ src/plugins/sync.rs | 11 ++++++++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/plugins/collision/broad_phase.rs b/src/plugins/collision/broad_phase.rs index d1676f4b..49761d0c 100644 --- a/src/plugins/collision/broad_phase.rs +++ b/src/plugins/collision/broad_phase.rs @@ -185,7 +185,7 @@ impl MapEntities for AabbIntervals { fn update_aabb_intervals( aabbs: Query<( &ColliderAabb, - &ColliderParent, + Option<&ColliderParent>, Option<&CollisionLayers>, Ref, Ref, @@ -199,10 +199,11 @@ fn update_aabb_intervals( aabbs.get(*collider_entity) { *aabb = *new_aabb; - *collider_parent = *new_parent; + *collider_parent = new_parent.map_or(ColliderParent(*collider_entity), |p| *p); *layers = new_layers.map_or(CollisionLayers::default(), |layers| *layers); - let is_static = rbs.get(new_parent.get()).is_ok_and(RigidBody::is_static); + let is_static = + new_parent.is_some_and(|p| rbs.get(p.get()).is_ok_and(RigidBody::is_static)); *is_inactive = is_static || (!position.is_changed() && !rotation.is_changed()); true @@ -219,7 +220,7 @@ fn add_new_aabb_intervals( aabbs: Query< ( Entity, - &ColliderParent, + Option<&ColliderParent>, &ColliderAabb, Option<&RigidBody>, Option<&CollisionLayers>, @@ -231,7 +232,7 @@ fn add_new_aabb_intervals( let aabbs = aabbs.iter().map(|(ent, parent, aabb, rb, layers)| { ( ent, - *parent, + parent.map_or(ColliderParent(ent), |p| *p), *aabb, // Default to treating collider as immovable/static for filtering unnecessary collision checks layers.map_or(CollisionLayers::default(), |layers| *layers), @@ -295,7 +296,7 @@ fn sweep_and_prune( /// Sorts a list iteratively using comparisons. In an ascending sort order, when a smaller value is encountered, it is moved lower in the list until it is larger than the item before it. /// /// This is relatively slow for large lists, but very efficient in cases where the list is already mostly sorted. -fn insertion_sort(items: &mut Vec, comparison: fn(&T, &T) -> bool) { +fn insertion_sort(items: &mut [T], comparison: fn(&T, &T) -> bool) { for i in 1..items.len() { let mut j = i; while j > 0 && comparison(&items[j - 1], &items[j]) { diff --git a/src/plugins/sync.rs b/src/plugins/sync.rs index fd99579f..4d71ea1a 100644 --- a/src/plugins/sync.rs +++ b/src/plugins/sync.rs @@ -410,8 +410,8 @@ fn transform_to_position( &mut Position, Option<&AccumulatedTranslation>, &mut Rotation, - &PreviousRotation, - &CenterOfMass, + Option<&PreviousRotation>, + Option<&CenterOfMass>, )>, ) { for ( @@ -433,7 +433,12 @@ fn transform_to_position( let previous_transform = previous_transform.compute_transform(); let pos = position.0 + accumulated_translation.map_or(Vector::ZERO, |t| { - get_pos_translation(t, previous_rotation, &rotation, center_of_mass) + get_pos_translation( + t, + &previous_rotation.copied().unwrap_or_default(), + &rotation, + ¢er_of_mass.copied().unwrap_or_default(), + ) }); #[cfg(feature = "2d")]