use bevy::math::{IVec3, Vec3};
pub use self::Dir::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Dir {
NORTH = 0,
EAST = 1,
SOUTH = 2,
WEST = 3,
UP = 4,
DOWN = 5,
NORTHEAST = 6,
SOUTHEAST = 7,
SOUTHWEST = 8,
NORTHWEST = 9,
NORTHEASTUP = 10,
SOUTHEASTUP = 11,
SOUTHWESTUP = 12,
NORTHWESTUP = 13,
NORTHEASTDOWN = 14,
SOUTHEASTDOWN = 15,
SOUTHWESTDOWN = 16,
NORTHWESTDOWN = 17,
}
impl Dir {
pub fn cardinal() -> std::iter::Copied<std::slice::Iter<'static, Dir>> {
[NORTH, EAST, SOUTH, WEST, UP, DOWN].iter().copied()
}
pub fn ordinal() -> std::iter::Copied<std::slice::Iter<'static, Dir>> {
[
NORTHEAST,
SOUTHEAST,
SOUTHWEST,
NORTHWEST,
NORTHEASTUP,
SOUTHEASTUP,
SOUTHWESTUP,
NORTHWESTUP,
NORTHEASTDOWN,
SOUTHEASTDOWN,
SOUTHWESTDOWN,
NORTHWESTDOWN,
]
.iter()
.copied()
}
pub fn all() -> std::iter::Copied<std::slice::Iter<'static, Dir>> {
[
NORTH,
EAST,
SOUTH,
WEST,
UP,
DOWN,
NORTHEAST,
SOUTHEAST,
SOUTHWEST,
NORTHWEST,
NORTHEASTUP,
SOUTHEASTUP,
SOUTHWESTUP,
NORTHWESTUP,
NORTHEASTDOWN,
SOUTHEASTDOWN,
SOUTHWESTDOWN,
NORTHWESTDOWN,
]
.iter()
.copied()
}
pub fn vector(self) -> (i32, i32, i32) {
match self {
NORTH => (0, 1, 0),
EAST => (1, 0, 0),
SOUTH => (0, -1, 0),
WEST => (-1, 0, 0),
UP => (0, 0, 1),
DOWN => (0, 0, -1),
NORTHEAST => (1, 1, 0),
SOUTHEAST => (1, -1, 0),
SOUTHWEST => (-1, -1, 0),
NORTHWEST => (-1, 1, 0),
NORTHEASTUP => (1, 1, 1),
SOUTHEASTUP => (1, -1, 1),
SOUTHWESTUP => (-1, -1, 1),
NORTHWESTUP => (-1, 1, 1),
NORTHEASTDOWN => (1, 1, -1),
SOUTHEASTDOWN => (1, -1, -1),
SOUTHWESTDOWN => (-1, -1, -1),
NORTHWESTDOWN => (-1, 1, -1),
}
}
pub fn dir_to(start: &Vec3, end: &Vec3) -> Self {
let delta = (end - start).normalize_or_zero();
let vec = IVec3::new(
delta.x.round() as i32,
delta.y.round() as i32,
delta.z.round() as i32,
);
match vec {
IVec3 { x: 0, y: 1, z: 0 } => NORTH,
IVec3 { x: 1, y: 0, z: 0 } => EAST,
IVec3 { x: 0, y: -1, z: 0 } => SOUTH,
IVec3 { x: -1, y: 0, z: 0 } => WEST,
IVec3 { x: 0, y: 0, z: 1 } => UP,
IVec3 { x: 0, y: 0, z: -1 } => DOWN,
IVec3 { x: 1, y: 1, z: 0 } => NORTHEAST,
IVec3 { x: 1, y: -1, z: 0 } => SOUTHEAST,
IVec3 { x: -1, y: -1, z: 0 } => SOUTHWEST,
IVec3 { x: -1, y: 1, z: 0 } => NORTHWEST,
IVec3 { x: 1, y: 1, z: 1 } => NORTHEASTUP,
IVec3 { x: 1, y: -1, z: 1 } => SOUTHEASTUP,
IVec3 { x: -1, y: -1, z: 1 } => SOUTHWESTUP,
IVec3 { x: -1, y: 1, z: 1 } => NORTHWESTUP,
IVec3 { x: 1, y: 1, z: -1 } => NORTHEASTDOWN,
IVec3 { x: 1, y: -1, z: -1 } => SOUTHEASTDOWN,
IVec3 {
x: -1,
y: -1,
z: -1,
} => SOUTHWESTDOWN,
IVec3 { x: -1, y: 1, z: -1 } => NORTHWESTDOWN,
_ => panic!("Not a valid direction"),
}
}
pub fn opposite(self) -> Dir {
match self {
NORTH => SOUTH,
EAST => WEST,
SOUTH => NORTH,
WEST => EAST,
UP => DOWN,
DOWN => UP,
NORTHEAST => SOUTHWEST,
SOUTHEAST => NORTHWEST,
SOUTHWEST => NORTHEAST,
NORTHWEST => SOUTHEAST,
NORTHEASTUP => SOUTHWESTDOWN,
SOUTHEASTUP => NORTHWESTDOWN,
SOUTHWESTUP => NORTHEASTDOWN,
NORTHWESTUP => SOUTHEASTDOWN,
NORTHEASTDOWN => SOUTHWESTUP,
SOUTHEASTDOWN => NORTHWESTUP,
SOUTHWESTDOWN => NORTHEASTUP,
NORTHWESTDOWN => SOUTHEASTUP,
}
}
pub fn is_verticle(self) -> bool {
matches!(
self,
UP | DOWN
| NORTHEASTUP
| SOUTHEASTUP
| SOUTHWESTUP
| NORTHWESTUP
| NORTHEASTDOWN
| SOUTHEASTDOWN
| SOUTHWESTDOWN
| NORTHWESTDOWN
)
}
}