1use crate::{meta::Settings, Asset, ErasedLoadedAsset, Handle, LabeledAsset, UntypedHandle};
2use atomicow::CowArc;
3use bevy_utils::{ConditionalSendFuture, HashMap};
4use core::{
5 borrow::Borrow,
6 convert::Infallible,
7 hash::Hash,
8 marker::PhantomData,
9 ops::{Deref, DerefMut},
10};
11use serde::{Deserialize, Serialize};
12
13pub trait AssetTransformer: Send + Sync + 'static {
17 type AssetInput: Asset;
19 type AssetOutput: Asset;
21 type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a>;
23 type Error: Into<Box<dyn core::error::Error + Send + Sync + 'static>>;
25
26 fn transform<'a>(
30 &'a self,
31 asset: TransformedAsset<Self::AssetInput>,
32 settings: &'a Self::Settings,
33 ) -> impl ConditionalSendFuture<Output = Result<TransformedAsset<Self::AssetOutput>, Self::Error>>;
34}
35
36pub struct TransformedAsset<A: Asset> {
38 pub(crate) value: A,
39 pub(crate) labeled_assets: HashMap<CowArc<'static, str>, LabeledAsset>,
40}
41
42impl<A: Asset> Deref for TransformedAsset<A> {
43 type Target = A;
44 fn deref(&self) -> &Self::Target {
45 &self.value
46 }
47}
48
49impl<A: Asset> DerefMut for TransformedAsset<A> {
50 fn deref_mut(&mut self) -> &mut Self::Target {
51 &mut self.value
52 }
53}
54
55impl<A: Asset> TransformedAsset<A> {
56 pub fn from_loaded(asset: ErasedLoadedAsset) -> Option<Self> {
58 if let Ok(value) = asset.value.downcast::<A>() {
59 return Some(TransformedAsset {
60 value: *value,
61 labeled_assets: asset.labeled_assets,
62 });
63 }
64 None
65 }
66 pub fn replace_asset<B: Asset>(self, asset: B) -> TransformedAsset<B> {
68 TransformedAsset {
69 value: asset,
70 labeled_assets: self.labeled_assets,
71 }
72 }
73 pub fn take_labeled_assets<B: Asset>(&mut self, labeled_source: TransformedAsset<B>) {
75 self.labeled_assets = labeled_source.labeled_assets;
76 }
77 #[inline]
79 pub fn get(&self) -> &A {
80 &self.value
81 }
82 #[inline]
84 pub fn get_mut(&mut self) -> &mut A {
85 &mut self.value
86 }
87 pub fn get_labeled<B: Asset, Q>(&mut self, label: &Q) -> Option<TransformedSubAsset<B>>
89 where
90 CowArc<'static, str>: Borrow<Q>,
91 Q: ?Sized + Hash + Eq,
92 {
93 let labeled = self.labeled_assets.get_mut(label)?;
94 let value = labeled.asset.value.downcast_mut::<B>()?;
95 Some(TransformedSubAsset {
96 value,
97 labeled_assets: &mut labeled.asset.labeled_assets,
98 })
99 }
100 pub fn get_erased_labeled<Q>(&self, label: &Q) -> Option<&ErasedLoadedAsset>
102 where
103 CowArc<'static, str>: Borrow<Q>,
104 Q: ?Sized + Hash + Eq,
105 {
106 let labeled = self.labeled_assets.get(label)?;
107 Some(&labeled.asset)
108 }
109 pub fn get_untyped_handle<Q>(&self, label: &Q) -> Option<UntypedHandle>
111 where
112 CowArc<'static, str>: Borrow<Q>,
113 Q: ?Sized + Hash + Eq,
114 {
115 let labeled = self.labeled_assets.get(label)?;
116 Some(labeled.handle.clone())
117 }
118 pub fn get_handle<Q, B: Asset>(&self, label: &Q) -> Option<Handle<B>>
120 where
121 CowArc<'static, str>: Borrow<Q>,
122 Q: ?Sized + Hash + Eq,
123 {
124 let labeled = self.labeled_assets.get(label)?;
125 if let Ok(handle) = labeled.handle.clone().try_typed::<B>() {
126 return Some(handle);
127 }
128 None
129 }
130 pub fn insert_labeled(
132 &mut self,
133 label: impl Into<CowArc<'static, str>>,
134 handle: impl Into<UntypedHandle>,
135 asset: impl Into<ErasedLoadedAsset>,
136 ) {
137 let labeled = LabeledAsset {
138 asset: asset.into(),
139 handle: handle.into(),
140 };
141 self.labeled_assets.insert(label.into(), labeled);
142 }
143 pub fn iter_labels(&self) -> impl Iterator<Item = &str> {
145 self.labeled_assets.keys().map(|s| &**s)
146 }
147}
148
149pub struct TransformedSubAsset<'a, A: Asset> {
151 value: &'a mut A,
152 labeled_assets: &'a mut HashMap<CowArc<'static, str>, LabeledAsset>,
153}
154
155impl<'a, A: Asset> Deref for TransformedSubAsset<'a, A> {
156 type Target = A;
157 fn deref(&self) -> &Self::Target {
158 self.value
159 }
160}
161
162impl<'a, A: Asset> DerefMut for TransformedSubAsset<'a, A> {
163 fn deref_mut(&mut self) -> &mut Self::Target {
164 self.value
165 }
166}
167
168impl<'a, A: Asset> TransformedSubAsset<'a, A> {
169 pub fn from_loaded(asset: &'a mut ErasedLoadedAsset) -> Option<Self> {
171 let value = asset.value.downcast_mut::<A>()?;
172 Some(TransformedSubAsset {
173 value,
174 labeled_assets: &mut asset.labeled_assets,
175 })
176 }
177 #[inline]
179 pub fn get(&self) -> &A {
180 self.value
181 }
182 #[inline]
184 pub fn get_mut(&mut self) -> &mut A {
185 self.value
186 }
187 pub fn get_labeled<B: Asset, Q>(&mut self, label: &Q) -> Option<TransformedSubAsset<B>>
189 where
190 CowArc<'static, str>: Borrow<Q>,
191 Q: ?Sized + Hash + Eq,
192 {
193 let labeled = self.labeled_assets.get_mut(label)?;
194 let value = labeled.asset.value.downcast_mut::<B>()?;
195 Some(TransformedSubAsset {
196 value,
197 labeled_assets: &mut labeled.asset.labeled_assets,
198 })
199 }
200 pub fn get_erased_labeled<Q>(&self, label: &Q) -> Option<&ErasedLoadedAsset>
202 where
203 CowArc<'static, str>: Borrow<Q>,
204 Q: ?Sized + Hash + Eq,
205 {
206 let labeled = self.labeled_assets.get(label)?;
207 Some(&labeled.asset)
208 }
209 pub fn get_untyped_handle<Q>(&self, label: &Q) -> Option<UntypedHandle>
211 where
212 CowArc<'static, str>: Borrow<Q>,
213 Q: ?Sized + Hash + Eq,
214 {
215 let labeled = self.labeled_assets.get(label)?;
216 Some(labeled.handle.clone())
217 }
218 pub fn get_handle<Q, B: Asset>(&self, label: &Q) -> Option<Handle<B>>
220 where
221 CowArc<'static, str>: Borrow<Q>,
222 Q: ?Sized + Hash + Eq,
223 {
224 let labeled = self.labeled_assets.get(label)?;
225 if let Ok(handle) = labeled.handle.clone().try_typed::<B>() {
226 return Some(handle);
227 }
228 None
229 }
230 pub fn insert_labeled(
232 &mut self,
233 label: impl Into<CowArc<'static, str>>,
234 handle: impl Into<UntypedHandle>,
235 asset: impl Into<ErasedLoadedAsset>,
236 ) {
237 let labeled = LabeledAsset {
238 asset: asset.into(),
239 handle: handle.into(),
240 };
241 self.labeled_assets.insert(label.into(), labeled);
242 }
243 pub fn iter_labels(&self) -> impl Iterator<Item = &str> {
245 self.labeled_assets.keys().map(|s| &**s)
246 }
247}
248
249pub struct IdentityAssetTransformer<A: Asset> {
251 _phantom: PhantomData<fn(A) -> A>,
252}
253
254impl<A: Asset> IdentityAssetTransformer<A> {
255 pub const fn new() -> Self {
256 Self {
257 _phantom: PhantomData,
258 }
259 }
260}
261
262impl<A: Asset> Default for IdentityAssetTransformer<A> {
263 fn default() -> Self {
264 Self::new()
265 }
266}
267
268impl<A: Asset> AssetTransformer for IdentityAssetTransformer<A> {
269 type AssetInput = A;
270 type AssetOutput = A;
271 type Settings = ();
272 type Error = Infallible;
273
274 async fn transform<'a>(
275 &'a self,
276 asset: TransformedAsset<Self::AssetInput>,
277 _settings: &'a Self::Settings,
278 ) -> Result<TransformedAsset<Self::AssetOutput>, Self::Error> {
279 Ok(asset)
280 }
281}