1use crate::*;
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 image: HtmlImageElement = HtmlImageElement::new().expect("should create image element");
91 let entry: AssetEntry = AssetEntry::new(
92 AssetType::Image,
93 AssetState::Loading,
94 Some(image.clone()),
95 url.clone(),
96 );
97 self.get_cache()
98 .borrow_mut()
99 .get_mut_entries()
100 .insert(url.clone(), entry);
101 *self.get_mut_pending_count() += 1;
102 let cache_clone: Rc<RefCell<AssetCache>> = self.get_cache().clone();
103 let url_for_onload: String = url.clone();
104 let url_for_onerror: String = url.clone();
105 let onload_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
106 let mut cache_ref = cache_clone.borrow_mut();
107 if let Some(mut entry) = cache_ref.get_entries().get(&url_for_onload).cloned() {
108 entry.set_state(AssetState::Loaded);
109 cache_ref
110 .get_mut_entries()
111 .insert(url_for_onload.clone(), entry);
112 }
113 }) as Box<dyn FnMut()>);
114 let cache_clone_err: Rc<RefCell<AssetCache>> = self.get_cache().clone();
115 let onerror_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
116 let mut cache_ref = cache_clone_err.borrow_mut();
117 if let Some(mut entry) = cache_ref.get_entries().get(&url_for_onerror).cloned() {
118 entry.set_state(AssetState::Error);
119 cache_ref
120 .get_mut_entries()
121 .insert(url_for_onerror.clone(), entry);
122 }
123 }) as Box<dyn FnMut()>);
124 image.set_onload(Some(onload_closure.as_ref().unchecked_ref()));
125 image.set_onerror(Some(onerror_closure.as_ref().unchecked_ref()));
126 image.set_src(&url);
127 self.get_closures().borrow_mut().push(onload_closure);
128 self.get_closures().borrow_mut().push(onerror_closure);
129 }
130
131 pub fn is_all_loaded(&self) -> bool {
137 self.get_cache().borrow().is_all_loaded()
138 }
139
140 pub fn get_image<U>(&self, url: U) -> Option<HtmlImageElement>
150 where
151 U: AsRef<str>,
152 {
153 self.get_cache().borrow().get_image(url.as_ref())
154 }
155
156 pub fn progress(&self) -> f64 {
162 let cache_ref = self.get_cache().borrow();
163 let total: usize = cache_ref.get_entries().len();
164 if total == 0 {
165 return 1.0;
166 }
167 cache_ref.loaded_count() as f64 / total as f64
168 }
169}
170
171impl Default for AssetLoader {
173 fn default() -> AssetLoader {
174 AssetLoader::new()
175 }
176}
177
178impl AssetLoader {
180 pub fn create_image_element<U>(url: U) -> Option<HtmlImageElement>
193 where
194 U: AsRef<str>,
195 {
196 let image: HtmlImageElement = HtmlImageElement::new().ok()?;
197 image.set_src(url.as_ref());
198 Some(image)
199 }
200}