1use bevy::{math::Vec3A, prelude::*};
12use num_traits::{Bounded, Num, Signed};
13use std::fmt::Debug;
14use typenum::Unsigned;
15
16pub trait Scalar: Bounded + Num + Clone + Copy + Signed + PartialOrd + Debug {}
18impl<T> Scalar for T where T: Bounded + Num + Clone + Copy + Signed + PartialOrd + Debug {}
19
20#[allow(clippy::module_name_repetitions)]
24pub trait SpatialPoint: Copy + Clone + PartialEq + Debug {
25 type Scalar: Scalar;
27
28 type Vec: Send + Sync + IntoSpatialPoint;
30
31 type Dimension: Unsigned;
33
34 fn at(&self, nth: usize) -> Self::Scalar;
39
40 fn distance_squared(&self, other: &Self) -> Self::Scalar;
42
43 fn min_point(&self, other: &Self) -> Self::Vec;
45
46 fn max_point(&self, other: &Self) -> Self::Vec;
48
49 fn entity(&self) -> Option<Entity>;
51
52 fn vec(&self) -> Self::Vec;
54}
55
56#[allow(clippy::module_name_repetitions)]
59pub trait IntoSpatialPoint: Send + Sync + Sized + Copy {
60 type Point: SpatialPoint + From<(Entity, Self)> + Copy;
62
63 fn into_spatial_point(self, e: Entity) -> Self::Point
65 where
66 Self::Point: From<(Entity, Self)>,
67 {
68 (e, self).into()
69 }
70}
71macro_rules! impl_spatial_point {
72 ($pointname:ident, $bvec:ty, $unit:ty, $dim:ty, $diml:literal) => {
73 #[derive(Clone, Copy, Debug, Default, PartialEq)]
75 pub struct $pointname {
76 pub vec: $bvec,
78 pub entity: Option<Entity>,
80 }
81
82 impl $pointname {
83 fn new(vec: $bvec, entity: Entity) -> Self {
84 $pointname {
85 vec,
86 entity: Some(entity),
87 }
88 }
89
90 fn from_vec(vec: $bvec) -> Self {
91 $pointname { vec, entity: None }
92 }
93 }
94
95 impl SpatialPoint for $pointname {
96 type Scalar = $unit;
97 type Vec = $bvec;
98 type Dimension = $dim;
99
100 #[inline]
101 fn at(&self, nth: usize) -> Self::Scalar {
102 self.vec[nth]
103 }
104
105 #[inline]
106 fn distance_squared(&self, other: &Self) -> Self::Scalar {
107 self.vec.distance_squared(other.vec)
108 }
109
110 #[inline]
111 fn min_point(&self, other: &Self) -> Self::Vec {
112 self.vec.min(other.vec)
113 }
114
115 #[inline]
116 fn max_point(&self, other: &Self) -> Self::Vec {
117 self.vec.max(other.vec)
118 }
119
120 #[inline]
121 fn entity(&self) -> Option<Entity> {
122 self.entity
123 }
124
125 #[inline]
126 fn vec(&self) -> Self::Vec {
127 self.vec
128 }
129 }
130
131 impl From<(Entity, $bvec)> for $pointname {
132 fn from(value: (Entity, $bvec)) -> Self {
133 $pointname::new(value.1, value.0)
134 }
135 }
136
137 impl From<($bvec, Entity)> for $pointname {
138 fn from(value: ($bvec, Entity)) -> Self {
139 $pointname::new(value.0, value.1)
140 }
141 }
142
143 impl From<$bvec> for $pointname {
144 fn from(value: $bvec) -> Self {
145 $pointname::from_vec(value)
146 }
147 }
148
149 impl IntoSpatialPoint for $bvec {
150 type Point = $pointname;
151 }
152 };
153}
154
155impl_spatial_point!(Point2, bevy::math::Vec2, f32, typenum::consts::U2, 2);
156impl_spatial_point!(Point3, bevy::math::Vec3, f32, typenum::consts::U3, 3);
157impl_spatial_point!(Point3A, bevy::math::Vec3A, f32, typenum::consts::U3, 3);
158impl_spatial_point!(PointD2, bevy::math::DVec2, f64, typenum::consts::U2, 2);
159impl_spatial_point!(PointD3, bevy::math::DVec3, f64, typenum::consts::U3, 3);
160
161pub trait VecFromTransform: IntoSpatialPoint {
164 fn from_transform(t: &Transform) -> Self;
166}
167
168impl VecFromTransform for Vec2 {
169 fn from_transform(t: &Transform) -> Self {
170 t.translation.truncate()
171 }
172}
173impl VecFromTransform for Vec3 {
174 fn from_transform(t: &Transform) -> Self {
175 t.translation
176 }
177}
178impl VecFromTransform for Vec3A {
179 fn from_transform(t: &Transform) -> Self {
180 t.translation.into()
181 }
182}
183
184pub trait VecFromGlobalTransform: IntoSpatialPoint {
188 fn from_transform(t: &GlobalTransform) -> Self;
190}
191
192impl VecFromGlobalTransform for Vec2 {
193 fn from_transform(t: &GlobalTransform) -> Self {
194 t.translation().truncate()
195 }
196}
197impl VecFromGlobalTransform for Vec3 {
198 fn from_transform(t: &GlobalTransform) -> Self {
199 t.translation()
200 }
201}
202impl VecFromGlobalTransform for Vec3A {
203 fn from_transform(t: &GlobalTransform) -> Self {
204 t.translation().into()
205 }
206}