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

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)
}
}