notan_app/assets/
manager.rs1use super::asset::Asset;
2use super::list::AssetList;
3use super::loader::*;
4use super::storage::AssetStorage;
5use super::utils::DoneSignal;
6
7use hashbrown::HashMap;
8use std::any::TypeId;
9use std::path::Path;
10use std::rc::Rc;
11
12#[cfg(feature = "drop_files")]
13use crate::DroppedFile;
14
15pub struct Assets {
16 storage: AssetStorage,
17 pub(crate) loaders: HashMap<String, LoaderCallback>,
18 byte_loader: LoaderCallback,
19}
20
21impl Assets {
22 pub(crate) fn new() -> Self {
23 let bytes_id = TypeId::of::<Vec<u8>>();
24 let byte_loader = LoaderCallback::Basic(
25 Some(bytes_id),
26 Rc::new(|storage, id, bytes| storage.parse::<Vec<u8>>(id, bytes)),
27 );
28
29 Self {
30 loaders: HashMap::new(),
31 storage: AssetStorage::default(),
32 byte_loader,
33 }
34 }
35
36 pub(crate) fn tick<S>(&mut self, mut params: LoaderParams<S>) -> Result<(), String> {
37 if let Some(mut to_update) = self.storage.try_load() {
38 while let Some((id, data)) = to_update.pop() {
39 let ext = Path::new(&id)
40 .extension()
41 .map(|ext| ext.to_str().unwrap())
42 .unwrap_or("");
43
44 let loader = match self.loaders.get(ext) {
45 Some(loader) => loader,
46 None => {
47 log::warn!(
48 "Not found a loader for '{}', loading as bytes (Vec<u8>)",
49 id
50 );
51 &self.byte_loader
52 }
53 };
54
55 loader.exec(&id, data, &mut self.storage, &mut params)?;
56 self.storage.clean_asset(&id)?;
57 }
58
59 self.storage.clean_ready_assets();
60 }
61
62 Ok(())
63 }
64
65 pub fn add_loader(&mut self, loader: AssetLoader) {
66 if let Err(e) = loader.apply(self) {
67 log::error!("{}", e);
68 }
69 }
70
71 fn load(&mut self, id: &str) -> Result<DoneSignal, String> {
72 let ext = Path::new(id)
73 .extension()
74 .map(|ext| ext.to_str().unwrap())
75 .unwrap_or("");
76
77 let loader = match self.loaders.get(ext) {
78 Some(loader) => loader,
79 None => {
80 log::warn!(
81 "Not found a loader for '{}', loading as bytes (Vec<u8>)",
82 id
83 );
84 &self.byte_loader
85 }
86 };
87
88 Ok(match loader.type_id() {
89 Some(type_id) => self.storage.register(id, type_id),
90 None => return Err("Loader without output type id".to_string()),
91 })
92 }
93
94 #[cfg(all(target_arch = "wasm32", feature = "drop_files"))]
95 fn load_wasm_dropped_file(&mut self, file: &DroppedFile) -> Result<DoneSignal, String> {
96 let id = file.name.clone();
97 let ext = Path::new(&id)
98 .extension()
99 .map(|ext| ext.to_str().unwrap())
100 .unwrap_or("");
101
102 let loader = match self.loaders.get(ext) {
103 Some(loader) => loader,
104 None => {
105 log::warn!(
106 "Not found a loader for '{}', loading as bytes (Vec<u8>)",
107 id
108 );
109 &self.byte_loader
110 }
111 };
112
113 Ok(match loader.type_id() {
114 Some(type_id) => self
115 .storage
116 .register_wasm_dropped_file(&id, file, type_id)?,
117 None => return Err("Loader without output type id".to_string()),
118 })
119 }
120
121 pub fn load_asset<A>(&mut self, id: &str) -> Result<Asset<A>, String>
122 where
123 A: Send + Sync + 'static,
124 {
125 let _ = self.load(id)?;
126 self.storage.get(id, true)
127 }
128
129 #[cfg(all(target_arch = "wasm32", feature = "drop_files"))]
130 fn load_wasm_dropped_file_asset<A>(&mut self, file: &DroppedFile) -> Result<Asset<A>, String>
131 where
132 A: Send + Sync + 'static,
133 {
134 let _ = self.load_wasm_dropped_file(file)?;
135 self.storage.get(&file.name, true)
136 }
137
138 pub fn load_list(&mut self, paths: &[&str]) -> Result<AssetList, String> {
139 let mut list = AssetList::new(self.storage.tracker.clone());
140 for id in paths {
141 let loaded = self.load(id)?;
142 list.insert(id, loaded);
143 }
144 Ok(list)
145 }
146
147 #[cfg(feature = "drop_files")]
148 pub fn load_dropped_file<A>(&mut self, file: &DroppedFile) -> Result<Asset<A>, String>
149 where
150 A: Send + Sync + 'static,
151 {
152 if let Some(path) = &file.path {
153 if let Some(id) = path.to_str() {
154 return self.load_asset(id);
155 }
156 }
157
158 #[cfg(target_arch = "wasm32")]
159 {
160 self.load_wasm_dropped_file_asset(file)
161 }
162
163 #[cfg(not(target_arch = "wasm32"))]
164 Err(format!("Can't load the dropped file {}", file.name))
165 }
166}