1use crate::{meta::Settings, Asset, ErasedLoadedAsset, Handle, LabeledAsset, UntypedHandle};
2use bevy_utils::{ConditionalSendFuture, CowArc, HashMap};
3use serde::{Deserialize, Serialize};
4use std::{
5 borrow::Borrow,
6 hash::Hash,
7 ops::{Deref, DerefMut},
8};
9
10pub trait AssetTransformer: Send + Sync + 'static {
12 type AssetInput: Asset;
14 type AssetOutput: Asset;
16 type Settings: Settings + Default + Serialize + for<'a> Deserialize<'a>;
18 type Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>;
20
21 fn transform<'a>(
25 &'a self,
26 asset: TransformedAsset<Self::AssetInput>,
27 settings: &'a Self::Settings,
28 ) -> impl ConditionalSendFuture<Output = Result<TransformedAsset<Self::AssetOutput>, Self::Error>>;
29}
30
31pub struct TransformedAsset<A: Asset> {
33 pub(crate) value: A,
34 pub(crate) labeled_assets: HashMap<CowArc<'static, str>, LabeledAsset>,
35}
36
37impl<A: Asset> Deref for TransformedAsset<A> {
38 type Target = A;
39 fn deref(&self) -> &Self::Target {
40 &self.value
41 }
42}
43
44impl<A: Asset> DerefMut for TransformedAsset<A> {
45 fn deref_mut(&mut self) -> &mut Self::Target {
46 &mut self.value
47 }
48}
49
50impl<A: Asset> TransformedAsset<A> {
51 pub fn from_loaded(asset: ErasedLoadedAsset) -> Option<Self> {
53 if let Ok(value) = asset.value.downcast::<A>() {
54 return Some(TransformedAsset {
55 value: *value,
56 labeled_assets: asset.labeled_assets,
57 });
58 }
59 None
60 }
61 pub fn replace_asset<B: Asset>(self, asset: B) -> TransformedAsset<B> {
63 TransformedAsset {
64 value: asset,
65 labeled_assets: self.labeled_assets,
66 }
67 }
68 pub fn take_labeled_assets<B: Asset>(&mut self, labeled_source: TransformedAsset<B>) {
70 self.labeled_assets = labeled_source.labeled_assets;
71 }
72 #[inline]
74 pub fn get(&self) -> &A {
75 &self.value
76 }
77 #[inline]
79 pub fn get_mut(&mut self) -> &mut A {
80 &mut self.value
81 }
82 pub fn get_labeled<B: Asset, Q>(&mut self, label: &Q) -> Option<TransformedSubAsset<B>>
84 where
85 CowArc<'static, str>: Borrow<Q>,
86 Q: ?Sized + Hash + Eq,
87 {
88 let labeled = self.labeled_assets.get_mut(label)?;
89 let value = labeled.asset.value.downcast_mut::<B>()?;
90 Some(TransformedSubAsset {
91 value,
92 labeled_assets: &mut labeled.asset.labeled_assets,
93 })
94 }
95 pub fn get_erased_labeled<Q>(&self, label: &Q) -> Option<&ErasedLoadedAsset>
97 where
98 CowArc<'static, str>: Borrow<Q>,
99 Q: ?Sized + Hash + Eq,
100 {
101 let labeled = self.labeled_assets.get(label)?;
102 Some(&labeled.asset)
103 }
104 pub fn get_untyped_handle<Q>(&self, label: &Q) -> Option<UntypedHandle>
106 where
107 CowArc<'static, str>: Borrow<Q>,
108 Q: ?Sized + Hash + Eq,
109 {
110 let labeled = self.labeled_assets.get(label)?;
111 Some(labeled.handle.clone())
112 }
113 pub fn get_handle<Q, B: Asset>(&self, label: &Q) -> Option<Handle<B>>
115 where
116 CowArc<'static, str>: Borrow<Q>,
117 Q: ?Sized + Hash + Eq,
118 {
119 let labeled = self.labeled_assets.get(label)?;
120 if let Ok(handle) = labeled.handle.clone().try_typed::<B>() {
121 return Some(handle);
122 }
123 None
124 }
125 pub fn insert_labeled(
127 &mut self,
128 label: impl Into<CowArc<'static, str>>,
129 handle: impl Into<UntypedHandle>,
130 asset: impl Into<ErasedLoadedAsset>,
131 ) {
132 let labeled = LabeledAsset {
133 asset: asset.into(),
134 handle: handle.into(),
135 };
136 self.labeled_assets.insert(label.into(), labeled);
137 }
138 pub fn iter_labels(&self) -> impl Iterator<Item = &str> {
140 self.labeled_assets.keys().map(|s| &**s)
141 }
142}
143
144pub struct TransformedSubAsset<'a, A: Asset> {
146 value: &'a mut A,
147 labeled_assets: &'a mut HashMap<CowArc<'static, str>, LabeledAsset>,
148}
149
150impl<'a, A: Asset> Deref for TransformedSubAsset<'a, A> {
151 type Target = A;
152 fn deref(&self) -> &Self::Target {
153 self.value
154 }
155}
156
157impl<'a, A: Asset> DerefMut for TransformedSubAsset<'a, A> {
158 fn deref_mut(&mut self) -> &mut Self::Target {
159 self.value
160 }
161}
162
163impl<'a, A: Asset> TransformedSubAsset<'a, A> {
164 pub fn from_loaded(asset: &'a mut ErasedLoadedAsset) -> Option<Self> {
166 let value = asset.value.downcast_mut::<A>()?;
167 Some(TransformedSubAsset {
168 value,
169 labeled_assets: &mut asset.labeled_assets,
170 })
171 }
172 #[inline]
174 pub fn get(&self) -> &A {
175 self.value
176 }
177 #[inline]
179 pub fn get_mut(&mut self) -> &mut A {
180 self.value
181 }
182 pub fn get_labeled<B: Asset, Q>(&mut self, label: &Q) -> Option<TransformedSubAsset<B>>
184 where
185 CowArc<'static, str>: Borrow<Q>,
186 Q: ?Sized + Hash + Eq,
187 {
188 let labeled = self.labeled_assets.get_mut(label)?;
189 let value = labeled.asset.value.downcast_mut::<B>()?;
190 Some(TransformedSubAsset {
191 value,
192 labeled_assets: &mut labeled.asset.labeled_assets,
193 })
194 }
195 pub fn get_erased_labeled<Q>(&self, label: &Q) -> Option<&ErasedLoadedAsset>
197 where
198 CowArc<'static, str>: Borrow<Q>,
199 Q: ?Sized + Hash + Eq,
200 {
201 let labeled = self.labeled_assets.get(label)?;
202 Some(&labeled.asset)
203 }
204 pub fn get_untyped_handle<Q>(&self, label: &Q) -> Option<UntypedHandle>
206 where
207 CowArc<'static, str>: Borrow<Q>,
208 Q: ?Sized + Hash + Eq,
209 {
210 let labeled = self.labeled_assets.get(label)?;
211 Some(labeled.handle.clone())
212 }
213 pub fn get_handle<Q, B: Asset>(&self, label: &Q) -> Option<Handle<B>>
215 where
216 CowArc<'static, str>: Borrow<Q>,
217 Q: ?Sized + Hash + Eq,
218 {
219 let labeled = self.labeled_assets.get(label)?;
220 if let Ok(handle) = labeled.handle.clone().try_typed::<B>() {
221 return Some(handle);
222 }
223 None
224 }
225 pub fn insert_labeled(
227 &mut self,
228 label: impl Into<CowArc<'static, str>>,
229 handle: impl Into<UntypedHandle>,
230 asset: impl Into<ErasedLoadedAsset>,
231 ) {
232 let labeled = LabeledAsset {
233 asset: asset.into(),
234 handle: handle.into(),
235 };
236 self.labeled_assets.insert(label.into(), labeled);
237 }
238 pub fn iter_labels(&self) -> impl Iterator<Item = &str> {
240 self.labeled_assets.keys().map(|s| &**s)
241 }
242}