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
86
87
88
89
90
91
92
use common::assets;
use serde::Deserialize;
use std::path::PathBuf;

// NOTE: we are free to split the manifest asset format and the format processed
// for display into separate structs but they happen to be identical for now

// See best practices for attribution: https://wiki.creativecommons.org/wiki/Best_practices_for_attribution

#[allow(dead_code)]
#[derive(Clone, Deserialize)]
pub struct Art {
    /// Name of the art.
    pub name: String,
    /// Link if the asset is from or derived from an external source that can be
    /// linked.
    #[serde(default)]
    pub source_link: String,
    /// List of authors for the credited art, field can be omitted if there are
    /// no authors to list.
    #[serde(default)]
    pub authors: Vec<String>,
    /// Relative path to the asset from the top level asset folder.
    /// Used so we can keep track of the actual files, but not currently used in
    /// the credits screen to display anything.
    pub asset_path: PathBuf,
    /// License that the art is under, can be omitted, if not present assumed to
    /// be GPL3.
    #[serde(default)]
    pub license: String,
    /// Link to the license if one is available.
    #[serde(default)]
    pub license_link: String,
    /// Notes on any modifications that were made if the original work was
    /// modified by us.
    #[serde(default)]
    pub modifications: String,
    /// Any additional attribution notes that may be desired and/or required by
    /// the respective license that can't be conveyed or would be awkward to
    /// convey with the other provided fields.
    #[serde(default)]
    pub notes: String,
}

#[derive(Clone, Deserialize)]
pub struct Contributor {
    pub name: String,
    /// Short note or description of the contributions
    /// Optional, can be left empty/omitted
    #[serde(default)]
    pub contributions: String,
}

/// Credits manifest processed into format for display in the UI
#[derive(Clone, Deserialize)]
pub struct Credits {
    pub music: Vec<Art>,
    pub fonts: Vec<Art>,
    pub other_art: Vec<Art>,
    pub contributors: Vec<Contributor>,
    // TODO: include credits for dependencies where the license requires attribution?
}

impl assets::Asset for Credits {
    type Loader = assets::RonLoader;

    const EXTENSION: &'static str = "ron";
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn all_art_asset_paths_exists() {
        use assets::AssetExt;
        let credits = Credits::load_expect_cloned("credits");

        credits
            .music
            .into_iter()
            .chain(credits.fonts)
            .chain(credits.other_art)
            .for_each(|art| {
                assert!(
                    assets::ASSETS_PATH.join(&art.asset_path).exists(),
                    "assets/{} does not exist!",
                    art.asset_path.display(),
                );
            });
    }
}