~starkingdoms/starkingdoms

ref: 0cc333bdb2e06402b212888c7ef0e830bfdc14ae starkingdoms/client/src/textures/loader_fast.rs -rw-r--r-- 3.8 KiB
0cc333bd — ghostlyzsh Merge branch 'master' of https://gitlab.com/starkingdoms.tk/starkingdoms.tk 2 years ago
                                                                                
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
use std::collections::HashMap;
use std::error::Error;
use std::io::Cursor;
use base64::Engine;
use image::ImageOutputFormat;
use log::debug;
use serde::{Deserialize, Serialize};
use crate::textures::{TextureManager, TextureSize};

pub const SPRITESHEET_IMAGE_FILE_FULL: &[u8] = include_bytes!("../../../assets/dist/spritesheet-full.png");
pub const SPRITESHEET_DATA_FILE_FULL: &str = include_str!("../../../assets/dist/spritesheet-full.ron");

pub const SPRITESHEET_IMAGE_FILE_375: &[u8] = include_bytes!("../../../assets/dist/spritesheet-375.png");
pub const SPRITESHEET_DATA_FILE_375: &str = include_str!("../../../assets/dist/spritesheet-375.ron");

pub const SPRITESHEET_IMAGE_FILE_125: &[u8] = include_bytes!("../../../assets/dist/spritesheet-125.png");
pub const SPRITESHEET_DATA_FILE_125: &str = include_str!("../../../assets/dist/spritesheet-125.ron");

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct SpritePosition {
    pub name: String,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub offsets: Option<[f32; 2]>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct SerializedSpriteSheet {
    pub texture_width: f32,
    pub texture_height: f32,
    pub sprites: Vec<SpritePosition>,
}

#[derive(Debug)]
pub struct TextureLoader {
    pub sprites: HashMap<String, String>
}
impl TextureManager for TextureLoader {
    fn load(size: TextureSize) -> Result<Self, Box<dyn Error>> where Self: Sized {
        debug!("Loading textures - starting fast texture loader (size: {})", size.to_string());
        let start = js_sys::Date::now() as u64;
        // load the generated spritesheet data
        let spritesheet_data: SerializedSpriteSheet = ron::from_str(pick_data_file(size))?;

        // load the generated spritesheet image
        let spritesheet_image = image::load_from_memory(pick_image_file(size))?;

        if spritesheet_image.width() as f32 != spritesheet_data.texture_width {
            return Err("Image width mismatch between spritesheet and data file".into());
        }
        if spritesheet_image.height() as f32 != spritesheet_data.texture_height {
            return Err("Image height mismatch between spritesheet and data file".into());
        }

        let mut sprites = HashMap::new();

        for sprite in spritesheet_data.sprites {
            debug!("Loading texture {} ({}x{}, start at {}, {})", sprite.name, sprite.width, sprite.height, sprite.x, sprite.y);
            let sprite_img = spritesheet_image.crop_imm(sprite.x as u32, sprite.y as u32, sprite.width as u32, sprite.height as u32);
            let mut image_data: Vec<u8> = Vec::new();
            sprite_img.write_to(&mut Cursor::new(&mut image_data), ImageOutputFormat::Png)
                .unwrap();
            let res_base64 = base64::engine::general_purpose::STANDARD.encode(image_data);
            sprites.insert(sprite.name, format!("data:image/png;base64,{}", res_base64));
        }

        let end = js_sys::Date::now() as u64;
        debug!("Loaded {} sprites from spritesheet in {} ms", sprites.len(), end - start);

        Ok(Self {
            sprites,
        })
    }

    fn get_texture(&self, texture_id: &str) -> Option<String> {
        self.sprites.get(texture_id).map(|u| u.clone())
    }
}

fn pick_data_file(for_size: TextureSize) -> &'static str {
    match for_size {
        TextureSize::Full => SPRITESHEET_DATA_FILE_FULL,
        TextureSize::Scaled375 => SPRITESHEET_DATA_FILE_375,
        TextureSize::Scaled125 => SPRITESHEET_DATA_FILE_125
    }
}

fn pick_image_file(for_size: TextureSize) -> &'static [u8] {
    match for_size {
        TextureSize::Full => SPRITESHEET_IMAGE_FILE_FULL,
        TextureSize::Scaled375 => SPRITESHEET_IMAGE_FILE_375,
        TextureSize::Scaled125 => SPRITESHEET_IMAGE_FILE_125
    }
}