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}