use crate::{coord, coord::Vec2, tile::Tile};
use std::collections::BTreeSet;
#[derive(Debug)]
pub struct ScreenBuffer {
width: usize,
pub valid: bool,
pub old: Vec<Tile>,
pub curr: Vec<Tile>,
pub changed: BTreeSet<Vec2>,
}
impl ScreenBuffer {
pub fn blank(size: Vec2) -> Self {
let curr = vec![Tile::default(); coord::to_index(size.y * size.x)];
let old = curr.clone();
Self {
width: coord::to_index(size.x),
valid: true,
curr,
old,
changed: BTreeSet::new(),
}
}
pub fn resize(&mut self, size: Vec2) {
let old_size = self.curr.len();
let new_size = coord::to_index(size.y * size.x);
let needs_clear = old_size.min(new_size);
let default_tile = Tile::default();
self.curr.resize(new_size, default_tile.clone());
self.old.resize(new_size, default_tile.clone());
for tile in &mut self.old[.. needs_clear] {
*tile = default_tile.clone();
}
for tile in &mut self.curr[.. needs_clear] {
*tile = default_tile.clone();
}
self.width = coord::to_index(size.x);
self.changed.clear();
}
pub fn next_tick(&mut self) {
self.changed.clear();
let (old, curr) = (&mut self.old, &self.curr);
old.clone_from(curr);
}
pub fn size(&self) -> Vec2 {
Vec2 {
y: coord::from_index(
self.curr.len().checked_div(self.width).unwrap_or(0),
),
x: coord::from_index(self.width),
}
}
pub fn make_index(&self, point: Vec2) -> Option<usize> {
let x = coord::to_index(point.x);
let y = coord::to_index(point.y);
if x >= self.width || self.curr.len() / self.width <= y {
None
} else {
Some(y * self.width + x % self.width)
}
}
}