-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.rs
172 lines (139 loc) · 3.75 KB
/
main.rs
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#![allow(dead_code, unused_imports)]
use custom_error::custom_error;
use std::env;
use std::fmt::Display;
use std::format as fmt;
use std::fs::File;
use std::io;
use structopt::StructOpt;
mod dep;
mod draw;
mod parse;
use crate::parse::SpriteT::Overlay;
use dep::*;
use draw::*;
use parse::*;
use std::path::{Path, PathBuf};
#[derive(StructOpt, Debug)]
#[structopt()]
struct Opts {
/// Output dir
#[structopt(short, long, parse(from_os_str))]
dir: Option<PathBuf>,
/// Limit variants to draw per sprite
#[structopt(short, long)]
limit: Option<usize>,
/// .lay files to parse
#[structopt(name = "LAY_FILES", parse(from_os_str))]
lay_files: Vec<PathBuf>,
/// Perform parsing only to test for errors.
/// Do not compose actual images
#[structopt(long)]
dry_run: bool,
}
custom_error! { pub PErr
IO{source: io::Error} = "IO: {source}",
Img{source: image::ImageError} = "image: {source}",
Etc{msg: String} = "{msg}",
}
#[inline]
fn raise_e(m: impl Into<String>) -> PErr {
PErr::Etc { msg: m.into() }
}
#[inline]
fn raise<T>(m: impl Into<String>) -> Result<T, PErr> {
Err(raise_e(m))
}
fn print_err(e: impl Display) {
eprintln!("[E] {}", e);
}
const LAY_EXT: &[&str] = &["_.lay", ".lay"];
const SRC_EXT: &str = ".png";
fn main() {
if let Err(e) = main_() {
print_err(e);
}
}
fn main_() -> Result<(), PErr> {
let o = Opts::from_args();
let layouts = &o.lay_files;
let out_dir = &o.dir;
match out_dir {
Some(d) if !d.is_dir() => return raise("out_dir isn't a directory"),
None if !o.dry_run => {
return raise("Output dir should be specified (-d)\nSee --help for details")
}
_ => (),
}
let total = o.lay_files.len();
if total == 0 {
return raise("no .lay files provided");
}
let status = |c: usize| move |t: &str| println!("[{}/{}] {}", c + 1, total, t);
for i in 0..layouts.len() {
if let Err(e) = lay_in(out_dir, &layouts[i], o.limit, !o.dry_run, status(i)) {
print_err(e);
}
}
Ok(())
}
fn lay_in(
out_dir: &Option<PathBuf>,
lay_i: &Path,
limit: Option<usize>,
draw_en: bool,
status: impl Fn(&str),
) -> Result<(), PErr> {
let limit_en = limit.is_some();
let limit = limit.unwrap_or(0);
let (lay_fn, lay_ext) = lay_i
.file_name()
.and_then(|n| n.to_str())
.and_then(|f| LAY_EXT.iter().find(|e| f.ends_with(**e)).map(|e| (f, e)))
.ok_or_else(|| raise_e("not a lay file"))?;
let sprite_name = lay_fn.trim_end_matches(lay_ext);
let src_fn = fmt!("{}{}", sprite_name, SRC_EXT);
let src_pa: PathBuf = {
let mut pb = PathBuf::new();
let p = lay_i.parent().ok_or_else(|| raise_e("no parent"))?;
pb.push(p);
pb.push(src_fn);
pb
};
status(sprite_name);
let lay = parse_lay(&mut File::open(lay_i)?)?;
let dep_refs = resolve_rc(&lay);
let leafs = leaf_sprites(&dep_refs);
let mut src = if draw_en {
Some(draw_prep(&src_pa)?)
} else {
None
};
for (pass, sp) in leafs.enumerate() {
if limit_en && pass >= limit {
eprintln!("[I] Limit reached, proceeding to next sprite");
break;
}
if sp.s.t == Overlay {
eprintln!("[W] Overlays are unsupported, skipping");
continue;
}
let s = sp.s;
let name_suf = match s.t {
SpriteT::Base => fmt!("b{}", s.id),
SpriteT::Sub => fmt!("s{}", s.id),
SpriteT::Dep { st, dep } => fmt!("t{}_d{}_{}", st, dep, s.id),
SpriteT::Overlay => fmt!("o{}", s.id),
};
let dep_lst = resolve_dep_list(&dep_refs, sp)?;
if let Some(src_i) = src.as_mut() {
let mut out = PathBuf::new();
out.push(out_dir.as_ref().unwrap());
out.push(fmt!("{}_{}{}", sprite_name, name_suf, SRC_EXT));
if let Err(e) = draw_sprites(src_i, &out, dep_lst.as_ref(), pass + 1, &lay) {
print_err(e);
}
}
}
Ok(())
}