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.
129 lines
3.2 KiB
129 lines
3.2 KiB
use std::ops::{self, Index, IndexMut}; |
|
|
|
use bevy::{ |
|
ecs::component::Component, |
|
math::{Dir3, IVec3, InvalidDirectionError}, |
|
}; |
|
use overload::overload; |
|
|
|
use super::BlockRegion; |
|
|
|
#[derive(Component, Clone, Copy, PartialEq, Eq, Hash, Debug)] |
|
pub struct BlockPos { |
|
pub x: i32, |
|
pub y: i32, |
|
pub z: i32, |
|
} |
|
|
|
impl BlockPos { |
|
pub const ORIGIN: BlockPos = Self::new(0, 0, 0); |
|
|
|
pub const fn new(x: i32, y: i32, z: i32) -> Self { |
|
Self { x, y, z } |
|
} |
|
|
|
pub fn region(self) -> BlockRegion { |
|
BlockRegion::new_unchecked(self, self) |
|
} |
|
|
|
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)) |
|
} |
|
|
|
pub fn offset(self, x: i32, y: i32, z: i32) -> Self { |
|
Self::new(self.x + x, self.y + y, self.z + z) |
|
} |
|
} |
|
|
|
impl std::fmt::Display for BlockPos { |
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
|
write!(f, "[{}, {}, {}]", self.x, self.y, self.z) |
|
} |
|
} |
|
|
|
// Offsetting |
|
|
|
overload!((l: BlockPos) + (r: IVec3) -> BlockPos { BlockPos::new(l.x + r.x, l.y + r.y, l.z + r.z) }); |
|
overload!((l: BlockPos) - (r: IVec3) -> BlockPos { BlockPos::new(l.x - r.x, l.y - r.y, l.z - r.z) }); |
|
overload!((s: &mut BlockPos) += (v: IVec3) { s.x += v.x; s.y += v.y; s.z += v.z; }); |
|
overload!((s: &mut BlockPos) -= (v: IVec3) { s.x -= v.x; s.y -= v.y; s.z -= v.z; }); |
|
|
|
// Difference |
|
|
|
overload!((l: BlockPos) - (r: BlockPos) -> IVec3 { IVec3::new(l.x - r.x, l.y - r.y, l.z - r.z) }); |
|
|
|
// Indexing |
|
|
|
impl Index<usize> for BlockPos { |
|
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 IndexMut<usize> for BlockPos { |
|
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"), |
|
} |
|
} |
|
} |
|
|
|
// Conversion |
|
|
|
impl From<(i32, i32, i32)> for BlockPos { |
|
fn from((x, y, z): (i32, i32, i32)) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
} |
|
impl From<BlockPos> for (i32, i32, i32) { |
|
fn from(BlockPos { x, y, z }: BlockPos) -> Self { |
|
(x, y, z) |
|
} |
|
} |
|
|
|
impl From<[i32; 3]> for BlockPos { |
|
fn from([x, y, z]: [i32; 3]) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
} |
|
impl From<BlockPos> for [i32; 3] { |
|
fn from(BlockPos { x, y, z }: BlockPos) -> Self { |
|
[x, y, z] |
|
} |
|
} |
|
|
|
impl From<IVec3> for BlockPos { |
|
fn from(IVec3 { x, y, z }: IVec3) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
} |
|
impl From<BlockPos> for IVec3 { |
|
fn from(BlockPos { x, y, z }: BlockPos) -> Self { |
|
Self::new(x, y, z) |
|
} |
|
}
|
|
|