You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
4.6 KiB
212 lines
4.6 KiB
use std::{ |
|
marker::PhantomData, |
|
ops::{Add, AddAssign, Index, IndexMut, Sub, SubAssign}, |
|
}; |
|
|
|
use bevy::{ |
|
ecs::component::Component, |
|
math::{Dir3, IVec3, InvalidDirectionError}, |
|
}; |
|
|
|
use super::Region; |
|
|
|
pub struct Pos<T> { |
|
pub x: i32, |
|
pub y: i32, |
|
pub z: i32, |
|
_marker: PhantomData<T>, |
|
} |
|
|
|
impl<T> Pos<T> { |
|
pub const ORIGIN: Self = Self::new(0, 0, 0); |
|
|
|
pub const fn new(x: i32, y: i32, z: i32) -> Self { |
|
Self { |
|
x, |
|
y, |
|
z, |
|
_marker: PhantomData, |
|
} |
|
} |
|
|
|
pub fn region(self) -> Region<T> { |
|
Region::new_unchecked(self.into(), self.into()) |
|
} |
|
|
|
pub fn distance_to(self, other: Self) -> f32 { |
|
(self.distance_to_squared(other) as f32).sqrt() |
|
} |
|
|
|
pub fn distance_to_squared(self, other: Self) -> i32 { |
|
IVec3::distance_squared(self.into(), other.into()) |
|
} |
|
|
|
pub fn direction_to(self, other: Self) -> Result<Dir3, InvalidDirectionError> { |
|
Dir3::new((other - self).as_vec3()) |
|
} |
|
|
|
pub fn min(self, rhs: Self) -> Self { |
|
Self::new(self.x.min(rhs.x), self.y.min(rhs.y), self.z.min(rhs.z)) |
|
} |
|
|
|
pub fn max(self, rhs: Self) -> Self { |
|
Self::new(self.x.max(rhs.x), self.y.max(rhs.y), self.z.max(rhs.z)) |
|
} |
|
} |
|
|
|
impl<T> std::fmt::Display for Pos<T> { |
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
write!(f, "[{}, {}, {}]", self.x, self.y, self.z) |
|
} |
|
} |
|
|
|
impl<T> std::fmt::Debug for Pos<T> { |
|
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
fmt.debug_tuple(stringify!(Pos<T>)) |
|
.field(&self.x) |
|
.field(&self.y) |
|
.field(&self.z) |
|
.finish() |
|
} |
|
} |
|
|
|
// Trait implementations that SHOULD be handled by #[derive] |
|
|
|
use bevy::ecs::component::StorageType; |
|
impl<T: Send + Sync + 'static> Component for Pos<T> { |
|
const STORAGE_TYPE: StorageType = StorageType::Table; |
|
} |
|
|
|
impl<T> Default for Pos<T> { |
|
fn default() -> Self { |
|
Self { |
|
x: 0, |
|
y: 0, |
|
z: 0, |
|
_marker: PhantomData, |
|
} |
|
} |
|
} |
|
|
|
impl<T> Clone for Pos<T> { |
|
fn clone(&self) -> Self { |
|
*self |
|
} |
|
} |
|
|
|
impl<T> Copy for Pos<T> {} |
|
|
|
impl<T> PartialEq for Pos<T> { |
|
fn eq(&self, other: &Self) -> bool { |
|
(self.x, self.y, self.z).eq(&(other.x, other.y, other.z)) |
|
} |
|
} |
|
|
|
impl<T> Eq for Pos<T> {} |
|
|
|
impl<T> std::hash::Hash for Pos<T> { |
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
|
(self.x, self.y, self.z).hash(state) |
|
} |
|
} |
|
|
|
// Conversion |
|
|
|
impl<T> From<(i32, i32, i32)> for Pos<T> { |
|
fn from((x, y, z): (i32, i32, i32)) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
} |
|
impl<T> From<Pos<T>> for (i32, i32, i32) { |
|
fn from(Pos { x, y, z, .. }: Pos<T>) -> Self { |
|
(x, y, z) |
|
} |
|
} |
|
|
|
impl<T> From<[i32; 3]> for Pos<T> { |
|
fn from([x, y, z]: [i32; 3]) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
} |
|
impl<T> From<Pos<T>> for [i32; 3] { |
|
fn from(Pos { x, y, z, .. }: Pos<T>) -> Self { |
|
[x, y, z] |
|
} |
|
} |
|
|
|
impl<T> From<IVec3> for Pos<T> { |
|
fn from(IVec3 { x, y, z }: IVec3) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
} |
|
impl<T> From<Pos<T>> for IVec3 { |
|
fn from(Pos { x, y, z, .. }: Pos<T>) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
} |
|
|
|
// Offsetting |
|
|
|
impl<T> Add<IVec3> for Pos<T> { |
|
type Output = Pos<T>; |
|
fn add(self, rhs: IVec3) -> Self::Output { |
|
Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z) |
|
} |
|
} |
|
|
|
impl<T> Sub<IVec3> for Pos<T> { |
|
type Output = Pos<T>; |
|
fn sub(self, rhs: IVec3) -> Self::Output { |
|
Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z) |
|
} |
|
} |
|
|
|
impl<T> AddAssign<IVec3> for Pos<T> { |
|
fn add_assign(&mut self, rhs: IVec3) { |
|
self.x += rhs.x; |
|
self.y += rhs.y; |
|
self.z += rhs.z; |
|
} |
|
} |
|
|
|
impl<T> SubAssign<IVec3> for Pos<T> { |
|
fn sub_assign(&mut self, rhs: IVec3) { |
|
self.x -= rhs.x; |
|
self.y -= rhs.y; |
|
self.z -= rhs.z; |
|
} |
|
} |
|
|
|
// Difference |
|
|
|
impl<T> Sub<Pos<T>> for Pos<T> { |
|
type Output = IVec3; |
|
fn sub(self, rhs: Self) -> IVec3 { |
|
IVec3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z) |
|
} |
|
} |
|
|
|
// Indexing |
|
|
|
impl<T> Index<usize> for Pos<T> { |
|
type Output = i32; |
|
fn index(&self, index: usize) -> &Self::Output { |
|
match index { |
|
0 => &self.x, |
|
1 => &self.y, |
|
2 => &self.z, |
|
_ => panic!("index out of bounds"), |
|
} |
|
} |
|
} |
|
|
|
impl<T> IndexMut<usize> for Pos<T> { |
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output { |
|
match index { |
|
0 => &mut self.x, |
|
1 => &mut self.y, |
|
2 => &mut self.z, |
|
_ => panic!("index out of bounds"), |
|
} |
|
} |
|
}
|
|
|