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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use crate::{
    assets::{database::AssetsDatabase, protocols::pack::PackAsset},
    error::*,
};

#[derive(Debug)]
pub struct AssetPackPreloader {
    paths: Vec<String>,
    ready_pack: bool,
    ready_from_pack: bool,
}

impl AssetPackPreloader {
    pub fn new(
        path: &str,
        assets: &mut AssetsDatabase,
        assets_from_pack: Vec<&str>,
    ) -> Result<Self> {
        let path = format!("pack://{}", path);
        if let Err(error) = assets.load(&path) {
            Err(Error::Message(format!(
                "Could not load asset pack: {}\n{:?}",
                path, error
            )))
        } else {
            let paths = std::iter::once(path)
                .chain(assets_from_pack.into_iter().map(|p| p.to_owned()))
                .collect::<Vec<String>>();
            Ok(Self {
                paths,
                ready_pack: false,
                ready_from_pack: false,
            })
        }
    }

    pub fn process(&mut self, assets: &mut AssetsDatabase) -> Result<bool> {
        if !self.ready_pack {
            if assets.are_ready(self.paths.iter().take(1)) {
                let path = &self.paths[0];
                if let Some(asset) = assets.asset_by_path(path) {
                    if let Some(pack) = asset.get::<PackAsset>() {
                        let engine = pack.make_fetch_engine();
                        assets.push_fetch_engine(Box::new(engine));
                        self.ready_pack = true;
                        if self.paths.len() > 1 {
                            for path in self.paths.iter().skip(1) {
                                if let Err(error) = assets.load(path) {
                                    return Err(Error::Message(format!(
                                        "Cannot load asset from pack: {}\n{:?}",
                                        path, error
                                    )));
                                }
                            }
                        } else {
                            self.ready_from_pack = true;
                        }
                    } else {
                        return Err(Error::Message(format!("Asset is not a pack: {}", path)));
                    }
                } else {
                    return Err(Error::Message(format!(
                        "Asset pack is not loaded: {}",
                        path
                    )));
                }
            }
            if !self.ready_pack {
                return Ok(false);
            }
        }
        if !self.ready_from_pack {
            if assets.are_ready(self.paths.iter().skip(1)) {
                self.ready_from_pack = true;
            } else {
                return Ok(false);
            }
        }
        Ok(true)
    }

    pub fn is_ready(&self) -> bool {
        self.ready_pack && self.ready_from_pack
    }
}