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'); const { mkdirp } = require('../utils/file'); // Parse Args // if(!args.temp) throw new Error(`Missing temp argument`); if(!args.in) throw new Error(`Missing in argument`); if(!args.out) throw new Error(`Missing out argument`); if(!args.dep) throw new Error(`Missing dep 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); console.log(outFile); // const cOut = path.resolve(args.temp, 'vn', `${args.dep}.c`); // const hOut = path.resolve(args.temp, 'vn', `${args.dep}.h`); if(!fs.existsSync(file)) throw new Error(`Could not find ${file}`); // if(fs.existsSync(outFile) && fs.existsSync(cOut) && fs.existsSync(hOut)) return; 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(path.dirname(file), 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; let strLayers = ``; 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 ); } strLayers += ` vnCharacterLayerAdd(vnc, ${scan.length}, ${baseImage.width}, ${y}, ${layer.x}, ${layer.y}, ${layer.width}, ${layer.height} ); `; y += layer.height; } mkdirp(outFile); await imageWrite(out, outFile); let name = character.attributes.name || args.name || args.dep; // mkdirp(cOut); // fs.writeFileSync(cOut, ` // #include "${args.dep}.h" // void vnCharacter${name}Init(vncharacter_t *vnc, texture_t *texture) { // assetTextureLoad(texture, VN_CHARACTER_${name.toUpperCase()}_TEXTURE); // vnCharacterInit(vnc, texture); // // Base Layer // vnCharacterLayerAdd(vnc, 1, 0, 0, 0, 0, ${baseImage.width}, ${baseImage.height}); // // Layers // ${strLayers} // } // `); // fs.writeFileSync(hOut, ` // #pragma once // #include // #include // #include // #include // #define VN_CHARACTER_${name.toUpperCase()}_TEXTURE "${args.out}" // void vnCharacter${name}Init(vncharacter_t *vnc, texture_t *texture); // `); })().catch(console.error);