Wire bake orchestrator and CLI
Connects scan + lock + pack + write into the full pipeline. CLI entry parses args, dispatches to bake(), prints summary or error. Five integration tests cover fresh bake, lock-aware ID preservation, deleted-tile tracking, oversize hard-fail, and bit-identical determinism across re-bakes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
71
src/bake.js
Normal file
71
src/bake.js
Normal file
@@ -0,0 +1,71 @@
|
||||
// src/bake.js
|
||||
const path = require('node:path');
|
||||
const { scanSourceDir } = require('./scan');
|
||||
const { loadLock, assignIds, serializeLock } = require('./lock');
|
||||
const { packMaxRects } = require('./pack');
|
||||
const { probeImageDims, composeAtlas, buildAtlasJson, writeOutputs } = require('./write');
|
||||
|
||||
async function bake(opts) {
|
||||
const {
|
||||
inDir,
|
||||
outDir,
|
||||
atlasId,
|
||||
tileSize = 64,
|
||||
maxSize = 4096,
|
||||
lockPath,
|
||||
blocksSightPattern,
|
||||
} = opts;
|
||||
|
||||
if (!atlasId) throw new Error('bake: --atlas-id is required');
|
||||
if (!inDir) throw new Error('bake: --in is required');
|
||||
if (!outDir) throw new Error('bake: --out is required');
|
||||
|
||||
const scanResult = scanSourceDir(inDir);
|
||||
if (scanResult.errors.length > 0) {
|
||||
const e = new Error(scanResult.errors[0]);
|
||||
e.scanErrors = scanResult.errors;
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Determine each source's tile-dimensions.
|
||||
// - If --tile-size is a positive integer, all tiles are forced to that
|
||||
// size (composeAtlas auto-resizes mismatched sources via jimp).
|
||||
// - If --tile-size === 'auto', each tile keeps its native dims.
|
||||
for (const src of scanResult.sources) {
|
||||
if (tileSize && tileSize !== 'auto') {
|
||||
src.w = tileSize;
|
||||
src.h = tileSize;
|
||||
} else {
|
||||
const dims = await probeImageDims(src.diffusePath);
|
||||
src.w = dims.width;
|
||||
src.h = dims.height;
|
||||
}
|
||||
}
|
||||
|
||||
const existingLock = loadLock(lockPath || path.join(outDir, 'tiles.atlas.lock.json'));
|
||||
const { tiles, lock } = assignIds(scanResult.sources, existingLock, atlasId);
|
||||
|
||||
const packResult = packMaxRects(tiles, maxSize);
|
||||
if (packResult.error) {
|
||||
throw new Error(packResult.message);
|
||||
}
|
||||
|
||||
const { diffuse, height } = await composeAtlas(packResult.placed, packResult.boundsW, packResult.boundsH);
|
||||
const atlasJson = buildAtlasJson(
|
||||
atlasId, 1, (tileSize === 'auto') ? null : tileSize,
|
||||
packResult.boundsW, packResult.boundsH,
|
||||
packResult.placed,
|
||||
blocksSightPattern,
|
||||
);
|
||||
|
||||
writeOutputs(outDir, diffuse, height, atlasJson, lock);
|
||||
return {
|
||||
outDir,
|
||||
atlasId,
|
||||
tileCount: packResult.placed.length,
|
||||
boundsW: packResult.boundsW,
|
||||
boundsH: packResult.boundsH,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { bake };
|
||||
Reference in New Issue
Block a user