1use crate::types::{ShapeId, Vec2};
12use crate::world::{World, WorldHandle};
13use boxdd_sys::ffi;
14use std::any::Any;
15
16const MAX_PROXY_POINTS: usize = ffi::B2_MAX_POLYGON_VERTICES as usize;
17
18fn collect_proxy_points<I, P>(points: I) -> Vec<ffi::b2Vec2>
19where
20 I: IntoIterator<Item = P>,
21 P: Into<Vec2>,
22{
23 let mut out: Vec<ffi::b2Vec2> = Vec::with_capacity(MAX_PROXY_POINTS);
24 for p in points.into_iter().take(MAX_PROXY_POINTS) {
25 out.push(ffi::b2Vec2::from(p.into()));
26 }
27 out
28}
29
30fn overlap_aabb_impl(world: ffi::b2WorldId, aabb: Aabb, filter: QueryFilter) -> Vec<ShapeId> {
31 struct Ctx<'a> {
32 out: &'a mut Vec<ShapeId>,
33 panicked: &'a mut bool,
34 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
35 }
36 unsafe extern "C" fn cb(shape_id: ffi::b2ShapeId, ctx: *mut core::ffi::c_void) -> bool {
37 let ctx = unsafe { &mut *(ctx as *mut Ctx<'_>) };
38 if *ctx.panicked {
39 return false;
40 }
41 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
42 ctx.out.push(shape_id);
43 true
44 }));
45 match r {
46 Ok(v) => v,
47 Err(p) => {
48 *ctx.panicked = true;
49 *ctx.panic = Some(p);
50 false
51 }
52 }
53 }
54
55 let mut out: Vec<ShapeId> = Vec::new();
56 let mut panicked = false;
57 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
58 let mut ctx = Ctx {
59 out: &mut out,
60 panicked: &mut panicked,
61 panic: &mut panic,
62 };
63 unsafe {
64 let _ = ffi::b2World_OverlapAABB(
65 world,
66 aabb.into(),
67 filter.0,
68 Some(cb),
69 &mut ctx as *mut _ as *mut _,
70 );
71 }
72 if let Some(p) = panic.take() {
73 std::panic::resume_unwind(p);
74 }
75 out
76}
77
78fn cast_ray_closest_impl<VO: Into<Vec2>, VT: Into<Vec2>>(
79 world: ffi::b2WorldId,
80 origin: VO,
81 translation: VT,
82 filter: QueryFilter,
83) -> RayResult {
84 let o: ffi::b2Vec2 = origin.into().into();
85 let t: ffi::b2Vec2 = translation.into().into();
86 let raw = unsafe { ffi::b2World_CastRayClosest(world, o, t, filter.0) };
87 RayResult::from(raw)
88}
89
90fn cast_ray_all_impl<VO: Into<Vec2>, VT: Into<Vec2>>(
91 world: ffi::b2WorldId,
92 origin: VO,
93 translation: VT,
94 filter: QueryFilter,
95) -> Vec<RayResult> {
96 struct Ctx<'a> {
97 out: &'a mut Vec<RayResult>,
98 panicked: &'a mut bool,
99 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
100 }
101 #[allow(clippy::unnecessary_cast)]
102 unsafe extern "C" fn cb(
103 shape_id: ffi::b2ShapeId,
104 point: ffi::b2Vec2,
105 normal: ffi::b2Vec2,
106 fraction: f32,
107 ctx: *mut core::ffi::c_void,
108 ) -> f32 {
109 let ctx = unsafe { &mut *(ctx as *mut Ctx<'_>) };
110 if *ctx.panicked {
111 return 0.0;
112 }
113 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
114 ctx.out.push(RayResult {
115 shape_id,
116 point: point.into(),
117 normal: normal.into(),
118 fraction,
119 hit: true,
120 });
121 1.0f32
122 }));
123 match r {
124 Ok(v) => v,
125 Err(p) => {
126 *ctx.panicked = true;
127 *ctx.panic = Some(p);
128 0.0
129 }
130 }
131 }
132 let mut out: Vec<RayResult> = Vec::new();
133 let mut panicked = false;
134 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
135 let mut ctx = Ctx {
136 out: &mut out,
137 panicked: &mut panicked,
138 panic: &mut panic,
139 };
140 let o: ffi::b2Vec2 = origin.into().into();
141 let t: ffi::b2Vec2 = translation.into().into();
142 unsafe {
143 let _ = ffi::b2World_CastRay(
144 world,
145 o,
146 t,
147 filter.0,
148 Some(cb),
149 &mut ctx as *mut _ as *mut _,
150 );
151 }
152 if let Some(p) = panic.take() {
153 std::panic::resume_unwind(p);
154 }
155 out
156}
157
158fn overlap_polygon_points_impl<I, P>(
159 world: ffi::b2WorldId,
160 points: I,
161 radius: f32,
162 filter: QueryFilter,
163) -> Vec<ShapeId>
164where
165 I: IntoIterator<Item = P>,
166 P: Into<Vec2>,
167{
168 let pts: Vec<ffi::b2Vec2> = collect_proxy_points(points);
169 if pts.is_empty() {
170 return Vec::new();
171 }
172 let proxy = unsafe { ffi::b2MakeProxy(pts.as_ptr(), pts.len() as i32, radius) };
173 let mut out = Vec::new();
174 let mut panicked = false;
175 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
176 struct Ctx<'a> {
177 out: &'a mut Vec<ShapeId>,
178 panicked: &'a mut bool,
179 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
180 }
181 unsafe extern "C" fn cb(shape_id: ffi::b2ShapeId, ctx: *mut core::ffi::c_void) -> bool {
182 let ctx = unsafe { &mut *(ctx as *mut Ctx<'_>) };
183 if *ctx.panicked {
184 return false;
185 }
186 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
187 ctx.out.push(shape_id);
188 true
189 }));
190 match r {
191 Ok(v) => v,
192 Err(p) => {
193 *ctx.panicked = true;
194 *ctx.panic = Some(p);
195 false
196 }
197 }
198 }
199 let mut ctx = Ctx {
200 out: &mut out,
201 panicked: &mut panicked,
202 panic: &mut panic,
203 };
204 unsafe {
205 let _ = ffi::b2World_OverlapShape(
206 world,
207 &proxy,
208 filter.0,
209 Some(cb),
210 &mut ctx as *mut _ as *mut _,
211 );
212 }
213 if let Some(p) = panic.take() {
214 std::panic::resume_unwind(p);
215 }
216 out
217}
218
219fn cast_shape_points_impl<I, P, VT>(
220 world: ffi::b2WorldId,
221 points: I,
222 radius: f32,
223 translation: VT,
224 filter: QueryFilter,
225) -> Vec<RayResult>
226where
227 I: IntoIterator<Item = P>,
228 P: Into<Vec2>,
229 VT: Into<Vec2>,
230{
231 struct Ctx<'a> {
232 out: &'a mut Vec<RayResult>,
233 panicked: &'a mut bool,
234 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
235 }
236 #[allow(clippy::unnecessary_cast)]
237 unsafe extern "C" fn cb(
238 shape_id: ffi::b2ShapeId,
239 point: ffi::b2Vec2,
240 normal: ffi::b2Vec2,
241 fraction: f32,
242 ctx: *mut core::ffi::c_void,
243 ) -> f32 {
244 let ctx = unsafe { &mut *(ctx as *mut Ctx<'_>) };
245 if *ctx.panicked {
246 return 0.0;
247 }
248 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
249 ctx.out.push(RayResult {
250 shape_id,
251 point: point.into(),
252 normal: normal.into(),
253 fraction,
254 hit: true,
255 });
256 1.0f32
257 }));
258 match r {
259 Ok(v) => v,
260 Err(p) => {
261 *ctx.panicked = true;
262 *ctx.panic = Some(p);
263 0.0
264 }
265 }
266 }
267 let pts: Vec<ffi::b2Vec2> = collect_proxy_points(points);
268 if pts.is_empty() {
269 return Vec::new();
270 }
271 let proxy = unsafe { ffi::b2MakeProxy(pts.as_ptr(), pts.len() as i32, radius) };
272 let mut out: Vec<RayResult> = Vec::new();
273 let mut panicked = false;
274 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
275 let mut ctx = Ctx {
276 out: &mut out,
277 panicked: &mut panicked,
278 panic: &mut panic,
279 };
280 let t: ffi::b2Vec2 = translation.into().into();
281 unsafe {
282 let _ = ffi::b2World_CastShape(
283 world,
284 &proxy,
285 t,
286 filter.0,
287 Some(cb),
288 &mut ctx as *mut _ as *mut _,
289 );
290 }
291 if let Some(p) = panic.take() {
292 std::panic::resume_unwind(p);
293 }
294 out
295}
296
297fn cast_mover_impl<V1: Into<Vec2>, V2: Into<Vec2>, VT: Into<Vec2>>(
298 world: ffi::b2WorldId,
299 c1: V1,
300 c2: V2,
301 radius: f32,
302 translation: VT,
303 filter: QueryFilter,
304) -> f32 {
305 let cap = ffi::b2Capsule {
306 center1: c1.into().into(),
307 center2: c2.into().into(),
308 radius,
309 };
310 let t: ffi::b2Vec2 = translation.into().into();
311 unsafe { ffi::b2World_CastMover(world, &cap, t, filter.0) }
312}
313
314fn overlap_polygon_points_with_offset_impl<I, P, V, A>(
315 world: ffi::b2WorldId,
316 points: I,
317 radius: f32,
318 position: V,
319 angle_radians: A,
320 filter: QueryFilter,
321) -> Vec<ShapeId>
322where
323 I: IntoIterator<Item = P>,
324 P: Into<Vec2>,
325 V: Into<Vec2>,
326 A: Into<f32>,
327{
328 let pts: Vec<ffi::b2Vec2> = collect_proxy_points(points);
329 if pts.is_empty() {
330 return Vec::new();
331 }
332 let (s, c) = angle_radians.into().sin_cos();
333 let pos: ffi::b2Vec2 = position.into().into();
334 let proxy = unsafe {
335 ffi::b2MakeOffsetProxy(
336 pts.as_ptr(),
337 pts.len() as i32,
338 radius,
339 pos,
340 ffi::b2Rot { c, s },
341 )
342 };
343 let mut out = Vec::new();
344 let mut panicked = false;
345 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
346 struct Ctx<'a> {
347 out: &'a mut Vec<ShapeId>,
348 panicked: &'a mut bool,
349 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
350 }
351 unsafe extern "C" fn cb(shape_id: ffi::b2ShapeId, ctx: *mut core::ffi::c_void) -> bool {
352 let ctx = unsafe { &mut *(ctx as *mut Ctx<'_>) };
353 if *ctx.panicked {
354 return false;
355 }
356 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
357 ctx.out.push(shape_id);
358 true
359 }));
360 match r {
361 Ok(v) => v,
362 Err(p) => {
363 *ctx.panicked = true;
364 *ctx.panic = Some(p);
365 false
366 }
367 }
368 }
369 let mut ctx = Ctx {
370 out: &mut out,
371 panicked: &mut panicked,
372 panic: &mut panic,
373 };
374 unsafe {
375 let _ = ffi::b2World_OverlapShape(
376 world,
377 &proxy,
378 filter.0,
379 Some(cb),
380 &mut ctx as *mut _ as *mut _,
381 );
382 }
383 if let Some(p) = panic.take() {
384 std::panic::resume_unwind(p);
385 }
386 out
387}
388
389fn cast_shape_points_with_offset_impl<I, P, V, A, VT>(
390 world: ffi::b2WorldId,
391 points: I,
392 radius: f32,
393 position: V,
394 angle_radians: A,
395 translation: VT,
396 filter: QueryFilter,
397) -> Vec<RayResult>
398where
399 I: IntoIterator<Item = P>,
400 P: Into<Vec2>,
401 V: Into<Vec2>,
402 A: Into<f32>,
403 VT: Into<Vec2>,
404{
405 struct Ctx<'a> {
406 out: &'a mut Vec<RayResult>,
407 panicked: &'a mut bool,
408 panic: &'a mut Option<Box<dyn Any + Send + 'static>>,
409 }
410 #[allow(clippy::unnecessary_cast)]
411 unsafe extern "C" fn cb(
412 shape_id: ffi::b2ShapeId,
413 point: ffi::b2Vec2,
414 normal: ffi::b2Vec2,
415 fraction: f32,
416 ctx: *mut core::ffi::c_void,
417 ) -> f32 {
418 let ctx = unsafe { &mut *(ctx as *mut Ctx<'_>) };
419 if *ctx.panicked {
420 return 0.0;
421 }
422 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
423 ctx.out.push(RayResult {
424 shape_id,
425 point: point.into(),
426 normal: normal.into(),
427 fraction,
428 hit: true,
429 });
430 1.0f32
431 }));
432 match r {
433 Ok(v) => v,
434 Err(p) => {
435 *ctx.panicked = true;
436 *ctx.panic = Some(p);
437 0.0
438 }
439 }
440 }
441 let pts: Vec<ffi::b2Vec2> = collect_proxy_points(points);
442 if pts.is_empty() {
443 return Vec::new();
444 }
445 let (s, c) = angle_radians.into().sin_cos();
446 let pos: ffi::b2Vec2 = position.into().into();
447 let proxy = unsafe {
448 ffi::b2MakeOffsetProxy(
449 pts.as_ptr(),
450 pts.len() as i32,
451 radius,
452 pos,
453 ffi::b2Rot { c, s },
454 )
455 };
456 let mut out: Vec<RayResult> = Vec::new();
457 let mut panicked = false;
458 let mut panic: Option<Box<dyn Any + Send + 'static>> = None;
459 let mut ctx = Ctx {
460 out: &mut out,
461 panicked: &mut panicked,
462 panic: &mut panic,
463 };
464 let t: ffi::b2Vec2 = translation.into().into();
465 unsafe {
466 let _ = ffi::b2World_CastShape(
467 world,
468 &proxy,
469 t,
470 filter.0,
471 Some(cb),
472 &mut ctx as *mut _ as *mut _,
473 );
474 }
475 if let Some(p) = panic.take() {
476 std::panic::resume_unwind(p);
477 }
478 out
479}
480
481#[doc(alias = "aabb")]
483#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
484#[repr(C)]
485#[derive(Copy, Clone, Debug, PartialEq)]
486pub struct Aabb {
487 pub lower: Vec2,
488 pub upper: Vec2,
489}
490
491#[cfg(feature = "bytemuck")]
492unsafe impl bytemuck::Zeroable for Aabb {}
493#[cfg(feature = "bytemuck")]
494unsafe impl bytemuck::Pod for Aabb {}
495
496#[cfg(feature = "bytemuck")]
497const _: () = {
498 assert!(core::mem::size_of::<Aabb>() == 16);
499 assert!(core::mem::align_of::<Aabb>() == 4);
500};
501
502impl From<Aabb> for ffi::b2AABB {
503 fn from(a: Aabb) -> Self {
504 ffi::b2AABB {
505 lowerBound: a.lower.into(),
506 upperBound: a.upper.into(),
507 }
508 }
509}
510
511impl Aabb {
512 #[inline]
514 pub fn new<L: Into<Vec2>, U: Into<Vec2>>(lower: L, upper: U) -> Self {
515 Self {
516 lower: lower.into(),
517 upper: upper.into(),
518 }
519 }
520 #[inline]
522 pub fn from_center_half_extents<C: Into<Vec2>, H: Into<Vec2>>(center: C, half: H) -> Self {
523 let c = center.into();
524 let h = half.into();
525 Self {
526 lower: Vec2::new(c.x - h.x, c.y - h.y),
527 upper: Vec2::new(c.x + h.x, c.y + h.y),
528 }
529 }
530}
531
532#[cfg(feature = "mint")]
533impl From<Aabb> for (mint::Point2<f32>, mint::Point2<f32>) {
534 #[inline]
535 fn from(a: Aabb) -> Self {
536 (a.lower.into(), a.upper.into())
537 }
538}
539
540#[cfg(feature = "mint")]
541impl From<(mint::Point2<f32>, mint::Point2<f32>)> for Aabb {
542 #[inline]
543 fn from((lower, upper): (mint::Point2<f32>, mint::Point2<f32>)) -> Self {
544 Self::new(lower, upper)
545 }
546}
547
548#[cfg(feature = "mint")]
549impl From<Aabb> for (mint::Vector2<f32>, mint::Vector2<f32>) {
550 #[inline]
551 fn from(a: Aabb) -> Self {
552 (a.lower.into(), a.upper.into())
553 }
554}
555
556#[cfg(feature = "mint")]
557impl From<(mint::Vector2<f32>, mint::Vector2<f32>)> for Aabb {
558 #[inline]
559 fn from((lower, upper): (mint::Vector2<f32>, mint::Vector2<f32>)) -> Self {
560 Self::new(lower, upper)
561 }
562}
563
564#[cfg(feature = "glam")]
565impl From<Aabb> for (glam::Vec2, glam::Vec2) {
566 #[inline]
567 fn from(a: Aabb) -> Self {
568 (a.lower.into(), a.upper.into())
569 }
570}
571
572#[cfg(feature = "glam")]
573impl From<(glam::Vec2, glam::Vec2)> for Aabb {
574 #[inline]
575 fn from((lower, upper): (glam::Vec2, glam::Vec2)) -> Self {
576 Self {
577 lower: lower.into(),
578 upper: upper.into(),
579 }
580 }
581}
582
583#[cfg(feature = "cgmath")]
584impl From<Aabb> for (cgmath::Point2<f32>, cgmath::Point2<f32>) {
585 #[inline]
586 fn from(a: Aabb) -> Self {
587 (a.lower.into(), a.upper.into())
588 }
589}
590
591#[cfg(feature = "cgmath")]
592impl From<(cgmath::Point2<f32>, cgmath::Point2<f32>)> for Aabb {
593 #[inline]
594 fn from((lower, upper): (cgmath::Point2<f32>, cgmath::Point2<f32>)) -> Self {
595 Self::new(lower, upper)
596 }
597}
598
599#[cfg(feature = "cgmath")]
600impl From<Aabb> for (cgmath::Vector2<f32>, cgmath::Vector2<f32>) {
601 #[inline]
602 fn from(a: Aabb) -> Self {
603 (a.lower.into(), a.upper.into())
604 }
605}
606
607#[cfg(feature = "cgmath")]
608impl From<(cgmath::Vector2<f32>, cgmath::Vector2<f32>)> for Aabb {
609 #[inline]
610 fn from((lower, upper): (cgmath::Vector2<f32>, cgmath::Vector2<f32>)) -> Self {
611 Self::new(lower, upper)
612 }
613}
614
615#[cfg(feature = "nalgebra")]
616impl From<Aabb> for (nalgebra::Point2<f32>, nalgebra::Point2<f32>) {
617 #[inline]
618 fn from(a: Aabb) -> Self {
619 (a.lower.into(), a.upper.into())
620 }
621}
622
623#[cfg(feature = "nalgebra")]
624impl From<(nalgebra::Point2<f32>, nalgebra::Point2<f32>)> for Aabb {
625 #[inline]
626 fn from((lower, upper): (nalgebra::Point2<f32>, nalgebra::Point2<f32>)) -> Self {
627 Self::new(lower, upper)
628 }
629}
630
631#[cfg(feature = "nalgebra")]
632impl From<Aabb> for (nalgebra::Vector2<f32>, nalgebra::Vector2<f32>) {
633 #[inline]
634 fn from(a: Aabb) -> Self {
635 (a.lower.into(), a.upper.into())
636 }
637}
638
639#[cfg(feature = "nalgebra")]
640impl From<(nalgebra::Vector2<f32>, nalgebra::Vector2<f32>)> for Aabb {
641 #[inline]
642 fn from((lower, upper): (nalgebra::Vector2<f32>, nalgebra::Vector2<f32>)) -> Self {
643 Self::new(lower, upper)
644 }
645}
646
647#[doc(alias = "query_filter")]
649#[derive(Copy, Clone, Debug)]
650pub struct QueryFilter(pub(crate) ffi::b2QueryFilter);
651
652impl Default for QueryFilter {
653 fn default() -> Self {
654 Self(unsafe { ffi::b2DefaultQueryFilter() })
655 }
656}
657
658#[cfg(feature = "serde")]
659impl serde::Serialize for QueryFilter {
660 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
661 where
662 S: serde::Serializer,
663 {
664 #[derive(serde::Serialize)]
665 struct Repr {
666 category_bits: u64,
667 mask_bits: u64,
668 }
669 Repr {
670 category_bits: self.0.categoryBits,
671 mask_bits: self.0.maskBits,
672 }
673 .serialize(serializer)
674 }
675}
676
677#[cfg(feature = "serde")]
678impl<'de> serde::Deserialize<'de> for QueryFilter {
679 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
680 where
681 D: serde::Deserializer<'de>,
682 {
683 #[derive(serde::Deserialize)]
684 struct Repr {
685 category_bits: u64,
686 mask_bits: u64,
687 }
688 let r = Repr::deserialize(deserializer)?;
689 Ok(Self(ffi::b2QueryFilter {
690 categoryBits: r.category_bits,
691 maskBits: r.mask_bits,
692 }))
693 }
694}
695
696impl QueryFilter {
697 pub fn category_bits(&self) -> u64 {
698 self.0.categoryBits
699 }
700
701 pub fn mask_bits(&self) -> u64 {
702 self.0.maskBits
703 }
704
705 pub fn mask(mut self, bits: u64) -> Self {
706 self.0.maskBits = bits;
707 self
708 }
709 pub fn category(mut self, bits: u64) -> Self {
710 self.0.categoryBits = bits;
711 self
712 }
713}
714
715#[doc(alias = "ray_result")]
717#[derive(Copy, Clone, Debug)]
718pub struct RayResult {
719 pub shape_id: ShapeId,
720 pub point: Vec2,
721 pub normal: Vec2,
722 pub fraction: f32,
723 pub hit: bool,
724}
725
726impl From<ffi::b2RayResult> for RayResult {
727 fn from(r: ffi::b2RayResult) -> Self {
728 Self {
729 shape_id: r.shapeId,
730 point: r.point.into(),
731 normal: r.normal.into(),
732 fraction: r.fraction,
733 hit: r.hit,
734 }
735 }
736}
737
738impl World {
739 pub fn overlap_aabb(&self, aabb: Aabb, filter: QueryFilter) -> Vec<ShapeId> {
752 crate::core::callback_state::assert_not_in_callback();
753 overlap_aabb_impl(self.raw(), aabb, filter)
754 }
755
756 pub fn try_overlap_aabb(
757 &self,
758 aabb: Aabb,
759 filter: QueryFilter,
760 ) -> crate::error::ApiResult<Vec<ShapeId>> {
761 crate::core::callback_state::check_not_in_callback()?;
762 Ok(overlap_aabb_impl(self.raw(), aabb, filter))
763 }
764
765 pub fn cast_ray_closest<VO: Into<Vec2>, VT: Into<Vec2>>(
775 &self,
776 origin: VO,
777 translation: VT,
778 filter: QueryFilter,
779 ) -> RayResult {
780 crate::core::callback_state::assert_not_in_callback();
781 cast_ray_closest_impl(self.raw(), origin, translation, filter)
782 }
783
784 pub fn try_cast_ray_closest<VO: Into<Vec2>, VT: Into<Vec2>>(
785 &self,
786 origin: VO,
787 translation: VT,
788 filter: QueryFilter,
789 ) -> crate::error::ApiResult<RayResult> {
790 crate::core::callback_state::check_not_in_callback()?;
791 Ok(cast_ray_closest_impl(
792 self.raw(),
793 origin,
794 translation,
795 filter,
796 ))
797 }
798
799 pub fn cast_ray_all<VO: Into<Vec2>, VT: Into<Vec2>>(
809 &self,
810 origin: VO,
811 translation: VT,
812 filter: QueryFilter,
813 ) -> Vec<RayResult> {
814 crate::core::callback_state::assert_not_in_callback();
815 cast_ray_all_impl(self.raw(), origin, translation, filter)
816 }
817
818 pub fn try_cast_ray_all<VO: Into<Vec2>, VT: Into<Vec2>>(
819 &self,
820 origin: VO,
821 translation: VT,
822 filter: QueryFilter,
823 ) -> crate::error::ApiResult<Vec<RayResult>> {
824 crate::core::callback_state::check_not_in_callback()?;
825 Ok(cast_ray_all_impl(self.raw(), origin, translation, filter))
826 }
827
828 pub fn overlap_polygon_points<I, P>(
839 &self,
840 points: I,
841 radius: f32,
842 filter: QueryFilter,
843 ) -> Vec<ShapeId>
844 where
845 I: IntoIterator<Item = P>,
846 P: Into<Vec2>,
847 {
848 crate::core::callback_state::assert_not_in_callback();
849 overlap_polygon_points_impl(self.raw(), points, radius, filter)
850 }
851
852 pub fn try_overlap_polygon_points<I, P>(
853 &self,
854 points: I,
855 radius: f32,
856 filter: QueryFilter,
857 ) -> crate::error::ApiResult<Vec<ShapeId>>
858 where
859 I: IntoIterator<Item = P>,
860 P: Into<Vec2>,
861 {
862 crate::core::callback_state::check_not_in_callback()?;
863 Ok(overlap_polygon_points_impl(
864 self.raw(),
865 points,
866 radius,
867 filter,
868 ))
869 }
870
871 pub fn cast_shape_points<I, P, VT>(
882 &self,
883 points: I,
884 radius: f32,
885 translation: VT,
886 filter: QueryFilter,
887 ) -> Vec<RayResult>
888 where
889 I: IntoIterator<Item = P>,
890 P: Into<Vec2>,
891 VT: Into<Vec2>,
892 {
893 crate::core::callback_state::assert_not_in_callback();
894 cast_shape_points_impl(self.raw(), points, radius, translation, filter)
895 }
896
897 pub fn try_cast_shape_points<I, P, VT>(
898 &self,
899 points: I,
900 radius: f32,
901 translation: VT,
902 filter: QueryFilter,
903 ) -> crate::error::ApiResult<Vec<RayResult>>
904 where
905 I: IntoIterator<Item = P>,
906 P: Into<Vec2>,
907 VT: Into<Vec2>,
908 {
909 crate::core::callback_state::check_not_in_callback()?;
910 Ok(cast_shape_points_impl(
911 self.raw(),
912 points,
913 radius,
914 translation,
915 filter,
916 ))
917 }
918
919 pub fn cast_mover<V1: Into<Vec2>, V2: Into<Vec2>, VT: Into<Vec2>>(
921 &self,
922 c1: V1,
923 c2: V2,
924 radius: f32,
925 translation: VT,
926 filter: QueryFilter,
927 ) -> f32 {
928 crate::core::callback_state::assert_not_in_callback();
929 cast_mover_impl(self.raw(), c1, c2, radius, translation, filter)
930 }
931
932 pub fn try_cast_mover<V1: Into<Vec2>, V2: Into<Vec2>, VT: Into<Vec2>>(
933 &self,
934 c1: V1,
935 c2: V2,
936 radius: f32,
937 translation: VT,
938 filter: QueryFilter,
939 ) -> crate::error::ApiResult<f32> {
940 crate::core::callback_state::check_not_in_callback()?;
941 Ok(cast_mover_impl(
942 self.raw(),
943 c1,
944 c2,
945 radius,
946 translation,
947 filter,
948 ))
949 }
950
951 pub fn overlap_polygon_points_with_offset<I, P, V, A>(
962 &self,
963 points: I,
964 radius: f32,
965 position: V,
966 angle_radians: A,
967 filter: QueryFilter,
968 ) -> Vec<ShapeId>
969 where
970 I: IntoIterator<Item = P>,
971 P: Into<Vec2>,
972 V: Into<Vec2>,
973 A: Into<f32>,
974 {
975 crate::core::callback_state::assert_not_in_callback();
976 overlap_polygon_points_with_offset_impl(
977 self.raw(),
978 points,
979 radius,
980 position,
981 angle_radians,
982 filter,
983 )
984 }
985
986 pub fn try_overlap_polygon_points_with_offset<I, P, V, A>(
987 &self,
988 points: I,
989 radius: f32,
990 position: V,
991 angle_radians: A,
992 filter: QueryFilter,
993 ) -> crate::error::ApiResult<Vec<ShapeId>>
994 where
995 I: IntoIterator<Item = P>,
996 P: Into<Vec2>,
997 V: Into<Vec2>,
998 A: Into<f32>,
999 {
1000 crate::core::callback_state::check_not_in_callback()?;
1001 Ok(overlap_polygon_points_with_offset_impl(
1002 self.raw(),
1003 points,
1004 radius,
1005 position,
1006 angle_radians,
1007 filter,
1008 ))
1009 }
1010
1011 pub fn cast_shape_points_with_offset<I, P, V, A, VT>(
1022 &self,
1023 points: I,
1024 radius: f32,
1025 position: V,
1026 angle_radians: A,
1027 translation: VT,
1028 filter: QueryFilter,
1029 ) -> Vec<RayResult>
1030 where
1031 I: IntoIterator<Item = P>,
1032 P: Into<Vec2>,
1033 V: Into<Vec2>,
1034 A: Into<f32>,
1035 VT: Into<Vec2>,
1036 {
1037 crate::core::callback_state::assert_not_in_callback();
1038 cast_shape_points_with_offset_impl(
1039 self.raw(),
1040 points,
1041 radius,
1042 position,
1043 angle_radians,
1044 translation,
1045 filter,
1046 )
1047 }
1048
1049 pub fn try_cast_shape_points_with_offset<I, P, V, A, VT>(
1050 &self,
1051 points: I,
1052 radius: f32,
1053 position: V,
1054 angle_radians: A,
1055 translation: VT,
1056 filter: QueryFilter,
1057 ) -> crate::error::ApiResult<Vec<RayResult>>
1058 where
1059 I: IntoIterator<Item = P>,
1060 P: Into<Vec2>,
1061 V: Into<Vec2>,
1062 A: Into<f32>,
1063 VT: Into<Vec2>,
1064 {
1065 crate::core::callback_state::check_not_in_callback()?;
1066 Ok(cast_shape_points_with_offset_impl(
1067 self.raw(),
1068 points,
1069 radius,
1070 position,
1071 angle_radians,
1072 translation,
1073 filter,
1074 ))
1075 }
1076}
1077
1078impl WorldHandle {
1079 pub fn overlap_aabb(&self, aabb: Aabb, filter: QueryFilter) -> Vec<ShapeId> {
1080 crate::core::callback_state::assert_not_in_callback();
1081 overlap_aabb_impl(self.raw(), aabb, filter)
1082 }
1083
1084 pub fn try_overlap_aabb(
1085 &self,
1086 aabb: Aabb,
1087 filter: QueryFilter,
1088 ) -> crate::error::ApiResult<Vec<ShapeId>> {
1089 crate::core::callback_state::check_not_in_callback()?;
1090 Ok(overlap_aabb_impl(self.raw(), aabb, filter))
1091 }
1092
1093 pub fn cast_ray_closest<VO: Into<Vec2>, VT: Into<Vec2>>(
1094 &self,
1095 origin: VO,
1096 translation: VT,
1097 filter: QueryFilter,
1098 ) -> RayResult {
1099 crate::core::callback_state::assert_not_in_callback();
1100 cast_ray_closest_impl(self.raw(), origin, translation, filter)
1101 }
1102
1103 pub fn try_cast_ray_closest<VO: Into<Vec2>, VT: Into<Vec2>>(
1104 &self,
1105 origin: VO,
1106 translation: VT,
1107 filter: QueryFilter,
1108 ) -> crate::error::ApiResult<RayResult> {
1109 crate::core::callback_state::check_not_in_callback()?;
1110 Ok(cast_ray_closest_impl(
1111 self.raw(),
1112 origin,
1113 translation,
1114 filter,
1115 ))
1116 }
1117
1118 pub fn cast_ray_all<VO: Into<Vec2>, VT: Into<Vec2>>(
1119 &self,
1120 origin: VO,
1121 translation: VT,
1122 filter: QueryFilter,
1123 ) -> Vec<RayResult> {
1124 crate::core::callback_state::assert_not_in_callback();
1125 cast_ray_all_impl(self.raw(), origin, translation, filter)
1126 }
1127
1128 pub fn try_cast_ray_all<VO: Into<Vec2>, VT: Into<Vec2>>(
1129 &self,
1130 origin: VO,
1131 translation: VT,
1132 filter: QueryFilter,
1133 ) -> crate::error::ApiResult<Vec<RayResult>> {
1134 crate::core::callback_state::check_not_in_callback()?;
1135 Ok(cast_ray_all_impl(self.raw(), origin, translation, filter))
1136 }
1137
1138 pub fn overlap_polygon_points<I, P>(
1139 &self,
1140 points: I,
1141 radius: f32,
1142 filter: QueryFilter,
1143 ) -> Vec<ShapeId>
1144 where
1145 I: IntoIterator<Item = P>,
1146 P: Into<Vec2>,
1147 {
1148 crate::core::callback_state::assert_not_in_callback();
1149 overlap_polygon_points_impl(self.raw(), points, radius, filter)
1150 }
1151
1152 pub fn try_overlap_polygon_points<I, P>(
1153 &self,
1154 points: I,
1155 radius: f32,
1156 filter: QueryFilter,
1157 ) -> crate::error::ApiResult<Vec<ShapeId>>
1158 where
1159 I: IntoIterator<Item = P>,
1160 P: Into<Vec2>,
1161 {
1162 crate::core::callback_state::check_not_in_callback()?;
1163 Ok(overlap_polygon_points_impl(
1164 self.raw(),
1165 points,
1166 radius,
1167 filter,
1168 ))
1169 }
1170
1171 pub fn cast_shape_points<I, P, VT>(
1172 &self,
1173 points: I,
1174 radius: f32,
1175 translation: VT,
1176 filter: QueryFilter,
1177 ) -> Vec<RayResult>
1178 where
1179 I: IntoIterator<Item = P>,
1180 P: Into<Vec2>,
1181 VT: Into<Vec2>,
1182 {
1183 crate::core::callback_state::assert_not_in_callback();
1184 cast_shape_points_impl(self.raw(), points, radius, translation, filter)
1185 }
1186
1187 pub fn try_cast_shape_points<I, P, VT>(
1188 &self,
1189 points: I,
1190 radius: f32,
1191 translation: VT,
1192 filter: QueryFilter,
1193 ) -> crate::error::ApiResult<Vec<RayResult>>
1194 where
1195 I: IntoIterator<Item = P>,
1196 P: Into<Vec2>,
1197 VT: Into<Vec2>,
1198 {
1199 crate::core::callback_state::check_not_in_callback()?;
1200 Ok(cast_shape_points_impl(
1201 self.raw(),
1202 points,
1203 radius,
1204 translation,
1205 filter,
1206 ))
1207 }
1208
1209 pub fn cast_mover<V1: Into<Vec2>, V2: Into<Vec2>, VT: Into<Vec2>>(
1210 &self,
1211 c1: V1,
1212 c2: V2,
1213 radius: f32,
1214 translation: VT,
1215 filter: QueryFilter,
1216 ) -> f32 {
1217 crate::core::callback_state::assert_not_in_callback();
1218 cast_mover_impl(self.raw(), c1, c2, radius, translation, filter)
1219 }
1220
1221 pub fn try_cast_mover<V1: Into<Vec2>, V2: Into<Vec2>, VT: Into<Vec2>>(
1222 &self,
1223 c1: V1,
1224 c2: V2,
1225 radius: f32,
1226 translation: VT,
1227 filter: QueryFilter,
1228 ) -> crate::error::ApiResult<f32> {
1229 crate::core::callback_state::check_not_in_callback()?;
1230 Ok(cast_mover_impl(
1231 self.raw(),
1232 c1,
1233 c2,
1234 radius,
1235 translation,
1236 filter,
1237 ))
1238 }
1239
1240 pub fn overlap_polygon_points_with_offset<I, P, V, A>(
1241 &self,
1242 points: I,
1243 radius: f32,
1244 position: V,
1245 angle_radians: A,
1246 filter: QueryFilter,
1247 ) -> Vec<ShapeId>
1248 where
1249 I: IntoIterator<Item = P>,
1250 P: Into<Vec2>,
1251 V: Into<Vec2>,
1252 A: Into<f32>,
1253 {
1254 crate::core::callback_state::assert_not_in_callback();
1255 overlap_polygon_points_with_offset_impl(
1256 self.raw(),
1257 points,
1258 radius,
1259 position,
1260 angle_radians,
1261 filter,
1262 )
1263 }
1264
1265 pub fn try_overlap_polygon_points_with_offset<I, P, V, A>(
1266 &self,
1267 points: I,
1268 radius: f32,
1269 position: V,
1270 angle_radians: A,
1271 filter: QueryFilter,
1272 ) -> crate::error::ApiResult<Vec<ShapeId>>
1273 where
1274 I: IntoIterator<Item = P>,
1275 P: Into<Vec2>,
1276 V: Into<Vec2>,
1277 A: Into<f32>,
1278 {
1279 crate::core::callback_state::check_not_in_callback()?;
1280 Ok(overlap_polygon_points_with_offset_impl(
1281 self.raw(),
1282 points,
1283 radius,
1284 position,
1285 angle_radians,
1286 filter,
1287 ))
1288 }
1289
1290 pub fn cast_shape_points_with_offset<I, P, V, A, VT>(
1291 &self,
1292 points: I,
1293 radius: f32,
1294 position: V,
1295 angle_radians: A,
1296 translation: VT,
1297 filter: QueryFilter,
1298 ) -> Vec<RayResult>
1299 where
1300 I: IntoIterator<Item = P>,
1301 P: Into<Vec2>,
1302 V: Into<Vec2>,
1303 A: Into<f32>,
1304 VT: Into<Vec2>,
1305 {
1306 crate::core::callback_state::assert_not_in_callback();
1307 cast_shape_points_with_offset_impl(
1308 self.raw(),
1309 points,
1310 radius,
1311 position,
1312 angle_radians,
1313 translation,
1314 filter,
1315 )
1316 }
1317
1318 pub fn try_cast_shape_points_with_offset<I, P, V, A, VT>(
1319 &self,
1320 points: I,
1321 radius: f32,
1322 position: V,
1323 angle_radians: A,
1324 translation: VT,
1325 filter: QueryFilter,
1326 ) -> crate::error::ApiResult<Vec<RayResult>>
1327 where
1328 I: IntoIterator<Item = P>,
1329 P: Into<Vec2>,
1330 V: Into<Vec2>,
1331 A: Into<f32>,
1332 VT: Into<Vec2>,
1333 {
1334 crate::core::callback_state::check_not_in_callback()?;
1335 Ok(cast_shape_points_with_offset_impl(
1336 self.raw(),
1337 points,
1338 radius,
1339 position,
1340 angle_radians,
1341 translation,
1342 filter,
1343 ))
1344 }
1345}