diff --git a/.gitignore b/.gitignore index 8bc691d..b09796f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ output/ Cargo.lock target/ blobfox-*.zip +species/custom/ diff --git a/Cargo.toml b/Cargo.toml index b0f2f12..d358b4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,4 @@ usvg = "0.23" tiny-skia = "0.6" png = "0.17" css-color-parser = "0.1.2" +wax = "0.5.0" diff --git a/src/bin/snuggle.rs b/src/bin/snuggle.rs index 1a0bc3d..59d9d43 100644 --- a/src/bin/snuggle.rs +++ b/src/bin/snuggle.rs @@ -5,6 +5,7 @@ use std::path::PathBuf; use std::collections::HashMap; use serde::{Serialize, Deserialize}; use xmltree::{Element, XMLNode}; +use wax::{Glob, Pattern}; use blobfox_template::{ parse, @@ -37,6 +38,43 @@ struct Desc { right: HashMap, } +#[derive(Parser, Clone)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Path to the description + #[clap(short, long, value_parser)] + desc: PathBuf, + + /// Disable automatically resizing the SVG's viewBox, defaults to false + #[clap(short, long, value_parser, default_value = "false")] + no_resize: bool, + + /// Dimension to export the images as; can be specified multiple times + #[clap(long, value_parser)] + dim: Vec, + + /// Input directory, containing the svgs to combine + #[clap(short, long, value_parser)] + input_dir: Option, + + /// Output directory + #[clap(short, long, value_parser)] + output_dir: Option, + + /// A glob to filter which emotes to output; supports wildcards, like `blobfox_snuggle*` + #[clap(value_parser)] + glob: Option, +} + +impl From for export::ExportArgs { + fn from(args: Args) -> export::ExportArgs { + export::ExportArgs { + no_resize: args.no_resize, + dim: args.dim, + } + } +} + fn main() { let args = Args::parse(); let input_dir = args.input_dir.clone().unwrap_or(PathBuf::from("output/vector/")); @@ -45,6 +83,8 @@ fn main() { let files = std::fs::read_dir(&input_dir).unwrap_or_else(|err| { panic!("Couldn't read directory {}: {}", input_dir.display(), err); }).filter_map(|entry| { + std::fs::read_dir(entry.ok()?.path()).ok() + }).flatten().filter_map(|entry| { let entry = entry.ok()?; Some((entry.path().file_stem()?.to_str()?.to_string(), entry.path())) }).collect::>(); @@ -56,6 +96,8 @@ fn main() { let export_args: export::ExportArgs = args.clone().into(); + let glob = args.glob.as_ref().map(|s| Glob::new(s).expect("Invalid parameter glob")); + for (left_name, left_path) in desc.left.iter() { if let Some(left_path) = files.get(left_path) { let left = std::fs::read_to_string(left_path).unwrap_or_else(|err| { @@ -64,6 +106,13 @@ fn main() { for (right_name, right_path) in desc.right.iter() { if let Some(right_path) = files.get(right_path) { + let name = format!("{}_{}_{}", left_name, desc.name, right_name); + if let Some(ref glob) = &glob { + if !glob.is_match(&*name) { + continue // Skip this emote + } + } + let right = std::fs::read_to_string(&right_path).unwrap_or_else(|err| { panic!("Couldn't open {}: {}", right_path.display(), err); }); @@ -71,12 +120,11 @@ fn main() { let snuggle = generate_snuggle(&left, &right, &desc); let snuggle = export::xml_to_str(&snuggle).unwrap(); - let name = format!("{}_{}_{}", left_name, desc.name, right_name); - export::export( snuggle, &output_dir, - name, + &desc.name, + &name, &export_args ).unwrap(); } @@ -156,7 +204,7 @@ fn bolden(amount: f64, xml: &mut Element) { *stroke_width = format!("{}", parsed + amount); } } else if xml.attributes.contains_key("fill") { - xml.attributes.insert("stroke-width", amount.to_string()); + xml.attributes.insert("stroke-width".to_string(), amount.to_string()); } if let Some(style) = xml.attributes.get_mut("style") { @@ -188,36 +236,3 @@ fn bolden(amount: f64, xml: &mut Element) { } } } - -#[derive(Parser, Clone)] -#[clap(author, version, about, long_about = None)] -struct Args { - /// Path to the description - #[clap(short, long, value_parser)] - desc: PathBuf, - - /// Disable automatically resizing the SVG's viewBox, defaults to false - #[clap(short, long, value_parser, default_value = "false")] - no_resize: bool, - - /// Dimension to export the images as; can be specified multiple times - #[clap(long, value_parser)] - dim: Vec, - - /// Input directory, containing the svgs to combine - #[clap(short, long, value_parser)] - input_dir: Option, - - /// Output directory - #[clap(short, long, value_parser)] - output_dir: Option, -} - -impl From for export::ExportArgs { - fn from(args: Args) -> export::ExportArgs { - export::ExportArgs { - no_resize: args.no_resize, - dim: args.dim, - } - } -} diff --git a/src/export.rs b/src/export.rs index 8f730b8..f6442f5 100644 --- a/src/export.rs +++ b/src/export.rs @@ -185,7 +185,8 @@ pub fn combine_defs(svg_str: String) -> Result { pub fn export( mut svg_str: String, output_dir: &PathBuf, - output_name: String, + species_name: &str, + output_name: &str, args: &ExportArgs, ) -> Result<(), ExportError> { if !args.no_resize { @@ -196,15 +197,15 @@ pub fn export( svg_str = combine_defs(svg_str)?; - mkdirp::mkdirp(output_dir.join("vector")).unwrap(); + mkdirp::mkdirp(output_dir.join(format!("vector/{}", species_name))).unwrap(); - let output = output_dir.join(&format!("vector/{}.svg", output_name)); + let output = output_dir.join(&format!("vector/{}/{}.svg", species_name, output_name)); std::fs::write(output.clone(), svg_str.clone()).map_err(|err| ExportError::Io(output, err))?; let svg_usvg = get_usvg(&svg_str)?; for resolution in args.dim.iter().copied().filter(|r| *r != 0).collect::>() { - mkdirp::mkdirp(output_dir.join(&format!("{}", resolution))).unwrap(); - let output = output_dir.join(&format!("{}/{}.png", resolution, output_name)); + mkdirp::mkdirp(output_dir.join(&format!("{}/{}", resolution, species_name))).unwrap(); + let output = output_dir.join(&format!("{}/{}/{}.png", resolution, species_name, output_name)); let mut image = tiny_skia::Pixmap::new(resolution, resolution).unwrap(); diff --git a/src/main.rs b/src/main.rs index f063643..b3bd418 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,8 @@ fn generate_variant(context: &RenderingContext, name: &str, output_dir: &PathBuf match export( svg, output_dir, - format!("{}_{}", context.species().name, name), + &context.species().name, + &format!("{}_{}", context.species().name, name), &args ) { Ok(_) => {}