unity-find-fault
Version:
A tool to find fault in unity project.
97 lines • 4.12 kB
JavaScript
import bytes from "bytes";
import fg from "fast-glob";
import fs from "fs-extra";
import path from "path";
import sharp from "sharp";
import { UnityHelper } from "./UnityHelper.js";
import { toolchain } from "../toolchain.js";
export class NPOT {
imgRoots = ['.'];
async fixAll() {
let minSize = toolchain.opts.minSize ? bytes(toolchain.opts.minSize) : 0;
if (toolchain.opts.input) {
await this.fixNPOT(path.join(toolchain.opts.projectRoot, toolchain.opts.input), true);
return;
}
const assetsRoot = path.join(toolchain.opts.projectRoot, 'Assets/AssetSources');
for (const ir of this.imgRoots) {
const imgRoot = path.join(assetsRoot, ir);
const imgs = await fg(['**/*.png', '**/*.jpg'], { cwd: imgRoot, ignore: ['font/**/@**/**/*'] });
for (const img of imgs) {
const file = path.join(imgRoot, img);
const fstat = await fs.stat(file);
if (minSize > 0) {
if (fstat.size < minSize) {
continue;
}
}
if (ir.includes('atlas/') && fstat.size < 51200) {
// 图集图片对大尺寸的图进行调整
continue;
}
await this.fixNPOT(file, false);
}
}
}
async fixNPOT(file, force) {
const s = sharp(file);
const meta = await s.metadata();
if (meta.width == null || meta.height == null) {
console.error('Cannot get width/height:', file);
return;
}
if (!force) {
if (toolchain.opts.minWh != null && meta.width < toolchain.opts.minWh && meta.height < toolchain.opts.minWh) {
return;
}
if (file.includes('atlas') && meta.width < 2048 && meta.height < 2048) {
// 图集图片对大尺寸的图进行调整
return;
}
}
let w = meta.width;
let h = meta.height;
// 读入maxTextureSize
const texture = await UnityHelper.loadMeta(file + '.meta');
const psMap = {};
for (const ps of texture.TextureImporter.platformSettings) {
psMap[ps.buildTarget] = ps.maxTextureSize;
}
const maxTextureSize = psMap['WebGL'] || psMap['DefaultTexturePlatform'];
const maxWH = Math.max(meta.width, meta.height);
// 如果原图尺寸超过maxTextureSize,需先进行缩放
if (maxWH > maxTextureSize) {
if (meta.width > meta.height) {
w = maxTextureSize;
h = Math.round(maxTextureSize / meta.width * meta.height);
}
else {
h = maxTextureSize;
w = Math.round(maxTextureSize / meta.height * meta.width);
}
}
if (w % 4 != 0 || h % 4 != 0) {
let nw = w % 4 == 0 ? w : (w + 4 - (w % 4));
let nh = h % 4 == 0 ? h : (h + 4 - (h % 4));
if (maxWH > maxTextureSize) {
// 恢复缩放
if (meta.width > meta.height) {
nw = Math.round(nw * meta.width / maxTextureSize);
nh = Math.round(nh * meta.width / maxTextureSize);
}
else {
nw = Math.round(nw * meta.height / maxTextureSize);
nh = Math.round(nh * meta.height / maxTextureSize);
}
}
const tmpSave = 'npot.tmp' + path.extname(file);
// 注意如果fit设置为contain,默认填充黑色不透明背景,需设置background
// await s.resize(nw, nh, { fit: 'contain', background: { r: 255, g: 255, b: 255, alpha: 0 } }).toFile(tmpSave);
await s.resize(nw, nh, { fit: 'fill' }).toFile(tmpSave);
await fs.copyFile(tmpSave, file);
await fs.unlink(tmpSave);
console.log(file, `${meta.width}×${meta.height} -> ${nw}×${nh}`);
}
}
}
//# sourceMappingURL=NPOT.js.map