1use super::*;
2
3impl AssetCache {
5 pub fn get_state<U>(&self, url: U) -> Option<AssetState>
15 where
16 U: AsRef<str>,
17 {
18 self.get_entries()
19 .get(url.as_ref())
20 .map(|entry: &AssetEntry| entry.get_state())
21 }
22
23 pub fn get_image<U>(&self, url: U) -> Option<HtmlImageElement>
33 where
34 U: AsRef<str>,
35 {
36 let entry: &AssetEntry = self.get_entries().get(url.as_ref())?;
37 if entry.get_state() != AssetState::Loaded {
38 return None;
39 }
40 entry.get_image()
41 }
42
43 pub fn is_all_loaded(&self) -> bool {
49 self.get_entries()
50 .values()
51 .all(|entry: &AssetEntry| entry.get_state() != AssetState::Loading)
52 }
53
54 pub fn loaded_count(&self) -> usize {
60 self.get_entries()
61 .values()
62 .filter(|entry: &&AssetEntry| entry.get_state() == AssetState::Loaded)
63 .count()
64 }
65
66 pub fn clear(&mut self) {
68 self.get_mut_entries().clear();
69 }
70}
71
72impl Default for AssetCache {
74 fn default() -> AssetCache {
75 AssetCache::new()
76 }
77}
78
79impl AssetLoader {
81 pub fn load_image(&mut self, url: String) {
90 let Ok(image) = HtmlImageElement::new() else {
91 return;
92 };
93 let entry: AssetEntry = AssetEntry::new(
94 AssetType::Image,
95 AssetState::Loading,
96 Some(image.clone()),
97 url.clone(),
98 );
99 self.get_cache()
100 .get_mut()
101 .get_mut_entries()
102 .insert(url.clone(), entry);
103 *self.get_mut_pending_count() += 1;
104 let cache_clone: Rc<EngineCell<AssetCache>> = self.get_cache().clone();
105 let url_for_onload: String = url.clone();
106 let url_for_onerror: String = url.clone();
107 let onload_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
108 let cache_ref: &mut AssetCache = cache_clone.get_mut();
109 if let Some(mut entry) = cache_ref.get_entries().get(&url_for_onload).cloned() {
110 entry.set_state(AssetState::Loaded);
111 cache_ref
112 .get_mut_entries()
113 .insert(url_for_onload.clone(), entry);
114 }
115 }));
116 let cache_clone_err: Rc<EngineCell<AssetCache>> = self.get_cache().clone();
117 let onerror_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
118 let cache_ref: &mut AssetCache = cache_clone_err.get_mut();
119 if let Some(mut entry) = cache_ref.get_entries().get(&url_for_onerror).cloned() {
120 entry.set_state(AssetState::Error);
121 cache_ref
122 .get_mut_entries()
123 .insert(url_for_onerror.clone(), entry);
124 }
125 }));
126 image.set_onload(Some(onload_closure.as_ref().unchecked_ref()));
127 image.set_onerror(Some(onerror_closure.as_ref().unchecked_ref()));
128 image.set_src(&url);
129 self.get_closures().get_mut().push(onload_closure);
130 self.get_closures().get_mut().push(onerror_closure);
131 }
132
133 pub fn is_all_loaded(&self) -> bool {
139 self.get_cache().get().is_all_loaded()
140 }
141
142 pub fn get_image<U>(&self, url: U) -> Option<HtmlImageElement>
152 where
153 U: AsRef<str>,
154 {
155 self.get_cache().get().get_image(url.as_ref())
156 }
157
158 pub fn progress(&self) -> f64 {
164 let cache_ref: &AssetCache = self.get_cache().get();
165 let total: usize = cache_ref.get_entries().len();
166 if total == 0 {
167 return 1.0;
168 }
169 cache_ref.loaded_count() as f64 / total as f64
170 }
171}
172
173impl Default for AssetLoader {
175 fn default() -> AssetLoader {
176 AssetLoader::new()
177 }
178}
179
180impl AssetLoader {
182 pub fn create_image_element<U>(url: U) -> Option<HtmlImageElement>
195 where
196 U: AsRef<str>,
197 {
198 let image: HtmlImageElement = HtmlImageElement::new().ok()?;
199 image.set_src(url.as_ref());
200 Some(image)
201 }
202}