Dawn/tools/vn/character-sheet-generator.js

88 lines
2.5 KiB
JavaScript

const path = require('path');
const { imageCreate, imageWrite, imageLoad, imageCopy } = require('./../utils/image');
const fs = require('fs');
const xml = require('xml-js');
const { args } = require('./../utils/args');
// Parse Args
if(!args.in) throw new Error(`Missing in argument`);
if(!args.out) throw new Error(`Missing out argument`);
if(!args.in.endsWith('xml')) throw new Error(`Invalid in XML`);
if(!args.out.endsWith('png')) throw new Error(`Invalid out PNG`);
// Determine in and out.
const file = path.resolve(args.in);
const outFile = path.resolve(args.out);
if(fs.existsSync(outFile)) return;
// Load XML
const data = xml.xml2js(fs.readFileSync(file, 'utf-8'));
const [ character ] = data.elements;
// Validate file.
if(!character.attributes.context) throw new Error(`Missing context`)
const dir = path.resolve('.', 'assets', character.attributes.context);
// Parse base and layers
const base = character.elements.find(e => e.name == 'base').attributes;
if(!base) throw new Error(`Failed to find base`);
const layers = character.elements
.filter(e => e.name == 'layer')
.map(e => e.attributes)
.map(e => ({
...e,
x: parseInt(e.x),
y: parseInt(e.y),
width: parseInt(e.width),
height: parseInt(e.height)
}))
;
(async () => {
// Load the base
const baseImage = await imageLoad(path.join(dir, base.file));
let columnsMax = 0;
let widthMax = 0;
layers.forEach((layer,row) => {
if(!layer.width || !layer.height || !layer.x || !layer.y) {
throw new Error(`Missing layer info`);
}
const layerDir = path.join(dir, layer.directory);
const scan = fs.readdirSync(layerDir);
columnsMax = Math.max(scan.length, columnsMax);
widthMax = Math.max(widthMax, layer.width);
});
// Create the output buffer
const out = imageCreate(
baseImage.width + (columnsMax * widthMax),
baseImage.height
);
// Copy the base
imageCopy(out, baseImage, 0, 0);
// Now begin copying the children, row is defined by the directory
let y = 0;
for(let row = 0; row < layers.length; row++) {
const layer = layers[row];
const layerDir = path.join(dir, layer.directory);
const scan = fs.readdirSync(layerDir);
// Column defined by the file index
for(let col = 0; col < scan.length; col++) {
const img = await imageLoad(path.join(layerDir, scan[col]));
console.log('Copying', scan[col]);
imageCopy(out, img,
baseImage.width+(col*layer.width), y,
layer
);
}
y += layer.height;
}
await imageWrite(out, outFile);
})().catch(console.error);