psd2prefab
Version:
A tool to convert psd to a unity prefab.
96 lines • 4.22 kB
JavaScript
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