Skip to main content

flatland_presentation/
player_config.rs

1//! Designer-authored player gfx presentation (`assets/gfx/player-presentation.yaml`).
2
3use std::path::Path;
4
5use serde::Deserialize;
6
7use crate::SpriteModeMap;
8
9#[derive(Debug, Clone, Default, Deserialize)]
10pub struct PlayerPresentationDoc {
11    #[serde(default)]
12    pub player_presentation: PlayerPresentationConfig,
13}
14
15#[derive(Debug, Clone, Default, Deserialize)]
16pub struct PlayerPresentationConfig {
17    #[serde(default)]
18    pub tile_id: Option<String>,
19    #[serde(default)]
20    pub sprite_modes: SpriteModeMap,
21}
22
23impl PlayerPresentationConfig {
24    pub fn empty() -> Self {
25        Self::default()
26    }
27}
28
29pub fn default_player_presentation_path() -> Option<std::path::PathBuf> {
30    let mut dir = std::env::current_dir().ok()?;
31    for _ in 0..6 {
32        let candidate = dir.join("assets/gfx/player-presentation.yaml");
33        if candidate.is_file() {
34            return Some(candidate);
35        }
36        if !dir.pop() {
37            break;
38        }
39    }
40    None
41}
42
43pub fn load_player_presentation(
44    path: impl AsRef<Path>,
45) -> anyhow::Result<PlayerPresentationConfig> {
46    let raw = std::fs::read_to_string(path.as_ref())?;
47    let doc: PlayerPresentationDoc = serde_yaml::from_str(&raw)?;
48    Ok(doc.player_presentation)
49}
50
51pub fn load_player_presentation_default() -> PlayerPresentationConfig {
52    default_player_presentation_path()
53        .and_then(|p| load_player_presentation(&p).ok())
54        .unwrap_or_default()
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn loads_repo_default() {
63        let path = default_player_presentation_path().expect("player-presentation.yaml");
64        let cfg = load_player_presentation(&path).expect("parse");
65        assert!(cfg.tile_id.is_some() || !cfg.sprite_modes.is_empty());
66    }
67}