Emit collision stopped events after a collider is removed.
This commit is contained in:
committed by
Sébastien Crozet
parent
063c638ec5
commit
d38740369c
@@ -14,6 +14,7 @@
|
|||||||
to simplify the user’s event handling.
|
to simplify the user’s event handling.
|
||||||
- The `ActiveEvents::CONTACT_EVENTS` and `ActiveEvents::INTERSECTION_EVENTS` flags have been replaced by a single
|
- The `ActiveEvents::CONTACT_EVENTS` and `ActiveEvents::INTERSECTION_EVENTS` flags have been replaced by a single
|
||||||
flag `ActiveEvents::COLLISION_EVENTS`.
|
flag `ActiveEvents::COLLISION_EVENTS`.
|
||||||
|
- Events `CollisionEvent::Stopped` are now generated after a collider is removed.
|
||||||
|
|
||||||
## v0.12.0-alpha.0 (2 Jan. 2022)
|
## v0.12.0-alpha.0 (2 Jan. 2022)
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -616,8 +616,8 @@ impl CCDSolver {
|
|||||||
.contains(ActiveEvents::COLLISION_EVENTS)
|
.contains(ActiveEvents::COLLISION_EVENTS)
|
||||||
{
|
{
|
||||||
// Emit one intersection-started and one intersection-stopped event.
|
// Emit one intersection-started and one intersection-stopped event.
|
||||||
events.handle_intersection_event(CollisionEvent::Started(toi.c1, toi.c2));
|
events.handle_collision_event(CollisionEvent::Started(toi.c1, toi.c2), None);
|
||||||
events.handle_intersection_event(CollisionEvent::Stopped(toi.c1, toi.c2));
|
events.handle_collision_event(CollisionEvent::Stopped(toi.c1, toi.c2, false), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
use crate::dynamics::RigidBodyHandle;
|
use crate::dynamics::RigidBodyHandle;
|
||||||
use crate::geometry::{ColliderHandle, Contact, ContactManifold};
|
use crate::geometry::{ColliderHandle, Contact, ContactManifold};
|
||||||
use crate::math::{Point, Real, Vector};
|
use crate::math::{Point, Real, Vector};
|
||||||
|
use crate::pipeline::EventHandler;
|
||||||
use parry::query::ContactManifoldsWorkspace;
|
use parry::query::ContactManifoldsWorkspace;
|
||||||
|
|
||||||
|
use super::CollisionEvent;
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
/// Flags affecting the behavior of the constraints solver for a given contact manifold.
|
/// Flags affecting the behavior of the constraints solver for a given contact manifold.
|
||||||
@@ -46,6 +49,45 @@ impl Default for ContactData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
/// The description of all the contacts between a pair of colliders.
|
||||||
|
pub struct IntersectionPair {
|
||||||
|
/// Are the colliders intersecting?
|
||||||
|
pub intersecting: bool,
|
||||||
|
/// Was a `CollisionEvent::Started` emitted for this collider?
|
||||||
|
pub(crate) start_event_emited: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntersectionPair {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
intersecting: false,
|
||||||
|
start_event_emited: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn emit_start_event(
|
||||||
|
&mut self,
|
||||||
|
collider1: ColliderHandle,
|
||||||
|
collider2: ColliderHandle,
|
||||||
|
events: &dyn EventHandler,
|
||||||
|
) {
|
||||||
|
self.start_event_emited = true;
|
||||||
|
events.handle_collision_event(CollisionEvent::new(collider1, collider2, true), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn emit_stop_event(
|
||||||
|
&mut self,
|
||||||
|
collider1: ColliderHandle,
|
||||||
|
collider2: ColliderHandle,
|
||||||
|
events: &dyn EventHandler,
|
||||||
|
) {
|
||||||
|
self.start_event_emited = false;
|
||||||
|
events.handle_collision_event(CollisionEvent::new(collider1, collider2, false), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
/// The description of all the contacts between a pair of colliders.
|
/// The description of all the contacts between a pair of colliders.
|
||||||
@@ -60,6 +102,8 @@ pub struct ContactPair {
|
|||||||
pub manifolds: Vec<ContactManifold>,
|
pub manifolds: Vec<ContactManifold>,
|
||||||
/// Is there any active contact in this contact pair?
|
/// Is there any active contact in this contact pair?
|
||||||
pub has_any_active_contact: bool,
|
pub has_any_active_contact: bool,
|
||||||
|
/// Was a `CollisionEvent::Started` emitted for this collider?
|
||||||
|
pub(crate) start_event_emited: bool,
|
||||||
pub(crate) workspace: Option<ContactManifoldsWorkspace>,
|
pub(crate) workspace: Option<ContactManifoldsWorkspace>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +114,7 @@ impl ContactPair {
|
|||||||
collider2,
|
collider2,
|
||||||
has_any_active_contact: false,
|
has_any_active_contact: false,
|
||||||
manifolds: Vec::new(),
|
manifolds: Vec::new(),
|
||||||
|
start_event_emited: false,
|
||||||
workspace: None,
|
workspace: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,6 +154,24 @@ impl ContactPair {
|
|||||||
|
|
||||||
deepest
|
deepest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn emit_start_event(&mut self, events: &dyn EventHandler) {
|
||||||
|
self.start_event_emited = true;
|
||||||
|
|
||||||
|
events.handle_collision_event(
|
||||||
|
CollisionEvent::new(self.collider1, self.collider2, true),
|
||||||
|
Some(self),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn emit_stop_event(&mut self, events: &dyn EventHandler) {
|
||||||
|
self.start_event_emited = false;
|
||||||
|
|
||||||
|
events.handle_collision_event(
|
||||||
|
CollisionEvent::new(self.collider1, self.collider2, false),
|
||||||
|
Some(self),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
pub use self::broad_phase_multi_sap::{BroadPhase, BroadPhasePairEvent, ColliderPair};
|
pub use self::broad_phase_multi_sap::{BroadPhase, BroadPhasePairEvent, ColliderPair};
|
||||||
pub use self::collider_components::*;
|
pub use self::collider_components::*;
|
||||||
pub use self::contact_pair::{ContactData, ContactManifoldData};
|
pub use self::contact_pair::{
|
||||||
pub use self::contact_pair::{ContactPair, SolverContact, SolverFlags};
|
ContactData, ContactManifoldData, ContactPair, IntersectionPair, SolverContact, SolverFlags,
|
||||||
|
};
|
||||||
pub use self::interaction_graph::{
|
pub use self::interaction_graph::{
|
||||||
ColliderGraphIndex, InteractionGraph, RigidBodyGraphIndex, TemporaryInteractionIndex,
|
ColliderGraphIndex, InteractionGraph, RigidBodyGraphIndex, TemporaryInteractionIndex,
|
||||||
};
|
};
|
||||||
@@ -56,8 +57,11 @@ pub use parry::shape::SharedShape;
|
|||||||
pub enum CollisionEvent {
|
pub enum CollisionEvent {
|
||||||
/// Event occurring when two colliders start being in contact (or intersecting)
|
/// Event occurring when two colliders start being in contact (or intersecting)
|
||||||
Started(ColliderHandle, ColliderHandle),
|
Started(ColliderHandle, ColliderHandle),
|
||||||
/// Event occurring when two colliders stop being in contact (or intersecting)
|
/// Event occurring when two colliders stop being in contact (or intersecting).
|
||||||
Stopped(ColliderHandle, ColliderHandle),
|
///
|
||||||
|
/// The boolean is set to `true` of this event originates from at least one of
|
||||||
|
/// the colliders being removed from the `ColliderSet`.
|
||||||
|
Stopped(ColliderHandle, ColliderHandle, bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CollisionEvent {
|
impl CollisionEvent {
|
||||||
@@ -65,31 +69,31 @@ impl CollisionEvent {
|
|||||||
if start {
|
if start {
|
||||||
Self::Started(h1, h2)
|
Self::Started(h1, h2)
|
||||||
} else {
|
} else {
|
||||||
Self::Stopped(h1, h2)
|
Self::Stopped(h1, h2, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a `Started` collision event?
|
/// Is this a `Started` collision event?
|
||||||
pub fn started(self) -> bool {
|
pub fn started(self) -> bool {
|
||||||
matches!(self, CollisionEvent::Started(_, _))
|
matches!(self, CollisionEvent::Started(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a `Stopped` collision event?
|
/// Is this a `Stopped` collision event?
|
||||||
pub fn stopped(self) -> bool {
|
pub fn stopped(self) -> bool {
|
||||||
matches!(self, CollisionEvent::Stopped(_, _))
|
matches!(self, CollisionEvent::Stopped(..))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The handle of the first collider involved in this collision event.
|
/// The handle of the first collider involved in this collision event.
|
||||||
pub fn collider1(self) -> ColliderHandle {
|
pub fn collider1(self) -> ColliderHandle {
|
||||||
match self {
|
match self {
|
||||||
Self::Started(h, _) | Self::Stopped(h, _) => h,
|
Self::Started(h, _) | Self::Stopped(h, _, _) => h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The handle of the second collider involved in this collision event.
|
/// The handle of the second collider involved in this collision event.
|
||||||
pub fn collider2(self) -> ColliderHandle {
|
pub fn collider2(self) -> ColliderHandle {
|
||||||
match self {
|
match self {
|
||||||
Self::Started(_, h) | Self::Stopped(_, h) => h,
|
Self::Started(_, h) | Self::Stopped(_, h, _) => h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::geometry::{
|
|||||||
BroadPhasePairEvent, ColliderChanges, ColliderGraphIndex, ColliderHandle, ColliderMaterial,
|
BroadPhasePairEvent, ColliderChanges, ColliderGraphIndex, ColliderHandle, ColliderMaterial,
|
||||||
ColliderPair, ColliderParent, ColliderPosition, ColliderShape, ColliderType, CollisionEvent,
|
ColliderPair, ColliderParent, ColliderPosition, ColliderShape, ColliderType, CollisionEvent,
|
||||||
ContactData, ContactManifold, ContactManifoldData, ContactPair, InteractionGraph,
|
ContactData, ContactManifold, ContactManifoldData, ContactPair, InteractionGraph,
|
||||||
SolverContact, SolverFlags,
|
IntersectionPair, SolverContact, SolverFlags,
|
||||||
};
|
};
|
||||||
use crate::math::{Real, Vector};
|
use crate::math::{Real, Vector};
|
||||||
use crate::pipeline::{
|
use crate::pipeline::{
|
||||||
@@ -56,7 +56,7 @@ pub struct NarrowPhase {
|
|||||||
)]
|
)]
|
||||||
query_dispatcher: Arc<dyn PersistentQueryDispatcher<ContactManifoldData, ContactData>>,
|
query_dispatcher: Arc<dyn PersistentQueryDispatcher<ContactManifoldData, ContactData>>,
|
||||||
contact_graph: InteractionGraph<ColliderHandle, ContactPair>,
|
contact_graph: InteractionGraph<ColliderHandle, ContactPair>,
|
||||||
intersection_graph: InteractionGraph<ColliderHandle, bool>,
|
intersection_graph: InteractionGraph<ColliderHandle, IntersectionPair>,
|
||||||
graph_indices: Coarena<ColliderGraphIndices>,
|
graph_indices: Coarena<ColliderGraphIndices>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ impl NarrowPhase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The intersection graph containing all intersection pairs and their intersection information.
|
/// The intersection graph containing all intersection pairs and their intersection information.
|
||||||
pub fn intersection_graph(&self) -> &InteractionGraph<ColliderHandle, bool> {
|
pub fn intersection_graph(&self) -> &InteractionGraph<ColliderHandle, IntersectionPair> {
|
||||||
&self.intersection_graph
|
&self.intersection_graph
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ impl NarrowPhase {
|
|||||||
.flat_map(move |id| {
|
.flat_map(move |id| {
|
||||||
self.intersection_graph
|
self.intersection_graph
|
||||||
.interactions_with(id)
|
.interactions_with(id)
|
||||||
.map(|e| (e.0, e.1, *e.2))
|
.map(|e| (e.0, e.1, e.2.intersecting))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ impl NarrowPhase {
|
|||||||
.flat_map(move |id| {
|
.flat_map(move |id| {
|
||||||
self.intersection_graph
|
self.intersection_graph
|
||||||
.interactions_with(id)
|
.interactions_with(id)
|
||||||
.map(|e| (e.0, e.1, *e.2))
|
.map(|e| (e.0, e.1, e.2.intersecting))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ impl NarrowPhase {
|
|||||||
let id2 = self.graph_indices.get_unknown_gen(collider2)?;
|
let id2 = self.graph_indices.get_unknown_gen(collider2)?;
|
||||||
self.intersection_graph
|
self.intersection_graph
|
||||||
.interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
|
.interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
|
||||||
.map(|c| *c.2)
|
.map(|c| c.2.intersecting)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The intersection pair involving two specific colliders.
|
/// The intersection pair involving two specific colliders.
|
||||||
@@ -227,7 +227,7 @@ impl NarrowPhase {
|
|||||||
let id2 = self.graph_indices.get(collider2.0)?;
|
let id2 = self.graph_indices.get(collider2.0)?;
|
||||||
self.intersection_graph
|
self.intersection_graph
|
||||||
.interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
|
.interaction_pair(id1.intersection_graph_index, id2.intersection_graph_index)
|
||||||
.map(|c| *c.2)
|
.map(|c| c.2.intersecting)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All the contact pairs maintained by this narrow-phase.
|
/// All the contact pairs maintained by this narrow-phase.
|
||||||
@@ -241,7 +241,7 @@ impl NarrowPhase {
|
|||||||
) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
|
) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
|
||||||
self.intersection_graph
|
self.intersection_graph
|
||||||
.interactions_with_endpoints()
|
.interactions_with_endpoints()
|
||||||
.map(|e| (e.0, e.1, *e.2))
|
.map(|e| (e.0, e.1, e.2.intersecting))
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[cfg(feature = "parallel")]
|
// #[cfg(feature = "parallel")]
|
||||||
@@ -297,6 +297,7 @@ impl NarrowPhase {
|
|||||||
bodies,
|
bodies,
|
||||||
&mut prox_id_remap,
|
&mut prox_id_remap,
|
||||||
&mut contact_id_remap,
|
&mut contact_id_remap,
|
||||||
|
events,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,20 +309,21 @@ impl NarrowPhase {
|
|||||||
&mut self,
|
&mut self,
|
||||||
intersection_graph_id: ColliderGraphIndex,
|
intersection_graph_id: ColliderGraphIndex,
|
||||||
contact_graph_id: ColliderGraphIndex,
|
contact_graph_id: ColliderGraphIndex,
|
||||||
islands: Option<&mut IslandManager>,
|
mut islands: Option<&mut IslandManager>,
|
||||||
colliders: &mut Colliders,
|
colliders: &mut Colliders,
|
||||||
bodies: &mut Bodies,
|
bodies: &mut Bodies,
|
||||||
prox_id_remap: &mut HashMap<ColliderHandle, ColliderGraphIndex>,
|
prox_id_remap: &mut HashMap<ColliderHandle, ColliderGraphIndex>,
|
||||||
contact_id_remap: &mut HashMap<ColliderHandle, ColliderGraphIndex>,
|
contact_id_remap: &mut HashMap<ColliderHandle, ColliderGraphIndex>,
|
||||||
|
events: &dyn EventHandler,
|
||||||
) where
|
) where
|
||||||
Bodies: ComponentSetMut<RigidBodyActivation>
|
Bodies: ComponentSetMut<RigidBodyActivation>
|
||||||
+ ComponentSet<RigidBodyType>
|
+ ComponentSet<RigidBodyType>
|
||||||
+ ComponentSetMut<RigidBodyIds>,
|
+ ComponentSetMut<RigidBodyIds>,
|
||||||
Colliders: ComponentSetOption<ColliderParent>,
|
Colliders: ComponentSetOption<ColliderParent>,
|
||||||
{
|
{
|
||||||
// Wake up every body in contact with the deleted collider.
|
// Wake up every body in contact with the deleted collider and generate Stopped collision events.
|
||||||
if let Some(islands) = islands {
|
if let Some(islands) = islands.as_deref_mut() {
|
||||||
for (a, b, _) in self.contact_graph.interactions_with(contact_graph_id) {
|
for (a, b, pair) in self.contact_graph.interactions_with(contact_graph_id) {
|
||||||
if let Some(parent) = colliders.get(a.0).map(|c| c.handle) {
|
if let Some(parent) = colliders.get(a.0).map(|c| c.handle) {
|
||||||
islands.wake_up(bodies, parent, true)
|
islands.wake_up(bodies, parent, true)
|
||||||
}
|
}
|
||||||
@@ -329,6 +331,24 @@ impl NarrowPhase {
|
|||||||
if let Some(parent) = colliders.get(b.0).map(|c| c.handle) {
|
if let Some(parent) = colliders.get(b.0).map(|c| c.handle) {
|
||||||
islands.wake_up(bodies, parent, true)
|
islands.wake_up(bodies, parent, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pair.start_event_emited {
|
||||||
|
events.handle_collision_event(CollisionEvent::Stopped(a, b, true), Some(pair));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If there is no island, don’t wake-up bodies, but do send the Stopped collision event.
|
||||||
|
for (a, b, pair) in self.contact_graph.interactions_with(contact_graph_id) {
|
||||||
|
if pair.start_event_emited {
|
||||||
|
events.handle_collision_event(CollisionEvent::Stopped(a, b, true), Some(pair));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Stopped collision events for intersections.
|
||||||
|
for (a, b, pair) in self.intersection_graph.interactions_with(contact_graph_id) {
|
||||||
|
if pair.start_event_emited {
|
||||||
|
events.handle_collision_event(CollisionEvent::Stopped(a, b, true), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,21 +526,21 @@ impl NarrowPhase {
|
|||||||
|| (mode == PairRemovalMode::Auto
|
|| (mode == PairRemovalMode::Auto
|
||||||
&& (co_type1.is_sensor() || co_type2.is_sensor()))
|
&& (co_type1.is_sensor() || co_type2.is_sensor()))
|
||||||
{
|
{
|
||||||
let was_intersecting = self
|
let intersection = self
|
||||||
.intersection_graph
|
.intersection_graph
|
||||||
.remove_edge(gid1.intersection_graph_index, gid2.intersection_graph_index);
|
.remove_edge(gid1.intersection_graph_index, gid2.intersection_graph_index);
|
||||||
|
|
||||||
// Emit an intersection lost event if we had an intersection before removing the edge.
|
// Emit an intersection lost event if we had an intersection before removing the edge.
|
||||||
if Some(true) == was_intersecting {
|
if let Some(mut intersection) = intersection {
|
||||||
let co_flag1: &ColliderFlags = colliders.index(pair.collider1.0);
|
if intersection.intersecting {
|
||||||
let co_flag2: &ColliderFlags = colliders.index(pair.collider2.0);
|
let co_flag1: &ColliderFlags = colliders.index(pair.collider1.0);
|
||||||
|
let co_flag2: &ColliderFlags = colliders.index(pair.collider2.0);
|
||||||
|
|
||||||
if (co_flag1.active_events | co_flag2.active_events)
|
if (co_flag1.active_events | co_flag2.active_events)
|
||||||
.contains(ActiveEvents::COLLISION_EVENTS)
|
.contains(ActiveEvents::COLLISION_EVENTS)
|
||||||
{
|
{
|
||||||
let prox_event =
|
intersection.emit_stop_event(pair.collider1, pair.collider2, events)
|
||||||
CollisionEvent::Stopped(pair.collider1, pair.collider2);
|
}
|
||||||
events.handle_intersection_event(prox_event)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -530,7 +550,7 @@ impl NarrowPhase {
|
|||||||
|
|
||||||
// Emit a contact stopped event if we had a contact before removing the edge.
|
// Emit a contact stopped event if we had a contact before removing the edge.
|
||||||
// Also wake up the dynamic bodies that were in contact.
|
// Also wake up the dynamic bodies that were in contact.
|
||||||
if let Some(ctct) = contact_pair {
|
if let Some(mut ctct) = contact_pair {
|
||||||
if ctct.has_any_active_contact {
|
if ctct.has_any_active_contact {
|
||||||
let co_parent1: Option<&ColliderParent> =
|
let co_parent1: Option<&ColliderParent> =
|
||||||
colliders.get(pair.collider1.0);
|
colliders.get(pair.collider1.0);
|
||||||
@@ -553,10 +573,7 @@ impl NarrowPhase {
|
|||||||
if (co_flag1.active_events | co_flag2.active_events)
|
if (co_flag1.active_events | co_flag2.active_events)
|
||||||
.contains(ActiveEvents::COLLISION_EVENTS)
|
.contains(ActiveEvents::COLLISION_EVENTS)
|
||||||
{
|
{
|
||||||
events.handle_contact_event(
|
ctct.emit_stop_event(events);
|
||||||
CollisionEvent::Stopped(pair.collider1, pair.collider2),
|
|
||||||
&ctct,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -615,7 +632,7 @@ impl NarrowPhase {
|
|||||||
let _ = self.intersection_graph.add_edge(
|
let _ = self.intersection_graph.add_edge(
|
||||||
gid1.intersection_graph_index,
|
gid1.intersection_graph_index,
|
||||||
gid2.intersection_graph_index,
|
gid2.intersection_graph_index,
|
||||||
false,
|
IntersectionPair::new(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -712,7 +729,7 @@ impl NarrowPhase {
|
|||||||
par_iter_mut!(&mut self.intersection_graph.graph.edges).for_each(|edge| {
|
par_iter_mut!(&mut self.intersection_graph.graph.edges).for_each(|edge| {
|
||||||
let handle1 = nodes[edge.source().index()].weight;
|
let handle1 = nodes[edge.source().index()].weight;
|
||||||
let handle2 = nodes[edge.target().index()].weight;
|
let handle2 = nodes[edge.target().index()].weight;
|
||||||
let had_intersection = edge.weight;
|
let had_intersection = edge.weight.intersecting;
|
||||||
|
|
||||||
// TODO: remove the `loop` once labels on blocks is stabilized.
|
// TODO: remove the `loop` once labels on blocks is stabilized.
|
||||||
'emit_events: loop {
|
'emit_events: loop {
|
||||||
@@ -755,13 +772,13 @@ impl NarrowPhase {
|
|||||||
if !co_flags1.active_collision_types.test(rb_type1, rb_type2)
|
if !co_flags1.active_collision_types.test(rb_type1, rb_type2)
|
||||||
&& !co_flags2.active_collision_types.test(rb_type1, rb_type2)
|
&& !co_flags2.active_collision_types.test(rb_type1, rb_type2)
|
||||||
{
|
{
|
||||||
edge.weight = false;
|
edge.weight.intersecting = false;
|
||||||
break 'emit_events;
|
break 'emit_events;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter based on collision groups.
|
// Filter based on collision groups.
|
||||||
if !co_flags1.collision_groups.test(co_flags2.collision_groups) {
|
if !co_flags1.collision_groups.test(co_flags2.collision_groups) {
|
||||||
edge.weight = false;
|
edge.weight.intersecting = false;
|
||||||
break 'emit_events;
|
break 'emit_events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,13 +796,13 @@ impl NarrowPhase {
|
|||||||
|
|
||||||
if !hooks.filter_intersection_pair(&context) {
|
if !hooks.filter_intersection_pair(&context) {
|
||||||
// No intersection allowed.
|
// No intersection allowed.
|
||||||
edge.weight = false;
|
edge.weight.intersecting = false;
|
||||||
break 'emit_events;
|
break 'emit_events;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos12 = co_pos1.inv_mul(co_pos2);
|
let pos12 = co_pos1.inv_mul(co_pos2);
|
||||||
edge.weight = query_dispatcher
|
edge.weight.intersecting = query_dispatcher
|
||||||
.intersection_test(&pos12, &**co_shape1, &**co_shape2)
|
.intersection_test(&pos12, &**co_shape1, &**co_shape2)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
break 'emit_events;
|
break 'emit_events;
|
||||||
@@ -796,13 +813,13 @@ impl NarrowPhase {
|
|||||||
let active_events = co_flags1.active_events | co_flags2.active_events;
|
let active_events = co_flags1.active_events | co_flags2.active_events;
|
||||||
|
|
||||||
if active_events.contains(ActiveEvents::COLLISION_EVENTS)
|
if active_events.contains(ActiveEvents::COLLISION_EVENTS)
|
||||||
&& had_intersection != edge.weight
|
&& had_intersection != edge.weight.intersecting
|
||||||
{
|
{
|
||||||
events.handle_intersection_event(CollisionEvent::new(
|
if edge.weight.intersecting {
|
||||||
handle1,
|
edge.weight.emit_start_event(handle1, handle2, events);
|
||||||
handle2,
|
} else {
|
||||||
edge.weight,
|
edge.weight.emit_stop_event(handle1, handle2, events);
|
||||||
));
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1029,15 +1046,9 @@ impl NarrowPhase {
|
|||||||
if pair.has_any_active_contact != had_any_active_contact {
|
if pair.has_any_active_contact != had_any_active_contact {
|
||||||
if active_events.contains(ActiveEvents::COLLISION_EVENTS) {
|
if active_events.contains(ActiveEvents::COLLISION_EVENTS) {
|
||||||
if pair.has_any_active_contact {
|
if pair.has_any_active_contact {
|
||||||
events.handle_contact_event(
|
pair.emit_start_event(events);
|
||||||
CollisionEvent::Started(pair.collider1, pair.collider2),
|
|
||||||
pair,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
events.handle_contact_event(
|
pair.emit_stop_event(events);
|
||||||
CollisionEvent::Stopped(pair.collider1, pair.collider2),
|
|
||||||
pair,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,18 +23,18 @@ impl Default for ActiveEvents {
|
|||||||
pub trait EventHandler: Send + Sync {
|
pub trait EventHandler: Send + Sync {
|
||||||
/// Handle a collision event.
|
/// Handle a collision event.
|
||||||
///
|
///
|
||||||
/// A intersection event is emitted when the state of intersection between two colliders changes.
|
/// A collision event is emitted when the state of intersection between two colliders changes.
|
||||||
fn handle_intersection_event(&self, event: CollisionEvent);
|
|
||||||
/// Handle a contact event.
|
|
||||||
///
|
///
|
||||||
/// A contact event is emitted when two collider start or stop touching, independently from the
|
/// # Parameters
|
||||||
/// number of contact points involved.
|
/// * `event` - The collision event.
|
||||||
fn handle_contact_event(&self, event: CollisionEvent, contact_pair: &ContactPair);
|
/// * `contact_pair` - The current state of contacts between the two colliders. This is set ot `None`
|
||||||
|
/// if at least one of the collider is a sensor (in which case no contact information
|
||||||
|
/// is ever computed).
|
||||||
|
fn handle_collision_event(&self, event: CollisionEvent, contact_pair: Option<&ContactPair>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventHandler for () {
|
impl EventHandler for () {
|
||||||
fn handle_intersection_event(&self, _event: CollisionEvent) {}
|
fn handle_collision_event(&self, _event: CollisionEvent, _contact_pair: Option<&ContactPair>) {}
|
||||||
fn handle_contact_event(&self, _event: CollisionEvent, _contact_pair: &ContactPair) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collision event handler that collects events into a crossbeam channel.
|
/// A collision event handler that collects events into a crossbeam channel.
|
||||||
@@ -50,11 +50,7 @@ impl ChannelEventCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EventHandler for ChannelEventCollector {
|
impl EventHandler for ChannelEventCollector {
|
||||||
fn handle_intersection_event(&self, event: CollisionEvent) {
|
fn handle_collision_event(&self, event: CollisionEvent, _: Option<&ContactPair>) {
|
||||||
let _ = self.event_sender.send(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_contact_event(&self, event: CollisionEvent, _: &ContactPair) {
|
|
||||||
let _ = self.event_sender.send(event);
|
let _ = self.event_sender.send(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user