1use std::marker::PhantomData;
7pub mod chain;
8pub mod helpers;
9
10use crate::body::Body;
11use crate::error::ApiResult;
12use crate::filter::Filter;
13use crate::types::{BodyId, ChainId, ShapeId, Vec2};
14use crate::world::World;
15use boxdd_sys::ffi;
16use std::os::raw::c_void;
17use std::rc::Rc;
18use std::sync::Arc;
19
20pub struct Shape<'w> {
22 pub(crate) id: ShapeId,
23 #[allow(dead_code)]
24 pub(crate) core: Arc<crate::core::world_core::WorldCore>,
25 _world: PhantomData<&'w World>,
26}
27
28pub struct OwnedShape {
30 id: ShapeId,
31 core: Arc<crate::core::world_core::WorldCore>,
32 destroy_on_drop: bool,
33 update_body_mass_on_drop: bool,
34 _not_send: PhantomData<Rc<()>>,
35}
36
37impl OwnedShape {
38 pub(crate) fn new(core: Arc<crate::core::world_core::WorldCore>, id: ShapeId) -> Self {
39 core.owned_shapes
40 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
41 Self {
42 id,
43 core,
44 destroy_on_drop: true,
45 update_body_mass_on_drop: true,
46 _not_send: PhantomData,
47 }
48 }
49
50 pub fn id(&self) -> ShapeId {
51 self.id
52 }
53
54 pub fn world_id(&self) -> ffi::b2WorldId {
55 self.assert_valid();
56 unsafe { ffi::b2Shape_GetWorld(self.id) }
57 }
58
59 pub fn try_world_id(&self) -> ApiResult<ffi::b2WorldId> {
60 self.check_valid()?;
61 Ok(unsafe { ffi::b2Shape_GetWorld(self.id) })
62 }
63
64 pub fn parent_chain_id(&self) -> Option<ChainId> {
65 self.assert_valid();
66 let cid = unsafe { ffi::b2Shape_GetParentChain(self.id) };
67 if unsafe { ffi::b2Chain_IsValid(cid) } {
68 Some(cid)
69 } else {
70 None
71 }
72 }
73
74 pub fn try_parent_chain_id(&self) -> ApiResult<Option<ChainId>> {
75 self.check_valid()?;
76 let cid = unsafe { ffi::b2Shape_GetParentChain(self.id) };
77 if unsafe { ffi::b2Chain_IsValid(cid) } {
78 Ok(Some(cid))
79 } else {
80 Ok(None)
81 }
82 }
83
84 pub fn is_valid(&self) -> bool {
85 crate::core::callback_state::assert_not_in_callback();
86 unsafe { ffi::b2Shape_IsValid(self.id) }
87 }
88
89 pub fn try_is_valid(&self) -> ApiResult<bool> {
90 crate::core::callback_state::check_not_in_callback()?;
91 Ok(unsafe { ffi::b2Shape_IsValid(self.id) })
92 }
93
94 #[inline]
95 fn assert_valid(&self) {
96 crate::core::debug_checks::assert_shape_valid(self.id);
97 }
98
99 #[inline]
100 fn check_valid(&self) -> ApiResult<()> {
101 crate::core::debug_checks::check_shape_valid(self.id)
102 }
103
104 pub fn as_id(&self) -> ShapeId {
106 self.id
107 }
108
109 pub fn is_sensor(&self) -> bool {
110 self.assert_valid();
111 unsafe { ffi::b2Shape_IsSensor(self.id) }
112 }
113
114 pub fn try_is_sensor(&self) -> ApiResult<bool> {
115 self.check_valid()?;
116 Ok(unsafe { ffi::b2Shape_IsSensor(self.id) })
117 }
118
119 pub fn shape_type(&self) -> ffi::b2ShapeType {
120 self.assert_valid();
121 unsafe { ffi::b2Shape_GetType(self.id) }
122 }
123
124 pub fn try_shape_type(&self) -> ApiResult<ffi::b2ShapeType> {
125 self.check_valid()?;
126 Ok(unsafe { ffi::b2Shape_GetType(self.id) })
127 }
128
129 pub fn body_id(&self) -> BodyId {
130 self.assert_valid();
131 unsafe { ffi::b2Shape_GetBody(self.id) }
132 }
133
134 pub fn try_body_id(&self) -> ApiResult<BodyId> {
135 self.check_valid()?;
136 Ok(unsafe { ffi::b2Shape_GetBody(self.id) })
137 }
138
139 pub fn circle(&self) -> ffi::b2Circle {
141 self.assert_valid();
142 unsafe { ffi::b2Shape_GetCircle(self.id) }
143 }
144 pub fn segment(&self) -> ffi::b2Segment {
145 self.assert_valid();
146 unsafe { ffi::b2Shape_GetSegment(self.id) }
147 }
148 pub fn capsule(&self) -> ffi::b2Capsule {
149 self.assert_valid();
150 unsafe { ffi::b2Shape_GetCapsule(self.id) }
151 }
152 pub fn polygon(&self) -> ffi::b2Polygon {
153 self.assert_valid();
154 unsafe { ffi::b2Shape_GetPolygon(self.id) }
155 }
156
157 pub fn closest_point<V: Into<Vec2>>(&self, target: V) -> Vec2 {
159 self.assert_valid();
160 let t: ffi::b2Vec2 = target.into().into();
161 Vec2::from(unsafe { ffi::b2Shape_GetClosestPoint(self.id, t) })
162 }
163
164 pub fn try_closest_point<V: Into<Vec2>>(&self, target: V) -> ApiResult<Vec2> {
165 self.check_valid()?;
166 let t: ffi::b2Vec2 = target.into().into();
167 Ok(Vec2::from(unsafe {
168 ffi::b2Shape_GetClosestPoint(self.id, t)
169 }))
170 }
171
172 pub fn apply_wind<V: Into<Vec2>>(&mut self, wind: V, drag: f32, lift: f32, wake: bool) {
174 self.assert_valid();
175 let w: ffi::b2Vec2 = wind.into().into();
176 unsafe { ffi::b2Shape_ApplyWind(self.id, w, drag, lift, wake) }
177 }
178
179 pub fn try_apply_wind<V: Into<Vec2>>(
180 &mut self,
181 wind: V,
182 drag: f32,
183 lift: f32,
184 wake: bool,
185 ) -> ApiResult<()> {
186 self.check_valid()?;
187 let w: ffi::b2Vec2 = wind.into().into();
188 unsafe { ffi::b2Shape_ApplyWind(self.id, w, drag, lift, wake) }
189 Ok(())
190 }
191
192 pub fn set_circle(&mut self, c: &ffi::b2Circle) {
193 self.assert_valid();
194 unsafe { ffi::b2Shape_SetCircle(self.id, c) }
195 }
196 pub fn try_set_circle(&mut self, c: &ffi::b2Circle) -> ApiResult<()> {
197 self.check_valid()?;
198 unsafe { ffi::b2Shape_SetCircle(self.id, c) }
199 Ok(())
200 }
201 pub fn set_segment(&mut self, s: &ffi::b2Segment) {
202 self.assert_valid();
203 unsafe { ffi::b2Shape_SetSegment(self.id, s) }
204 }
205 pub fn try_set_segment(&mut self, s: &ffi::b2Segment) -> ApiResult<()> {
206 self.check_valid()?;
207 unsafe { ffi::b2Shape_SetSegment(self.id, s) }
208 Ok(())
209 }
210 pub fn set_capsule(&mut self, c: &ffi::b2Capsule) {
211 self.assert_valid();
212 unsafe { ffi::b2Shape_SetCapsule(self.id, c) }
213 }
214 pub fn try_set_capsule(&mut self, c: &ffi::b2Capsule) -> ApiResult<()> {
215 self.check_valid()?;
216 unsafe { ffi::b2Shape_SetCapsule(self.id, c) }
217 Ok(())
218 }
219 pub fn set_polygon(&mut self, p: &ffi::b2Polygon) {
220 self.assert_valid();
221 unsafe { ffi::b2Shape_SetPolygon(self.id, p) }
222 }
223 pub fn try_set_polygon(&mut self, p: &ffi::b2Polygon) -> ApiResult<()> {
224 self.check_valid()?;
225 unsafe { ffi::b2Shape_SetPolygon(self.id, p) }
226 Ok(())
227 }
228
229 pub fn filter(&self) -> Filter {
230 self.assert_valid();
231 Filter::from(unsafe { ffi::b2Shape_GetFilter(self.id) })
232 }
233 pub fn try_filter(&self) -> ApiResult<Filter> {
234 self.check_valid()?;
235 Ok(Filter::from(unsafe { ffi::b2Shape_GetFilter(self.id) }))
236 }
237 pub fn set_filter(&mut self, f: Filter) {
238 self.assert_valid();
239 unsafe { ffi::b2Shape_SetFilter(self.id, f.into()) }
240 }
241 pub fn try_set_filter(&mut self, f: Filter) -> ApiResult<()> {
242 self.check_valid()?;
243 unsafe { ffi::b2Shape_SetFilter(self.id, f.into()) }
244 Ok(())
245 }
246
247 pub fn set_density(&mut self, density: f32, update_body_mass: bool) {
248 self.assert_valid();
249 unsafe { ffi::b2Shape_SetDensity(self.id, density, update_body_mass) }
250 }
251 pub fn try_set_density(&mut self, density: f32, update_body_mass: bool) -> ApiResult<()> {
252 self.check_valid()?;
253 unsafe { ffi::b2Shape_SetDensity(self.id, density, update_body_mass) }
254 Ok(())
255 }
256 pub fn density(&self) -> f32 {
257 self.assert_valid();
258 unsafe { ffi::b2Shape_GetDensity(self.id) }
259 }
260 pub fn try_density(&self) -> ApiResult<f32> {
261 self.check_valid()?;
262 Ok(unsafe { ffi::b2Shape_GetDensity(self.id) })
263 }
264
265 pub fn set_friction(&mut self, friction: f32) {
266 self.assert_valid();
267 unsafe { ffi::b2Shape_SetFriction(self.id, friction) }
268 }
269 pub fn try_set_friction(&mut self, friction: f32) -> ApiResult<()> {
270 self.check_valid()?;
271 unsafe { ffi::b2Shape_SetFriction(self.id, friction) }
272 Ok(())
273 }
274 pub fn friction(&self) -> f32 {
275 self.assert_valid();
276 unsafe { ffi::b2Shape_GetFriction(self.id) }
277 }
278 pub fn try_friction(&self) -> ApiResult<f32> {
279 self.check_valid()?;
280 Ok(unsafe { ffi::b2Shape_GetFriction(self.id) })
281 }
282
283 pub fn set_restitution(&mut self, restitution: f32) {
284 self.assert_valid();
285 unsafe { ffi::b2Shape_SetRestitution(self.id, restitution) }
286 }
287 pub fn try_set_restitution(&mut self, restitution: f32) -> ApiResult<()> {
288 self.check_valid()?;
289 unsafe { ffi::b2Shape_SetRestitution(self.id, restitution) }
290 Ok(())
291 }
292 pub fn restitution(&self) -> f32 {
293 self.assert_valid();
294 unsafe { ffi::b2Shape_GetRestitution(self.id) }
295 }
296 pub fn try_restitution(&self) -> ApiResult<f32> {
297 self.check_valid()?;
298 Ok(unsafe { ffi::b2Shape_GetRestitution(self.id) })
299 }
300
301 pub fn set_user_material(&mut self, material: u64) {
302 self.assert_valid();
303 unsafe { ffi::b2Shape_SetUserMaterial(self.id, material) }
304 }
305 pub fn try_set_user_material(&mut self, material: u64) -> ApiResult<()> {
306 self.check_valid()?;
307 unsafe { ffi::b2Shape_SetUserMaterial(self.id, material) }
308 Ok(())
309 }
310 pub fn user_material(&self) -> u64 {
311 self.assert_valid();
312 unsafe { ffi::b2Shape_GetUserMaterial(self.id) }
313 }
314 pub fn try_user_material(&self) -> ApiResult<u64> {
315 self.check_valid()?;
316 Ok(unsafe { ffi::b2Shape_GetUserMaterial(self.id) })
317 }
318
319 pub fn set_surface_material(&mut self, material: &SurfaceMaterial) {
320 self.assert_valid();
321 unsafe { ffi::b2Shape_SetSurfaceMaterial(self.id, &material.0) }
322 }
323 pub fn try_set_surface_material(&mut self, material: &SurfaceMaterial) -> ApiResult<()> {
324 self.check_valid()?;
325 unsafe { ffi::b2Shape_SetSurfaceMaterial(self.id, &material.0) }
326 Ok(())
327 }
328 pub fn surface_material(&self) -> SurfaceMaterial {
329 self.assert_valid();
330 SurfaceMaterial(unsafe { ffi::b2Shape_GetSurfaceMaterial(self.id) })
331 }
332 pub fn try_surface_material(&self) -> ApiResult<SurfaceMaterial> {
333 self.check_valid()?;
334 Ok(SurfaceMaterial(unsafe {
335 ffi::b2Shape_GetSurfaceMaterial(self.id)
336 }))
337 }
338
339 pub fn contact_data(&self) -> Vec<ffi::b2ContactData> {
340 self.assert_valid();
341 let cap = unsafe { ffi::b2Shape_GetContactCapacity(self.id) }.max(0) as usize;
342 if cap == 0 {
343 return Vec::new();
344 }
345 let mut vec: Vec<ffi::b2ContactData> = Vec::with_capacity(cap);
346 let wrote = unsafe { ffi::b2Shape_GetContactData(self.id, vec.as_mut_ptr(), cap as i32) }
347 .max(0) as usize;
348 unsafe { vec.set_len(wrote.min(cap)) };
349 vec
350 }
351
352 pub fn try_contact_data(&self) -> ApiResult<Vec<ffi::b2ContactData>> {
353 self.check_valid()?;
354 let cap = unsafe { ffi::b2Shape_GetContactCapacity(self.id) }.max(0) as usize;
355 if cap == 0 {
356 return Ok(Vec::new());
357 }
358 let mut vec: Vec<ffi::b2ContactData> = Vec::with_capacity(cap);
359 let wrote = unsafe { ffi::b2Shape_GetContactData(self.id, vec.as_mut_ptr(), cap as i32) }
360 .max(0) as usize;
361 unsafe { vec.set_len(wrote.min(cap)) };
362 Ok(vec)
363 }
364
365 pub fn sensor_capacity(&self) -> i32 {
367 self.assert_valid();
368 unsafe { ffi::b2Shape_GetSensorCapacity(self.id) }
369 }
370
371 pub fn try_sensor_capacity(&self) -> ApiResult<i32> {
372 self.check_valid()?;
373 Ok(unsafe { ffi::b2Shape_GetSensorCapacity(self.id) })
374 }
375
376 pub fn sensor_overlaps(&self) -> Vec<ShapeId> {
377 self.assert_valid();
378 let cap = self.sensor_capacity();
379 if cap <= 0 {
380 return Vec::new();
381 }
382 let mut ids: Vec<ShapeId> = Vec::with_capacity(cap as usize);
383 let wrote =
384 unsafe { ffi::b2Shape_GetSensorData(self.id, ids.as_mut_ptr(), cap) }.max(0) as usize;
385 unsafe { ids.set_len(wrote.min(cap as usize)) };
386 ids
387 }
388
389 pub fn try_sensor_overlaps(&self) -> ApiResult<Vec<ShapeId>> {
390 self.check_valid()?;
391 let cap = unsafe { ffi::b2Shape_GetSensorCapacity(self.id) };
392 if cap <= 0 {
393 return Ok(Vec::new());
394 }
395 let mut ids: Vec<ShapeId> = Vec::with_capacity(cap as usize);
396 let wrote =
397 unsafe { ffi::b2Shape_GetSensorData(self.id, ids.as_mut_ptr(), cap) }.max(0) as usize;
398 unsafe { ids.set_len(wrote.min(cap as usize)) };
399 Ok(ids)
400 }
401
402 pub fn sensor_overlaps_valid(&self) -> Vec<ShapeId> {
403 self.sensor_overlaps()
404 .into_iter()
405 .filter(|&sid| unsafe { ffi::b2Shape_IsValid(sid) })
406 .collect()
407 }
408
409 pub unsafe fn set_user_data_ptr(&mut self, p: *mut c_void) {
418 self.assert_valid();
419 let _ = self.core.clear_shape_user_data(self.id);
420 unsafe { ffi::b2Shape_SetUserData(self.id, p) }
421 }
422 pub unsafe fn try_set_user_data_ptr(&mut self, p: *mut c_void) -> ApiResult<()> {
429 self.check_valid()?;
430 let _ = self.core.clear_shape_user_data(self.id);
431 unsafe { ffi::b2Shape_SetUserData(self.id, p) }
432 Ok(())
433 }
434 pub fn user_data_ptr(&self) -> *mut c_void {
435 self.assert_valid();
436 unsafe { ffi::b2Shape_GetUserData(self.id) }
437 }
438
439 pub fn try_user_data_ptr(&self) -> ApiResult<*mut c_void> {
440 self.check_valid()?;
441 Ok(unsafe { ffi::b2Shape_GetUserData(self.id) })
442 }
443
444 pub fn set_user_data<T: 'static>(&mut self, value: T) {
449 self.assert_valid();
450 let p = self.core.set_shape_user_data(self.id, value);
451 unsafe { ffi::b2Shape_SetUserData(self.id, p) };
452 }
453
454 pub fn try_set_user_data<T: 'static>(&mut self, value: T) -> ApiResult<()> {
455 self.check_valid()?;
456 let p = self.core.set_shape_user_data(self.id, value);
457 unsafe { ffi::b2Shape_SetUserData(self.id, p) };
458 Ok(())
459 }
460
461 pub fn clear_user_data(&mut self) -> bool {
463 self.assert_valid();
464 let had = self.core.clear_shape_user_data(self.id);
465 if had {
466 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
467 }
468 had
469 }
470
471 pub fn try_clear_user_data(&mut self) -> ApiResult<bool> {
472 self.check_valid()?;
473 let had = self.core.clear_shape_user_data(self.id);
474 if had {
475 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
476 }
477 Ok(had)
478 }
479
480 pub fn with_user_data<T: 'static, R>(&self, f: impl FnOnce(&T) -> R) -> Option<R> {
481 self.assert_valid();
482 self.core
483 .try_with_shape_user_data(self.id, f)
484 .expect("user data type mismatch")
485 }
486
487 pub fn try_with_user_data<T: 'static, R>(
488 &self,
489 f: impl FnOnce(&T) -> R,
490 ) -> ApiResult<Option<R>> {
491 self.check_valid()?;
492 self.core.try_with_shape_user_data(self.id, f)
493 }
494
495 pub fn with_user_data_mut<T: 'static, R>(&mut self, f: impl FnOnce(&mut T) -> R) -> Option<R> {
496 self.assert_valid();
497 self.core
498 .try_with_shape_user_data_mut(self.id, f)
499 .expect("user data type mismatch")
500 }
501
502 pub fn try_with_user_data_mut<T: 'static, R>(
503 &mut self,
504 f: impl FnOnce(&mut T) -> R,
505 ) -> ApiResult<Option<R>> {
506 self.check_valid()?;
507 self.core.try_with_shape_user_data_mut(self.id, f)
508 }
509
510 pub fn take_user_data<T: 'static>(&mut self) -> Option<T> {
511 self.assert_valid();
512 let v = self
513 .core
514 .take_shape_user_data::<T>(self.id)
515 .expect("user data type mismatch");
516 if v.is_some() {
517 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
518 }
519 v
520 }
521
522 pub fn try_take_user_data<T: 'static>(&mut self) -> ApiResult<Option<T>> {
523 self.check_valid()?;
524 let v = self.core.take_shape_user_data::<T>(self.id)?;
525 if v.is_some() {
526 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
527 }
528 Ok(v)
529 }
530
531 pub fn update_body_mass_on_drop(mut self, flag: bool) -> Self {
532 self.update_body_mass_on_drop = flag;
533 self
534 }
535
536 pub fn into_id(mut self) -> ShapeId {
538 self.destroy_on_drop = false;
539 self.id
540 }
541
542 pub fn destroy(mut self, update_body_mass: bool) {
544 if self.destroy_on_drop && unsafe { ffi::b2Shape_IsValid(self.id) } {
545 if crate::core::callback_state::in_callback() || self.core.events_buffers_are_borrowed()
546 {
547 self.core
548 .defer_destroy(crate::core::world_core::DeferredDestroy::Shape {
549 id: self.id,
550 update_body_mass,
551 });
552 } else {
553 unsafe { ffi::b2DestroyShape(self.id, update_body_mass) };
554 let _ = self.core.clear_shape_user_data(self.id);
555 #[cfg(feature = "serialize")]
556 self.core.remove_shape_flags(self.id);
557 }
558 }
559 self.destroy_on_drop = false;
560 }
561}
562
563impl Drop for OwnedShape {
564 fn drop(&mut self) {
565 let _ = self.core.id;
566 let prev = self
567 .core
568 .owned_shapes
569 .fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
570 debug_assert!(prev > 0, "owned shape counter underflow");
571 if self.destroy_on_drop && unsafe { ffi::b2Shape_IsValid(self.id) } {
572 if crate::core::callback_state::in_callback() || self.core.events_buffers_are_borrowed()
573 {
574 self.core
575 .defer_destroy(crate::core::world_core::DeferredDestroy::Shape {
576 id: self.id,
577 update_body_mass: self.update_body_mass_on_drop,
578 });
579 } else {
580 unsafe { ffi::b2DestroyShape(self.id, self.update_body_mass_on_drop) };
581 let _ = self.core.clear_shape_user_data(self.id);
582 #[cfg(feature = "serialize")]
583 self.core.remove_shape_flags(self.id);
584 }
585 }
586 }
587}
588
589impl<'w> Shape<'w> {
590 pub(crate) fn new(core: Arc<crate::core::world_core::WorldCore>, id: ShapeId) -> Self {
591 Self {
592 id,
593 core,
594 _world: PhantomData,
595 }
596 }
597
598 #[inline]
599 fn assert_valid(&self) {
600 crate::core::debug_checks::assert_shape_valid(self.id);
601 }
602
603 #[inline]
604 fn check_valid(&self) -> ApiResult<()> {
605 crate::core::debug_checks::check_shape_valid(self.id)
606 }
607
608 pub fn id(&self) -> ShapeId {
609 self.id
610 }
611
612 pub fn world_id(&self) -> ffi::b2WorldId {
613 self.assert_valid();
614 unsafe { ffi::b2Shape_GetWorld(self.id) }
615 }
616
617 pub fn try_world_id(&self) -> ApiResult<ffi::b2WorldId> {
618 self.check_valid()?;
619 Ok(unsafe { ffi::b2Shape_GetWorld(self.id) })
620 }
621
622 pub fn parent_chain_id(&self) -> Option<ChainId> {
623 self.assert_valid();
624 let cid = unsafe { ffi::b2Shape_GetParentChain(self.id) };
625 if unsafe { ffi::b2Chain_IsValid(cid) } {
626 Some(cid)
627 } else {
628 None
629 }
630 }
631
632 pub fn try_parent_chain_id(&self) -> ApiResult<Option<ChainId>> {
633 self.check_valid()?;
634 let cid = unsafe { ffi::b2Shape_GetParentChain(self.id) };
635 if unsafe { ffi::b2Chain_IsValid(cid) } {
636 Ok(Some(cid))
637 } else {
638 Ok(None)
639 }
640 }
641
642 pub fn is_valid(&self) -> bool {
643 crate::core::callback_state::assert_not_in_callback();
644 unsafe { ffi::b2Shape_IsValid(self.id) }
645 }
646
647 pub fn try_is_valid(&self) -> ApiResult<bool> {
648 crate::core::callback_state::check_not_in_callback()?;
649 Ok(unsafe { ffi::b2Shape_IsValid(self.id) })
650 }
651
652 pub fn shape_type(&self) -> ffi::b2ShapeType {
653 self.assert_valid();
654 unsafe { ffi::b2Shape_GetType(self.id) }
655 }
656
657 pub fn try_shape_type(&self) -> ApiResult<ffi::b2ShapeType> {
658 self.check_valid()?;
659 Ok(unsafe { ffi::b2Shape_GetType(self.id) })
660 }
661
662 pub fn body_id(&self) -> BodyId {
663 self.assert_valid();
664 unsafe { ffi::b2Shape_GetBody(self.id) }
665 }
666
667 pub fn try_body_id(&self) -> ApiResult<BodyId> {
668 self.check_valid()?;
669 Ok(unsafe { ffi::b2Shape_GetBody(self.id) })
670 }
671
672 pub fn circle(&self) -> ffi::b2Circle {
674 self.assert_valid();
675 unsafe { ffi::b2Shape_GetCircle(self.id) }
676 }
677 pub fn segment(&self) -> ffi::b2Segment {
678 self.assert_valid();
679 unsafe { ffi::b2Shape_GetSegment(self.id) }
680 }
681 pub fn capsule(&self) -> ffi::b2Capsule {
682 self.assert_valid();
683 unsafe { ffi::b2Shape_GetCapsule(self.id) }
684 }
685 pub fn polygon(&self) -> ffi::b2Polygon {
686 self.assert_valid();
687 unsafe { ffi::b2Shape_GetPolygon(self.id) }
688 }
689
690 pub fn closest_point<V: Into<Vec2>>(&self, target: V) -> Vec2 {
692 self.assert_valid();
693 let t: ffi::b2Vec2 = target.into().into();
694 Vec2::from(unsafe { ffi::b2Shape_GetClosestPoint(self.id, t) })
695 }
696
697 pub fn try_closest_point<V: Into<Vec2>>(&self, target: V) -> ApiResult<Vec2> {
698 self.check_valid()?;
699 let t: ffi::b2Vec2 = target.into().into();
700 Ok(Vec2::from(unsafe {
701 ffi::b2Shape_GetClosestPoint(self.id, t)
702 }))
703 }
704
705 pub fn apply_wind<V: Into<Vec2>>(&mut self, wind: V, drag: f32, lift: f32, wake: bool) {
707 self.assert_valid();
708 let w: ffi::b2Vec2 = wind.into().into();
709 unsafe { ffi::b2Shape_ApplyWind(self.id, w, drag, lift, wake) }
710 }
711
712 pub fn try_apply_wind<V: Into<Vec2>>(
713 &mut self,
714 wind: V,
715 drag: f32,
716 lift: f32,
717 wake: bool,
718 ) -> ApiResult<()> {
719 self.check_valid()?;
720 let w: ffi::b2Vec2 = wind.into().into();
721 unsafe { ffi::b2Shape_ApplyWind(self.id, w, drag, lift, wake) }
722 Ok(())
723 }
724
725 pub fn set_circle(&mut self, c: &ffi::b2Circle) {
727 self.assert_valid();
728 unsafe { ffi::b2Shape_SetCircle(self.id, c) }
729 }
730 pub fn try_set_circle(&mut self, c: &ffi::b2Circle) -> ApiResult<()> {
731 self.check_valid()?;
732 unsafe { ffi::b2Shape_SetCircle(self.id, c) }
733 Ok(())
734 }
735 pub fn set_segment(&mut self, s: &ffi::b2Segment) {
736 self.assert_valid();
737 unsafe { ffi::b2Shape_SetSegment(self.id, s) }
738 }
739 pub fn try_set_segment(&mut self, s: &ffi::b2Segment) -> ApiResult<()> {
740 self.check_valid()?;
741 unsafe { ffi::b2Shape_SetSegment(self.id, s) }
742 Ok(())
743 }
744 pub fn set_capsule(&mut self, c: &ffi::b2Capsule) {
745 self.assert_valid();
746 unsafe { ffi::b2Shape_SetCapsule(self.id, c) }
747 }
748 pub fn try_set_capsule(&mut self, c: &ffi::b2Capsule) -> ApiResult<()> {
749 self.check_valid()?;
750 unsafe { ffi::b2Shape_SetCapsule(self.id, c) }
751 Ok(())
752 }
753 pub fn set_polygon(&mut self, p: &ffi::b2Polygon) {
754 self.assert_valid();
755 unsafe { ffi::b2Shape_SetPolygon(self.id, p) }
756 }
757 pub fn try_set_polygon(&mut self, p: &ffi::b2Polygon) -> ApiResult<()> {
758 self.check_valid()?;
759 unsafe { ffi::b2Shape_SetPolygon(self.id, p) }
760 Ok(())
761 }
762
763 pub fn filter(&self) -> Filter {
764 self.assert_valid();
765 Filter::from(unsafe { ffi::b2Shape_GetFilter(self.id) })
766 }
767 pub fn try_filter(&self) -> ApiResult<Filter> {
768 self.check_valid()?;
769 Ok(Filter::from(unsafe { ffi::b2Shape_GetFilter(self.id) }))
770 }
771 pub fn set_filter(&mut self, f: Filter) {
772 self.assert_valid();
773 unsafe { ffi::b2Shape_SetFilter(self.id, f.into()) }
774 }
775 pub fn try_set_filter(&mut self, f: Filter) -> ApiResult<()> {
776 self.check_valid()?;
777 unsafe { ffi::b2Shape_SetFilter(self.id, f.into()) }
778 Ok(())
779 }
780
781 pub fn is_sensor(&self) -> bool {
783 self.assert_valid();
784 unsafe { ffi::b2Shape_IsSensor(self.id) }
785 }
786 pub fn try_is_sensor(&self) -> ApiResult<bool> {
787 self.check_valid()?;
788 Ok(unsafe { ffi::b2Shape_IsSensor(self.id) })
789 }
790 pub fn set_density(&mut self, density: f32, update_body_mass: bool) {
791 self.assert_valid();
792 unsafe { ffi::b2Shape_SetDensity(self.id, density, update_body_mass) }
793 }
794 pub fn try_set_density(&mut self, density: f32, update_body_mass: bool) -> ApiResult<()> {
795 self.check_valid()?;
796 unsafe { ffi::b2Shape_SetDensity(self.id, density, update_body_mass) }
797 Ok(())
798 }
799 pub fn density(&self) -> f32 {
800 self.assert_valid();
801 unsafe { ffi::b2Shape_GetDensity(self.id) }
802 }
803 pub fn try_density(&self) -> ApiResult<f32> {
804 self.check_valid()?;
805 Ok(unsafe { ffi::b2Shape_GetDensity(self.id) })
806 }
807 pub fn set_friction(&mut self, friction: f32) {
808 self.assert_valid();
809 unsafe { ffi::b2Shape_SetFriction(self.id, friction) }
810 }
811 pub fn try_set_friction(&mut self, friction: f32) -> ApiResult<()> {
812 self.check_valid()?;
813 unsafe { ffi::b2Shape_SetFriction(self.id, friction) }
814 Ok(())
815 }
816 pub fn friction(&self) -> f32 {
817 self.assert_valid();
818 unsafe { ffi::b2Shape_GetFriction(self.id) }
819 }
820 pub fn try_friction(&self) -> ApiResult<f32> {
821 self.check_valid()?;
822 Ok(unsafe { ffi::b2Shape_GetFriction(self.id) })
823 }
824 pub fn set_restitution(&mut self, restitution: f32) {
825 self.assert_valid();
826 unsafe { ffi::b2Shape_SetRestitution(self.id, restitution) }
827 }
828 pub fn try_set_restitution(&mut self, restitution: f32) -> ApiResult<()> {
829 self.check_valid()?;
830 unsafe { ffi::b2Shape_SetRestitution(self.id, restitution) }
831 Ok(())
832 }
833 pub fn restitution(&self) -> f32 {
834 self.assert_valid();
835 unsafe { ffi::b2Shape_GetRestitution(self.id) }
836 }
837 pub fn try_restitution(&self) -> ApiResult<f32> {
838 self.check_valid()?;
839 Ok(unsafe { ffi::b2Shape_GetRestitution(self.id) })
840 }
841 pub fn set_user_material(&mut self, material: u64) {
842 self.assert_valid();
843 unsafe { ffi::b2Shape_SetUserMaterial(self.id, material) }
844 }
845 pub fn try_set_user_material(&mut self, material: u64) -> ApiResult<()> {
846 self.check_valid()?;
847 unsafe { ffi::b2Shape_SetUserMaterial(self.id, material) }
848 Ok(())
849 }
850 pub fn user_material(&self) -> u64 {
851 self.assert_valid();
852 unsafe { ffi::b2Shape_GetUserMaterial(self.id) }
853 }
854 pub fn try_user_material(&self) -> ApiResult<u64> {
855 self.check_valid()?;
856 Ok(unsafe { ffi::b2Shape_GetUserMaterial(self.id) })
857 }
858 pub fn set_surface_material(&mut self, material: &SurfaceMaterial) {
859 self.assert_valid();
860 unsafe { ffi::b2Shape_SetSurfaceMaterial(self.id, &material.0) }
861 }
862 pub fn try_set_surface_material(&mut self, material: &SurfaceMaterial) -> ApiResult<()> {
863 self.check_valid()?;
864 unsafe { ffi::b2Shape_SetSurfaceMaterial(self.id, &material.0) }
865 Ok(())
866 }
867 pub fn surface_material(&self) -> SurfaceMaterial {
868 self.assert_valid();
869 SurfaceMaterial(unsafe { ffi::b2Shape_GetSurfaceMaterial(self.id) })
870 }
871 pub fn try_surface_material(&self) -> ApiResult<SurfaceMaterial> {
872 self.check_valid()?;
873 Ok(SurfaceMaterial(unsafe {
874 ffi::b2Shape_GetSurfaceMaterial(self.id)
875 }))
876 }
877
878 pub unsafe fn set_user_data_ptr(&mut self, p: *mut core::ffi::c_void) {
888 self.assert_valid();
889 let _ = self.core.clear_shape_user_data(self.id);
890 unsafe { ffi::b2Shape_SetUserData(self.id, p) }
891 }
892 pub unsafe fn try_set_user_data_ptr(&mut self, p: *mut core::ffi::c_void) -> ApiResult<()> {
899 self.check_valid()?;
900 let _ = self.core.clear_shape_user_data(self.id);
901 unsafe { ffi::b2Shape_SetUserData(self.id, p) }
902 Ok(())
903 }
904 pub fn user_data_ptr(&self) -> *mut core::ffi::c_void {
905 self.assert_valid();
906 unsafe { ffi::b2Shape_GetUserData(self.id) }
907 }
908
909 pub fn try_user_data_ptr(&self) -> ApiResult<*mut core::ffi::c_void> {
910 self.check_valid()?;
911 Ok(unsafe { ffi::b2Shape_GetUserData(self.id) })
912 }
913
914 pub fn set_user_data<T: 'static>(&mut self, value: T) {
919 self.assert_valid();
920 let p = self.core.set_shape_user_data(self.id, value);
921 unsafe { ffi::b2Shape_SetUserData(self.id, p) };
922 }
923
924 pub fn try_set_user_data<T: 'static>(&mut self, value: T) -> ApiResult<()> {
925 self.check_valid()?;
926 let p = self.core.set_shape_user_data(self.id, value);
927 unsafe { ffi::b2Shape_SetUserData(self.id, p) };
928 Ok(())
929 }
930
931 pub fn clear_user_data(&mut self) -> bool {
933 self.assert_valid();
934 let had = self.core.clear_shape_user_data(self.id);
935 if had {
936 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
937 }
938 had
939 }
940
941 pub fn try_clear_user_data(&mut self) -> ApiResult<bool> {
942 self.check_valid()?;
943 let had = self.core.clear_shape_user_data(self.id);
944 if had {
945 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
946 }
947 Ok(had)
948 }
949
950 pub fn with_user_data<T: 'static, R>(&self, f: impl FnOnce(&T) -> R) -> Option<R> {
951 self.assert_valid();
952 self.core
953 .try_with_shape_user_data(self.id, f)
954 .expect("user data type mismatch")
955 }
956
957 pub fn try_with_user_data<T: 'static, R>(
958 &self,
959 f: impl FnOnce(&T) -> R,
960 ) -> ApiResult<Option<R>> {
961 self.check_valid()?;
962 self.core.try_with_shape_user_data(self.id, f)
963 }
964
965 pub fn with_user_data_mut<T: 'static, R>(&mut self, f: impl FnOnce(&mut T) -> R) -> Option<R> {
966 self.assert_valid();
967 self.core
968 .try_with_shape_user_data_mut(self.id, f)
969 .expect("user data type mismatch")
970 }
971
972 pub fn try_with_user_data_mut<T: 'static, R>(
973 &mut self,
974 f: impl FnOnce(&mut T) -> R,
975 ) -> ApiResult<Option<R>> {
976 self.check_valid()?;
977 self.core.try_with_shape_user_data_mut(self.id, f)
978 }
979
980 pub fn take_user_data<T: 'static>(&mut self) -> Option<T> {
981 self.assert_valid();
982 let v = self
983 .core
984 .take_shape_user_data::<T>(self.id)
985 .expect("user data type mismatch");
986 if v.is_some() {
987 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
988 }
989 v
990 }
991
992 pub fn try_take_user_data<T: 'static>(&mut self) -> ApiResult<Option<T>> {
993 self.check_valid()?;
994 let v = self.core.take_shape_user_data::<T>(self.id)?;
995 if v.is_some() {
996 unsafe { ffi::b2Shape_SetUserData(self.id, core::ptr::null_mut()) };
997 }
998 Ok(v)
999 }
1000
1001 pub fn contact_data(&self) -> Vec<ffi::b2ContactData> {
1002 self.assert_valid();
1003 let cap = unsafe { ffi::b2Shape_GetContactCapacity(self.id) }.max(0) as usize;
1004 if cap == 0 {
1005 return Vec::new();
1006 }
1007 let mut vec: Vec<ffi::b2ContactData> = Vec::with_capacity(cap);
1008 let wrote = unsafe { ffi::b2Shape_GetContactData(self.id, vec.as_mut_ptr(), cap as i32) }
1009 .max(0) as usize;
1010 unsafe { vec.set_len(wrote.min(cap)) };
1011 vec
1012 }
1013
1014 pub fn try_contact_data(&self) -> ApiResult<Vec<ffi::b2ContactData>> {
1015 self.check_valid()?;
1016 let cap = unsafe { ffi::b2Shape_GetContactCapacity(self.id) }.max(0) as usize;
1017 if cap == 0 {
1018 return Ok(Vec::new());
1019 }
1020 let mut vec: Vec<ffi::b2ContactData> = Vec::with_capacity(cap);
1021 let wrote = unsafe { ffi::b2Shape_GetContactData(self.id, vec.as_mut_ptr(), cap as i32) }
1022 .max(0) as usize;
1023 unsafe { vec.set_len(wrote.min(cap)) };
1024 Ok(vec)
1025 }
1026
1027 pub fn sensor_capacity(&self) -> i32 {
1030 self.assert_valid();
1031 unsafe { ffi::b2Shape_GetSensorCapacity(self.id) }
1032 }
1033
1034 pub fn try_sensor_capacity(&self) -> ApiResult<i32> {
1035 self.check_valid()?;
1036 Ok(unsafe { ffi::b2Shape_GetSensorCapacity(self.id) })
1037 }
1038
1039 pub fn sensor_overlaps(&self) -> Vec<ShapeId> {
1042 self.assert_valid();
1043 let cap = self.sensor_capacity();
1044 if cap <= 0 {
1045 return Vec::new();
1046 }
1047 let mut ids: Vec<ShapeId> = Vec::with_capacity(cap as usize);
1048 let wrote =
1049 unsafe { ffi::b2Shape_GetSensorData(self.id, ids.as_mut_ptr(), cap) }.max(0) as usize;
1050 unsafe { ids.set_len(wrote.min(cap as usize)) };
1051 ids
1052 }
1053
1054 pub fn try_sensor_overlaps(&self) -> ApiResult<Vec<ShapeId>> {
1055 self.check_valid()?;
1056 let cap = unsafe { ffi::b2Shape_GetSensorCapacity(self.id) };
1057 if cap <= 0 {
1058 return Ok(Vec::new());
1059 }
1060 let mut ids: Vec<ShapeId> = Vec::with_capacity(cap as usize);
1061 let wrote =
1062 unsafe { ffi::b2Shape_GetSensorData(self.id, ids.as_mut_ptr(), cap) }.max(0) as usize;
1063 unsafe { ids.set_len(wrote.min(cap as usize)) };
1064 Ok(ids)
1065 }
1066
1067 pub fn sensor_overlaps_valid(&self) -> Vec<ShapeId> {
1069 self.sensor_overlaps()
1070 .into_iter()
1071 .filter(|&sid| unsafe { ffi::b2Shape_IsValid(sid) })
1072 .collect()
1073 }
1074
1075 pub fn destroy(self, update_body_mass: bool) {
1079 crate::core::callback_state::assert_not_in_callback();
1080 if unsafe { ffi::b2Shape_IsValid(self.id) } {
1081 unsafe { ffi::b2DestroyShape(self.id, update_body_mass) };
1082 let _ = self.core.clear_shape_user_data(self.id);
1083 #[cfg(feature = "serialize")]
1084 self.core.remove_shape_flags(self.id);
1085 }
1086 }
1087
1088 pub fn try_destroy(self, update_body_mass: bool) -> ApiResult<()> {
1089 self.check_valid()?;
1090 if unsafe { ffi::b2Shape_IsValid(self.id) } {
1091 unsafe { ffi::b2DestroyShape(self.id, update_body_mass) };
1092 let _ = self.core.clear_shape_user_data(self.id);
1093 #[cfg(feature = "serialize")]
1094 self.core.remove_shape_flags(self.id);
1095 }
1096 Ok(())
1097 }
1098}
1099
1100#[derive(Clone, Debug)]
1102pub struct SurfaceMaterial(pub(crate) ffi::b2SurfaceMaterial);
1103
1104impl Default for SurfaceMaterial {
1105 fn default() -> Self {
1106 Self(unsafe { ffi::b2DefaultSurfaceMaterial() })
1107 }
1108}
1109
1110impl SurfaceMaterial {
1111 pub fn friction(mut self, v: f32) -> Self {
1112 self.0.friction = v;
1113 self
1114 }
1115 pub fn restitution(mut self, v: f32) -> Self {
1116 self.0.restitution = v;
1117 self
1118 }
1119 pub fn rolling_resistance(mut self, v: f32) -> Self {
1120 self.0.rollingResistance = v;
1121 self
1122 }
1123 pub fn tangent_speed(mut self, v: f32) -> Self {
1124 self.0.tangentSpeed = v;
1125 self
1126 }
1127 pub fn user_material_id(mut self, v: u64) -> Self {
1128 self.0.userMaterialId = v;
1129 self
1130 }
1131 pub fn custom_color(mut self, rgba: u32) -> Self {
1132 self.0.customColor = rgba;
1133 self
1134 }
1135}
1136
1137#[doc(alias = "shape_def")]
1139#[doc(alias = "shapedef")]
1140#[derive(Clone, Debug)]
1141pub struct ShapeDef(pub(crate) ffi::b2ShapeDef);
1142
1143impl Default for ShapeDef {
1144 fn default() -> Self {
1145 Self(unsafe { ffi::b2DefaultShapeDef() })
1146 }
1147}
1148
1149impl ShapeDef {
1150 pub fn builder() -> ShapeDefBuilder {
1151 ShapeDefBuilder {
1152 def: Self::default(),
1153 }
1154 }
1155}
1156
1157#[doc(alias = "shape_builder")]
1158#[doc(alias = "shapebuilder")]
1159#[derive(Clone, Debug)]
1160pub struct ShapeDefBuilder {
1161 def: ShapeDef,
1162}
1163
1164impl ShapeDefBuilder {
1165 pub fn material(mut self, mat: SurfaceMaterial) -> Self {
1167 self.def.0.material = mat.0;
1168 self
1169 }
1170 pub fn density(mut self, v: f32) -> Self {
1172 self.def.0.density = v;
1173 self
1174 }
1175 pub fn filter(mut self, f: ffi::b2Filter) -> Self {
1177 self.def.0.filter = f;
1178 self
1179 }
1180 pub fn filter_ex(mut self, f: Filter) -> Self {
1182 self.def.0.filter = f.into();
1183 self
1184 }
1185 pub fn enable_custom_filtering(mut self, flag: bool) -> Self {
1190 self.def.0.enableCustomFiltering = flag;
1191 self
1192 }
1193 pub fn sensor(mut self, flag: bool) -> Self {
1195 self.def.0.isSensor = flag;
1196 self
1197 }
1198 pub fn enable_sensor_events(mut self, flag: bool) -> Self {
1200 self.def.0.enableSensorEvents = flag;
1201 self
1202 }
1203 pub fn enable_contact_events(mut self, flag: bool) -> Self {
1205 self.def.0.enableContactEvents = flag;
1206 self
1207 }
1208 pub fn enable_hit_events(mut self, flag: bool) -> Self {
1210 self.def.0.enableHitEvents = flag;
1211 self
1212 }
1213 pub fn enable_pre_solve_events(mut self, flag: bool) -> Self {
1218 self.def.0.enablePreSolveEvents = flag;
1219 self
1220 }
1221 pub fn invoke_contact_creation(mut self, flag: bool) -> Self {
1223 self.def.0.invokeContactCreation = flag;
1224 self
1225 }
1226 pub fn update_body_mass(mut self, flag: bool) -> Self {
1228 self.def.0.updateBodyMass = flag;
1229 self
1230 }
1231 #[must_use]
1232 pub fn build(self) -> ShapeDef {
1233 self.def
1234 }
1235}
1236
1237#[cfg(feature = "serde")]
1239impl serde::Serialize for SurfaceMaterial {
1240 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1241 where
1242 S: serde::Serializer,
1243 {
1244 #[derive(serde::Serialize)]
1245 struct Repr {
1246 friction: f32,
1247 restitution: f32,
1248 rolling_resistance: f32,
1249 tangent_speed: f32,
1250 user_material_id: u64,
1251 custom_color: u32,
1252 }
1253 let r = Repr {
1254 friction: self.0.friction,
1255 restitution: self.0.restitution,
1256 rolling_resistance: self.0.rollingResistance,
1257 tangent_speed: self.0.tangentSpeed,
1258 user_material_id: self.0.userMaterialId,
1259 custom_color: self.0.customColor,
1260 };
1261 r.serialize(serializer)
1262 }
1263}
1264
1265#[cfg(feature = "serde")]
1266impl<'de> serde::Deserialize<'de> for SurfaceMaterial {
1267 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1268 where
1269 D: serde::Deserializer<'de>,
1270 {
1271 #[derive(serde::Deserialize)]
1272 struct Repr {
1273 #[serde(default)]
1274 friction: f32,
1275 #[serde(default)]
1276 restitution: f32,
1277 #[serde(default)]
1278 rolling_resistance: f32,
1279 #[serde(default)]
1280 tangent_speed: f32,
1281 #[serde(default)]
1282 user_material_id: u64,
1283 #[serde(default)]
1284 custom_color: u32,
1285 }
1286 let r = Repr::deserialize(deserializer)?;
1287 let mut sm = SurfaceMaterial::default();
1288 sm = sm
1289 .friction(r.friction)
1290 .restitution(r.restitution)
1291 .rolling_resistance(r.rolling_resistance)
1292 .tangent_speed(r.tangent_speed)
1293 .user_material_id(r.user_material_id)
1294 .custom_color(r.custom_color);
1295 Ok(sm)
1296 }
1297}
1298
1299#[cfg(feature = "serde")]
1300impl serde::Serialize for ShapeDef {
1301 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1302 where
1303 S: serde::Serializer,
1304 {
1305 #[derive(serde::Serialize)]
1306 struct Repr {
1307 material: SurfaceMaterial,
1308 density: f32,
1309 filter: Filter,
1310 enable_custom_filtering: bool,
1311 is_sensor: bool,
1312 enable_sensor_events: bool,
1313 enable_contact_events: bool,
1314 enable_hit_events: bool,
1315 enable_pre_solve_events: bool,
1316 invoke_contact_creation: bool,
1317 update_body_mass: bool,
1318 }
1319 let r = Repr {
1320 material: SurfaceMaterial(self.0.material),
1321 density: self.0.density,
1322 filter: Filter::from(self.0.filter),
1323 enable_custom_filtering: self.0.enableCustomFiltering,
1324 is_sensor: self.0.isSensor,
1325 enable_sensor_events: self.0.enableSensorEvents,
1326 enable_contact_events: self.0.enableContactEvents,
1327 enable_hit_events: self.0.enableHitEvents,
1328 enable_pre_solve_events: self.0.enablePreSolveEvents,
1329 invoke_contact_creation: self.0.invokeContactCreation,
1330 update_body_mass: self.0.updateBodyMass,
1331 };
1332 r.serialize(serializer)
1333 }
1334}
1335
1336#[cfg(feature = "serde")]
1337impl<'de> serde::Deserialize<'de> for ShapeDef {
1338 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1339 where
1340 D: serde::Deserializer<'de>,
1341 {
1342 #[derive(serde::Deserialize)]
1343 struct Repr {
1344 #[serde(default)]
1345 material: Option<SurfaceMaterial>,
1346 #[serde(default)]
1347 density: f32,
1348 #[serde(default)]
1349 filter: Option<Filter>,
1350 #[serde(default)]
1351 enable_custom_filtering: bool,
1352 #[serde(default)]
1353 is_sensor: bool,
1354 #[serde(default)]
1355 enable_sensor_events: bool,
1356 #[serde(default)]
1357 enable_contact_events: bool,
1358 #[serde(default)]
1359 enable_hit_events: bool,
1360 #[serde(default)]
1361 enable_pre_solve_events: bool,
1362 #[serde(default)]
1363 invoke_contact_creation: bool,
1364 #[serde(default)]
1365 update_body_mass: bool,
1366 }
1367 let r = Repr::deserialize(deserializer)?;
1368 let mut b = ShapeDef::builder();
1369 if let Some(mat) = r.material {
1370 b = b.material(mat);
1371 }
1372 if let Some(f) = r.filter {
1373 b = b.filter_ex(f);
1374 }
1375 b = b
1376 .density(r.density)
1377 .enable_custom_filtering(r.enable_custom_filtering)
1378 .sensor(r.is_sensor)
1379 .enable_sensor_events(r.enable_sensor_events)
1380 .enable_contact_events(r.enable_contact_events)
1381 .enable_hit_events(r.enable_hit_events)
1382 .enable_pre_solve_events(r.enable_pre_solve_events)
1383 .invoke_contact_creation(r.invoke_contact_creation)
1384 .update_body_mass(r.update_body_mass);
1385 Ok(b.build())
1386 }
1387}
1388
1389#[inline]
1391pub fn circle<V: Into<crate::types::Vec2>>(center: V, radius: f32) -> ffi::b2Circle {
1392 ffi::b2Circle {
1393 center: ffi::b2Vec2::from(center.into()),
1394 radius,
1395 }
1396}
1397
1398#[inline]
1400pub fn segment<V: Into<crate::types::Vec2>>(p1: V, p2: V) -> ffi::b2Segment {
1401 ffi::b2Segment {
1402 point1: ffi::b2Vec2::from(p1.into()),
1403 point2: ffi::b2Vec2::from(p2.into()),
1404 }
1405}
1406
1407pub use helpers::{box_polygon, capsule, polygon_from_points};
1409
1410impl<'w> Body<'w> {
1414 pub fn create_circle_shape(&mut self, def: &ShapeDef, c: &ffi::b2Circle) -> Shape<'w> {
1415 crate::core::debug_checks::assert_body_valid(self.id);
1416 let id = unsafe { ffi::b2CreateCircleShape(self.id, &def.0, c) };
1417 #[cfg(feature = "serialize")]
1418 self.core.record_shape_flags(id, &def.0);
1419 Shape::new(Arc::clone(&self.core), id)
1420 }
1421 pub fn create_segment_shape(&mut self, def: &ShapeDef, s: &ffi::b2Segment) -> Shape<'w> {
1422 crate::core::debug_checks::assert_body_valid(self.id);
1423 let id = unsafe { ffi::b2CreateSegmentShape(self.id, &def.0, s) };
1424 #[cfg(feature = "serialize")]
1425 self.core.record_shape_flags(id, &def.0);
1426 Shape::new(Arc::clone(&self.core), id)
1427 }
1428 pub fn create_capsule_shape(&mut self, def: &ShapeDef, c: &ffi::b2Capsule) -> Shape<'w> {
1429 crate::core::debug_checks::assert_body_valid(self.id);
1430 let id = unsafe { ffi::b2CreateCapsuleShape(self.id, &def.0, c) };
1431 #[cfg(feature = "serialize")]
1432 self.core.record_shape_flags(id, &def.0);
1433 Shape::new(Arc::clone(&self.core), id)
1434 }
1435 pub fn create_polygon_shape(&mut self, def: &ShapeDef, p: &ffi::b2Polygon) -> Shape<'w> {
1436 crate::core::debug_checks::assert_body_valid(self.id);
1437 let id = unsafe { ffi::b2CreatePolygonShape(self.id, &def.0, p) };
1438 #[cfg(feature = "serialize")]
1439 self.core.record_shape_flags(id, &def.0);
1440 Shape::new(Arc::clone(&self.core), id)
1441 }
1442
1443 pub fn create_box(&mut self, def: &ShapeDef, half_w: f32, half_h: f32) -> Shape<'w> {
1445 let poly = unsafe { ffi::b2MakeBox(half_w, half_h) };
1446 self.create_polygon_shape(def, &poly)
1447 }
1448 pub fn create_circle_simple(&mut self, def: &ShapeDef, radius: f32) -> Shape<'w> {
1449 let c = ffi::b2Circle {
1450 center: ffi::b2Vec2 { x: 0.0, y: 0.0 },
1451 radius,
1452 };
1453 self.create_circle_shape(def, &c)
1454 }
1455 pub fn create_segment_simple<V: Into<crate::types::Vec2>>(
1456 &mut self,
1457 def: &ShapeDef,
1458 p1: V,
1459 p2: V,
1460 ) -> Shape<'w> {
1461 let seg = ffi::b2Segment {
1462 point1: ffi::b2Vec2::from(p1.into()),
1463 point2: ffi::b2Vec2::from(p2.into()),
1464 };
1465 self.create_segment_shape(def, &seg)
1466 }
1467 pub fn create_capsule_simple<V: Into<crate::types::Vec2>>(
1468 &mut self,
1469 def: &ShapeDef,
1470 c1: V,
1471 c2: V,
1472 radius: f32,
1473 ) -> Shape<'w> {
1474 let cap = ffi::b2Capsule {
1475 center1: ffi::b2Vec2::from(c1.into()),
1476 center2: ffi::b2Vec2::from(c2.into()),
1477 radius,
1478 };
1479 self.create_capsule_shape(def, &cap)
1480 }
1481 pub fn create_polygon_from_points<I, P>(
1482 &mut self,
1483 def: &ShapeDef,
1484 points: I,
1485 radius: f32,
1486 ) -> Option<Shape<'w>>
1487 where
1488 I: IntoIterator<Item = P>,
1489 P: Into<crate::types::Vec2>,
1490 {
1491 let poly = crate::shapes::polygon_from_points(points, radius)?;
1492 Some(self.create_polygon_shape(def, &poly))
1493 }
1494}
1495