micro_games_kit/assets/
texture.rs1use crate::{assets::name_from_path, context::GameContext, game::GameSubsystem};
2use anput::world::World;
3use image::{GenericImage, GenericImageView, RgbaImage};
4use keket::{
5 database::{handle::AssetHandle, path::AssetPathStatic},
6 protocol::AssetProtocol,
7};
8use spitfire_glow::renderer::GlowTextureFormat;
9use std::error::Error;
10
11pub struct TextureAsset {
12 pub image: RgbaImage,
13 pub cols: u32,
14 pub rows: u32,
15}
16
17pub struct TextureAssetSubsystem;
18
19impl GameSubsystem for TextureAssetSubsystem {
20 fn run(&mut self, context: GameContext, _: f32) {
21 for entity in context.assets.storage.added().iter_of::<TextureAsset>() {
22 if let Some((path, asset)) = context
23 .assets
24 .storage
25 .lookup_one::<true, (&AssetPathStatic, &TextureAsset)>(entity)
26 {
27 let pages = asset.cols * asset.rows;
28 context.draw.textures.insert(
29 name_from_path(&path).to_owned().into(),
30 context
31 .graphics
32 .texture(
33 asset.image.width(),
34 asset.image.height() / pages,
35 pages,
36 GlowTextureFormat::Rgba,
37 Some(asset.image.as_raw()),
38 )
39 .unwrap(),
40 );
41 }
42 }
43 for entity in context.assets.storage.removed().iter_of::<TextureAsset>() {
44 if let Some(path) = context
45 .assets
46 .storage
47 .lookup_one::<true, &AssetPathStatic>(entity)
48 {
49 context.draw.textures.remove(name_from_path(&path));
50 }
51 }
52 }
53}
54
55pub struct TextureAssetProtocol;
56
57impl AssetProtocol for TextureAssetProtocol {
58 fn name(&self) -> &str {
59 "texture"
60 }
61
62 fn process_bytes(
63 &mut self,
64 handle: AssetHandle,
65 storage: &mut World,
66 bytes: Vec<u8>,
67 ) -> Result<(), Box<dyn Error>> {
68 let path = storage.component::<true, AssetPathStatic>(handle.entity())?;
69 let mut cols = 1;
70 let mut rows = 1;
71 for (key, value) in path.meta_items() {
72 if key == "cols" || key == "c" {
73 cols = value.parse().unwrap_or(1);
74 } else if key == "rows" || key == "r" {
75 rows = value.parse().unwrap_or(1);
76 }
77 }
78 let mut image = image::load_from_memory(&bytes)
79 .map_err(|_| format!("Failed to load texture: {:?}", path.path()))?
80 .into_rgba8();
81 drop(path);
82 let pages = cols * rows;
83 image = if cols > 1 || rows > 1 {
84 let width = image.width() / cols;
85 let height = image.height() / rows;
86 let mut result = RgbaImage::new(width, height * pages);
87 for row in 0..rows {
88 for col in 0..cols {
89 let view = image.view(col * width, row * height, width, height);
90 result
91 .copy_from(&*view, 0, (row * cols + col) * height)
92 .unwrap();
93 }
94 }
95 result
96 } else {
97 image
98 };
99
100 storage.insert(handle.entity(), (TextureAsset { image, cols, rows },))?;
101
102 Ok(())
103 }
104}