tato_pipe 0.1.3

Converts PNG files to binary data for the Tato game engine
Documentation
use crate::*;
use std::collections::HashMap;
use std::{vec, vec::Vec};

// #[derive(Debug)]
pub(crate) struct TilesetBuilder {
    pub specs: Specs,
    pub palette_id: u8,
    pub(crate) pixels :Vec<u8>,
    pub(crate) next_tile:u8,
    pub(crate) tile_count:u8,
    pub(crate) tile_hash: HashMap::<Vec<u8>, Tile>,
    pub(crate) anims: Vec<Anim>,
    pub(crate) fonts: Vec<Font>,
    pub(crate) tilemaps: Vec<Tilemap>,
    pub(crate) anim_names: Vec<String>,
    pub(crate) font_names: Vec<String>,
    pub(crate) tilemap_names: Vec<String>,
}


// impl<AnimKind, const TILE_LEN:usize> TilesetBuilder<TILE_LEN>
impl TilesetBuilder {

    pub(crate) fn new(specs:Specs, palette_id:impl PaletteEnum) -> Self {
        Self {
            specs,
            tile_hash: HashMap::new(),
            pixels: vec![],
            palette_id: palette_id.into(),
            next_tile: 0,
            tile_count: 0,
            anims: vec![],
            anim_names: vec![],
            fonts: vec![],
            font_names: vec![],
            tilemaps: vec![],
            tilemap_names: vec![],
        }
    }


    /// Main workhorse function! Splits images into 8x8 tiles (8 pixels wide, as many pixels as it needs tall). Returns the indices, the flags and the number of tiles
    pub(crate) fn add_tiles(&mut self, img:&ImageBuilder, group:u8, is_collider:bool) -> Vec<Tile> {        
        let mut tiles = vec![];
        let tile_length = self.specs.tile_width as usize * self.specs.tile_height as usize;

        for frame_v in 0 .. img.frames_v as usize {
            for frame_h in 0 .. img.frames_h as usize {
                for row in 0 .. img.rows_per_frame as usize {
                    for col in 0 .. img.cols_per_frame as usize {
                        let mut tile_candidate = vec![0u8; tile_length];
                        let mut tile_candidate_flip_h = vec![0u8; tile_length];
                        let abs_col = (frame_h * img.cols_per_frame as usize) + col;
                        let abs_row = (frame_v * img.rows_per_frame as usize) + row;
                        
                        for y in 0 .. self.specs.tile_height as usize {
                            for x in 0 .. self.specs.tile_width as usize {
                                let mirror_x = self.specs.tile_width as usize - x - 1;
                                let abs_x = (self.specs.tile_width as usize * abs_col) + x;
                                let abs_y = (self.specs.tile_height as usize * abs_row) + y;
                                let index = (img.width * abs_y) + abs_x;
                                let value = img.pixels[index];
                                tile_candidate[(self.specs.tile_width as usize * y) + x] = value;
                                tile_candidate_flip_h[(self.specs.tile_width as usize * y ) + mirror_x] = value;
                            }
                        }
                        
                        // If hashmap doesn't contain tile, add it
                        if !self.tile_hash.contains_key(&tile_candidate) {
                            // Insert normal tile in hashmap
                            let mut new_tile = Tile{
                                index: self.next_tile,
                                group,
                                flags: 0,
                            };
                            new_tile.set_collider(is_collider);
                            self.tile_hash.insert(tile_candidate.clone(), new_tile);

                            // Insert horizontally mirrored tile in hashmap
                            let mut tile_flipped_h = new_tile;
                            tile_flipped_h.set_flipped_h(true);
                            self.tile_hash.insert(tile_candidate_flip_h, tile_flipped_h);

                            // Add tile pixels to tileset data
                            self.pixels.extend_from_slice(&tile_candidate);

                            // Populates index and attribute vectors that will be returned
                            println!("Creating tile {}", self.next_tile);
                            tiles.push(new_tile);
                            
                            // Next
                            if self.next_tile == 255 { panic!("Error: Tileset capacity exceeded") };
                            self.next_tile += 1;
                            self.tile_count += 1;
                        
                        } else {
                            // If tile is already in hashmap, reuse its index
                            let reused_tile = self.tile_hash.get(&tile_candidate).unwrap();
                            tiles.push(*reused_tile);
                        }
                    }
                }
            }
        }

        tiles
    }

}