forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
custom_asset.rs
162 lines (138 loc) · 4.22 KB
/
custom_asset.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! Implements loader for a custom asset type.
use bevy::utils::thiserror;
use bevy::{
asset::{io::Reader, ron, AssetLoader, AsyncReadExt, LoadContext},
prelude::*,
reflect::TypePath,
utils::BoxedFuture,
};
use serde::Deserialize;
use thiserror::Error;
#[derive(Asset, TypePath, Debug, Deserialize)]
struct CustomAsset {
#[allow(dead_code)]
value: i32,
}
#[derive(Default)]
struct CustomAssetLoader;
/// Possible errors that can be produced by [`CustomAssetLoader`]
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum CustomAssetLoaderError {
/// An [IO](std::io) Error
#[error("Could not load asset: {0}")]
Io(#[from] std::io::Error),
/// A [RON](ron) Error
#[error("Could not parse RON: {0}")]
RonSpannedError(#[from] ron::error::SpannedError),
}
impl AssetLoader for CustomAssetLoader {
type Asset = CustomAsset;
type Settings = ();
type Error = CustomAssetLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
_load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let custom_asset = ron::de::from_bytes::<CustomAsset>(&bytes)?;
Ok(custom_asset)
})
}
fn extensions(&self) -> &[&str] {
&["custom"]
}
}
#[derive(Asset, TypePath, Debug)]
struct Blob {
bytes: Vec<u8>,
}
#[derive(Default)]
struct BlobAssetLoader;
/// Possible errors that can be produced by [`CustomAssetLoader`]
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum BlobAssetLoaderError {
/// An [IO](std::io) Error
#[error("Could not load file: {0}")]
Io(#[from] std::io::Error),
}
impl AssetLoader for BlobAssetLoader {
type Asset = Blob;
type Settings = ();
type Error = BlobAssetLoaderError;
fn load<'a>(
&'a self,
reader: &'a mut Reader,
_settings: &'a (),
_load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Box::pin(async move {
info!("Loading Blob...");
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
Ok(Blob { bytes })
})
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::<State>()
.init_asset::<CustomAsset>()
.init_asset::<Blob>()
.init_asset_loader::<CustomAssetLoader>()
.init_asset_loader::<BlobAssetLoader>()
.add_systems(Startup, setup)
.add_systems(Update, print_on_load)
.run();
}
#[derive(Resource, Default)]
struct State {
handle: Handle<CustomAsset>,
other_handle: Handle<CustomAsset>,
blob: Handle<Blob>,
printed: bool,
}
fn setup(mut state: ResMut<State>, asset_server: Res<AssetServer>) {
// Recommended way to load an asset
state.handle = asset_server.load("data/asset.custom");
// File extensions are optional, but are recommended for project management and last-resort inference
state.other_handle = asset_server.load("data/asset_no_extension");
// Will use BlobAssetLoader instead of CustomAssetLoader thanks to type inference
state.blob = asset_server.load("data/asset.custom");
}
fn print_on_load(
mut state: ResMut<State>,
custom_assets: Res<Assets<CustomAsset>>,
blob_assets: Res<Assets<Blob>>,
) {
let custom_asset = custom_assets.get(&state.handle);
let other_custom_asset = custom_assets.get(&state.other_handle);
let blob = blob_assets.get(&state.blob);
// Can't print results if the assets aren't ready
if state.printed {
return;
}
if custom_asset.is_none() {
info!("Custom Asset Not Ready");
return;
}
if other_custom_asset.is_none() {
info!("Other Custom Asset Not Ready");
return;
}
if blob.is_none() {
info!("Blob Not Ready");
return;
}
info!("Custom asset loaded: {:?}", custom_asset.unwrap());
info!("Custom asset loaded: {:?}", other_custom_asset.unwrap());
info!("Blob Size: {:?} Bytes", blob.unwrap().bytes.len());
// Once printed, we won't print again
state.printed = true;
}