use std::collections::HashMap;
use std::error::Error;
use std::fs;
use std::fs::File;
use std::path::PathBuf;
use crate::config::{ASSET_DIR, ASSETS_DIST_SUBDIR, ASSETS_FINAL_SUBDIR, ASSETS_SRC_SUBDIR};
use crate::ninja::NinjaWriter;
pub fn configure_assets(writer: &mut NinjaWriter<File>, root: &PathBuf) -> Result<(), Box<dyn Error>> {
// scan for assets
let asset_src_dir = root.join(ASSET_DIR).join(ASSETS_SRC_SUBDIR);
let mut found_assets = vec![];
let files_in_src_dir = fs::read_dir(asset_src_dir)?;
for maybe_asset in files_in_src_dir {
let maybe_asset = maybe_asset?;
if maybe_asset.file_name().to_str().unwrap().ends_with(".svg") {
found_assets.push(maybe_asset.path());
}
}
println!("[spacetime] asset scan: found {} assets", found_assets.len());
let default_asset_size = 512;
let asset_overrides = HashMap::from([
("earth.ink.svg", 2048),
("moon.ink.svg", 2048)
]);
// generate an inkscape rule for all required asset sizes
let mut written_rules_for = vec![];
gen_inkscape_rule(default_asset_size, writer, &mut written_rules_for)?;
for size in asset_overrides.values() {
gen_inkscape_rule(*size, writer, &mut written_rules_for)?;
}
println!("[spacetime] generated {} image conversion rules", written_rules_for.len() * 3);
let mut files_375 = vec![];
let mut files_125 = vec![];
let mut files_full = vec![];
for asset in &found_assets {
gen_convert_rule(asset, root, writer, &mut files_375, &mut files_full, &mut files_125, asset_size(asset.to_str().unwrap(), &asset_overrides, default_asset_size))?;
}
println!("[spacetime] generated {} image conversion steps", files_full.len() + files_125.len() + files_375.len());
gen_packer_rule(root, writer, &files_375, &files_full, &files_125)?;
println!("[spacetime] generated asset build commands");
Ok(())
}
fn gen_packer_rule(root: &PathBuf, writer: &mut NinjaWriter<File>, files_375: &Vec<PathBuf>, files_full: &Vec<PathBuf>, files_125: &Vec<PathBuf>) -> Result<(), Box<dyn Error>> {
writer.rule("pack", &format!("cd {} && atlasify -m 4096,4096 -o $out $in && touch $out", root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).to_string_lossy()), None, None, None, Some("console"), None, None, None, None)?;
writer.build(vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-full").to_str().unwrap().to_string()], "pack".to_string(), files_full.iter().map(|u| u.to_str().unwrap().to_string()).collect(), vec![], vec![], HashMap::new(), vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-full.json").to_str().unwrap().to_string(), root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-full.png").to_str().unwrap().to_string()], None, None)?;
writer.build(vec!["asset-full".to_string()], "phony".to_string(), vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-full").to_str().unwrap().to_string()], vec![], vec![], HashMap::new(), vec![], None, None)?;
writer.build(vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-125").to_str().unwrap().to_string()], "pack".to_string(), files_125.iter().map(|u| u.to_str().unwrap().to_string()).collect(), vec![], vec![], HashMap::new(), vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-125.json").to_str().unwrap().to_string(), root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-125.png").to_str().unwrap().to_string()], None, None)?;
writer.build(vec!["asset-125".to_string()], "phony".to_string(), vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-125").to_str().unwrap().to_string()], vec![], vec![], HashMap::new(), vec![], None, None)?;
writer.build(vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-375").to_str().unwrap().to_string()], "pack".to_string(), files_375.iter().map(|u| u.to_str().unwrap().to_string()).collect(), vec![], vec![], HashMap::new(), vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-375.json").to_str().unwrap().to_string(), root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-375.png").to_str().unwrap().to_string()], None, None)?;
writer.build(vec!["asset-375".to_string()], "phony".to_string(), vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-375").to_str().unwrap().to_string()], vec![], vec![], HashMap::new(), vec![], None, None)?;
writer.build(vec!["asset".to_string()], "phony".to_string(), vec![root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-375").to_str().unwrap().to_string(), root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-full").to_str().unwrap().to_string(), root.join(ASSET_DIR).join(ASSETS_DIST_SUBDIR).join("spritesheet-125").to_str().unwrap().to_string()], vec![], vec![], HashMap::new(), vec![], None, None)?;
Ok(())
}
fn gen_convert_rule(asset: &PathBuf, root: &PathBuf, writer: &mut NinjaWriter<File>, files_375: &mut Vec<PathBuf>, files_full: &mut Vec<PathBuf>, files_125: &mut Vec<PathBuf>, size: i32) -> Result<(), Box<dyn Error>> {
let out_full = root.join(ASSET_DIR).join(ASSETS_FINAL_SUBDIR).join("full/").join(asset.file_stem().unwrap().to_str().unwrap().to_string() + ".png");
files_full.push(out_full.clone());
let rule_full = format!("inkscape_{}_px_full", size);
writer.build(vec![out_full.to_str().unwrap().to_string()], rule_full, vec![asset.to_str().unwrap().to_string()], vec![], vec![], HashMap::new(), vec![], None, None)?;
let out_375 = root.join(ASSET_DIR).join(ASSETS_FINAL_SUBDIR).join("375/").join(asset.file_stem().unwrap().to_str().unwrap().to_string() + ".png");
files_375.push(out_375.clone());
let rule_375 = format!("inkscape_{}_px_375", size);
writer.build(vec![out_375.to_str().unwrap().to_string()], rule_375, vec![asset.to_str().unwrap().to_string()], vec![], vec![], HashMap::new(), vec![], None, None)?;
let out_125 = root.join(ASSET_DIR).join(ASSETS_FINAL_SUBDIR).join("125/").join(asset.file_stem().unwrap().to_str().unwrap().to_string() + ".png");
files_125.push(out_125.clone());
let rule_125 = format!("inkscape_{}_px_125", size);
writer.build(vec![out_125.to_str().unwrap().to_string()], rule_125, vec![asset.to_str().unwrap().to_string()], vec![], vec![], HashMap::new(), vec![], None, None)?;
Ok(())
}
fn asset_size(asset: &str, overrides: &HashMap<&str, i32>, default: i32) -> i32 {
*overrides.get(asset).unwrap_or(&default)
}
fn gen_inkscape_rule(size: i32, writer: &mut NinjaWriter<File>, written: &mut Vec<i32>) -> Result<(), Box<dyn Error>> {
if written.contains(&size) {
return Ok(())
}
writer.rule(&format!("inkscape_{}_px_full", size), &format!("inkscape -w {} -h {} $in -o $out", size, size), None, None, None, None, None, None, None, None)?;
writer.rule(&format!("inkscape_{}_px_375", size), &format!("inkscape -w {} -h {} $in -o $out", (size as f64 * 0.375) as i32, (size as f64 * 0.375) as i32), None, None, None, None, None, None, None, None)?;
writer.rule(&format!("inkscape_{}_px_125", size), &format!("inkscape -w {} -h {} $in -o $out", (size as f64 * 0.125) as i32, (size as f64 * 0.125) as i32), None, None, None, None, None, None, None, None)?;
written.push(size);
Ok(())
}