#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use bevy_math::{uvec2, IVec2, UVec2};
pub const NORTH: IVec2 = IVec2 { x: 0, y: 1 };
pub const NORTH_EAST: IVec2 = IVec2 { x: 1, y: 1 };
pub const NORTH_WEST: IVec2 = IVec2 { x: -1, y: 1 };
pub const EAST: IVec2 = IVec2 { x: 1, y: 0 };
pub const SOUTH: IVec2 = IVec2 { x: 0, y: -1 };
pub const SOUTH_EAST: IVec2 = IVec2 { x: 1, y: -1 };
pub const SOUTH_WEST: IVec2 = IVec2 { x: -1, y: -1 };
pub const WEST: IVec2 = IVec2 { x: -1, y: 0 };
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
North,
NorthEast,
NorthWest,
East,
South,
SouthEast,
SouthWest,
West,
}
impl Direction {
pub const CARDINAL: [Direction; 4] = [Self::North, Self::East, Self::South, Self::West];
pub const DIAGONAL: [Direction; 4] = [
Self::NorthEast,
Self::SouthEast,
Self::SouthWest,
Self::NorthWest,
];
pub const ALL: [Direction; 8] = [
Self::North,
Self::NorthEast,
Self::East,
Self::SouthEast,
Self::South,
Self::SouthWest,
Self::West,
Self::NorthWest,
];
#[inline]
pub fn iter_cardinal() -> impl Iterator<Item = Direction> {
Self::CARDINAL.iter().copied()
}
#[inline]
pub fn iter_diagonal() -> impl Iterator<Item = Direction> {
Self::DIAGONAL.iter().copied()
}
#[inline]
pub fn iter() -> impl Iterator<Item = Direction> {
Self::ALL.iter().copied()
}
#[inline]
#[must_use]
pub fn unit(&self) -> IVec2 {
match self {
Direction::North => NORTH,
Direction::NorthEast => NORTH_EAST,
Direction::NorthWest => NORTH_WEST,
Direction::East => EAST,
Direction::South => SOUTH,
Direction::SouthEast => SOUTH_EAST,
Direction::SouthWest => SOUTH_WEST,
Direction::West => WEST,
}
}
#[inline]
#[must_use]
pub fn move_ipoint(&self, point: IVec2, by: i32) -> IVec2 {
point + self.unit() * by
}
#[inline]
#[must_use]
pub fn move_upoint(&self, point: UVec2, by: u32) -> UVec2 {
let r = point.as_ivec2() + self.unit() * by as i32;
if r.x < 0 || r.y < 0 {
UVec2::default()
} else if r.x < 0 {
uvec2(0, r.y as u32)
} else if r.y < 0 {
uvec2(r.x as u32, 0)
} else {
r.as_uvec2()
}
}
#[inline]
#[must_use]
pub fn is_cardinal(&self) -> bool {
matches!(
self,
Direction::North | Direction::East | Direction::South | Direction::West
)
}
#[inline]
#[must_use]
pub fn is_diagonal(&self) -> bool {
matches!(
self,
Direction::NorthEast
| Direction::NorthWest
| Direction::SouthEast
| Direction::SouthWest
)
}
}