1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
use super::tile::{self, TileHeader};
use crate::Result;
use crate::TileProvider;
use sdl2::surface::Surface;
use std::fs::File;
use std::io::Read;
use std::path::Path;

pub struct TileCache<'t> {
    tiles: Vec<Surface<'t>>,
}

pub struct FileProperties {
    pub transparent: bool,
    pub name: &'static str,
    pub num_tiles: usize,
}

impl FileProperties {
    fn build(
        transparent: bool,
        name: &'static str,
        num_tiles: usize,
    ) -> FileProperties {
        FileProperties {
            transparent,
            name,
            num_tiles,
        }
    }

    pub fn get_all() -> Vec<Self> {
        let p = Self::build;
        vec![
            p(true, "back0.dn1", 48),
            p(false, "back1.dn1", 48),
            p(false, "back2.dn1", 48),
            p(false, "back3.dn1", 48),
            p(true, "solid0.dn1", 48),
            p(false, "solid1.dn1", 48),
            p(false, "solid2.dn1", 48),
            p(false, "solid3.dn1", 48),
            p(true, "anim0.dn1", 48),
            p(true, "anim1.dn1", 48),
            p(true, "anim2.dn1", 48),
            p(true, "anim3.dn1", 48),
            p(true, "anim4.dn1", 48),
            p(true, "anim5.dn1", 48),
            p(true, "object0.dn1", 50),
            p(true, "object1.dn1", 50),
            p(true, "object2.dn1", 50),
            p(true, "man0.dn1", 48),
            p(true, "man1.dn1", 48),
            p(true, "man2.dn1", 48),
            p(true, "man3.dn1", 48),
            p(true, "man4.dn1", 48),
            p(true, "font1.dn1", 50),
            p(true, "font2.dn1", 50),
            p(true, "border.dn1", 48),
            p(true, "numbers.dn1", 44),
        ]
    }
}

impl<'t> TileProvider for TileCache<'t> {
    fn get_tile(&self, index: usize) -> Option<&Surface> {
        self.tiles.get(index)
    }
}

impl<'t> TileCache<'t> {
    pub fn load_from_path(path: &Path) -> Result<Self> {
        let mut tiles = Vec::new();

        for FileProperties {
            transparent,
            name,
            num_tiles,
        } in FileProperties::get_all().into_iter()
        {
            let path = path.join(name);
            let mut file = File::open(path)?;
            let header = TileHeader::load_from(&mut file)?;
            let num_tiles =
                std::cmp::min(num_tiles, header.tiles as usize);
            tiles.append(&mut Self::load_file(
                &mut file,
                header,
                num_tiles,
                transparent,
            )?);
        }

        Ok(TileCache { tiles })
    }

    fn load_file<R: Read>(
        r: &mut R,
        header: TileHeader,
        num_tiles: usize,
        has_transparency: bool,
    ) -> Result<Vec<Surface<'t>>> {
        let mut tiles = Vec::new();
        for _ in 0..num_tiles {
            tiles.push(tile::load(r, header, has_transparency)?);
        }
        Ok(tiles)
    }
}