use crate::palette::{ColorIndex, GbColor, Palette};
use crate::tile::{RgbaTile, TileFormat, TileSet, TILE_PIXELS};
use crate::TILE_SIZE;
pub const BG_MAP_WIDTH: u32 = 32;
pub const BG_MAP_HEIGHT: u32 = 32;
pub const BG_MAP_PIXEL_WIDTH: u32 = BG_MAP_WIDTH * TILE_SIZE;
pub const BG_MAP_PIXEL_HEIGHT: u32 = BG_MAP_HEIGHT * TILE_SIZE;
pub const BG_MAP_SIZE: usize = (BG_MAP_WIDTH * BG_MAP_HEIGHT) as usize;
pub struct TileCache {
cached: Vec<RgbaTile>,
valid: bool,
}
impl TileCache {
pub fn new() -> Self {
Self {
cached: Vec::new(),
valid: false,
}
}
pub fn ensure(&mut self, tileset: &TileSet, palette: &Palette) {
if self.valid {
return;
}
let count = tileset.len();
self.cached.clear();
self.cached.reserve(count);
for i in 0..count {
let tile = tileset.get(i);
let mut rgba = RgbaTile::blank();
for row in 0..TILE_PIXELS {
for col in 0..TILE_PIXELS {
let color_idx = tile.pixels[row][col];
rgba.pixels[row][col] = palette.color(GbColor::from_u8(color_idx));
}
}
self.cached.push(rgba);
}
self.valid = true;
}
pub fn ensure_with_format<C: ColorIndex>(&mut self, tileset: &TileSet, palette: &Palette<C>) {
if self.valid {
return;
}
let format = tileset.tile_format();
let count = tileset.len();
self.cached.clear();
self.cached.reserve(count);
for i in 0..count {
match format {
TileFormat::FullColor => {
if let Some(rgba_tile) = tileset.get_rgba(i) {
self.cached.push(rgba_tile.clone());
} else {
self.cached.push(RgbaTile::blank());
}
}
_ => {
let tile = tileset.get(i);
let mut rgba = RgbaTile::blank();
for row in 0..TILE_PIXELS {
for col in 0..TILE_PIXELS {
let color_idx = tile.pixels[row][col];
rgba.pixels[row][col] = palette.color(C::from_u8(color_idx));
}
}
self.cached.push(rgba);
}
}
}
self.valid = true;
}
pub fn invalidate(&mut self) {
self.valid = false;
}
#[inline]
pub fn get(&self, index: usize) -> Option<&RgbaTile> {
self.cached.get(index)
}
}
impl Default for TileCache {
fn default() -> Self {
Self::new()
}
}