1use crate::position::BlockPos;
2
3pub struct Cursor3d {
4 index: usize,
5
6 origin: BlockPos,
7
8 width: usize,
9 height: usize,
10 depth: usize,
11
12 end: usize,
13}
14
15impl Cursor3d {
16 pub fn origin(&self) -> BlockPos {
17 self.origin
18 }
19}
20
21impl Iterator for Cursor3d {
22 type Item = CursorIteration;
23
24 fn next(&mut self) -> Option<Self::Item> {
25 if self.index == self.end {
26 return None;
27 }
28 let x = self.index % self.width;
29 let r = self.index / self.width;
30 let y = r % self.height;
31 let z = r / self.height;
32 self.index += 1;
33
34 let mut iteration_type = 0;
35 if x == 0 || x == self.width - 1 {
36 iteration_type += 1;
37 }
38 if y == 0 || y == self.height - 1 {
39 iteration_type += 1;
40 }
41 if z == 0 || z == self.depth - 1 {
42 iteration_type += 1;
43 }
44
45 Some(CursorIteration {
46 pos: BlockPos {
47 x: self.origin.x + x as i32,
48 y: self.origin.y + y as i32,
49 z: self.origin.z + z as i32,
50 },
51 iteration_type: iteration_type.into(),
52 })
53 }
54}
55
56#[repr(u8)]
57#[derive(Eq, PartialEq, Debug)]
58pub enum CursorIterationType {
59 Inside = 0,
60 Face = 1,
61 Edge = 2,
62 Corner = 3,
63}
64
65pub struct CursorIteration {
66 pub pos: BlockPos,
67 pub iteration_type: CursorIterationType,
68}
69
70impl Cursor3d {
71 pub fn new(origin: BlockPos, end: BlockPos) -> Self {
72 let width = (end.x - origin.x + 1)
73 .try_into()
74 .expect("Impossible width.");
75 let height = (end.y - origin.y + 1)
76 .try_into()
77 .expect("Impossible height.");
78 let depth = (end.z - origin.z + 1)
79 .try_into()
80 .expect("Impossible depth.");
81
82 Self {
83 index: 0,
84
85 origin,
86
87 width,
88 height,
89 depth,
90
91 end: width * height * depth,
92 }
93 }
94}
95
96impl From<u8> for CursorIterationType {
97 fn from(value: u8) -> Self {
98 match value {
99 0 => CursorIterationType::Inside,
100 1 => CursorIterationType::Face,
101 2 => CursorIterationType::Edge,
102 3 => CursorIterationType::Corner,
103 _ => panic!("Invalid iteration type"),
104 }
105 }
106}