micro_games_kit/assets/
font.rs1use crate::{context::GameContext, game::GameSubsystem};
2use anput::world::World;
3use fontdue::Font;
4use keket::{
5 database::{handle::AssetHandle, path::AssetPathStatic},
6 protocol::AssetProtocol,
7};
8use std::error::Error;
9
10use super::name_from_path;
11
12pub struct FontAsset {
13 pub font: Font,
14}
15
16pub struct FontAssetSubsystem;
17
18impl GameSubsystem for FontAssetSubsystem {
19 fn run(&mut self, context: GameContext, _: f32) {
20 for entity in context.assets.storage.added().iter_of::<FontAsset>() {
21 if let Some((path, asset)) = context
22 .assets
23 .storage
24 .lookup_one::<true, (&AssetPathStatic, &FontAsset)>(entity)
25 {
26 context
27 .draw
28 .fonts
29 .insert(name_from_path(&path).to_owned(), asset.font.clone());
30 }
31 }
32 for entity in context.assets.storage.removed().iter_of::<FontAsset>() {
33 if let Some(path) = context
34 .assets
35 .storage
36 .lookup_one::<true, &AssetPathStatic>(entity)
37 {
38 context.draw.fonts.remove(name_from_path(&path));
39 }
40 }
41 }
42}
43
44pub struct FontAssetProtocol;
45
46impl AssetProtocol for FontAssetProtocol {
47 fn name(&self) -> &str {
48 "font"
49 }
50
51 fn process_bytes(
52 &mut self,
53 handle: AssetHandle,
54 storage: &mut World,
55 bytes: Vec<u8>,
56 ) -> Result<(), Box<dyn Error>> {
57 let path = storage.component::<true, AssetPathStatic>(handle.entity())?;
58 let font = Font::from_bytes(bytes, Default::default())
59 .map_err(|_| format!("Failed to load font: {:?}", path.path()))?;
60 drop(path);
61
62 storage.insert(handle.entity(), (FontAsset { font },))?;
63
64 Ok(())
65 }
66}