1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum Direction {
9 Down,
10 Up,
11 North,
12 South,
13 West,
14 East,
15}
16
17impl Direction {
18 pub const ALL: [Direction; 6] = [
20 Direction::Down,
21 Direction::Up,
22 Direction::North,
23 Direction::South,
24 Direction::West,
25 Direction::East,
26 ];
27
28 pub fn offset(&self) -> (i32, i32, i32) {
30 match self {
31 Direction::Down => (0, -1, 0),
32 Direction::Up => (0, 1, 0),
33 Direction::North => (0, 0, -1),
34 Direction::South => (0, 0, 1),
35 Direction::West => (-1, 0, 0),
36 Direction::East => (1, 0, 0),
37 }
38 }
39
40 pub fn normal(&self) -> [f32; 3] {
42 match self {
43 Direction::Down => [0.0, -1.0, 0.0],
44 Direction::Up => [0.0, 1.0, 0.0],
45 Direction::North => [0.0, 0.0, -1.0],
46 Direction::South => [0.0, 0.0, 1.0],
47 Direction::West => [-1.0, 0.0, 0.0],
48 Direction::East => [1.0, 0.0, 0.0],
49 }
50 }
51
52 pub fn opposite(&self) -> Direction {
54 match self {
55 Direction::Down => Direction::Up,
56 Direction::Up => Direction::Down,
57 Direction::North => Direction::South,
58 Direction::South => Direction::North,
59 Direction::West => Direction::East,
60 Direction::East => Direction::West,
61 }
62 }
63
64 pub fn axis(&self) -> Axis {
66 match self {
67 Direction::Down | Direction::Up => Axis::Y,
68 Direction::North | Direction::South => Axis::Z,
69 Direction::West | Direction::East => Axis::X,
70 }
71 }
72
73 pub fn from_str(s: &str) -> Option<Self> {
75 match s.to_lowercase().as_str() {
76 "down" => Some(Direction::Down),
77 "up" => Some(Direction::Up),
78 "north" => Some(Direction::North),
79 "south" => Some(Direction::South),
80 "west" => Some(Direction::West),
81 "east" => Some(Direction::East),
82 _ => None,
83 }
84 }
85
86 pub fn rotate_x(self, degrees: i32) -> Direction {
89 let steps = ((degrees / 90) % 4 + 4) % 4;
90 let mut dir = self;
91 for _ in 0..steps {
92 dir = match dir {
93 Direction::Up => Direction::North,
94 Direction::North => Direction::Down,
95 Direction::Down => Direction::South,
96 Direction::South => Direction::Up,
97 Direction::East => Direction::East,
99 Direction::West => Direction::West,
100 };
101 }
102 dir
103 }
104
105 pub fn rotate_y(self, degrees: i32) -> Direction {
108 let steps = ((degrees / 90) % 4 + 4) % 4;
109 let mut dir = self;
110 for _ in 0..steps {
111 dir = match dir {
112 Direction::North => Direction::East,
113 Direction::East => Direction::South,
114 Direction::South => Direction::West,
115 Direction::West => Direction::North,
116 Direction::Up => Direction::Up,
118 Direction::Down => Direction::Down,
119 };
120 }
121 dir
122 }
123
124 pub fn rotate_by_transform(self, x_rot: i32, y_rot: i32) -> Direction {
126 self.rotate_x(x_rot).rotate_y(y_rot)
128 }
129}
130
131impl std::fmt::Display for Direction {
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 match self {
134 Direction::Down => write!(f, "down"),
135 Direction::Up => write!(f, "up"),
136 Direction::North => write!(f, "north"),
137 Direction::South => write!(f, "south"),
138 Direction::West => write!(f, "west"),
139 Direction::East => write!(f, "east"),
140 }
141 }
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
146#[serde(rename_all = "lowercase")]
147pub enum Axis {
148 X,
149 Y,
150 Z,
151}
152
153impl Axis {
154 pub fn unit_vector(&self) -> [f32; 3] {
156 match self {
157 Axis::X => [1.0, 0.0, 0.0],
158 Axis::Y => [0.0, 1.0, 0.0],
159 Axis::Z => [0.0, 0.0, 1.0],
160 }
161 }
162
163 pub fn from_str(s: &str) -> Option<Self> {
165 match s.to_lowercase().as_str() {
166 "x" => Some(Axis::X),
167 "y" => Some(Axis::Y),
168 "z" => Some(Axis::Z),
169 _ => None,
170 }
171 }
172}
173
174impl std::fmt::Display for Axis {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 match self {
177 Axis::X => write!(f, "x"),
178 Axis::Y => write!(f, "y"),
179 Axis::Z => write!(f, "z"),
180 }
181 }
182}