rig-parts 1.52.0 → 1.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.ts +34 -8
- package/docs/AUTHORING.md +230 -16
- package/docs/STABILITY.md +1 -1
- package/package.json +1 -1
- package/src/assemble.ts +309 -15
- package/src/build.ts +30 -2
- package/src/check.ts +139 -12
- package/src/clothconfig.ts +78 -1
- package/src/config.ts +9 -7
- package/src/instruments.ts +9 -2
- package/src/limbs.ts +10 -0
- package/src/parts.ts +21 -3
- package/src/propose.ts +204 -11
package/cli.ts
CHANGED
|
@@ -27,11 +27,11 @@ import { makeInputs } from './src/inputs.ts';
|
|
|
27
27
|
import { idleKeysOf, isIdleKeys } from './src/rig.ts';
|
|
28
28
|
import { depthSkipLine, exportLayers, figuresPhrase, hiddenLayerLine, implausibleRules, layerFigures, type LayerSet, layerSetDiff, pct, readLayers, readWrapperLayers, ruleSummary, templateLayerNames, templatePsdBytes, times } from './src/layers.ts';
|
|
29
29
|
import { checkImageSize, choosePerson, KEYPOINTS_SPEC, loadKeypoints, type RigJoints, toRigJoints } from './src/keypoints.ts';
|
|
30
|
-
import { basisLines, branchSqueezeLine, checkProposal, compare, compareLines, DEFAULT_GRID_RULE, draftTurn, drawLandmarks, FIGURE_GRID_DIVISOR, FRINGE_STEP_PX, GRID_RULES, type GridRule, HIP_MIN_FRACTION, type DraftLintFinding, lint, lintLine, type PartSet, proposeWithBasis, readPartSet, serializeProposal, withTurn, WRIST_ON_PART_PX } from './src/propose.ts';
|
|
30
|
+
import { basisLines, branchSqueezeLine, checkProposal, compare, compareLines, DEFAULT_GRID_RULE, draftTurn, drawLandmarks, FIGURE_GRID_DIVISOR, FRINGE_STEP_PX, GRID_RULES, type GridRule, HIP_MIN_FRACTION, type DraftLintFinding, lint, lintLine, type PartSet, proposalAsConfig, proposeWithBasis, readPartSet, serializeProposal, withTurn, WRIST_ON_PART_PX } from './src/propose.ts';
|
|
31
31
|
import { BASIS_FILE, BASIS_SPEC, basisFile, basisLine, coverageLines, serializeBasis } from './src/diagnostics.ts';
|
|
32
32
|
import { BEND_DEGREES, BEND_WORST_SHARE, DUST_MAX_PX, DUST_MAX_SHARE, IDLE_BOUND_PX, MESH_DRAFT_REPORT, MESH_DRAFT_SPEC, meshDraftStage, MORE_TRIANGLES_FLAG, relativeConfigPaths, TOLERANCE_FIGURE_DIVISOR } from './src/meshdraft.ts';
|
|
33
33
|
import { meshStatsStage } from './src/meshstats.ts';
|
|
34
|
-
import { clothConfigEdits, editPaths, previousCount, writtenClothConfig } from './src/clothconfig.ts';
|
|
34
|
+
import { chainsLeftBehind, clothConfigEdits, editPaths, previousCount, writtenClothConfig } from './src/clothconfig.ts';
|
|
35
35
|
import { PROVENANCE_FILE, REMESH_SPEC, remeshStage } from './src/remesh.ts';
|
|
36
36
|
import { RETUNE_FILE, RETUNE_SPEC, retuneStage } from './src/retune.ts';
|
|
37
37
|
import { checkPainting } from './src/paintcheck.ts';
|
|
@@ -224,8 +224,12 @@ usage:
|
|
|
224
224
|
({across, max, shape}, issue #518) drafts the parts it meshes in the
|
|
225
225
|
influence mode at their lattice's cell, the radius as stated or drafted
|
|
226
226
|
as the farthest lattice vertex from its nearest link plus 3 cells, and
|
|
227
|
-
a LINT line names each drafted radius and both figures.
|
|
228
|
-
|
|
227
|
+
a LINT line names each drafted radius and both figures. A keyed bone
|
|
228
|
+
the recipe leaves the only keyed child of its parent joins it in one
|
|
229
|
+
chain CHAIN_LAG holds to non-decreasing amplitudes (issue #572): a LINT
|
|
230
|
+
line names each link of such a chain below the link above, with both
|
|
231
|
+
amplitudes and the least that passes; no amplitude is changed. Without
|
|
232
|
+
--cloth nothing changes.
|
|
229
233
|
|
|
230
234
|
rig-parts propose … --cloth <config.json> [--write-config <out.json> [--from <previous.json>]]
|
|
231
235
|
Also write the --cloth config's own text with what the recipe drafts
|
|
@@ -1388,18 +1392,39 @@ function cmdPropose(args: string[]): number {
|
|
|
1388
1392
|
: withTurn(drafted, draftTurn(P, { ...(fullRun === undefined ? {} : { full: readLayers(fullRun) }), ...(headRun === undefined ? {} : { head: readLayers(headRun) }) }, drafted));
|
|
1389
1393
|
// Emit only after green: a proposal the config loader would refuse is not written, nor a basis record that does not hold to it.
|
|
1390
1394
|
checkProposal(P, prop);
|
|
1395
|
+
// The same parts drafted without the recipe: what --write-config measures its edits against, and what issue #572's chain reading compares with.
|
|
1396
|
+
const plain = cloth === null ? null : proposeWithBasis(P, joints, wristSnap, gridRule, null).proposal;
|
|
1391
1397
|
// Issue #537: the sections the recipe moves, measured against the same parts drafted without it, spliced before anything is written.
|
|
1392
1398
|
const written =
|
|
1393
|
-
writeArg === undefined || clothArg === undefined
|
|
1399
|
+
writeArg === undefined || clothArg === undefined || plain === null
|
|
1394
1400
|
? null
|
|
1395
1401
|
: (() => {
|
|
1396
1402
|
const text = readFileSync(clothArg, 'utf8');
|
|
1397
1403
|
// Issue #552: bones, constraints and motion.tracks entry by entry; a hand edit the recipe would drop is refused by name.
|
|
1398
1404
|
// Issue #571: with --from, the same parts drafted a third time with the previous recipe.
|
|
1399
1405
|
const previous = previousCloth === null ? null : proposeWithBasis(P, joints, wristSnap, gridRule, previousCloth).proposal;
|
|
1400
|
-
const edits = clothConfigEdits(drafted,
|
|
1401
|
-
return { at: writeArg, text: writtenClothConfig(clothArg, text, edits), paths: editPaths(edits), vouched: previousCount(edits), relative: relativeConfigPaths(dirname(resolve(clothArg)), JSON.parse(text) as Record<string, unknown>) };
|
|
1406
|
+
const edits = clothConfigEdits(drafted, plain, JSON.parse(text) as unknown, false, previous);
|
|
1407
|
+
return { at: writeArg, input: text, text: writtenClothConfig(clothArg, text, edits), paths: editPaths(edits), vouched: previousCount(edits), relative: relativeConfigPaths(dirname(resolve(clothArg)), JSON.parse(text) as Record<string, unknown>) };
|
|
1402
1408
|
})();
|
|
1409
|
+
// Issue #572: the keyed chains CHAIN_LAG reads only once the recipe took its trees' idle keys — in the config written
|
|
1410
|
+
// against the --cloth config with --write-config, else in the proposal against the draft without the recipe.
|
|
1411
|
+
const leftBehind: { findings: DraftLintFinding[]; unread: string | null } = (() => {
|
|
1412
|
+
if (plain === null) return { findings: [], unread: null };
|
|
1413
|
+
if (written === null) return { findings: chainsLeftBehind(proposalAsConfig(P, plain), proposalAsConfig(P, prop)), unread: null };
|
|
1414
|
+
const read = (what: string, text: string): CharacterConfig | string => {
|
|
1415
|
+
try {
|
|
1416
|
+
return proposalAsConfig(P, JSON.parse(text) as Record<string, unknown>);
|
|
1417
|
+
} catch (err) {
|
|
1418
|
+
if (!(err instanceof PartsError)) throw err;
|
|
1419
|
+
return `${what} does not load as a config (${err.problems[0].code}: ${err.problems[0].object})`;
|
|
1420
|
+
}
|
|
1421
|
+
};
|
|
1422
|
+
const before = read(String(clothArg), written.input);
|
|
1423
|
+
const after = read(written.at, written.text);
|
|
1424
|
+
if (typeof before === 'string') return { findings: [], unread: before };
|
|
1425
|
+
if (typeof after === 'string') return { findings: [], unread: after };
|
|
1426
|
+
return { findings: chainsLeftBehind(before, after), unread: null };
|
|
1427
|
+
})();
|
|
1403
1428
|
const bfile = basisFile(P, prop, basis, cfg === null || cmpPath === undefined ? null : { where: cmpPath, config: cfg });
|
|
1404
1429
|
const img = drawLandmarks(P, painting, prop.bones, 'PROPOSAL - CORRECT ME');
|
|
1405
1430
|
mkdirSync(render, { recursive: true });
|
|
@@ -1413,7 +1438,8 @@ function cmdPropose(args: string[]): number {
|
|
|
1413
1438
|
}
|
|
1414
1439
|
console.log(`wrote proposal.json (${prop.bones.length} bone entries, ${Object.keys(prop.meshes).length} meshes) and render/landmarks.png (+_head) under ${out}`);
|
|
1415
1440
|
for (const n of prop.notes) console.log(`note: ${n}`);
|
|
1416
|
-
|
|
1441
|
+
if (leftBehind.unread !== null) console.log(`note: the keyed chains were not read after the recipe (issue #572): ${leftBehind.unread}`);
|
|
1442
|
+
printLint(P, prop, joints, [...draftLint, ...leftBehind.findings]);
|
|
1417
1443
|
console.log(basisLine(bfile, out));
|
|
1418
1444
|
if (written !== null && clothArg !== undefined) {
|
|
1419
1445
|
const from = fromArg === undefined ? '' : `; --from ${fromArg}: ${written.vouched} ${written.vouched === 1 ? 'entry' : 'entries'} taken as the previous recipe's draft`;
|