use devotee_backend::BackendImage;
use super::{Image, PixelsIterator};
use crate::util::vector::Vector;
#[derive(Clone, Copy, Debug)]
pub struct Sprite<P, const W: usize, const H: usize> {
data: [[P; W]; H],
}
impl<P, const W: usize, const H: usize> Sprite<P, W, H>
where
P: Copy,
{
pub const fn with_color(color: P) -> Self {
let data = [[color; W]; H];
Self { data }
}
pub const fn with_data(data: [[P; W]; H]) -> Self {
Self { data }
}
}
impl<P, const W: usize, const H: usize> Image for Sprite<P, W, H>
where
P: Copy,
{
type Pixel = P;
type PixelRef<'a> = &'a P where P:'a;
type PixelMut<'a> = &'a mut P where P:'a;
fn pixel(&self, position: Vector<i32>) -> Option<&P> {
if position.x() < 0 || position.y() < 0 {
return None;
}
let (x, y) = (position.x() as usize, position.y() as usize);
if x >= W || y >= H {
None
} else {
Some(&self.data[y][x])
}
}
fn pixel_mut(&mut self, position: Vector<i32>) -> Option<&mut P> {
if position.x() < 0 || position.y() < 0 {
return None;
}
let (x, y) = (position.x() as usize, position.y() as usize);
if x >= W || y >= H {
None
} else {
Some(&mut self.data[y][x])
}
}
unsafe fn unsafe_pixel(&self, position: Vector<i32>) -> &P {
let (x, y) = (position.x() as usize, position.y() as usize);
&self.data[y][x]
}
unsafe fn unsafe_pixel_mut(&mut self, position: Vector<i32>) -> &mut P {
let (x, y) = (position.x() as usize, position.y() as usize);
&mut self.data[y][x]
}
fn width(&self) -> i32 {
W as i32
}
fn height(&self) -> i32 {
H as i32
}
fn clear(&mut self, color: P) {
self.data = [[color; W]; H];
}
}
impl<P, const W: usize, const H: usize> Default for Sprite<P, W, H>
where
P: Default + Copy,
{
fn default() -> Self {
Self::with_color(Default::default())
}
}
impl<'a, P: 'a, const W: usize, const H: usize> PixelsIterator<'a, P> for Sprite<P, W, H>
where
P: Copy,
{
type Iterator = SpriteIter<'a, P, W, H>;
fn pixels(&'a self) -> Self::Iterator {
SpriteIter {
sprite: self,
index: 0,
}
}
}
pub struct SpriteIter<'a, P, const W: usize, const H: usize> {
sprite: &'a Sprite<P, W, H>,
index: usize,
}
impl<'a, P, const W: usize, const H: usize> Iterator for SpriteIter<'a, P, W, H> {
type Item = &'a P;
fn next(&mut self) -> Option<Self::Item> {
let current = self.index;
if current < W * H {
self.index += 1;
Some(&self.sprite.data[current / W][current % W])
} else {
None
}
}
}
impl<'a, P: 'a, const W: usize, const H: usize> BackendImage<'a, P> for Sprite<P, W, H>
where
P: Copy,
{
type Iterator = SpriteIter<'a, P, W, H>;
unsafe fn pixel_unsafe(&self, x: u32, y: u32) -> &P {
Image::unsafe_pixel(self, Vector::new(x as i32, y as i32))
}
fn width(&self) -> u32 {
W as u32
}
fn height(&self) -> u32 {
H as u32
}
fn pixels(&'a self) -> Self::Iterator {
PixelsIterator::pixels(self)
}
}