From 24947d12a2440b8a5580823e026cb0a259c68553 Mon Sep 17 00:00:00 2001 From: Travis Lange Date: Sat, 11 Nov 2023 19:06:20 -0500 Subject: [PATCH] added support for active collision events regardless if started was called --- src/geometry/contact_pair.rs | 30 ++++++++++++++++++++++++++++++ src/geometry/mod.rs | 11 +++++++---- src/geometry/narrow_phase.rs | 11 +++++++++++ src/pipeline/event_handler.rs | 4 ++++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 3bef40da2..250d26de7 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -101,6 +101,22 @@ impl IntersectionPair { None, ); } + + pub(crate) fn emit_active_event( + &mut self, + bodies: &RigidBodySet, + colliders: &ColliderSet, + collider1: ColliderHandle, + collider2: ColliderHandle, + events: &dyn EventHandler, + ) { + events.handle_collision_event( + bodies, + colliders, + CollisionEvent::Active(collider1, collider2, CollisionEventFlags::SENSOR), + None, + ); + } } #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -231,6 +247,20 @@ impl ContactPair { Some(self), ); } + + pub(crate) fn emit_active_event( + &mut self, + bodies: &RigidBodySet, + colliders: &ColliderSet, + events: &dyn EventHandler, + ) { + events.handle_collision_event( + bodies, + colliders, + CollisionEvent::Active(self.collider1, self.collider2, CollisionEventFlags::empty()), + Some(self), + ); + } } #[derive(Clone, Debug)] diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index a91c4b90c..3ce5c46e0 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -76,6 +76,9 @@ pub enum CollisionEvent { Started(ColliderHandle, ColliderHandle, CollisionEventFlags), /// Event occurring when two colliders stop colliding. Stopped(ColliderHandle, ColliderHandle, CollisionEventFlags), + /// Event occurring when two colliders are actively colliding. + /// Even after `CollisionEvent::Started` has already been called. + Active(ColliderHandle, ColliderHandle, CollisionEventFlags), } impl CollisionEvent { @@ -92,21 +95,21 @@ impl CollisionEvent { /// The handle of the first collider involved in this collision event. pub fn collider1(self) -> ColliderHandle { match self { - Self::Started(h, _, _) | Self::Stopped(h, _, _) => h, + Self::Started(h, _, _) | Self::Stopped(h, _, _) | Self::Active(h, _, _) => h, } } /// The handle of the second collider involved in this collision event. pub fn collider2(self) -> ColliderHandle { match self { - Self::Started(_, h, _) | Self::Stopped(_, h, _) => h, + Self::Started(_, h, _) | Self::Stopped(_, h, _) | Self::Active(_, h, _) => h, } } /// Was at least one of the colliders involved in the collision a sensor? pub fn sensor(self) -> bool { match self { - Self::Started(_, _, f) | Self::Stopped(_, _, f) => { + Self::Started(_, _, f) | Self::Stopped(_, _, f) | Self::Active(_, _, f) => { f.contains(CollisionEventFlags::SENSOR) } } @@ -115,7 +118,7 @@ impl CollisionEvent { /// Was at least one of the colliders involved in the collision removed? pub fn removed(self) -> bool { match self { - Self::Started(_, _, f) | Self::Stopped(_, _, f) => { + Self::Started(_, _, f) | Self::Stopped(_, _, f) | Self::Active(_, _, f) => { f.contains(CollisionEventFlags::REMOVED) } } diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs index 4500284db..3b87940c8 100644 --- a/src/geometry/narrow_phase.rs +++ b/src/geometry/narrow_phase.rs @@ -762,6 +762,11 @@ impl NarrowPhase { let active_events = co1.flags.active_events | co2.flags.active_events; + if had_intersection && active_events.contains(ActiveEvents::ACTIVE_COLLISION_EVENTS) { + edge.weight + .emit_active_event(bodies, colliders, handle1, handle2, events); + } + if active_events.contains(ActiveEvents::COLLISION_EVENTS) && had_intersection != edge.weight.intersecting { @@ -993,6 +998,12 @@ impl NarrowPhase { let active_events = co1.flags.active_events | co2.flags.active_events; + if pair.has_any_active_contact + && active_events.contains(ActiveEvents::ACTIVE_COLLISION_EVENTS) + { + pair.emit_active_event(bodies, colliders, events); + } + if pair.has_any_active_contact != had_any_active_contact { if active_events.contains(ActiveEvents::COLLISION_EVENTS) { if pair.has_any_active_contact { diff --git a/src/pipeline/event_handler.rs b/src/pipeline/event_handler.rs index 7957ccf3e..59081865c 100644 --- a/src/pipeline/event_handler.rs +++ b/src/pipeline/event_handler.rs @@ -13,6 +13,10 @@ bitflags::bitflags! { /// If set, Rapier will call `EventHandler::handle_contact_force_event` /// whenever relevant for this collider. const CONTACT_FORCE_EVENTS = 0b0010; + /// If set, Rapier will call `EventHandler::handle_collision_event` + /// whenever relevant for this collider. Even after `CollisionEvent::Started` + /// has already been called. + const ACTIVE_COLLISION_EVENTS = 0b0100; } }