1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::dynamics::RigidBodySet;
use crate::geometry::{ColliderSet, CollisionEvent, ContactForceEvent, ContactPair};
use crate::math::Real;
use crossbeam::channel::Sender;

bitflags::bitflags! {
    #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
    /// Flags affecting the events generated for this collider.
    pub struct ActiveEvents: u32 {
        /// If set, Rapier will call `EventHandler::handle_collision_event`
        /// whenever relevant for this collider.
        const COLLISION_EVENTS = 0b0001;
        /// If set, Rapier will call `EventHandler::handle_contact_force_event`
        /// whenever relevant for this collider.
        const CONTACT_FORCE_EVENTS = 0b0010;
    }
}

impl Default for ActiveEvents {
    fn default() -> Self {
        ActiveEvents::empty()
    }
}

/// Trait implemented by structures responsible for handling events generated by the physics engine.
///
/// Implementors of this trait will typically collect these events for future processing.
pub trait EventHandler: Send + Sync {
    /// Handle a collision event.
    ///
    /// A collision event is emitted when the state of intersection between two colliders changes.
    /// At least one of the involved colliders must have the `ActiveEvents::COLLISION_EVENTS` flag
    /// set.
    ///
    /// # Parameters
    /// * `event` - The collision event.
    /// * `bodies` - The set of rigid-bodies.
    /// * `colliders` - The set of colliders.
    /// * `contact_pair` - The current state of contacts between the two colliders. This is set to `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,
        bodies: &RigidBodySet,
        colliders: &ColliderSet,
        event: CollisionEvent,
        contact_pair: Option<&ContactPair>,
    );

    /// Handle a force event.
    ///
    /// A force event is generated whenever the total force magnitude applied between two
    /// colliders is `> Collider::contact_force_event_threshold` value of any of these
    /// colliders with the `ActiveEvents::CONTACT_FORCE_EVENTS` flag set.
    ///
    /// The "total force magnitude" here means "the sum of the magnitudes of the forces applied at
    /// all the contact points in a contact pair". Therefore, if the contact pair involves two
    /// forces `{0.0, 1.0, 0.0}` and `{0.0, -1.0, 0.0}`, then the total force magnitude tested
    /// against the `contact_force_event_threshold` is `2.0` even if the sum of these forces is actually the
    /// zero vector.
    fn handle_contact_force_event(
        &self,
        dt: Real,
        bodies: &RigidBodySet,
        colliders: &ColliderSet,
        contact_pair: &ContactPair,
        total_force_magnitude: Real,
    );
}

impl EventHandler for () {
    fn handle_collision_event(
        &self,
        _bodies: &RigidBodySet,
        _colliders: &ColliderSet,
        _event: CollisionEvent,
        _contact_pair: Option<&ContactPair>,
    ) {
    }

    fn handle_contact_force_event(
        &self,
        _dt: Real,
        _bodies: &RigidBodySet,
        _colliders: &ColliderSet,
        _contact_pair: &ContactPair,
        _total_force_magnitude: Real,
    ) {
    }
}

/// A collision event handler that collects events into a crossbeam channel.
pub struct ChannelEventCollector {
    collision_event_sender: Sender<CollisionEvent>,
    contact_force_event_sender: Sender<ContactForceEvent>,
}

impl ChannelEventCollector {
    /// Initialize a new collision event handler from crossbeam channel senders.
    pub fn new(
        collision_event_sender: Sender<CollisionEvent>,
        contact_force_event_sender: Sender<ContactForceEvent>,
    ) -> Self {
        Self {
            collision_event_sender,
            contact_force_event_sender,
        }
    }
}

impl EventHandler for ChannelEventCollector {
    fn handle_collision_event(
        &self,
        _bodies: &RigidBodySet,
        _colliders: &ColliderSet,
        event: CollisionEvent,
        _: Option<&ContactPair>,
    ) {
        let _ = self.collision_event_sender.send(event);
    }

    fn handle_contact_force_event(
        &self,
        dt: Real,
        _bodies: &RigidBodySet,
        _colliders: &ColliderSet,
        contact_pair: &ContactPair,
        total_force_magnitude: Real,
    ) {
        let result = ContactForceEvent::from_contact_pair(dt, contact_pair, total_force_magnitude);
        let _ = self.contact_force_event_sender.send(result);
    }
}