lpcg/
builder.rs

1use std::{
2    fmt::Display,
3    path::{Path, PathBuf},
4};
5
6use crate::{input::Input, layer::Layer};
7use image::{imageops, DynamicImage};
8
9pub struct Builder {
10    spritesheets: PathBuf,
11}
12
13impl Builder {
14    pub fn new(spritesheets: PathBuf) -> Self {
15        Self { spritesheets }
16    }
17
18    pub fn build(&self, input: Input) -> BuildResult {
19        let mut result = BuildResult::new();
20        let mut background_path = self.spritesheets.clone();
21        background_path.push("background.png");
22        let mut final_image = match image::open(&background_path) {
23            Ok(image) => image,
24            Err(error) => {
25                return BuildResult::error(BuildError::UnexpectedError(format!(
26                    "Unable to open '{:?}' file : {}",
27                    background_path, error
28                )))
29            }
30        };
31
32        for layer in input.layers() {
33            let layer_path = match layer.path(Path::new(&self.spritesheets)) {
34                Ok(layer_path) => layer_path,
35                Err(error) => {
36                    result
37                        .errors
38                        .push(BuildError::LayerError(layer.clone(), error.to_string()));
39                    continue;
40                }
41            };
42            let layer_image = match image::open(&layer_path) {
43                Ok(image) => image,
44                Err(error) => {
45                    result.errors.push(BuildError::LayerError(
46                        layer.clone(),
47                        format!("{:?} : '{}'", layer_path, error),
48                    ));
49                    continue;
50                }
51            };
52            imageops::overlay(&mut final_image, &layer_image, 0, 0);
53        }
54
55        result.output = Some(final_image);
56        result
57    }
58}
59
60#[derive(Clone)]
61pub enum BuildError {
62    LayerError(Layer, String),
63    UnexpectedError(String),
64}
65
66impl Display for BuildError {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        match self {
69            BuildError::LayerError(layer, error) => {
70                f.write_str(&format!("Layer error '{}' : '{}'", layer.name(), error))
71            }
72            BuildError::UnexpectedError(error) => {
73                f.write_str(&format!("Unexpected error : '{}'", error))
74            }
75        }
76    }
77}
78
79pub struct BuildResult {
80    pub errors: Vec<BuildError>,
81    pub output: Option<DynamicImage>,
82}
83
84impl BuildResult {
85    pub fn error(error: BuildError) -> Self {
86        Self {
87            errors: vec![error],
88            output: None,
89        }
90    }
91    pub fn new() -> Self {
92        Self {
93            errors: vec![],
94            output: None,
95        }
96    }
97}