nano9 0.1.0-alpha.3

A Pico-8 compatibility layer for Bevy
Documentation
use bevy::prelude::*;

#[derive(Debug, Clone, Reflect, Default)]
pub struct Palette {
    pub data: Vec<[u8; 4]>,
}

#[derive(thiserror::Error, Debug)]
pub enum PalError {
    #[error("no such palette {0}")]
    NoSuchPalette(usize),
    #[error("no such color {0}")]
    NoSuchColor(usize),
    #[error("no such color {color} in palette {palette}")]
    NoSuchPaletteColor { color: usize, palette: usize },
}

impl Palette {
    pub fn from_image(image: &Image, row: Option<u32>) -> Self {
        let size = image.size();
        let mut data = Vec::new();
        if let Some(row) = row {
            for i in 0..size.x {
                let color: Srgba = image.get_color_at(i, row).unwrap().into();
                data.push(color.to_u8_array());
            }
        } else {
            for j in 0..size.y {
                for i in 0..size.x {
                    let color: Srgba = image.get_color_at(i, j).unwrap().into();
                    data.push(color.to_u8_array());
                }
            }
        }
        Palette { data }
    }

    pub fn from_slice(slice: &[[u8; 4]]) -> Self {
        Palette {
            data: Vec::from(slice),
        }
    }

    pub fn write_color(&self, index: usize, pixel_bytes: &mut [u8]) -> Result<(), PalError> {
        let data = self
            .data
            .get(index)
            .ok_or(PalError::NoSuchColor(index))?;
        pixel_bytes.copy_from_slice(&data[0..pixel_bytes.len()]);
        Ok(())
    }

    pub fn get_color(&self, index: usize) -> Result<Srgba, PalError> {
        self.data
            .get(index)
            .ok_or(PalError::NoSuchColor(index))
            .map(|a| Srgba::rgba_u8(a[0], a[1], a[2], a[3]))
    }
}