42 lines
2 KiB
JavaScript
42 lines
2 KiB
JavaScript
|
|
// Take-file writer. Format is specified in docs/roto-puppet.md, "The take
|
||
|
|
// format". Line-oriented text on purpose: Poco can parse it with fopen/fgets
|
||
|
|
// from poco/src/safefile.c and strtok/atoi/atof from poco/src/strlib.c, so the
|
||
|
|
// Animator Pro render script needs no new native code.
|
||
|
|
|
||
|
|
const r = (v) => Math.round(v);
|
||
|
|
|
||
|
|
export function writeTake(take) {
|
||
|
|
const L = [];
|
||
|
|
L.push(`take name=${take.name} frames=${take.frames} width=${take.width} height=${take.height} exposure=${take.exposure}`);
|
||
|
|
L.push('');
|
||
|
|
take.palette.forEach((p, i) => L.push(`pal ${i} ${p.name.padEnd(11)} ${i}`));
|
||
|
|
L.push('');
|
||
|
|
// v1 emits a single frozen plate derived from the face oval. A real project
|
||
|
|
// replaces this with hand-drawn angles referenced by cel frame; the record
|
||
|
|
// shape is the same either way.
|
||
|
|
L.push(`plate 0 kind=poly slot_mouth=${r(take.slot.x)},${r(take.slot.y)} scale=1.00 rot=0 squash=1.00`);
|
||
|
|
L.push('');
|
||
|
|
for (const part of take.parts) {
|
||
|
|
const bits = [`part ${part.name.padEnd(9)} kind=${part.kind} z=${part.z}`];
|
||
|
|
if (part.color !== undefined) bits.push(`color=${part.color}`);
|
||
|
|
if (part.kind === 'poly') bits.push('closed=1 fill=1');
|
||
|
|
bits.push(`interp=${part.interp}`);
|
||
|
|
if (part.parent) bits.push(`parent=${part.parent}`);
|
||
|
|
L.push(bits.join(' '));
|
||
|
|
}
|
||
|
|
L.push('');
|
||
|
|
for (const part of take.parts) {
|
||
|
|
for (const k of part.keys) {
|
||
|
|
if (k.hidden) { L.push(`key ${part.name.padEnd(9)} f=${k.f} hidden`); continue; }
|
||
|
|
if (part.kind === 'plate') { L.push(`key ${part.name.padEnd(9)} f=${k.f} plate=${k.plate}`); continue; }
|
||
|
|
const pts = k.pts.map((p) => `${r(p.x)},${r(p.y)}`).join(' ');
|
||
|
|
// f is authoritative (what renders); src is the pre-snap extreme frame,
|
||
|
|
// kept only as a tuning signal - a key dragged far means the minimum-hold
|
||
|
|
// and the exposure grid are fighting.
|
||
|
|
L.push(`key ${part.name.padEnd(9)} f=${k.f} src=${k.src} n=${k.pts.length} ${pts}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
L.push('');
|
||
|
|
return L.join('\n');
|
||
|
|
}
|