Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/asset/custom_asset.rs
6592 views
1
//! Implements loader for a custom asset type.
2
3
use bevy::{
4
asset::{io::Reader, AssetLoader, LoadContext},
5
prelude::*,
6
reflect::TypePath,
7
};
8
use serde::Deserialize;
9
use thiserror::Error;
10
11
#[derive(Asset, TypePath, Debug, Deserialize)]
12
struct 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)]
21
struct CustomAssetLoader;
22
23
/// Possible errors that can be produced by [`CustomAssetLoader`]
24
#[non_exhaustive]
25
#[derive(Debug, Error)]
26
enum CustomAssetLoaderError {
27
/// An [IO](std::io) Error
28
#[error("Could not load asset: {0}")]
29
Io(#[from] std::io::Error),
30
/// A [RON](ron) Error
31
#[error("Could not parse RON: {0}")]
32
RonSpannedError(#[from] ron::error::SpannedError),
33
}
34
35
impl 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)]
57
struct Blob {
58
bytes: Vec<u8>,
59
}
60
61
#[derive(Default)]
62
struct BlobAssetLoader;
63
64
/// Possible errors that can be produced by [`BlobAssetLoader`]
65
#[non_exhaustive]
66
#[derive(Debug, Error)]
67
enum BlobAssetLoaderError {
68
/// An [IO](std::io) Error
69
#[error("Could not load file: {0}")]
70
Io(#[from] std::io::Error),
71
}
72
73
impl 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
92
fn 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)]
106
struct State {
107
handle: Handle<CustomAsset>,
108
other_handle: Handle<CustomAsset>,
109
blob: Handle<Blob>,
110
printed: bool,
111
}
112
113
fn setup(mut state: ResMut<State>, asset_server: Res<AssetServer>) {
114
// Recommended way to load an asset
115
state.handle = asset_server.load("data/asset.custom");
116
117
// File extensions are optional, but are recommended for project management and last-resort inference
118
state.other_handle = asset_server.load("data/asset_no_extension");
119
120
// Will use BlobAssetLoader instead of CustomAssetLoader thanks to type inference
121
state.blob = asset_server.load("data/asset.custom");
122
}
123
124
fn 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
// Can't print results if the assets aren't ready
134
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
// Once printed, we won't print again
158
state.printed = true;
159
}
160
161