2026-05-20 16:53:23 -04:00
|
|
|
/* Render a scene to a print-ready CMYK PDF from the CLI.
|
|
|
|
|
Two modes:
|
|
|
|
|
node tools/render-pdf.mjs --seed SEED [outfile] [pagePt] (seed → all params)
|
|
|
|
|
node tools/render-pdf.mjs [preset] [seed] [outfile] (legacy preset mode)
|
|
|
|
|
*/
|
|
|
|
|
import { writeFileSync } from 'node:fs';
|
|
|
|
|
import { generateScene } from '../src/scene/scene.js';
|
|
|
|
|
import { buildPDF } from '../src/render/pdf.js';
|
|
|
|
|
import { paramsFromSeed } from '../src/scene/params.js';
|
|
|
|
|
import { GROUPS, TOGGLES, FIXED, PRESETS } from '../src/ui/controls.js';
|
|
|
|
|
|
|
|
|
|
const argv = process.argv.slice(2);
|
|
|
|
|
let params, out, page = 1728;
|
|
|
|
|
|
|
|
|
|
if (argv[0] === '--seed') {
|
|
|
|
|
const seed = argv[1] || 'ENTROPY-001';
|
|
|
|
|
params = { ...FIXED, ...paramsFromSeed(seed) };
|
|
|
|
|
out = argv[2];
|
|
|
|
|
if (argv[3]) page = +argv[3];
|
|
|
|
|
} else {
|
|
|
|
|
const [preset, seed, o] = argv;
|
|
|
|
|
params = { ...FIXED, seed: seed || 'ENTROPY-001' };
|
|
|
|
|
for (const g of GROUPS) for (const c of g.controls) params[c.id] = c.value;
|
|
|
|
|
for (const t of TOGGLES) params[t.id] = t.value;
|
|
|
|
|
if (preset && PRESETS[preset]) Object.assign(params, PRESETS[preset]);
|
|
|
|
|
if (seed) params.seed = seed;
|
|
|
|
|
out = o;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-20 17:10:32 -04:00
|
|
|
// generic k=v overrides (e.g. diskBubbles=false shockStain=0.8)
|
|
|
|
|
for (const a of argv) {
|
|
|
|
|
if (!a.includes('=')) continue;
|
|
|
|
|
const [k, ...rest] = a.split('=');
|
|
|
|
|
const v = rest.join('=');
|
|
|
|
|
params[k] = v === 'true' ? true : v === 'false' ? false : (v.trim() !== '' && !isNaN(+v) ? +v : v);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-20 16:53:23 -04:00
|
|
|
const pdf = buildPDF(generateScene(params), params, page);
|
|
|
|
|
const file = out || `/tmp/bc-${params.seed}.pdf`;
|
|
|
|
|
writeFileSync(file, pdf);
|
|
|
|
|
console.log(`PDF -> ${file} (${(pdf.length / 1024).toFixed(0)} KB)`);
|