1use std::{
2 fmt,
3 ops::{Add, AddAssign, MulAssign, Sub, SubAssign},
4};
5
6use crate::{Div, Mul, Vec2, lerp};
7
8#[repr(C)]
15#[derive(Clone, Copy, Default, PartialEq)]
16#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
17#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
18pub struct Pos2 {
19 pub x: f32,
21
22 pub y: f32,
24 }
26
27#[inline(always)]
29pub const fn pos2(x: f32, y: f32) -> Pos2 {
30 Pos2 { x, y }
31}
32
33impl From<[f32; 2]> for Pos2 {
37 #[inline(always)]
38 fn from(v: [f32; 2]) -> Self {
39 Self { x: v[0], y: v[1] }
40 }
41}
42
43impl From<&[f32; 2]> for Pos2 {
44 #[inline(always)]
45 fn from(v: &[f32; 2]) -> Self {
46 Self { x: v[0], y: v[1] }
47 }
48}
49
50impl From<Pos2> for [f32; 2] {
51 #[inline(always)]
52 fn from(v: Pos2) -> Self {
53 [v.x, v.y]
54 }
55}
56
57impl From<&Pos2> for [f32; 2] {
58 #[inline(always)]
59 fn from(v: &Pos2) -> Self {
60 [v.x, v.y]
61 }
62}
63
64impl From<(f32, f32)> for Pos2 {
68 #[inline(always)]
69 fn from(v: (f32, f32)) -> Self {
70 Self { x: v.0, y: v.1 }
71 }
72}
73
74impl From<&(f32, f32)> for Pos2 {
75 #[inline(always)]
76 fn from(v: &(f32, f32)) -> Self {
77 Self { x: v.0, y: v.1 }
78 }
79}
80
81impl From<Pos2> for (f32, f32) {
82 #[inline(always)]
83 fn from(v: Pos2) -> Self {
84 (v.x, v.y)
85 }
86}
87
88impl From<&Pos2> for (f32, f32) {
89 #[inline(always)]
90 fn from(v: &Pos2) -> Self {
91 (v.x, v.y)
92 }
93}
94
95#[cfg(feature = "mint")]
99impl From<mint::Point2<f32>> for Pos2 {
100 #[inline(always)]
101 fn from(v: mint::Point2<f32>) -> Self {
102 Self::new(v.x, v.y)
103 }
104}
105
106#[cfg(feature = "mint")]
107impl From<Pos2> for mint::Point2<f32> {
108 #[inline(always)]
109 fn from(v: Pos2) -> Self {
110 Self { x: v.x, y: v.y }
111 }
112}
113
114impl Pos2 {
117 pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
121
122 pub const NAN: Self = Self {
123 x: f32::NAN,
124 y: f32::NAN,
125 };
126
127 #[inline(always)]
128 pub const fn new(x: f32, y: f32) -> Self {
129 Self { x, y }
130 }
131
132 #[inline(always)]
135 pub fn to_vec2(self) -> Vec2 {
136 Vec2 {
137 x: self.x,
138 y: self.y,
139 }
140 }
141
142 #[inline]
143 pub fn distance(self, other: Self) -> f32 {
144 (self - other).length()
145 }
146
147 #[inline]
148 pub fn distance_sq(self, other: Self) -> f32 {
149 (self - other).length_sq()
150 }
151
152 #[inline(always)]
153 pub fn floor(self) -> Self {
154 pos2(self.x.floor(), self.y.floor())
155 }
156
157 #[inline(always)]
158 pub fn round(self) -> Self {
159 pos2(self.x.round(), self.y.round())
160 }
161
162 #[inline(always)]
163 pub fn ceil(self) -> Self {
164 pos2(self.x.ceil(), self.y.ceil())
165 }
166
167 #[inline(always)]
169 pub fn is_finite(self) -> bool {
170 self.x.is_finite() && self.y.is_finite()
171 }
172
173 #[inline(always)]
175 pub fn any_nan(self) -> bool {
176 self.x.is_nan() || self.y.is_nan()
177 }
178
179 #[must_use]
180 #[inline]
181 pub fn min(self, other: Self) -> Self {
182 pos2(self.x.min(other.x), self.y.min(other.y))
183 }
184
185 #[must_use]
186 #[inline]
187 pub fn max(self, other: Self) -> Self {
188 pos2(self.x.max(other.x), self.y.max(other.y))
189 }
190
191 #[must_use]
192 #[inline]
193 pub fn clamp(self, min: Self, max: Self) -> Self {
194 Self {
195 x: self.x.clamp(min.x, max.x),
196 y: self.y.clamp(min.y, max.y),
197 }
198 }
199
200 pub fn lerp(&self, other: Self, t: f32) -> Self {
202 Self {
203 x: lerp(self.x..=other.x, t),
204 y: lerp(self.y..=other.y, t),
205 }
206 }
207}
208
209impl std::ops::Index<usize> for Pos2 {
210 type Output = f32;
211
212 #[inline(always)]
213 fn index(&self, index: usize) -> &f32 {
214 match index {
215 0 => &self.x,
216 1 => &self.y,
217 _ => panic!("Pos2 index out of bounds: {index}"),
218 }
219 }
220}
221
222impl std::ops::IndexMut<usize> for Pos2 {
223 #[inline(always)]
224 fn index_mut(&mut self, index: usize) -> &mut f32 {
225 match index {
226 0 => &mut self.x,
227 1 => &mut self.y,
228 _ => panic!("Pos2 index out of bounds: {index}"),
229 }
230 }
231}
232
233impl Eq for Pos2 {}
234
235impl AddAssign<Vec2> for Pos2 {
236 #[inline(always)]
237 fn add_assign(&mut self, rhs: Vec2) {
238 *self = Self {
239 x: self.x + rhs.x,
240 y: self.y + rhs.y,
241 };
242 }
243}
244
245impl SubAssign<Vec2> for Pos2 {
246 #[inline(always)]
247 fn sub_assign(&mut self, rhs: Vec2) {
248 *self = Self {
249 x: self.x - rhs.x,
250 y: self.y - rhs.y,
251 };
252 }
253}
254
255impl Add<Vec2> for Pos2 {
256 type Output = Self;
257
258 #[inline(always)]
259 fn add(self, rhs: Vec2) -> Self {
260 Self {
261 x: self.x + rhs.x,
262 y: self.y + rhs.y,
263 }
264 }
265}
266
267impl Sub for Pos2 {
268 type Output = Vec2;
269
270 #[inline(always)]
271 fn sub(self, rhs: Self) -> Vec2 {
272 Vec2 {
273 x: self.x - rhs.x,
274 y: self.y - rhs.y,
275 }
276 }
277}
278
279impl Sub<Vec2> for Pos2 {
280 type Output = Self;
281
282 #[inline(always)]
283 fn sub(self, rhs: Vec2) -> Self {
284 Self {
285 x: self.x - rhs.x,
286 y: self.y - rhs.y,
287 }
288 }
289}
290
291impl Mul<f32> for Pos2 {
292 type Output = Self;
293
294 #[inline(always)]
295 fn mul(self, factor: f32) -> Self {
296 Self {
297 x: self.x * factor,
298 y: self.y * factor,
299 }
300 }
301}
302
303impl Mul<Pos2> for f32 {
304 type Output = Pos2;
305
306 #[inline(always)]
307 fn mul(self, vec: Pos2) -> Pos2 {
308 Pos2 {
309 x: self * vec.x,
310 y: self * vec.y,
311 }
312 }
313}
314
315impl MulAssign<f32> for Pos2 {
316 #[inline(always)]
317 fn mul_assign(&mut self, rhs: f32) {
318 self.x *= rhs;
319 self.y *= rhs;
320 }
321}
322
323impl Div<f32> for Pos2 {
324 type Output = Self;
325
326 #[inline(always)]
327 fn div(self, factor: f32) -> Self {
328 Self {
329 x: self.x / factor,
330 y: self.y / factor,
331 }
332 }
333}
334
335impl fmt::Debug for Pos2 {
336 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337 if let Some(precision) = f.precision() {
338 write!(f, "[{1:.0$} {2:.0$}]", precision, self.x, self.y)
339 } else {
340 write!(f, "[{:.1} {:.1}]", self.x, self.y)
341 }
342 }
343}
344
345impl fmt::Display for Pos2 {
346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347 f.write_str("[")?;
348 self.x.fmt(f)?;
349 f.write_str(" ")?;
350 self.y.fmt(f)?;
351 f.write_str("]")?;
352 Ok(())
353 }
354}