1use crate::Transform;
26use crate::types::Vec2;
27use crate::world::World;
28use boxdd_sys::ffi;
29use smallvec::SmallVec;
30use std::any::Any;
31use std::ffi::CStr;
32
33pub type HexColor = ffi::b2HexColor;
34
35#[derive(Clone, Debug)]
36pub enum DebugDrawCmd {
37 Polygon {
38 vertices: Vec<Vec2>,
39 color: HexColor,
40 },
41 SolidPolygon {
42 transform: Transform,
43 vertices: Vec<Vec2>,
44 radius: f32,
45 color: HexColor,
46 },
47 Circle {
48 center: Vec2,
49 radius: f32,
50 color: HexColor,
51 },
52 SolidCircle {
53 transform: Transform,
54 radius: f32,
55 color: HexColor,
56 },
57 SolidCapsule {
58 p1: Vec2,
59 p2: Vec2,
60 radius: f32,
61 color: HexColor,
62 },
63 Segment {
64 p1: Vec2,
65 p2: Vec2,
66 color: HexColor,
67 },
68 Transform(Transform),
69 Point {
70 p: Vec2,
71 size: f32,
72 color: HexColor,
73 },
74 String {
75 p: Vec2,
76 s: String,
77 color: HexColor,
78 },
79}
80
81pub trait DebugDraw {
83 fn draw_polygon(&mut self, _vertices: &[Vec2], _color: HexColor) {}
84 fn draw_solid_polygon(
85 &mut self,
86 _transform: Transform,
87 _vertices: &[Vec2],
88 _radius: f32,
89 _color: HexColor,
90 ) {
91 }
92 fn draw_circle(&mut self, _center: Vec2, _radius: f32, _color: HexColor) {}
93 fn draw_solid_circle(&mut self, _transform: Transform, _radius: f32, _color: HexColor) {}
94 fn draw_solid_capsule(&mut self, _p1: Vec2, _p2: Vec2, _radius: f32, _color: HexColor) {}
95 fn draw_segment(&mut self, _p1: Vec2, _p2: Vec2, _color: HexColor) {}
96 fn draw_transform(&mut self, _transform: Transform) {}
97 fn draw_point(&mut self, _p: Vec2, _size: f32, _color: HexColor) {}
98 fn draw_string(&mut self, _p: Vec2, _s: &str, _color: HexColor) {}
99}
100
101pub trait RawDebugDraw {
103 fn draw_polygon(&mut self, _vertices: &[ffi::b2Vec2], _color: HexColor) {}
104 fn draw_solid_polygon(
105 &mut self,
106 _transform: ffi::b2Transform,
107 _vertices: &[ffi::b2Vec2],
108 _radius: f32,
109 _color: HexColor,
110 ) {
111 }
112 fn draw_circle(&mut self, _center: ffi::b2Vec2, _radius: f32, _color: HexColor) {}
113 fn draw_solid_circle(&mut self, _transform: ffi::b2Transform, _radius: f32, _color: HexColor) {}
114 fn draw_solid_capsule(
115 &mut self,
116 _p1: ffi::b2Vec2,
117 _p2: ffi::b2Vec2,
118 _radius: f32,
119 _color: HexColor,
120 ) {
121 }
122 fn draw_segment(&mut self, _p1: ffi::b2Vec2, _p2: ffi::b2Vec2, _color: HexColor) {}
123 fn draw_transform(&mut self, _transform: ffi::b2Transform) {}
124 fn draw_point(&mut self, _p: ffi::b2Vec2, _size: f32, _color: HexColor) {}
125 fn draw_string(&mut self, _p: ffi::b2Vec2, _s: &CStr, _color: HexColor) {}
126}
127
128#[derive(Copy, Clone, Debug)]
129pub struct DebugDrawOptions {
130 pub drawing_bounds: ffi::b2AABB,
131 pub force_scale: f32,
132 pub joint_scale: f32,
133 pub draw_shapes: bool,
134 pub draw_joints: bool,
135 pub draw_joint_extras: bool,
136 pub draw_bounds: bool,
137 pub draw_mass: bool,
138 pub draw_body_names: bool,
139 pub draw_contacts: bool,
141 pub draw_graph_colors: bool,
142 pub draw_contact_features: bool,
143 pub draw_contact_normals: bool,
144 pub draw_contact_forces: bool,
145 pub draw_friction_forces: bool,
146 pub draw_islands: bool,
147}
148
149impl Default for DebugDrawOptions {
150 fn default() -> Self {
151 Self {
152 drawing_bounds: ffi::b2AABB {
153 lowerBound: ffi::b2Vec2 {
154 x: -1.0e9,
155 y: -1.0e9,
156 },
157 upperBound: ffi::b2Vec2 { x: 1.0e9, y: 1.0e9 },
158 },
159 force_scale: 1.0,
160 joint_scale: 1.0,
161 draw_shapes: true,
162 draw_joints: true,
163 draw_joint_extras: false,
164 draw_bounds: false,
165 draw_mass: false,
166 draw_body_names: false,
167 draw_contacts: false,
168 draw_graph_colors: false,
169 draw_contact_features: false,
170 draw_contact_normals: false,
171 draw_contact_forces: false,
172 draw_friction_forces: false,
173 draw_islands: false,
174 }
175 }
176}
177
178struct DebugCtx<'a> {
179 drawer: &'a mut dyn DebugDraw,
180 panicked: &'a mut bool,
181 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
182}
183struct RawDebugCtx<'a> {
184 drawer: &'a mut dyn RawDebugDraw,
185 panicked: &'a mut bool,
186 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
187}
188
189impl World {
190 pub fn debug_draw_collect(&mut self, opts: DebugDrawOptions) -> Vec<DebugDrawCmd> {
194 crate::core::callback_state::assert_not_in_callback();
195 struct Collector {
196 cmds: Vec<DebugDrawCmd>,
197 }
198 impl DebugDraw for Collector {
199 fn draw_polygon(&mut self, vertices: &[Vec2], color: HexColor) {
200 self.cmds.push(DebugDrawCmd::Polygon {
201 vertices: vertices.to_vec(),
202 color,
203 });
204 }
205 fn draw_solid_polygon(
206 &mut self,
207 transform: Transform,
208 vertices: &[Vec2],
209 radius: f32,
210 color: HexColor,
211 ) {
212 self.cmds.push(DebugDrawCmd::SolidPolygon {
213 transform,
214 vertices: vertices.to_vec(),
215 radius,
216 color,
217 });
218 }
219 fn draw_circle(&mut self, center: Vec2, radius: f32, color: HexColor) {
220 self.cmds.push(DebugDrawCmd::Circle {
221 center,
222 radius,
223 color,
224 });
225 }
226 fn draw_solid_circle(&mut self, transform: Transform, radius: f32, color: HexColor) {
227 self.cmds.push(DebugDrawCmd::SolidCircle {
228 transform,
229 radius,
230 color,
231 });
232 }
233 fn draw_solid_capsule(&mut self, p1: Vec2, p2: Vec2, radius: f32, color: HexColor) {
234 self.cmds.push(DebugDrawCmd::SolidCapsule {
235 p1,
236 p2,
237 radius,
238 color,
239 });
240 }
241 fn draw_segment(&mut self, p1: Vec2, p2: Vec2, color: HexColor) {
242 self.cmds.push(DebugDrawCmd::Segment { p1, p2, color });
243 }
244 fn draw_transform(&mut self, transform: Transform) {
245 self.cmds.push(DebugDrawCmd::Transform(transform));
246 }
247 fn draw_point(&mut self, p: Vec2, size: f32, color: HexColor) {
248 self.cmds.push(DebugDrawCmd::Point { p, size, color });
249 }
250 fn draw_string(&mut self, p: Vec2, s: &str, color: HexColor) {
251 self.cmds.push(DebugDrawCmd::String {
252 p,
253 s: s.to_owned(),
254 color,
255 });
256 }
257 }
258
259 let mut c = Collector { cmds: Vec::new() };
260 self.debug_draw(&mut c, opts);
261 c.cmds
262 }
263
264 pub fn debug_draw(&mut self, drawer: &mut impl DebugDraw, opts: DebugDrawOptions) {
270 crate::core::callback_state::assert_not_in_callback();
271 let mut panicked = false;
272 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
273 let mut ctx = DebugCtx {
274 drawer,
275 panicked: &mut panicked,
276 panic: &mut panic,
277 };
278 let mut dd = unsafe { ffi::b2DefaultDebugDraw() };
279 unsafe extern "C" fn draw_polygon_cb(
281 vertices: *const ffi::b2Vec2,
282 count: i32,
283 color: HexColor,
284 context: *mut core::ffi::c_void,
285 ) {
286 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
287 if *ctx.panicked {
288 return;
289 }
290 let n = count.max(0) as usize;
291 if n == 0 || vertices.is_null() {
292 return;
293 }
294 let src = unsafe { core::slice::from_raw_parts(vertices, n) };
295 let mut verts: SmallVec<[Vec2; 8]> = SmallVec::with_capacity(src.len().min(8));
296 for v in src.iter().copied() {
297 verts.push(Vec2::from(v));
298 }
299 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
300 let _g = crate::core::callback_state::CallbackGuard::enter();
301 ctx.drawer.draw_polygon(&verts, color);
302 }));
303 if let Err(p) = r {
304 *ctx.panicked = true;
305 *ctx.panic = Some(p);
306 }
307 }
308 unsafe extern "C" fn draw_solid_polygon_cb(
309 transform: ffi::b2Transform,
310 vertices: *const ffi::b2Vec2,
311 count: i32,
312 radius: f32,
313 color: HexColor,
314 context: *mut core::ffi::c_void,
315 ) {
316 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
317 if *ctx.panicked {
318 return;
319 }
320 let n = count.max(0) as usize;
321 if n == 0 || vertices.is_null() {
322 return;
323 }
324 let src = unsafe { core::slice::from_raw_parts(vertices, n) };
325 let mut verts: SmallVec<[Vec2; 8]> = SmallVec::with_capacity(src.len().min(8));
326 for v in src.iter().copied() {
327 verts.push(Vec2::from(v));
328 }
329 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
330 let _g = crate::core::callback_state::CallbackGuard::enter();
331 ctx.drawer
332 .draw_solid_polygon(Transform::from(transform), &verts, radius, color);
333 }));
334 if let Err(p) = r {
335 *ctx.panicked = true;
336 *ctx.panic = Some(p);
337 }
338 }
339 unsafe extern "C" fn draw_circle_cb(
340 center: ffi::b2Vec2,
341 radius: f32,
342 color: HexColor,
343 context: *mut core::ffi::c_void,
344 ) {
345 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
346 if *ctx.panicked {
347 return;
348 }
349 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
350 let _g = crate::core::callback_state::CallbackGuard::enter();
351 ctx.drawer.draw_circle(Vec2::from(center), radius, color);
352 }));
353 if let Err(p) = r {
354 *ctx.panicked = true;
355 *ctx.panic = Some(p);
356 }
357 }
358 unsafe extern "C" fn draw_solid_circle_cb(
359 transform: ffi::b2Transform,
360 radius: f32,
361 color: HexColor,
362 context: *mut core::ffi::c_void,
363 ) {
364 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
365 if *ctx.panicked {
366 return;
367 }
368 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
369 let _g = crate::core::callback_state::CallbackGuard::enter();
370 ctx.drawer
371 .draw_solid_circle(Transform::from(transform), radius, color);
372 }));
373 if let Err(p) = r {
374 *ctx.panicked = true;
375 *ctx.panic = Some(p);
376 }
377 }
378 unsafe extern "C" fn draw_solid_capsule_cb(
379 p1: ffi::b2Vec2,
380 p2: ffi::b2Vec2,
381 radius: f32,
382 color: HexColor,
383 context: *mut core::ffi::c_void,
384 ) {
385 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
386 if *ctx.panicked {
387 return;
388 }
389 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
390 let _g = crate::core::callback_state::CallbackGuard::enter();
391 ctx.drawer
392 .draw_solid_capsule(Vec2::from(p1), Vec2::from(p2), radius, color);
393 }));
394 if let Err(p) = r {
395 *ctx.panicked = true;
396 *ctx.panic = Some(p);
397 }
398 }
399 unsafe extern "C" fn draw_line_cb(
400 p1: ffi::b2Vec2,
401 p2: ffi::b2Vec2,
402 color: HexColor,
403 context: *mut core::ffi::c_void,
404 ) {
405 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
406 if *ctx.panicked {
407 return;
408 }
409 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
410 let _g = crate::core::callback_state::CallbackGuard::enter();
411 ctx.drawer
412 .draw_segment(Vec2::from(p1), Vec2::from(p2), color);
413 }));
414 if let Err(p) = r {
415 *ctx.panicked = true;
416 *ctx.panic = Some(p);
417 }
418 }
419 unsafe extern "C" fn draw_transform_cb(
420 transform: ffi::b2Transform,
421 context: *mut core::ffi::c_void,
422 ) {
423 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
424 if *ctx.panicked {
425 return;
426 }
427 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
428 let _g = crate::core::callback_state::CallbackGuard::enter();
429 ctx.drawer.draw_transform(Transform::from(transform));
430 }));
431 if let Err(p) = r {
432 *ctx.panicked = true;
433 *ctx.panic = Some(p);
434 }
435 }
436 unsafe extern "C" fn draw_point_cb(
437 p: ffi::b2Vec2,
438 size: f32,
439 color: HexColor,
440 context: *mut core::ffi::c_void,
441 ) {
442 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
443 if *ctx.panicked {
444 return;
445 }
446 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
447 let _g = crate::core::callback_state::CallbackGuard::enter();
448 ctx.drawer.draw_point(Vec2::from(p), size, color);
449 }));
450 if let Err(p) = r {
451 *ctx.panicked = true;
452 *ctx.panic = Some(p);
453 }
454 }
455 unsafe extern "C" fn draw_string_cb(
456 p: ffi::b2Vec2,
457 s: *const core::ffi::c_char,
458 color: HexColor,
459 context: *mut core::ffi::c_void,
460 ) {
461 let ctx = unsafe { &mut *(context as *mut DebugCtx) };
462 if *ctx.panicked {
463 return;
464 }
465 if !s.is_null() {
466 let cs = unsafe { CStr::from_ptr(s) };
467 let s = cs.to_string_lossy();
468 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
469 let _g = crate::core::callback_state::CallbackGuard::enter();
470 ctx.drawer.draw_string(Vec2::from(p), &s, color);
471 }));
472 if let Err(p) = r {
473 *ctx.panicked = true;
474 *ctx.panic = Some(p);
475 }
476 }
477 }
478
479 dd.DrawPolygonFcn = Some(draw_polygon_cb);
480 dd.DrawSolidPolygonFcn = Some(draw_solid_polygon_cb);
481 dd.DrawCircleFcn = Some(draw_circle_cb);
482 dd.DrawSolidCircleFcn = Some(draw_solid_circle_cb);
483 dd.DrawSolidCapsuleFcn = Some(draw_solid_capsule_cb);
484 dd.DrawLineFcn = Some(draw_line_cb);
485 dd.DrawTransformFcn = Some(draw_transform_cb);
486 dd.DrawPointFcn = Some(draw_point_cb);
487 dd.DrawStringFcn = Some(draw_string_cb);
488
489 dd.drawingBounds = opts.drawing_bounds;
491 dd.forceScale = opts.force_scale;
492 dd.jointScale = opts.joint_scale;
493 dd.drawShapes = opts.draw_shapes;
494 dd.drawJoints = opts.draw_joints;
495 dd.drawJointExtras = opts.draw_joint_extras;
496 dd.drawBounds = opts.draw_bounds;
497 dd.drawMass = opts.draw_mass;
498 dd.drawBodyNames = opts.draw_body_names;
499 dd.drawContactPoints = opts.draw_contacts;
500 dd.drawGraphColors = opts.draw_graph_colors;
501 dd.drawContactFeatures = opts.draw_contact_features;
502 dd.drawContactNormals = opts.draw_contact_normals;
503 dd.drawContactForces = opts.draw_contact_forces;
504 dd.drawFrictionForces = opts.draw_friction_forces;
505 dd.drawIslands = opts.draw_islands;
506 dd.context = &mut ctx as *mut _ as *mut _;
507
508 unsafe { ffi::b2World_Draw(self.raw(), &mut dd) };
509
510 self.core_arc().process_deferred_destroys();
512
513 if let Some(p) = panic.take() {
514 std::panic::resume_unwind(p);
515 }
516 }
517
518 pub fn debug_draw_raw(&mut self, drawer: &mut impl RawDebugDraw, opts: DebugDrawOptions) {
524 crate::core::callback_state::assert_not_in_callback();
525 let mut panicked = false;
526 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
527 let mut ctx = RawDebugCtx {
528 drawer,
529 panicked: &mut panicked,
530 panic: &mut panic,
531 };
532 let mut dd = unsafe { ffi::b2DefaultDebugDraw() };
533 unsafe extern "C" fn draw_polygon_cb(
534 vertices: *const ffi::b2Vec2,
535 count: i32,
536 color: HexColor,
537 context: *mut core::ffi::c_void,
538 ) {
539 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
540 if *ctx.panicked {
541 return;
542 }
543 let n = count.max(0) as usize;
544 if n == 0 || vertices.is_null() {
545 return;
546 }
547 let slice = unsafe { core::slice::from_raw_parts(vertices, n) };
548 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
549 let _g = crate::core::callback_state::CallbackGuard::enter();
550 ctx.drawer.draw_polygon(slice, color);
551 }));
552 if let Err(p) = r {
553 *ctx.panicked = true;
554 *ctx.panic = Some(p);
555 }
556 }
557 unsafe extern "C" fn draw_solid_polygon_cb(
558 transform: ffi::b2Transform,
559 vertices: *const ffi::b2Vec2,
560 count: i32,
561 radius: f32,
562 color: HexColor,
563 context: *mut core::ffi::c_void,
564 ) {
565 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
566 if *ctx.panicked {
567 return;
568 }
569 let n = count.max(0) as usize;
570 if n == 0 || vertices.is_null() {
571 return;
572 }
573 let slice = unsafe { core::slice::from_raw_parts(vertices, n) };
574 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
575 let _g = crate::core::callback_state::CallbackGuard::enter();
576 ctx.drawer
577 .draw_solid_polygon(transform, slice, radius, color);
578 }));
579 if let Err(p) = r {
580 *ctx.panicked = true;
581 *ctx.panic = Some(p);
582 }
583 }
584 unsafe extern "C" fn draw_circle_cb(
585 center: ffi::b2Vec2,
586 radius: f32,
587 color: HexColor,
588 context: *mut core::ffi::c_void,
589 ) {
590 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
591 if *ctx.panicked {
592 return;
593 }
594 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
595 let _g = crate::core::callback_state::CallbackGuard::enter();
596 ctx.drawer.draw_circle(center, radius, color);
597 }));
598 if let Err(p) = r {
599 *ctx.panicked = true;
600 *ctx.panic = Some(p);
601 }
602 }
603 unsafe extern "C" fn draw_solid_circle_cb(
604 transform: ffi::b2Transform,
605 radius: f32,
606 color: HexColor,
607 context: *mut core::ffi::c_void,
608 ) {
609 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
610 if *ctx.panicked {
611 return;
612 }
613 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
614 let _g = crate::core::callback_state::CallbackGuard::enter();
615 ctx.drawer.draw_solid_circle(transform, radius, color);
616 }));
617 if let Err(p) = r {
618 *ctx.panicked = true;
619 *ctx.panic = Some(p);
620 }
621 }
622 unsafe extern "C" fn draw_solid_capsule_cb(
623 p1: ffi::b2Vec2,
624 p2: ffi::b2Vec2,
625 radius: f32,
626 color: HexColor,
627 context: *mut core::ffi::c_void,
628 ) {
629 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
630 if *ctx.panicked {
631 return;
632 }
633 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
634 let _g = crate::core::callback_state::CallbackGuard::enter();
635 ctx.drawer.draw_solid_capsule(p1, p2, radius, color);
636 }));
637 if let Err(p) = r {
638 *ctx.panicked = true;
639 *ctx.panic = Some(p);
640 }
641 }
642 unsafe extern "C" fn draw_line_cb(
643 p1: ffi::b2Vec2,
644 p2: ffi::b2Vec2,
645 color: HexColor,
646 context: *mut core::ffi::c_void,
647 ) {
648 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
649 if *ctx.panicked {
650 return;
651 }
652 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
653 let _g = crate::core::callback_state::CallbackGuard::enter();
654 ctx.drawer.draw_segment(p1, p2, color);
655 }));
656 if let Err(p) = r {
657 *ctx.panicked = true;
658 *ctx.panic = Some(p);
659 }
660 }
661 unsafe extern "C" fn draw_transform_cb(
662 transform: ffi::b2Transform,
663 context: *mut core::ffi::c_void,
664 ) {
665 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
666 if *ctx.panicked {
667 return;
668 }
669 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
670 let _g = crate::core::callback_state::CallbackGuard::enter();
671 ctx.drawer.draw_transform(transform);
672 }));
673 if let Err(p) = r {
674 *ctx.panicked = true;
675 *ctx.panic = Some(p);
676 }
677 }
678 unsafe extern "C" fn draw_point_cb(
679 p: ffi::b2Vec2,
680 size: f32,
681 color: HexColor,
682 context: *mut core::ffi::c_void,
683 ) {
684 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
685 if *ctx.panicked {
686 return;
687 }
688 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
689 let _g = crate::core::callback_state::CallbackGuard::enter();
690 ctx.drawer.draw_point(p, size, color);
691 }));
692 if let Err(p) = r {
693 *ctx.panicked = true;
694 *ctx.panic = Some(p);
695 }
696 }
697 unsafe extern "C" fn draw_string_cb(
698 p: ffi::b2Vec2,
699 s: *const core::ffi::c_char,
700 color: HexColor,
701 context: *mut core::ffi::c_void,
702 ) {
703 let ctx = unsafe { &mut *(context as *mut RawDebugCtx) };
704 if *ctx.panicked {
705 return;
706 }
707 if !s.is_null() {
708 let cs = unsafe { CStr::from_ptr(s) };
709 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
710 let _g = crate::core::callback_state::CallbackGuard::enter();
711 ctx.drawer.draw_string(p, cs, color);
712 }));
713 if let Err(p) = r {
714 *ctx.panicked = true;
715 *ctx.panic = Some(p);
716 }
717 }
718 }
719 dd.DrawPolygonFcn = Some(draw_polygon_cb);
720 dd.DrawSolidPolygonFcn = Some(draw_solid_polygon_cb);
721 dd.DrawCircleFcn = Some(draw_circle_cb);
722 dd.DrawSolidCircleFcn = Some(draw_solid_circle_cb);
723 dd.DrawSolidCapsuleFcn = Some(draw_solid_capsule_cb);
724 dd.DrawLineFcn = Some(draw_line_cb);
725 dd.DrawTransformFcn = Some(draw_transform_cb);
726 dd.DrawPointFcn = Some(draw_point_cb);
727 dd.DrawStringFcn = Some(draw_string_cb);
728 dd.drawingBounds = opts.drawing_bounds;
729 dd.forceScale = opts.force_scale;
730 dd.jointScale = opts.joint_scale;
731 dd.drawShapes = opts.draw_shapes;
732 dd.drawJoints = opts.draw_joints;
733 dd.drawJointExtras = opts.draw_joint_extras;
734 dd.drawBounds = opts.draw_bounds;
735 dd.drawMass = opts.draw_mass;
736 dd.drawBodyNames = opts.draw_body_names;
737 dd.drawContactPoints = opts.draw_contacts;
738 dd.drawGraphColors = opts.draw_graph_colors;
739 dd.drawContactFeatures = opts.draw_contact_features;
740 dd.drawContactNormals = opts.draw_contact_normals;
741 dd.drawContactForces = opts.draw_contact_forces;
742 dd.drawFrictionForces = opts.draw_friction_forces;
743 dd.drawIslands = opts.draw_islands;
744 dd.context = &mut ctx as *mut _ as *mut _;
745 unsafe { ffi::b2World_Draw(self.raw(), &mut dd) };
746
747 self.core_arc().process_deferred_destroys();
749
750 if let Some(p) = panic.take() {
751 std::panic::resume_unwind(p);
752 }
753 }
754}