UNPKG

psd2prefab

Version:

A tool to convert psd to a unity prefab.

96 lines 4.22 kB
import fs from 'fs-extra'; import path from 'path'; import pixelmatch from 'pixelmatch'; import { PNG } from 'pngjs'; import randomstring from 'randomstring'; import { readPsd } from 'ag-psd'; import 'ag-psd/dist/initializeCanvas.js'; import env from './Env.js'; import { PrefabGenerator } from './PrefabGenerator.js'; export class Convertor { nameUsageMap = {}; canvasFileMap = {}; canvasMap = {}; prefabGen = new PrefabGenerator(); async make() { const buffer = await fs.readFile(env.opts.input); // read only document structure // const psd1 = readPsd(buffer, { skipCompositeImageData: true, skipThumbnail: true, skipLinkedFilesData: true }) const psd = readPsd(buffer, { skipCompositeImageData: true, skipThumbnail: true, skipLinkedFilesData: true }); // by defaults `canvas` field type is HTMLCanvasElement, so it needs to be cast to `any` // or node-canvas `Canvas` type, in order to call `toBuffer` method if (psd.children !== undefined) { for (const child of psd.children) { if (child.hidden === true) continue; await this.saveCanvas(child); } } await this.prefabGen.make(psd); } async saveCanvas(layer) { if (layer.canvas !== undefined && (layer.text === undefined || this.prefabGen.isArtFont(layer))) { const canvas = layer.canvas; const canvasURL = canvas.toDataURL(); let pngFile = this.canvasFileMap[canvasURL]; if (pngFile === undefined) { // compare buffers const buffer = canvas.toBuffer(); const png = PNG.sync.read(buffer); const size = `${canvas.width}x${canvas.height}`; let infos = this.canvasMap[size]; if (infos !== undefined) { for (const info of infos) { const diff = pixelmatch(png.data, info.png.data, null, png.width, png.height, { threshold: 0.1 }); if (diff === 0) { console.log(`${layer.name ?? '??'} is exactly the same as ${info.file} by PIXELMATCH`); pngFile = info.file; break; } } } else { this.canvasMap[size] = infos = []; } if (pngFile === undefined) { let pngName = layer.name; if (pngName === undefined) { pngName = 'noname'; } else { // remove slashes pngName = pngName.replace(/\s+/g, '').replace(/\//g, '').replace(/\\/g, ''); } // if (pngName === '多边形1') { // console.log(canvasURL) // } if (pngName in this.nameUsageMap) { pngName += '_' + randomstring.generate(6); } this.nameUsageMap[pngName] = 1; pngFile = path.join(env.cfg.PNG_ROOT.replace(/\$name\$/g, env.opts.name), pngName + '.png'); this.canvasFileMap[canvasURL] = pngFile; infos.push({ buffer, png, file: pngFile }); console.log('saving png:', pngFile); const pngPath = path.join(env.opts.project, pngFile); await fs.ensureDir(path.dirname(pngPath)); await fs.writeFileSync(pngPath, buffer); } } else { console.log(`${layer.name ?? '??'} is exactly the same as ${pngFile} by URL`); } const layerAlias = layer; layerAlias.pngFile = pngFile; } if (layer.children !== undefined) { for (const child of layer.children) { if (child.hidden === true) continue; await this.saveCanvas(child); } } } } //# sourceMappingURL=Convertor.js.map