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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
//! boxdd: Safe, ergonomic Rust bindings for Box2D (v3 C API)
//!
//! Highlights
//! - Thin safe layer on top of the official Box2D v3 C API.
//! - Modular API: world, bodies, shapes, joints, queries, collision geometry, events, debug draw.
//! - Ergonomics: builder patterns, world-space helpers, and optional math interop (`mint`/`cgmath`/`nalgebra`/`glam`).
//! - Hot-path friendly APIs: keep the convenience `Vec`-returning methods, reuse caller-owned buffers with `*_into`, or use `visit_*` overlap queries to avoid result-container allocation entirely.
//! - Character mover helpers: cast movers, collect collision planes, solve planes, and clip velocity without raw FFI.
//! - Standalone collision geometry helpers: shape proxies, segment/GJK distance, manifolds, shape cast, TOI, recoverable `try_*` validation paths, AABB validation/ray cast, and deterministic global math helpers.
//! - Core math types (`Vec2`, `Rot`, `Transform`) use explicit `from_raw(...)` / `into_raw()` naming for Box2D interop instead of implicit raw conversions.
//! - Global Box2D foundation helpers expose allocated-byte inspection, timing ticks/millisecond helpers, thread yielding, and deterministic hashing without dropping to `boxdd_sys::ffi`.
//! - Shape geometry uses crate-owned values (`Circle`, `Segment`, `ChainSegment`, `Capsule`, `Polygon`) across helpers, shape editing, and creation, including square/rounded/offset/hull-based polygon builders plus standalone and construction-time `try_*` geometry helpers without raw FFI.
//! - Chain runtime material helpers use visible live-segment indexing on open chains instead of Box2D's ghost-placeholder storage layout.
//! - Safe shape/joint mutators front-load obvious Box2D assert preconditions such as non-negative material scalars and ordered joint limits.
//! - Pointer-bearing config wrappers keep their raw re-entry explicit: `BodyDef::from_raw(...)`
//! and `WorldDef::from_raw(...)` are `unsafe`.
//! - Live shapes expose safe runtime helpers for AABB, point tests, direct ray casts, computed mass data, and runtime event toggles.
//! - Bodies expose safe runtime helpers for rotation, sleep/awake/enabled/bullet/name controls, attached shape/joint enumeration, and body-level contact/hit event toggles.
//! - Joints expose safe runtime helpers for joint kind, connected body ids, `collide_connected`, constraint tuning, local frames, wake controls, and type-specific runtime state across distance/prismatic/revolute/weld/wheel/motor families.
//! - `ContactId` values from contact events or snapshots expose direct safe inherent helpers for validity checks and crate-owned/raw contact-data reads.
//! - World runtime helpers expose counters, per-stage `Profile` timings, explosion control, and `try_*` access for callback-sensitive tuning toggles.
//! - Core value types such as `ShapeType`, `MassData`, `SurfaceMaterial`, and contact manifolds are crate-owned instead of leaking raw Box2D structs.
//! - Typed material mixing callbacks for friction and restitution using `user_material_id`.
//! - Three usage styles:
//! - Owned handles: `OwnedBody`/`OwnedShape`/`OwnedJoint`/`OwnedChain` (Drop destroys; easy to store).
//! - Scoped handles: `Body<'_>`/`Shape<'_>`/`Joint<'_>`/`Chain<'_>` (dropping only releases the world borrow).
//! - ID-style: raw ids (`BodyId`/`ShapeId`/`JointId`/`ChainId`) for maximum flexibility.
//! - Safe handle methods validate ids and panic on invalid ids (prevents UB if an id becomes stale).
//! For recoverable failures (invalid ids / wrong typed-joint family / calling during Box2D callbacks), use `try_*` APIs returning `ApiResult<T>`.
//! - Threading: `World` and owned handles are `!Send`/`!Sync`. Run physics on one thread; in async runtimes prefer
//! `spawn_local`/`LocalSet`, or create the world inside a dedicated physics thread and communicate via channels.
//!
//! Quickstart (owned handles)
//! ```no_run
//! use boxdd::{World, WorldDef, BodyBuilder, ShapeDef, shapes, Vec2};
//! let def = WorldDef::builder().gravity(Vec2::new(0.0, -9.8)).build();
//! let mut world = World::new(def).unwrap();
//! let mut body = world.create_body_owned(BodyBuilder::new().position([0.0, 2.0]).build());
//! let sdef = ShapeDef::builder().density(1.0).build();
//! let poly = shapes::box_polygon(0.5, 0.5);
//! let _shape = body.create_polygon_shape(&sdef, &poly);
//! world.step(1.0/60.0, 4);
//! ```
//!
//! Quickstart (scoped handles)
//! ```no_run
//! use boxdd::{World, WorldDef, BodyBuilder, ShapeDef, shapes, Vec2};
//! let def = WorldDef::builder().gravity(Vec2::new(0.0, -9.8)).build();
//! let mut world = World::new(def).unwrap();
//! {
//! // Limit the borrow of `world` by scoping the body handle.
//! let mut body = world.create_body(BodyBuilder::new().position([0.0, 2.0]).build());
//! let sdef = ShapeDef::builder().density(1.0).build();
//! let poly = shapes::box_polygon(0.5, 0.5);
//! let _shape = body.create_polygon_shape(&sdef, &poly);
//! }
//! world.step(1.0/60.0, 4);
//! ```
//!
//! Quickstart (ID-style)
//! ```no_run
//! use boxdd::{World, WorldDef, BodyBuilder, ShapeDef, shapes, Vec2};
//! let def = WorldDef::builder().gravity(Vec2::new(0.0, -9.8)).build();
//! let mut world = World::new(def).unwrap();
//! let body_id = world.create_body_id(BodyBuilder::new().position([0.0, 2.0]).build());
//! let sdef = ShapeDef::builder().density(1.0).build();
//! let poly = shapes::box_polygon(0.5, 0.5);
//! let _shape_id = world.create_polygon_shape_for(body_id, &sdef, &poly);
//! world.step(1.0/60.0, 4);
//! ```
//!
//! Math interop (optional features)
//! - `Vec2` always accepts `[f32; 2]` and `(f32, f32)` anywhere `Into<Vec2>` is used.
//! - With `mint`, `cgmath`, `nalgebra`, or `glam` enabled, `Vec2` also accepts those crates'
//! 2D vector/point types via `From`/`Into`.
//! - Returned vectors can be converted back using `From` to the corresponding math types.
//! - `mint` also covers `Rot <-> mint::RowMatrix2` / `mint::ColumnMatrix2`, plus row- and
//! column-major 2D affine matrices for `Transform`.
//!
//! Modules
//! - `world`, `body`, `contact`, `shapes`, `joints`, `query`, `collision`, `events`, `debug_draw`, `prelude`.
//! Import `boxdd::prelude::*` for the most common types.
//!
//! Queries (AABB + Ray Cast)
//! ```no_run
//! use boxdd::{World, WorldDef, BodyBuilder, ShapeDef, shapes, Vec2, Aabb, QueryFilter};
//! let mut world = World::new(WorldDef::builder().gravity([0.0,-9.8]).build()).unwrap();
//! let b = world.create_body_id(BodyBuilder::new().position([0.0, 2.0]).build());
//! let sdef = ShapeDef::builder().density(1.0).build();
//! world.create_polygon_shape_for(b, &sdef, &shapes::box_polygon(0.5, 0.5));
//! // AABB overlap
//! let hits = world.overlap_aabb(Aabb::from_center_half_extents([0.0, 1.0], [1.0, 1.5]), QueryFilter::default());
//! assert!(!hits.is_empty());
//! let mut reused = Vec::new();
//! world.overlap_aabb_into(
//! Aabb::from_center_half_extents([0.0, 1.0], [1.0, 1.5]),
//! QueryFilter::default(),
//! &mut reused,
//! );
//! assert_eq!(hits.len(), reused.len());
//! let mut visited = 0;
//! let complete = world.visit_overlap_aabb(
//! Aabb::from_center_half_extents([0.0, 1.0], [1.0, 1.5]),
//! QueryFilter::default(),
//! |_| {
//! visited += 1;
//! true
//! },
//! );
//! assert!(complete);
//! assert_eq!(hits.len(), visited);
//! // Ray (closest)
//! let r = world.cast_ray_closest(Vec2::new(0.0, 5.0), Vec2::new(0.0, -10.0), QueryFilter::default());
//! if r.hit { let _ = (r.point, r.normal, r.fraction); }
//! ```
//!
//! Character Mover Helpers
//! ```no_run
//! use boxdd::{clip_vector, solve_planes, CollisionPlane, QueryFilter, Vec2, World, WorldDef};
//! let world = World::new(WorldDef::default()).unwrap();
//! let planes = world.collide_mover([0.0_f32, 0.75], [0.0, 1.75], 0.25, QueryFilter::default());
//! let mut rigid: Vec<CollisionPlane> = planes
//! .into_iter()
//! .filter_map(|p| p.into_rigid_collision_plane())
//! .collect();
//! let solved = solve_planes([0.0_f32, -0.1], &mut rigid);
//! let _clipped_velocity = clip_vector(Vec2::new(0.0, -1.0), &rigid);
//! let _ = solved.translation;
//! ```
//!
//! Collision Geometry
//! ```no_run
//! use boxdd::{
//! segment_distance, shape_distance, DistanceInput, ShapeProxy, SimplexCache, ToiInput,
//! ToiState, Sweep, Transform,
//! };
//! let proxy_a = ShapeProxy::new([[-1.0_f32, -1.0], [1.0, -1.0], [1.0, 1.0], [-1.0, 1.0]], 0.0).unwrap();
//! let proxy_b = ShapeProxy::new([[2.0_f32, -1.0], [2.0, 1.0]], 0.0).unwrap();
//! let mut cache = SimplexCache::default();
//! let seg = segment_distance([-1.0_f32, 0.0], [1.0, 0.0], [0.0, -1.0], [0.0, 1.0]);
//! assert!(seg.distance_squared >= 0.0);
//! let distance = shape_distance(
//! DistanceInput::new(proxy_a, proxy_b, Transform::IDENTITY, Transform::IDENTITY),
//! &mut cache,
//! );
//! assert!(distance.distance >= 0.0);
//! let toi = boxdd::time_of_impact(ToiInput::new(
//! proxy_a,
//! proxy_b,
//! Sweep::new([0.0_f32, 0.0], [0.0, 0.0], [0.0, 0.0], boxdd::Rot::IDENTITY, boxdd::Rot::IDENTITY),
//! Sweep::new([0.0_f32, 0.0], [0.0, 0.0], [-2.0, 0.0], boxdd::Rot::IDENTITY, boxdd::Rot::IDENTITY),
//! ));
//! let _ = matches!(toi.state, ToiState::Hit | ToiState::Separated | ToiState::Overlapped | ToiState::Failed | ToiState::Unknown);
//! ```
//!
//! Material Mixing Callbacks
//! ```no_run
//! use boxdd::{MaterialMixInput, World, WorldDef};
//! let mut world = World::new(WorldDef::default()).unwrap();
//! world.set_friction_callback(|a: MaterialMixInput, b: MaterialMixInput| {
//! if a.user_material_id == 1 || b.user_material_id == 1 {
//! 0.0
//! } else {
//! (a.coefficient * b.coefficient).sqrt()
//! }
//! });
//! ```
//!
//! Feature Flags
//! - `serialize`: scene snapshot helpers (save/apply world config; build/restore minimal full-scene snapshot).
//! - `pkg-config`: allow linking against a system `box2d` via pkg-config.
//! - `mint`: lightweight math interop types (`mint::Vector2`, `mint::Point2`, `mint::RowMatrix2` /
//! `mint::ColumnMatrix2` for `Rot`, and row/column-major 2D affine matrices for `Transform`).
//! - `cgmath` / `nalgebra` / `glam`: conversions with their 2D math types.
//! - `bytemuck`: `Pod`/`Zeroable` for core math types (`Vec2`, `Rot`, `Transform`, `Aabb`) for zero-copy interop.
//!
//! Threading and async
//! - `WorldDef::builder().worker_count(n)` preserves Box2D's worker-count setting, but actual
//! multithreaded stepping still requires explicit raw task callbacks through
//! `unsafe WorldBuilder::task_system_raw(...)` / `WorldDef::set_task_system_raw(...)`. It does
//! not make `World`, `WorldHandle`, or owned handles `Send`/`Sync`.
//! - Keep the world on one thread/task. In async runtimes prefer `spawn_local` / `LocalSet`; in
//! multi-threaded engines prefer a dedicated physics thread plus channels.
//! - `set_custom_filter*`, `set_pre_solve*`, `set_friction_callback`, and `set_restitution_callback`
//! may run on Box2D worker threads and therefore require `Send + Sync` closures.
//! - See `examples/physics_thread.rs` for the dedicated-thread pattern.
//!
//! Error handling
//! - The default safe surface panics on misuse such as stale ids or calling Box2D while the world
//! is locked in a callback. This keeps the common path terse and avoids Rust-level UB.
//! - At runtime boundaries, prefer `try_*` APIs and handle `ApiError` explicitly.
//! - `try_*` setters also turn obvious Box2D assert preconditions into recoverable `ApiError`
//! values instead of relying on assert-enabled native builds.
//! - `WorldDef`, `BodyDef`, `ShapeDef`, `SurfaceMaterial`, `JointBase`, and concrete
//! `*JointDef` values expose `validate()` for preflight checks before crossing the FFI boundary.
//! - Crate-owned geometry values (`Circle`, `Segment`, `Capsule`, `ChainSegment`, `Polygon`) also
//! expose `is_valid()` / `validate()` for preflight geometry checks, and the world-free helper
//! methods (`mass_data`, `aabb`, `contains_point`, `ray_cast`, `transformed`) follow the same
//! panic-by-default plus recoverable `try_*` split as the rest of the crate.
//!
//! Events
//! - Four access styles:
//! - By value: `World` and `WorldHandle` expose `contact_events()`/`sensor_events()`/`body_events()`/`joint_events()` for owned data that can be stored or used cross-frame.
//! - Reusable buffers: `World` and `WorldHandle` also expose `*_events_into(...)` to reuse caller-owned event storage across frames.
//! - Zero‑copy views: `with_*_events_view(...)` iterate without allocations (borrows internal buffers).
//! - Raw slices: `unsafe { with_*_events_raw(...) }` expose FFI slices (borrows internal buffers).
//! - Callback-sensitive event entrypoints also expose matching `try_*` variants so callback-lock
//! failures can return `ApiError::InCallback` instead of forcing panic-only control flow.
//! - Borrowed view/raw event APIs intentionally stay on `World`, not `WorldHandle`, because they
//! are tied to the completed step's world-local event buffers and deferred-destroy flushing behavior.
//!
//! Example (reusable buffers + zero‑copy views)
//! ```no_run
//! use boxdd::{ContactEvents, World, WorldDef};
//! let mut world = World::new(WorldDef::default()).unwrap();
//! let mut contact_events = ContactEvents::default();
//! world.contact_events_into(&mut contact_events);
//! world.with_contact_events_view(|begin, end, hit| {
//! let _ = (begin.count(), end.count(), hit.count());
//! });
//! world.with_sensor_events_view(|beg, end| { let _ = (beg.count(), end.count()); });
//! world.with_body_events_view(|moves| { for m in moves { let _ = (m.body_id(), m.fell_asleep()); } });
//! world.with_joint_events_view(|j| { let _ = j.count(); });
//! ```
pub use OwnedBody;
pub use ;
pub use ;
pub use RotFromGlamError;
pub use RotFromMintError;
pub use TransformFromCgmathError;
pub use TransformFromGlamError;
pub use TransformFromMintError;
pub use ;
pub use ;
pub use ;
pub use ;
pub use Filter;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ExplosionDef;