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
91
92
93
94
95
96
97
98
use std::ops::Range;

use bevy::prelude::{Bundle, Color, Component, IVec2, Image, Transform};

use crate::TILE_SIZE;

#[derive(Component)]
pub struct DeletingTile;

#[derive(Bundle)]
pub struct TileBundle {
    transform: Transform,
    tile: Tile,
}

impl TileBundle {
    pub fn new(tile: Tile, location: IVec2) -> Self {
        Self {
            tile,
            transform: Transform::from_xyz(location.x as f32, location.y as f32, 0.0),
        }
    }
}

#[derive(Component, Debug, Clone, PartialEq)]
pub struct Tile {
    pub(crate) pixels: [[Color; TILE_SIZE]; TILE_SIZE],
}

impl Tile {
    pub fn from_color(color: Color) -> Self {
        Self {
            pixels: [[color; TILE_SIZE]; TILE_SIZE],
        }
    }

    pub fn from_pixels(pixels: [[Color; TILE_SIZE]; TILE_SIZE]) -> Self {
        Self { pixels }
    }

    pub fn from_image(image: &Image, pixel_range: (Range<usize>, Range<usize>)) -> Self {
        let mut colors = [[Color::NONE; TILE_SIZE]; TILE_SIZE];

        assert_eq!(pixel_range.0.len(), TILE_SIZE);
        assert_eq!(pixel_range.1.len(), TILE_SIZE);

        for x in pixel_range.0.clone() {
            for y in pixel_range.1.clone() {
                let pixel_index = y * image.size().x as usize * 4 + x * 4;

                colors[y - pixel_range.1.start][x - pixel_range.0.start] = Color::rgba_u8(
                    image.data[pixel_index],
                    image.data[pixel_index + 1],
                    image.data[pixel_index + 2],
                    image.data[pixel_index + 3],
                );
            }
        }

        Self { pixels: colors }
    }

    pub fn set_pixel(&mut self, loc: IVec2, color: Color) {
        if !verify_pixel_loc(loc) {
            return;
        }

        self.pixels[loc.y as usize][loc.x as usize] = color
    }

    pub fn get_pixel(&self, loc: IVec2) -> Option<Color> {
        if !verify_pixel_loc(loc) {
            return None;
        }

        Some(self.pixels[loc.y as usize][loc.x as usize])
    }

    pub fn pixel_count(&self) -> usize {
        let mut pixel_count = 0;
        for x in 0..TILE_SIZE {
            for y in 0..TILE_SIZE {
                if self.pixels[y][x].a() > 0.0 {
                    pixel_count += 1;
                }
            }
        }

        pixel_count
    }
}

fn verify_pixel_loc(loc: IVec2) -> bool {
    if loc.x < 0 || loc.x >= TILE_SIZE as i32 || loc.y < 0 || loc.y >= TILE_SIZE as i32 {
        return false;
    }
    true
}