1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use glam::{IVec2, UVec2};

use crate::{GridPoint, Size2d};

use super::GridShape;

pub struct GridRect {
    pub position: IVec2,
    pub size: UVec2,
}

impl GridRect {
    pub fn new(pos: impl GridPoint, size: impl Size2d) -> GridRect {
        GridRect {
            position: pos.as_ivec2(),
            size: size.as_uvec2(),
        }
    }

    pub fn iter(&self) -> GridRectIter {
        GridRectIter::new(self)
    }

    pub fn move_center(&mut self, position: impl GridPoint) {
        self.position = position.as_ivec2() - (self.size / 2).as_ivec2()
    }

    pub fn min(&self) -> IVec2 {
        self.position
    }

    pub fn max(&self) -> IVec2 {
        self.position + self.size.as_ivec2()
    }
}

impl GridShape for GridRect {
    type Iterator = GridRectIter;

    fn iter(&self) -> Self::Iterator {
        GridRectIter::new(self)
    }
}

pub struct GridRectIter {
    curr: IVec2,
    start: IVec2,
    end: IVec2,
}

impl GridRectIter {
    pub fn new(rect: &GridRect) -> Self {
        GridRectIter {
            start: rect.position,
            curr: rect.position,
            end: rect.position + rect.size.as_ivec2(),
        }
    }
}

impl Iterator for GridRectIter {
    type Item = IVec2;

    fn next(&mut self) -> Option<Self::Item> {
        if self.curr.cmpge(self.end).any() {
            return None;
        }

        let p = self.curr;
        self.curr.x += 1;
        if self.curr.x == self.end.x {
            self.curr.x = self.start.x;
            self.curr.y += 1;
        }
        Some(p)
    }
}

#[cfg(test)]
mod tests {
    use super::GridRect;

    #[test]
    fn iter() {
        let rect = GridRect::new([0, 0], [3, 3]);
        for p in rect.iter() {
            println!("{}", p);
        }
    }
}