1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use crate::{assets::database::AssetsDatabase, error::*, fetch::FetchEngine};
enum Phase {
None,
Start(Box<dyn FetchEngine>),
Loading,
Ready,
}
pub struct AssetsPreloader {
paths: Vec<String>,
phase: Phase,
}
impl AssetsPreloader {
pub fn new<E>(engine: E, paths: Vec<&str>) -> Self
where
E: FetchEngine + 'static,
{
let paths = paths.into_iter().map(|p| p.to_owned()).collect::<Vec<_>>();
Self {
paths,
phase: Phase::Start(Box::new(engine)),
}
}
pub fn process(&mut self, assets: &mut AssetsDatabase) -> Result<bool> {
match std::mem::replace(&mut self.phase, Phase::None) {
Phase::Start(engine) => {
assets.push_fetch_engine(engine);
if self.paths.is_empty() {
self.phase = Phase::Ready;
} else {
self.phase = Phase::Loading;
for path in &self.paths {
if let Err(error) = assets.load(path) {
return Err(Error::Message(format!(
"Cannot load asset: {}\n{:?}",
path, error
)));
}
}
}
}
Phase::Loading => {
if assets.is_ready() && assets.are_ready(self.paths.iter()) {
assets.pop_fetch_engine();
self.phase = Phase::Ready;
} else {
self.phase = Phase::Loading;
}
}
Phase::Ready => {
self.phase = Phase::Ready;
return Ok(true);
}
Phase::None => {}
}
Ok(false)
}
pub fn is_ready(&self) -> bool {
matches!(self.phase, Phase::Ready)
}
}