custom_asset/
custom_asset.rs1use bevy::{
4 asset::{io::Reader, AssetLoader, LoadContext},
5 prelude::*,
6 reflect::TypePath,
7};
8use serde::Deserialize;
9use thiserror::Error;
10
11#[derive(Asset, TypePath, Debug, Deserialize)]
12struct CustomAsset {
13 #[expect(
14 dead_code,
15 reason = "Used to show how the data inside an asset file will be loaded into the struct"
16 )]
17 value: i32,
18}
19
20#[derive(Default)]
21struct CustomAssetLoader;
22
23#[non_exhaustive]
25#[derive(Debug, Error)]
26enum CustomAssetLoaderError {
27 #[error("Could not load asset: {0}")]
29 Io(#[from] std::io::Error),
30 #[error("Could not parse RON: {0}")]
32 RonSpannedError(#[from] ron::error::SpannedError),
33}
34
35impl AssetLoader for CustomAssetLoader {
36 type Asset = CustomAsset;
37 type Settings = ();
38 type Error = CustomAssetLoaderError;
39 async fn load(
40 &self,
41 reader: &mut dyn Reader,
42 _settings: &(),
43 _load_context: &mut LoadContext<'_>,
44 ) -> Result<Self::Asset, Self::Error> {
45 let mut bytes = Vec::new();
46 reader.read_to_end(&mut bytes).await?;
47 let custom_asset = ron::de::from_bytes::<CustomAsset>(&bytes)?;
48 Ok(custom_asset)
49 }
50
51 fn extensions(&self) -> &[&str] {
52 &["custom"]
53 }
54}
55
56#[derive(Asset, TypePath, Debug)]
57struct Blob {
58 bytes: Vec<u8>,
59}
60
61#[derive(Default)]
62struct BlobAssetLoader;
63
64#[non_exhaustive]
66#[derive(Debug, Error)]
67enum BlobAssetLoaderError {
68 #[error("Could not load file: {0}")]
70 Io(#[from] std::io::Error),
71}
72
73impl AssetLoader for BlobAssetLoader {
74 type Asset = Blob;
75 type Settings = ();
76 type Error = BlobAssetLoaderError;
77
78 async fn load(
79 &self,
80 reader: &mut dyn Reader,
81 _settings: &(),
82 _load_context: &mut LoadContext<'_>,
83 ) -> Result<Self::Asset, Self::Error> {
84 info!("Loading Blob...");
85 let mut bytes = Vec::new();
86 reader.read_to_end(&mut bytes).await?;
87
88 Ok(Blob { bytes })
89 }
90}
91
92fn main() {
93 App::new()
94 .add_plugins(DefaultPlugins)
95 .init_resource::<State>()
96 .init_asset::<CustomAsset>()
97 .init_asset::<Blob>()
98 .init_asset_loader::<CustomAssetLoader>()
99 .init_asset_loader::<BlobAssetLoader>()
100 .add_systems(Startup, setup)
101 .add_systems(Update, print_on_load)
102 .run();
103}
104
105#[derive(Resource, Default)]
106struct State {
107 handle: Handle<CustomAsset>,
108 other_handle: Handle<CustomAsset>,
109 blob: Handle<Blob>,
110 printed: bool,
111}
112
113fn setup(mut state: ResMut<State>, asset_server: Res<AssetServer>) {
114 state.handle = asset_server.load("data/asset.custom");
116
117 state.other_handle = asset_server.load("data/asset_no_extension");
119
120 state.blob = asset_server.load("data/asset.custom");
122}
123
124fn print_on_load(
125 mut state: ResMut<State>,
126 custom_assets: Res<Assets<CustomAsset>>,
127 blob_assets: Res<Assets<Blob>>,
128) {
129 let custom_asset = custom_assets.get(&state.handle);
130 let other_custom_asset = custom_assets.get(&state.other_handle);
131 let blob = blob_assets.get(&state.blob);
132
133 if state.printed {
135 return;
136 }
137
138 if custom_asset.is_none() {
139 info!("Custom Asset Not Ready");
140 return;
141 }
142
143 if other_custom_asset.is_none() {
144 info!("Other Custom Asset Not Ready");
145 return;
146 }
147
148 if blob.is_none() {
149 info!("Blob Not Ready");
150 return;
151 }
152
153 info!("Custom asset loaded: {:?}", custom_asset.unwrap());
154 info!("Custom asset loaded: {:?}", other_custom_asset.unwrap());
155 info!("Blob Size: {} Bytes", blob.unwrap().bytes.len());
156
157 state.printed = true;
159}