oxygengine_composite_renderer/
sprite_sheet_asset_protocol.rs1use crate::math::Rect;
2use core::{
3 assets::{
4 asset::{Asset, AssetId},
5 protocol::{AssetLoadResult, AssetProtocol, AssetVariant, Meta},
6 },
7 Ignite, Scalar,
8};
9use serde::{Deserialize, Serialize};
10use std::{any::Any, collections::HashMap, str::from_utf8};
11
12#[derive(Ignite, Debug, Clone, Serialize, Deserialize)]
13pub struct SpriteSheetInfo {
14 pub meta: SpriteSheetInfoMeta,
15 #[serde(default)]
16 pub frames: HashMap<String, SpriteSheetInfoFrame>,
17}
18
19#[derive(Ignite, Debug, Clone, Serialize, Deserialize)]
20pub struct SpriteSheetInfoMeta {
21 pub image: String,
22 #[serde(default)]
23 pub size: SpriteSheetInfoMetaSize,
24 #[serde(default)]
25 pub scale: String,
26}
27
28impl SpriteSheetInfoMeta {
29 pub fn image_name(&self) -> String {
30 let parts = self.image.split("://").collect::<Vec<_>>();
31 if parts.len() > 1 {
32 parts[1].to_owned()
33 } else {
34 self.image.clone()
35 }
36 }
37}
38
39#[derive(Ignite, Debug, Default, Clone, Copy, Serialize, Deserialize)]
40pub struct SpriteSheetInfoMetaSize {
41 #[serde(default)]
42 pub w: Scalar,
43 #[serde(default)]
44 pub h: Scalar,
45}
46
47#[derive(Ignite, Debug, Default, Clone, Serialize, Deserialize)]
48pub struct SpriteSheetInfoFrame {
49 #[serde(default)]
50 pub frame: Rect,
51 #[serde(default)]
52 pub rotated: bool,
53 #[serde(default)]
54 pub trimmed: bool,
55 #[serde(alias = "spriteSourceSize")]
56 #[serde(default)]
57 pub sprite_source_size: Rect,
58 #[serde(alias = "sourceSize")]
59 #[serde(default)]
60 pub source_size: SpriteSheetInfoMetaSize,
61}
62
63pub struct SpriteSheetAsset {
64 info: SpriteSheetInfo,
65 image_asset: AssetId,
66}
67
68impl SpriteSheetAsset {
69 pub fn info(&self) -> &SpriteSheetInfo {
70 &self.info
71 }
72
73 pub fn image_asset(&self) -> AssetId {
74 self.image_asset
75 }
76}
77
78pub struct SpriteSheetAssetProtocol;
79
80impl AssetProtocol for SpriteSheetAssetProtocol {
81 fn name(&self) -> &str {
82 "atlas"
83 }
84
85 fn on_load(&mut self, data: Vec<u8>) -> AssetLoadResult {
86 let data = from_utf8(&data).unwrap();
87 let info: SpriteSheetInfo = serde_json::from_str(data).unwrap();
88 let image = info.meta.image.clone();
89 AssetLoadResult::Yield(Some(Box::new(info)), vec![("image".to_owned(), image)])
90 }
91
92 fn on_resume(&mut self, payload: Meta, list: &[(&str, &Asset)]) -> AssetLoadResult {
93 let info = *(payload.unwrap() as Box<dyn Any + Send>)
94 .downcast::<SpriteSheetInfo>()
95 .unwrap();
96 let image_asset = list
97 .get(0)
98 .expect("Could not obtain sprite sheet image asset")
99 .1
100 .id();
101 AssetLoadResult::Data(Box::new(SpriteSheetAsset { info, image_asset }))
102 }
103
104 fn on_unload(&mut self, asset: &Asset) -> Option<Vec<AssetVariant>> {
105 asset
106 .get::<SpriteSheetAsset>()
107 .map(|asset| vec![AssetVariant::Id(asset.image_asset)])
108 }
109}