Skip to main content

box3d_rust/
events.rs

1// Port of the event types from include/box3d/types.h (events group).
2//
3// The C aggregate views (b3SensorEvents, b3ContactEvents, b3BodyEvents,
4// b3JointEvents) are pointer+count pairs over world-owned arrays. The Rust
5// world API returns slices; BodyEvents/JointEvents collapse to a single
6// slice while SensorEvents/ContactEvents keep grouping structs because they
7// bundle several arrays.
8//
9// SPDX-FileCopyrightText: 2025 Erin Catto
10// SPDX-License-Identifier: MIT
11
12use crate::id::{BodyId, ContactId, JointId, ShapeId};
13use crate::manifold::Manifold;
14use crate::math_functions::{Pos, Vec3, WorldTransform};
15
16/// The contact data for solid shape pairs. Manifolds are an owned snapshot of
17/// the contact's current manifolds (C exposes a transient pointer).
18/// (b3ContactData)
19#[derive(Debug, Clone, PartialEq)]
20pub struct ContactData {
21    /// The contact id. May become orphaned; use contact_is_valid before other use.
22    pub contact_id: ContactId,
23    /// The first shape id.
24    pub shape_id_a: ShapeId,
25    /// The second shape id.
26    pub shape_id_b: ShapeId,
27    /// Contact manifolds (owned copy; C: const b3Manifold* + manifoldCount).
28    pub manifolds: Vec<Manifold>,
29}
30
31/// A begin-touch event is generated when a shape starts to overlap a sensor
32/// shape. (b3SensorBeginTouchEvent)
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub struct SensorBeginTouchEvent {
35    /// The id of the sensor shape
36    pub sensor_shape_id: ShapeId,
37    /// The id of the shape that began touching the sensor shape
38    pub visitor_shape_id: ShapeId,
39}
40
41/// An end touch event is generated when a shape stops overlapping a sensor
42/// shape. Always confirm the shape id is valid before use. (b3SensorEndTouchEvent)
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub struct SensorEndTouchEvent {
45    /// The id of the sensor shape. @warning may have been destroyed
46    pub sensor_shape_id: ShapeId,
47    /// The id of the shape that stopped touching. @warning may have been destroyed
48    pub visitor_shape_id: ShapeId,
49}
50
51/// Sensor events buffered in the world for the current time step.
52/// Borrowed from world storage; invalidated by the next `World::step`.
53/// (b3SensorEvents)
54#[derive(Debug, Clone, Copy)]
55pub struct SensorEvents<'a> {
56    /// Array of sensor begin touch events
57    pub begin_events: &'a [SensorBeginTouchEvent],
58    /// Array of sensor end touch events (previous double-buffer slot)
59    pub end_events: &'a [SensorEndTouchEvent],
60}
61
62/// A begin-touch event is generated when two shapes begin touching.
63/// (b3ContactBeginTouchEvent)
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub struct ContactBeginTouchEvent {
66    /// Id of the first shape
67    pub shape_id_a: ShapeId,
68    /// Id of the second shape
69    pub shape_id_b: ShapeId,
70    /// The transient contact id. May be destroyed automatically when the world
71    /// is modified or simulated.
72    pub contact_id: ContactId,
73}
74
75/// An end touch event is generated when two shapes stop touching.
76/// (b3ContactEndTouchEvent)
77#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub struct ContactEndTouchEvent {
79    /// Id of the first shape. @warning may have been destroyed
80    pub shape_id_a: ShapeId,
81    /// Id of the second shape. @warning may have been destroyed
82    pub shape_id_b: ShapeId,
83    /// Id of the contact. @warning may have been destroyed
84    pub contact_id: ContactId,
85}
86
87/// A hit touch event is generated when two shapes collide faster than the hit
88/// speed threshold. (b3ContactHitEvent)
89#[derive(Debug, Clone, Copy, PartialEq)]
90pub struct ContactHitEvent {
91    /// Id of the first shape
92    pub shape_id_a: ShapeId,
93    /// Id of the second shape
94    pub shape_id_b: ShapeId,
95    /// Id of the contact. @warning may have been destroyed
96    pub contact_id: ContactId,
97    /// Point where the shapes hit, a mid-point between the two surfaces.
98    pub point: Pos,
99    /// Normal vector pointing from shape A to shape B
100    pub normal: Vec3,
101    /// The speed the shapes are approaching. Always positive.
102    pub approach_speed: f32,
103    /// User material on shape A
104    pub user_material_id_a: u64,
105    /// User material on shape B
106    pub user_material_id_b: u64,
107}
108
109/// Body move event, triggered when a body moves due to simulation. Not
110/// reported for bodies moved by the user. (b3BodyMoveEvent)
111#[derive(Debug, Clone, Copy, PartialEq)]
112pub struct BodyMoveEvent {
113    pub user_data: u64,
114    pub transform: WorldTransform,
115    pub body_id: BodyId,
116    pub fell_asleep: bool,
117}
118
119/// Joint event, reported for awake joints whose force and/or torque exceed the
120/// threshold. (b3JointEvent)
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122pub struct JointEvent {
123    /// The joint id
124    pub joint_id: JointId,
125    /// The user data from the joint for convenience
126    pub user_data: u64,
127}
128
129/// Contact events buffered in the world after a time step. (b3ContactEvents)
130#[derive(Debug, Clone, Copy)]
131pub struct ContactEvents<'a> {
132    pub begin_events: &'a [ContactBeginTouchEvent],
133    pub end_events: &'a [ContactEndTouchEvent],
134    pub hit_events: &'a [ContactHitEvent],
135}