use std::borrow::Cow;
use assets_manager::{loader::Loader, Asset};
use blit::{slice::Slice, Blit, BlitBuffer, BlitOptions, ToBlitBuffer};
use image::ImageFormat;
use vek::{Extent2, Vec2};
use crate::SIZE;
#[derive(Debug)]
pub struct Sprite {
sprite: BlitBuffer,
}
impl Sprite {
pub fn from_buffer(buffer: &[u32], size: Extent2<usize>) -> Self {
let sprite = BlitBuffer::from_buffer(buffer, size.w, 127);
Self { sprite }
}
pub fn render(&self, canvas: &mut [u32], offset: Vec2<f64>) {
self.sprite.blit(
canvas,
SIZE.into_tuple().into(),
&BlitOptions::new_position(offset.x as i32, offset.y as i32),
);
}
pub fn render_vertical_slice(
&self,
canvas: &mut [u32],
offset: Vec2<f64>,
width: f64,
slice: Slice,
) {
self.sprite.blit(
canvas,
SIZE.into_tuple().into(),
&BlitOptions::new_position(offset.x as i32, offset.y as i32)
.with_vertical_slice(slice)
.with_area((width, self.height())),
);
}
pub fn render_options(&self, canvas: &mut [u32], blit_options: &BlitOptions) {
self.sprite
.blit(canvas, SIZE.into_tuple().into(), blit_options);
}
pub fn is_pixel_transparent(&self, pixel: Vec2<u32>) -> bool {
let offset: Vec2<i32> = pixel.as_();
let index: i32 = offset.x + offset.y * self.sprite.width() as i32;
let pixel = self.sprite.pixels()[index as usize];
pixel == 0
}
pub fn width(&self) -> u32 {
self.sprite.width()
}
pub fn height(&self) -> u32 {
self.sprite.height()
}
pub fn size(&self) -> Extent2<u32> {
Extent2::new(self.width(), self.height())
}
pub fn into_blit_buffer(self) -> BlitBuffer {
self.sprite
}
pub fn pixels_mut(&mut self) -> &mut [u32] {
self.sprite.pixels_mut()
}
}
impl Asset for Sprite {
const EXTENSION: &'static str = "png";
type Loader = SpriteLoader;
}
pub struct SpriteLoader;
impl Loader<Sprite> for SpriteLoader {
fn load(content: Cow<[u8]>, _ext: &str) -> Result<Sprite, assets_manager::BoxedError> {
let sprite = image::load_from_memory_with_format(&content, ImageFormat::Png)?
.into_rgba8()
.to_blit_buffer_with_alpha(127);
Ok(Sprite { sprite })
}
}