rig-parts 1.49.2 → 1.51.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 +27 -7
- package/docs/AUTHORING.md +74 -14
- package/docs/STABILITY.md +5 -5
- package/package.json +1 -1
- package/src/assemble.ts +68 -6
- package/src/build.ts +50 -8
- package/src/check.ts +158 -14
- package/src/clothconfig.ts +67 -13
- package/src/config.ts +21 -1
- package/src/parts.ts +22 -3
package/cli.ts
CHANGED
|
@@ -30,7 +30,7 @@ import { checkImageSize, choosePerson, KEYPOINTS_SPEC, loadKeypoints, type RigJo
|
|
|
30
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';
|
|
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
|
-
import { clothConfigEdits, editPaths, writtenClothConfig } from './src/clothconfig.ts';
|
|
33
|
+
import { clothConfigEdits, editPaths, previousCount, writtenClothConfig } from './src/clothconfig.ts';
|
|
34
34
|
import { PROVENANCE_FILE, REMESH_SPEC, remeshStage } from './src/remesh.ts';
|
|
35
35
|
import { RETUNE_FILE, RETUNE_SPEC, retuneStage } from './src/retune.ts';
|
|
36
36
|
import { checkPainting } from './src/paintcheck.ts';
|
|
@@ -226,7 +226,7 @@ usage:
|
|
|
226
226
|
a LINT line names each drafted radius and both figures. Without --cloth
|
|
227
227
|
nothing changes.
|
|
228
228
|
|
|
229
|
-
rig-parts propose … --cloth <config.json> [--write-config <out.json>]
|
|
229
|
+
rig-parts propose … --cloth <config.json> [--write-config <out.json> [--from <previous.json>]]
|
|
230
230
|
Also write the --cloth config's own text with what the recipe drafts
|
|
231
231
|
spliced in (issue #537), the way mesh-draft writes its config, so that
|
|
232
232
|
rig --config <out.json> builds it. What is spliced is measured: the
|
|
@@ -246,6 +246,14 @@ usage:
|
|
|
246
246
|
(PROPOSE_WRITE_CONFIG_CONFLICT), or when the spliced text does not
|
|
247
247
|
parse to the config with the sections set, naming the first key
|
|
248
248
|
that moved (PROPOSE_WRITE_CONFIG_SPLICE).
|
|
249
|
+
--from <previous.json> (issue #571, only with --write-config) names
|
|
250
|
+
the config the recipe is changed from: its cloth block is read as
|
|
251
|
+
--cloth's is, the same parts are drafted a third time with it, and an
|
|
252
|
+
entry equal to that previous recipe's draft is the recipe's, replaced
|
|
253
|
+
(or removed) as one equal to the draft without the recipe is; an entry
|
|
254
|
+
equal to none of the three drafts is still refused by name, its field
|
|
255
|
+
read against the previous recipe's draft. The write line counts the
|
|
256
|
+
entries the previous draft vouched for. Without --from nothing changes.
|
|
249
257
|
|
|
250
258
|
rig-parts propose --parts <dir> --source <painting.png> --out <dir> --from-config <config.json>
|
|
251
259
|
Draw the config's CURRENT bones instead (<out>/render/landmarks_config.png
|
|
@@ -714,6 +722,11 @@ usage:
|
|
|
714
722
|
and check's artifact, take them). --requirements is forwarded to check
|
|
715
723
|
(as for check); the file's own shape is read before assemble runs, and
|
|
716
724
|
its names resolve against the rig in the check, before it builds.
|
|
725
|
+
Without the flag, config.requirements (a path beside the config) is
|
|
726
|
+
read in its place; a flag naming other bytes than the declaration is
|
|
727
|
+
BUILD_REQUIREMENTS_CONFLICT, before assemble. check.json's
|
|
728
|
+
requirements.file records the path as typed or declared, its sha256
|
|
729
|
+
and the file's keys.
|
|
717
730
|
--environment is forwarded to check (as for check); the schedule is read
|
|
718
731
|
by rig-c's reader before assemble runs, so a malformed one is refused,
|
|
719
732
|
CHECK_ENVIRONMENT, under [assemble] before anything is assembled.
|
|
@@ -910,7 +923,7 @@ const TAKES = {
|
|
|
910
923
|
layers: { valued: ['--export', '--template', '--canvas'], switches: [] },
|
|
911
924
|
sheet: { valued: ['--source', '--layers', '--out', '--cell', '--cols'], switches: [] },
|
|
912
925
|
rig: { valued: ['--config', '--parts', '--out', '--idle-keys', '--page-edges', '--pack-shape'], switches: [] },
|
|
913
|
-
propose: { valued: ['--parts', '--source', '--out', '--from-config', '--compare', '--full', '--head', '--canvas', '--keypoints', '--person', '--wrist-snap', '--grid-rule', '--cloth', '--write-config'], switches: ['--head-box', '--no-back-hair'] },
|
|
926
|
+
propose: { valued: ['--parts', '--source', '--out', '--from-config', '--compare', '--full', '--head', '--canvas', '--keypoints', '--person', '--wrist-snap', '--grid-rule', '--cloth', '--write-config', '--from'], switches: ['--head-box', '--no-back-hair'] },
|
|
914
927
|
compare: { valued: ['--left', '--right', '--map'], switches: [] },
|
|
915
928
|
check: { valued: ['--rig', '--out', '--parts', '--source', '--page-edges', '--pack-shape', '--requirements', '--set', '--environment'], switches: ['--seam-pairs', '--keep-stills', '--all-sets'] },
|
|
916
929
|
loop: { valued: ['--frames', '--out'], switches: ['--palette'] },
|
|
@@ -1311,6 +1324,9 @@ function cmdPropose(args: string[]): number {
|
|
|
1311
1324
|
const writeArg = flags.get('--write-config');
|
|
1312
1325
|
if (writeArg !== undefined && flags.has('--from-config')) return usage('--write-config writes what the recipe drafts into its config; --from-config proposes nothing');
|
|
1313
1326
|
if (writeArg !== undefined && clothArg === undefined) return usage('--write-config writes the --cloth config with what its recipe drafts spliced in; give --cloth <config.json>');
|
|
1327
|
+
// Issue #571: the config the recipe is changed from; an entry equal to its recipe's draft is the recipe's, not a hand edit.
|
|
1328
|
+
const fromArg = flags.get('--from');
|
|
1329
|
+
if (fromArg !== undefined && writeArg === undefined) return usage('--from names the config the recipe is changed from, for --write-config; give --write-config <out.json>');
|
|
1314
1330
|
if (writeArg !== undefined) {
|
|
1315
1331
|
const ours = ['proposal.json', BASIS_FILE].map((f) => resolve(out, f));
|
|
1316
1332
|
if (existsSync(writeArg) || ours.includes(resolve(writeArg))) {
|
|
@@ -1318,6 +1334,7 @@ function cmdPropose(args: string[]): number {
|
|
|
1318
1334
|
}
|
|
1319
1335
|
}
|
|
1320
1336
|
const cloth = clothArg === undefined ? null : loadClothConfig(clothArg).cloth;
|
|
1337
|
+
const previousCloth = fromArg === undefined ? null : loadClothConfig(fromArg).cloth;
|
|
1321
1338
|
const partsDir = existsSync(partsArg) && statSync(partsArg).isFile() ? dirname(partsArg) : partsArg;
|
|
1322
1339
|
if (!existsSync(source)) {
|
|
1323
1340
|
throw new PartsError([{ code: 'PROPOSE_SOURCE_PRESENT', object: source, detail: 'no such file; the painting is drawn under the overlay' }]);
|
|
@@ -1361,8 +1378,10 @@ function cmdPropose(args: string[]): number {
|
|
|
1361
1378
|
: (() => {
|
|
1362
1379
|
const text = readFileSync(clothArg, 'utf8');
|
|
1363
1380
|
// Issue #552: bones, constraints and motion.tracks entry by entry; a hand edit the recipe would drop is refused by name.
|
|
1364
|
-
|
|
1365
|
-
|
|
1381
|
+
// Issue #571: with --from, the same parts drafted a third time with the previous recipe.
|
|
1382
|
+
const previous = previousCloth === null ? null : proposeWithBasis(P, joints, wristSnap, gridRule, previousCloth).proposal;
|
|
1383
|
+
const edits = clothConfigEdits(drafted, proposeWithBasis(P, joints, wristSnap, gridRule, null).proposal, JSON.parse(text) as unknown, false, previous);
|
|
1384
|
+
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>) };
|
|
1366
1385
|
})();
|
|
1367
1386
|
const bfile = basisFile(P, prop, basis, cfg === null || cmpPath === undefined ? null : { where: cmpPath, config: cfg });
|
|
1368
1387
|
const img = drawLandmarks(P, painting, prop.bones, 'PROPOSAL - CORRECT ME');
|
|
@@ -1380,10 +1399,11 @@ function cmdPropose(args: string[]): number {
|
|
|
1380
1399
|
printLint(P, prop, joints, draftLint);
|
|
1381
1400
|
console.log(basisLine(bfile, out));
|
|
1382
1401
|
if (written !== null && clothArg !== undefined) {
|
|
1402
|
+
const from = fromArg === undefined ? '' : `; --from ${fromArg}: ${written.vouched} ${written.vouched === 1 ? 'entry' : 'entries'} taken as the previous recipe's draft`;
|
|
1383
1403
|
console.log(
|
|
1384
1404
|
written.paths.length > 0
|
|
1385
|
-
? `wrote ${written.at}: ${clothArg}'s text with ${written.paths.join(', ')} spliced in from the draft; every other byte as read`
|
|
1386
|
-
: `wrote ${written.at}: ${clothArg}'s text byte for byte; every entry the recipe drafts is already as drafted`,
|
|
1405
|
+
? `wrote ${written.at}: ${clothArg}'s text with ${written.paths.join(', ')} spliced in from the draft; every other byte as read${from}`
|
|
1406
|
+
: `wrote ${written.at}: ${clothArg}'s text byte for byte; every entry the recipe drafts is already as drafted${from}`,
|
|
1387
1407
|
);
|
|
1388
1408
|
if (written.relative.length > 0 && dirname(resolve(written.at)) !== dirname(resolve(clothArg))) {
|
|
1389
1409
|
console.log(`note: ${written.relative.map((r) => `${r.at} "${r.value}"`).join(', ')} written as stated; the loader resolves each against the directory the config sits in, ${dirname(written.at)} for ${written.at}, not ${dirname(clothArg)}; put the config beside ${clothArg} or rewrite them`);
|
package/docs/AUTHORING.md
CHANGED
|
@@ -128,8 +128,9 @@ read by no CPU stage).
|
|
|
128
128
|
| `stops` | rig (handed to rig-c as `rig.json`'s `stops`, and moves slots, mesh weights and child bones on stopped links onto `<link>_d`); `propose --from-config` (`LINT stop on <chain> …`) | **authored**, optional (issues #404, #447): `[{chain, links?, against, at, inward, outward, lower?: {inward, outward}}]` — rig-c's leg stops (`RigStop`, rig-c 2.56.0, `rig-c/src/stop.ts`). `chain` is a chain `bones` declares (`CONFIG_NAME_RESOLVES`, `RIG_NAME_RESOLVES`); `links`, optional, is a non-empty list of links of that chain (`CONFIG_NAME_RESOLVES`, `CONFIG_FIELD_TYPE`), or absent for every link of `chain` in chain order; `against` is a bone `bones` declares, a chain link as `<chain><i>` (`CONFIG_NAME_RESOLVES`, `RIG_NAME_RESOLVES`); `at` is `[x, y]` in `against`'s local space, as rig-c's stop takes it (`CONFIG_FIELD_TYPE`): since each chain link (`leg_r0`, `leg_r1`) is turned to point along its segment (`+x` from origin to next link or tip, `+y` 90° counter-clockwise in Spine world), `at: [d, n]` sits `d` px from `against`'s origin toward its end and `n` px perpendicular to it; `inward`, `outward` and `lower.inward`, `lower.outward` are finite numbers (`CONFIG_FIELD_TYPE`). Every other stop rule — non-negative bounds, each stopped link written by a constraint, `against` not under the stopped chain, the aim not degenerate, `\|rest\| + outward <= 180°` (`RIG_STOP_BOUNDS`) — is rigc's to accept or refuse at the rig stage's gate, in rigc's words (`RIG_RIGC_GREEN`). **Rising-limb / prone geometry (issue #447):** rig-c's `expandStops` aims `<chain>_rest` from `links[0]`'s setup origin at `<chain>_touch` (`at` in `against`'s local frame) and clamps `<link>_d` inside `[rest − inward, rest + outward]`; Spine wraps rotation at `±180°`, so `\|rest\| + outward <= 180°` is required (`RIG_STOP_BOUNDS`). Whenever `<chain>_touch` lies **above** `links[0]`'s root in rig pixels (`ty < y0`, i.e. higher Spine `y` — e.g. stopping a hanging cloth chain against a rising shin `leg_<s1>` in a prone or kneeling pose where the knee sits below `links[0]` and the ankle above it, so positive `at[0]` walks upward along the shin past `links[0]`'s root), `rest` lands in the upper half-plane (`\|rest\| > 90°`) and `\|rest\| + outward` exceeds `180°`. Stop against the descending thigh (`leg_<s0>`), set `links` to start at a link whose root sits above `<chain>_touch`, or omit the stop when the rising shin sits outside the hanging chain's sweep; `propose --from-config` prints `LINT stop on <chain> …` with the exact coordinates and angles when `<chain>_touch` lies above `links[0]`'s root or `\|rest\| + outward > 180°`. For every stopped link `<link>`, the rig stage moves any slot on `<link>`, any mesh weight on `<link>`, and any bone whose parent is `<link>` (a branched cloth tree's branches hanging from `<trunk_last>`, before `--idle-keys ctl` adds `<bone>_ctl` and before `turn` adds `turn_<part>_<bone>`) onto `<link>_d`, the drawn link bone rig-c's `expandStops` creates at `<link>`'s setup frame to carry the clamped rotation. Absent, `rig.json` carries no `stops` and no byte of any output moves |
|
|
129
129
|
| `turn` | rig (adds the turn control) | **proposed** only with `propose --full`/`--head` (issue #251), then corrected: `{pivot, depths, deform?, band?, radius?, surface?: {radius?}, head?: {pivot?, radius?}}`. `depths` holds, per part, the See-through layer's `depth_median` the part came from (larger = further back), read from the run the part was assembled from; a `painting:` patch has none and is not carried. A rider (issue #271) — a part from an `eyewhite`, `irides`, `eyelash`, `eyebrow`, `nose` or `mouth` layer — is drafted at the `face` part's depth, 0.001 nearer when parts.json draws it after the face and 0.001 further when before: See-through makes no depth of its own for the eye group (it cuts them from one depth map of the combined eyes) and clamps nose and mouth to the face's median − 0.001, and the two runs' own medians for these layers disagreed by up to 0.47 and swapped their order against the face. Every other layer — ears, headwear and earwear included — keeps its own median, unless it rides another part's bone. With no `face` part, or more than one, the riders keep their own and a note says so. A rider by bone (issue #535) — a part every *ownable* bone of which (a chain link, or a bone no other bone hangs from; `head`, `chest` and any bone with a child are shared and never count on their own) is *hosted* by another carried part, the host of a bone being the carried part that binds it (its region's bone; a mesh's `segments`, `contour` and `auto` regions' bones) with the most `opaque_px`, the earlier in parts.json on a tie, and which hosts no bone itself — is drafted at its host's depth, 0.001 nearer when drawn after the host and 0.001 further when before, and a note names the host, the bones and its own median: a pin, clip or ornament on the back hair's links travels with the back hair, not with its own layer's depth. `propose` reads the proposal's own `bones`, `meshes` and `regions`; the face riders are read by their tag first and never by their bones. A part bound to two hosts' bones rides neither and a note says so. In the rig stage, an authored depth on a rider by bone whose fraction differs from its host's by more than 0.1 of the dial (`TURN_RIDER_APART`, a share of `pivot − nearest`) is refused (`CONFIG_TURN_RIDER_DEPTH`); the host is read off `parts.json`'s `opaque_px`, so the config loader cannot see it. One note lists each part's depth and where it came from; a carrier the other run places more than 10 % of `pivot − nearest` away gets a note naming both values and the run read — the two runs are not reconciled. `pivot` is the depth that stays put; `propose` drafts the mean of the parts' depths weighted by `opaque_px`, the one depth at which the painted pixels' centroid does not slide under the dial. The rig stage adds a bone `turn` under `root` at its origin that nothing keys — its local x is the dial, in rig px — and carries each part by `(pivot − depth) / (pivot − nearest depth)` of it: the nearest part all of it, a part behind the pivot the other way, a part at the pivot not at all. Each part rides leaf twins (`turn_<part>_<bone>`, an identity child of every bone its slot and weights bind) moved by one `transform` constraint (`turn_<part>`, after the config's own); the idle's keys, the `<bone>_ctl` controls and a physics constraint stay on the bones, and the dial moves none of them. Optional `deform` (`Partial<FaceDeformFractions>`, issue #436) overrides the Set B ×2.5 face surface deformation table (`FACE_DEFORM_FRACTIONS`, checked against `FACE_DEFORM_RANGES` by `CONFIG_TURN_DEFORM_RANGE`); when `applyFaceSurfaceDeform` runs on a rig whose `motion` carries `tilt` or `turn` slider `derive` keys, it requires `config.turn` (`CONFIG_TURN_REQUIRED`, issue #478; `propose --full`/`--head` drafts it), promotes `face` on `head` (or `turn_face_head` when `turn` is declared) to the uneven 5×5 grid mesh, keys `face`, `hair_front` and `hair_back` deform timelines and ear/topknot tracks from `evalPitchFaceSurface` and `evalYawFaceSurface`, and samples the same deform field across each `features` member's rest span (`featRx = (24 / 106) · W`, `featRy = (12 / 128) · H`) with its depth fraction `z / zRef` as the field's angle input and chord foreshortening (`scalex` narrowing on the leading side and widening on the trailing side, `scaley` on pitch) so every feature's bounding box stays inside the deformed face plate across the rated band (issue #468). On yaw (`issue #479`), `evalYawFaceSurface` evaluates a **cylinder projection** (`cylinderYawDx`: `Δx(x, θ, R) = R · (sin(clamp(arcsin(clamp(x / R, −1, 1)) − θ, −π/2, π/2)) − clamp(x / R, −1, 1))`) of radius `R` (`turnSurfaceRadius`: `turn.surface.radius ?? turn.radius ?? turn.head.radius`, positive rig px checked by `CONFIG_FIELD_TYPE`, defaulting to half the face plate's opaque width `W / 2`) tapered by a cubic Hermite outline weight (`wOutline = 1` for `\|ux\| <= 0.7`, reaching `0` at `\|ux\| = 1.0`) so features slide across a fixed outline (`iris` shift within `±2%` of `cylinderYawDx`), the trailing cheek strip widens (`>= 1.54×` at `±15°`), and the leading jaw edge holds fixed (`0 px` shift) unless explicit horizontal `turn.deform` overrides (`turn_mid_x`, `turn_lead_compress_x`, `turn_trail_shift_x`) request the flat yaw table. On yaw (`issue #478`), `applyFaceSurfaceDeform` also derives a **head-only pivot** (`headTurnPivot`: `turn.head.pivot` when authored, otherwise the `opaque_px`-weighted mean of `depths[part]` across the head parts `DEFAULT_HEAD_TURN_PARTS` — `face`, `hair_front`, `hair_back`, `ear_r`, `ear_l`, `hairpin` — from `parts.json`, falling back to `turn.pivot`) so a forward torso or arm in `turn.depths` does not pull the head's rotation axis in front of `face`: `hair_back` (`depth_median > headPivot`, negative `headTurnFraction`) and `hairpin` behind `headPivot` translate opposite to the face's turn (`dx = s · turn_face_center_x · W · (headPivot − depth) / (headPivot − nearestHeadDepth)`), emerging on the trailing side to compensate for the leading-cheek foreshortening and keeping the combined head silhouette width near-constant across `±15°` without any same-sign `turn_hair_back_cheek_x` term. Optional `band` (`number` or `{yaw?, pitch?}`, positive degrees, issue #472) declares the rig's rated face turn band (default `FACE_RATED_BAND`: `yaw <= 15°`, `pitch <= 12°`); declaring a `turn.band` or a `motion.animations_from` `turn`/`tilt` `derive.degrees` above `±15°` yaw or `±12°` pitch without an `assemble.alternates` entry that replaces `face` is refused (`CONFIG_FACE_BAND_EXCEEDED`), and on a single-plate rig `applyFaceSurfaceDeform` adds self-targeting transform constraints `yaw_clamp` (`[-15, 15]`) and `pitch_clamp` (`[-12, 12]`) ahead of the slider constraints so driving `yaw` or `pitch` beyond the rated band clamps at the boundary. At rest: with `turn` declared, no pixel differs by more than 1 level at dial 0 (not byte-identical; the cause is float noise in the identity child bones, and the constraints add nothing); without `turn`, byte-identical. Neither `pivot` nor `depths` has a default (`CONFIG_FIELD_PRESENT`); `pivot` and `head.pivot` must lie behind the nearest part (`CONFIG_TURN_PIVOT_BEHIND_NEAREST`). Absent, no control is added and no byte of any output moves |
|
|
130
130
|
| `scene` | assemble (the recomposite, its holes and the figure's mask); check, through `parts.json`'s `scene` block (`RECOMPOSITE_HOLES`, the seam) | **authored**, optional; `propose` writes none (issue #242). `{}` declares the painting a scene: the figure and its surroundings in one image, See-through's full run holding only the figure. With it, `assemble` reads the recomposite figures, the hole list and the `uncovered:` lines inside the figure — the rig pixels where any full-run layer's alpha is above 8 (`OPAQUE_ALPHA_ABOVE`, the cut every layer's painted pixels are read by) — each line starting `inside the figure (config.scene: …, <n> of <m> rig px)`; writes that figure as `figure_rig.png` (white on black) beside the recomposite, and a `scene` block in `parts.json`; flags error pixels on the error map inside it only (outside, the painting grey); and `check` leaves out of the seam every frame pixel whose composite sample reaches the painting's outermost row or column, saying how many (`seam_border` in `check.json`, and on the seam line). It takes no field: the figure and its threshold are derived. A key in it other than a record or an annotation is `CONFIG_KEY_KNOWN`. Absent, no byte of any output moves |
|
|
131
|
-
| `cloth` | `propose --cloth` only; no other stage reads it, so it moves no byte of any build | **authored**, optional (issue #364): one recipe per tag, `{"bottomwear": {…}, "back hair": {…}, "front hair": {…}}`, each `{chains, links, wind, gravity, split?, length_ratio?, strength?, damping?, alternate_damping?, translate?, swing?, part?, influence?}`. `influence` (issue #518) — `{across, max, shape, radius?}`: the parts this recipe meshes are drafted in the influence mode (`meshes.<part>.influence` above) at their lattice's cell, with `across`, `max` and `shape` as declared (each required — the reading behind the radius did not vary them) and `radius` as declared or, absent, drafted as the farthest vertex's distance plus 3 cells (the `influence.radius` row); without it the parts keep their lattice. `chains` — trees across the piece (for `back hair`, per side of the eye axis), a whole number, 1 or more; `links` — links from root to tip on every path, 1 or more; `split` — `{at, into}`: the first `at` links are the trunk, which forks into `into` (2 or more) branches; `at` below `links` (`CONFIG_CLOTH_SPLIT_BEFORE_TIP`); `length_ratio` — a path's last link over its first, above 0, default 0.5; `strength` — `{trunk, branch, edge}`, each above 0 and below the spring's stability bound (`CONFIG_CLOTH_SPRING_STABLE`), default 100 / 100 / 50; `damping` — in [0, 1], absent: rig-c's default; `alternate_damping` — the odd trees' damping, in [0, 1], beside `damping` and different from it (`CONFIG_CLOTH_ALTERNATE_DIFFERS`); `wind`, `gravity` — `[root, tip]`, each 0 or more, tip at or above root (`CONFIG_CLOTH_RESPONSE_GROWS_TO_TIP`); `translate` — the x and y mix of a dangling end's flutter, above 0 and at most 1; `swing` — `bottomwear` only, `{scales}`, one positive scale per tree (`CONFIG_CLOTH_SWING_SCALE_PER_TREE`); `part` — `bottomwear` only (`CONFIG_CLOTH_PART_ON_BOTTOMWEAR`), a non-empty part or cut-piece name: the `topwear` part that holds a skirt See-through returned inside it (a dress), or its skirt piece cut by `assemble.cuts`, which takes the skirt's trees (issue #402, *A skirt inside topwear* below; the part is checked by `propose`, `PROPOSE_CLOTH_PART`). The two defaults are the recipe's own, measured on its synthetic fixture (the recipe below). The recipe below says what each field drafts. The config written: `propose --cloth <config.json> --write-config <out.json>` (issue #537) writes this config's own text back with the sections the recipe drafts spliced in — `
|
|
131
|
+
| `cloth` | `propose --cloth` only; no other stage reads it, so it moves no byte of any build | **authored**, optional (issue #364): one recipe per tag, `{"bottomwear": {…}, "back hair": {…}, "front hair": {…}}`, each `{chains, links, wind, gravity, split?, length_ratio?, strength?, damping?, alternate_damping?, translate?, swing?, part?, influence?}`. `influence` (issue #518) — `{across, max, shape, radius?}`: the parts this recipe meshes are drafted in the influence mode (`meshes.<part>.influence` above) at their lattice's cell, with `across`, `max` and `shape` as declared (each required — the reading behind the radius did not vary them) and `radius` as declared or, absent, drafted as the farthest vertex's distance plus 3 cells (the `influence.radius` row); without it the parts keep their lattice. `chains` — trees across the piece (for `back hair`, per side of the eye axis), a whole number, 1 or more; `links` — links from root to tip on every path, 1 or more; `split` — `{at, into}`: the first `at` links are the trunk, which forks into `into` (2 or more) branches; `at` below `links` (`CONFIG_CLOTH_SPLIT_BEFORE_TIP`); `length_ratio` — a path's last link over its first, above 0, default 0.5; `strength` — `{trunk, branch, edge}`, each above 0 and below the spring's stability bound (`CONFIG_CLOTH_SPRING_STABLE`), default 100 / 100 / 50; `damping` — in [0, 1], absent: rig-c's default; `alternate_damping` — the odd trees' damping, in [0, 1], beside `damping` and different from it (`CONFIG_CLOTH_ALTERNATE_DIFFERS`); `wind`, `gravity` — `[root, tip]`, each 0 or more, tip at or above root (`CONFIG_CLOTH_RESPONSE_GROWS_TO_TIP`); `translate` — the x and y mix of a dangling end's flutter, above 0 and at most 1; `swing` — `bottomwear` only, `{scales}`, one positive scale per tree (`CONFIG_CLOTH_SWING_SCALE_PER_TREE`); `part` — `bottomwear` only (`CONFIG_CLOTH_PART_ON_BOTTOMWEAR`), a non-empty part or cut-piece name: the `topwear` part that holds a skirt See-through returned inside it (a dress), or its skirt piece cut by `assemble.cuts`, which takes the skirt's trees (issue #402, *A skirt inside topwear* below; the part is checked by `propose`, `PROPOSE_CLOTH_PART`). The two defaults are the recipe's own, measured on its synthetic fixture (the recipe below). The recipe below says what each field drafts. The config written: `propose --cloth <config.json> --write-config <out.json>` (issue #537) writes this config's own text back with the sections the recipe drafts spliced in — `meshes.<part>` and `regions.<part>`, and `bones`, `constraints` and `motion.tracks` entry by entry by name (issue #552) — and every other byte as read; `--from <previous config>` (issue #571) takes an entry equal to the previous recipe's draft as the recipe's (*The config written*, under the recipe below) |
|
|
132
132
|
| `proposed_rig_scale` | assemble, rig, build, `propose --from-config`/`--compare` | **proposed** by `propose` (issue #354): `parts.json`'s `scale_rig_per_source`, the `assemble.rig_scale` the rig sections (`bones`, `meshes`, `limbs`, `motion`) were drafted at. Held equal to `assemble.rig_scale` when present (`CONFIG_PROPOSED_RIG_SCALE`; 0, negative or not a number: `CONFIG_FIELD_TYPE`). Absent on a hand-authored config, where no byte of any output moves |
|
|
133
|
+
| `requirements` | build (read in place of `--requirements` when the flag is not given), and so its check | **authored**, optional, never proposed (issue #556): a path, relative to the config file's directory, to the `spine-parts-requirements/1` file the build's check reads (§7, *Declared requirements*) — so a rig that needs one (a `not_swinging` part, a `may_fold`) rebuilds from its config alone. `build` reads it before assemble, as it reads the flag's file, and `check.json`'s `requirements.file` records it with `path` as declared. Given beside `--requirements`, the two must name the same file once resolved, or a file of the same bytes, and the declaration is read and recorded (a build given both writes what the config alone writes); otherwise `BUILD_REQUIREMENTS_CONFLICT`, naming both. Not a non-empty string: `CONFIG_FIELD_TYPE`; no such file, where the config is read from a path: `CONFIG_FILE_PRESENT`. `check`, `compose`, `mesh-draft`, `remesh` and `retune` do not read it: their `--requirements` is the only door. Absent, nothing is read and no byte of any output moves |
|
|
133
134
|
|
|
134
135
|
**One drawing, one band; beyond it, another drawing (issue #472).** A single front-facing
|
|
135
136
|
`face` plate has one painted outline, one nose ridge, and two eyes in front-view topology.
|
|
@@ -522,13 +523,30 @@ layers, as follows; every step is arithmetic on the declared bones and the layer
|
|
|
522
523
|
both segments' parts) within half a pixel of the line, the run through the joint (its nearest
|
|
523
524
|
pixel within 1 px of it, neighbours at most 1.5 px apart), first to last plus one pixel, to 3
|
|
524
525
|
places. The tool invents no pixel of it: each is the `cap` image's where that image is not
|
|
525
|
-
transparent, else the layer's where the limb has art there, else **
|
|
526
|
-
|
|
527
|
-
|
|
526
|
+
transparent, else the layer's where the limb has art there, else the **upper segment's** art
|
|
527
|
+
there (issue #557 — the shin's pixels where the boot's layer does not reach over the knee, the
|
|
528
|
+
shin's again for a shoe that starts below the ankle line; until #557 only `cap_shape: "disc"`
|
|
529
|
+
read it), else **missing**. The line `assemble` prints for each joint counts them and gives the
|
|
530
|
+
cap's box, `[x, y, w, h]` in rig px (`N px from "<upper>"` only where the upper segment gave a
|
|
531
|
+
pixel, so a full cap prints what it printed):
|
|
528
532
|
|
|
529
533
|
limb cap: "arm_r" joint "elbow" at [332, 424], on "forearm_r": a disc of radius 19.9165 px (the limb 39.833 px across the joint line), box [312, 404, 40, 40] — on the upper side of the line 621 px from the layer, 7 px missing — …
|
|
530
534
|
|
|
531
|
-
The missing pixels are where
|
|
535
|
+
The missing pixels are where no layer of the limb has a pixel: where the painting hides the limb,
|
|
536
|
+
or where the disc passes its outline — the half-disc is half the limb's width about the bone's
|
|
537
|
+
origin, so a bone off the limb's middle puts the far side of the disc past the outline (every
|
|
538
|
+
missing pixel on the public `wind` example is that: 9 to 72 per joint, each on one side, none
|
|
539
|
+
within the half-width about the joint). **A cap with missing pixels is short** (issue #557): its
|
|
540
|
+
record carries `short_px: {left, right}` — the missing pixels by side of the limb's axis at the
|
|
541
|
+
joint line, `left` where a pixel centre's offset across the axis is 0 or above (the side toward
|
|
542
|
+
smaller x when the limb hangs down the rig), `right` the other, the two adding up to
|
|
543
|
+
`missing_px` — and `assemble` prints one `LINT` line after its `limb cap:` line:
|
|
544
|
+
|
|
545
|
+
LINT "shin_r" cap at [34, 30] (limb "leg_r", joint "knee", radius 4 px): short_px left 0, right 3: no layer gives them — 3 px of the disc on the upper side of the cut, where neither the layer of "boots" nor that of "legs" has a pixel of the limb; the rest of the disc is filled, 17 px from "shin_r"'s layer, 6 px from "thigh_r"; under cap_shape "disc" the disc is the half-width about the joint, 4 px, and 3 of them lie within it
|
|
546
|
+
|
|
547
|
+
The last clause, on a cap without `cap_shape`, counts how many of them the disc of the
|
|
548
|
+
half-width about the joint would still hold: none means `cap_shape: "disc"` closes the
|
|
549
|
+
shortfall (it does on every `wind` joint). A full cap writes no `short_px` and prints no `LINT`.
|
|
532
550
|
Paint them — and, if the layer's own pixels carry the limb's outline across the cap, the whole
|
|
533
551
|
cap — into a `w`x`h` image whose pixel `(i, j)` is rig pixel `(x + i, y + j)`, and name it in
|
|
534
552
|
the segment's `cap`; its transparent pixels keep the layer's. The record is `parts.json`'s
|
|
@@ -541,8 +559,9 @@ layers, as follows; every step is arithmetic on the declared bones and the layer
|
|
|
541
559
|
the limb's art across the line either way. It is measured, never typed; a joint on the very edge of
|
|
542
560
|
the run has none and is `ASSEMBLE_LIMB_JOINT_ON_ART`. The cap's pixels come from the image, then
|
|
543
561
|
the layer, then **the upper segment's art** where the lower's layer has none (the shin painted down
|
|
544
|
-
to the ankle is the shoe's cap)
|
|
545
|
-
cap:` line adds `N px from "<upper>"
|
|
562
|
+
to the ankle is the shoe's cap) — the plain cap's order too since issue #557 — and only where no
|
|
563
|
+
segment has art are they missing. The `limb cap:` line adds `N px from "<upper>"` always, and the
|
|
564
|
+
record `shape` and `upper_px` (without the shape, `upper_px` only when above 0). The upper piece's
|
|
546
565
|
**corner** at the cut is kept where it is: on a joint off the limb's middle, a corner trimmed to the
|
|
547
566
|
disc leaves a notch at rest when no piece takes it, or a stub out of the bent lower piece's outline
|
|
548
567
|
when the lower takes it (pictured in the pull request that added these two fields).
|
|
@@ -587,7 +606,9 @@ layers, as follows; every step is arithmetic on the declared bones and the layer
|
|
|
587
606
|
bar at each, against the same pose with the joint's own art drawn under the limb — so a cap
|
|
588
607
|
that does not cover the turn is a FAIL naming the joint and the angle, where the rest pose
|
|
589
608
|
showed nothing. A joint whose cap is `cap_shape: "disc"` is held to more: no pixel of its disc
|
|
590
|
-
over 40 at any pose, the disc being the cap's whole claim.
|
|
609
|
+
over 40 at any pose, the disc being the cap's whole claim. Each pose's row also prints the
|
|
610
|
+
**contour step** (issue #557), the step the eye sees in the outline where the cut meets it — a
|
|
611
|
+
reading, never a bar (§7). `TIP_OVER_ROOT` does not read a limb part (it turns at its joint; it does not
|
|
591
612
|
hang), and its row says so.
|
|
592
613
|
|
|
593
614
|
The first character built this way (the exam-01 test rig, issue #349) read, per joint, 5 to 10
|
|
@@ -1666,7 +1687,29 @@ recipe re-drafts or removes that the author changed by hand (it equals neither d
|
|
|
1666
1687
|
not dropped: the run is refused, `PROPOSE_WRITE_CONFIG_CONFLICT`, naming the entry
|
|
1667
1688
|
(`config.constraints[40] "skirt0a_0_physics"` in CL207), the first field the hand edit holds and
|
|
1668
1689
|
what the draft writes there, every conflict at once and nothing written; take the draft
|
|
1669
|
-
by removing the hand edit, or leave the recipe out for that part. A
|
|
1690
|
+
by removing the hand edit, or leave the recipe out for that part. **A changed recipe
|
|
1691
|
+
(issue #571).** The draft of the recipe as it stood before a change is neither of the
|
|
1692
|
+
two drafts, so a config holding that draft untouched would read as hand-edited at every
|
|
1693
|
+
entry the change moves (29 refusals on the public `wind` example with
|
|
1694
|
+
`cloth.bottomwear.links` 3 → 4). `--from <previous config>`, given beside
|
|
1695
|
+
`--write-config`, names the config the recipe is changed from: its `cloth` block is read
|
|
1696
|
+
as `--cloth`'s is (a missing file or a missing `cloth` block is refused by the same
|
|
1697
|
+
codes), and the same parts are drafted a third time with it. An entry equal to that
|
|
1698
|
+
previous recipe's draft is then the recipe's, as one equal to the draft without the
|
|
1699
|
+
recipe is: replaced by the draft, or removed where the draft no longer holds the name
|
|
1700
|
+
(a link the change took away). An entry equal to none of the three drafts is still
|
|
1701
|
+
refused, `PROPOSE_WRITE_CONFIG_CONFLICT`, the detail reading "it equals neither the draft,
|
|
1702
|
+
the draft without the recipe, nor the previous recipe's draft" and naming the first field
|
|
1703
|
+
that differs from the previous recipe's draft (the entry a person most likely edited
|
|
1704
|
+
from). The write line ends `--from <path>: n entries taken as the previous recipe's
|
|
1705
|
+
draft`. `meshes.<part>` and `regions.<part>` are unchanged by `--from`: a mesh the
|
|
1706
|
+
recipe drafts is replaced whole already, and one the two drafts agree at is not touched.
|
|
1707
|
+
Without `--from` every rule and every byte is the writer's before #571; with a `--from`
|
|
1708
|
+
whose recipe equals `--cloth`'s the previous draft is the draft, and the written config
|
|
1709
|
+
is byte for byte the one written without it (CL209–CL212 hold each on the cloth fixture,
|
|
1710
|
+
CL213–CL215 on `wind`). The written config is the recipe's draft, not a verdict on it: on
|
|
1711
|
+
`wind`, `links` 3 → 4 writes the skirt entries of its proposal value for value, and that
|
|
1712
|
+
draft fails `CHECK_TIP_OVER_ROOT` on the skirt in `build`; 3 → 2 builds green (CL215). A `meshes.<part>` the
|
|
1670
1713
|
recipe drafts is still the draft's whole, as a hand-edited lattice does not survive
|
|
1671
1714
|
`mesh-draft`, and a mesh it does not draft keeps its bytes. Every other byte is the
|
|
1672
1715
|
input's; a section the input lacks (a config holding only `key` and `cloth`) is
|
|
@@ -1680,7 +1723,8 @@ wrote back byte for byte (measured once, when the flag landed). The text is writ
|
|
|
1680
1723
|
(`motion.animations_from`, `generation.control.skeleton`) resolves against the directory
|
|
1681
1724
|
the written config sits in, so the out path belongs beside the input, and when it is not
|
|
1682
1725
|
a note names each such path. Refused before anything is written: `--write-config`
|
|
1683
|
-
without `--cloth` or beside `--from-config
|
|
1726
|
+
without `--cloth` or beside `--from-config`, and `--from` without `--write-config`
|
|
1727
|
+
(`USAGE`), an out path that exists or that
|
|
1684
1728
|
the run writes itself (`PROPOSE_WRITE_CONFIG_FRESH`), a hand edit to an entry the
|
|
1685
1729
|
recipe owns (`PROPOSE_WRITE_CONFIG_CONFLICT`), and a text whose splice does not
|
|
1686
1730
|
parse to the config with the sections set — a key stated twice
|
|
@@ -2279,12 +2323,12 @@ move off it (`AS245`).
|
|
|
2279
2323
|
| --- | --- | --- | --- |
|
|
2280
2324
|
| `layers` | the table, then one `author-made: layer "author:<label>" — …` line per layer the author made (group `author` in the table; §5, *A layer the author made*), then the `WARN` lines | every tag the plan will need has opaque pixels; one `face` in the head run; `0 WARN line(s)` | a run whose layer PNG is not its box's size (`LAYERS_PNG_MATCHES_BBOX`); a `WARN PLAN_LAYER_…` line (§6, *Plausibility*) |
|
|
2281
2325
|
| `sheet` of both runs | the tile list (and the sheet, if you can see) | eyes, irises, lashes and brows as left/right pairs in the head run | a head box that cut off an ornament: move `head_box`, re-run the head crop |
|
|
2282
|
-
| `assemble` | one line per part — its counts (`op=` opaque, `vis=` visible, `src=` taken / candidates, `unproj=` visible but not projected, `drift=<n> (<p>% of core)`, `merged=`, `seam=`; *parts.json*, below). `drift=` is `refused_drift_px` in rig px and its share of the part's candidates, `projected_core_px`, which it is a subset of (issue #314); no bar reads either. On the four public examples the share runs to 94.5 % (`scarf` `hair_back`, 479 of 507) and the count to 26,472 (`scarf` `topwear`, 22.3 %), and the seam override repaints refused top-most pixels afterwards, so a large count says where See-through's colour was not taken, not that the part is unlike the painting: the `drift:` line below is the one that names a body of them another part holds. Then the `pixels:` totals (opaque = visible + occluded; taken; visible but not projected), then `recomposite vs source: mean \|d\|, within 8, error px > 40, uncovered error px`, then `uncovered holes (8-connected): N` and the largest five as `uncovered hole K: <px> px at x,y wxh (between "<part>" <px> px, …)`, then one `uncovered: <n> of the <N> uncovered error px lie on the full run's "<tag>", in a body of <px> px at x,y wxh; <the rule that left it out>` line per full-run layer the plan does not take from the full run whose uncovered error holds a body (5x5-opened, 8-connected, at least 150 full-run px in rig px), then one `drift: "<part>" refuses <n> px of <run>:<tag> (its colour more than 90 off the painting, max channel), in a body of <px> px at x,y wxh (…); by the plan's draw order "<holder>" holds <px> px of it (…), "<holder>" drawn in front of "<part>"` line per part whose drift refusals hold a body (the same opening and bar) that another part holds in the draw order — that layer is not what the painting shows there (none on the five public paintings); and look at `render/recomposite_error_rig.png`. Between the part lines and the totals, one `author-made: part "<part>" (<run>:author:<label>) — …` line per part from a layer the author made (below, *A layer the author made*), then one `cut: "<part>" opaque <n> = "<part>" <kept> + "<piece>" <taken> …` line per part an `assemble.cuts` entry cut (below; it ends `; under <n> px filled, <m> px left empty` when a cut of that part has `under`), then — with `config.limbs` (issue #349) — one `limb cut: "<part>" opaque <n> = "<segment part>" <px> + …` line per part a limb takes and one `limb cap:` line per joint, its cap's pixels from the cap image, from the layer and missing, and its box
|
|
2326
|
+
| `assemble` | one line per part — its counts (`op=` opaque, `vis=` visible, `src=` taken / candidates, `unproj=` visible but not projected, `drift=<n> (<p>% of core)`, `merged=`, `seam=`; *parts.json*, below). `drift=` is `refused_drift_px` in rig px and its share of the part's candidates, `projected_core_px`, which it is a subset of (issue #314); no bar reads either. On the four public examples the share runs to 94.5 % (`scarf` `hair_back`, 479 of 507) and the count to 26,472 (`scarf` `topwear`, 22.3 %), and the seam override repaints refused top-most pixels afterwards, so a large count says where See-through's colour was not taken, not that the part is unlike the painting: the `drift:` line below is the one that names a body of them another part holds. Then the `pixels:` totals (opaque = visible + occluded; taken; visible but not projected), then `recomposite vs source: mean \|d\|, within 8, error px > 40, uncovered error px`, then `uncovered holes (8-connected): N` and the largest five as `uncovered hole K: <px> px at x,y wxh (between "<part>" <px> px, …)`, then one `uncovered: <n> of the <N> uncovered error px lie on the full run's "<tag>", in a body of <px> px at x,y wxh; <the rule that left it out>` line per full-run layer the plan does not take from the full run whose uncovered error holds a body (5x5-opened, 8-connected, at least 150 full-run px in rig px), then one `drift: "<part>" refuses <n> px of <run>:<tag> (its colour more than 90 off the painting, max channel), in a body of <px> px at x,y wxh (…); by the plan's draw order "<holder>" holds <px> px of it (…), "<holder>" drawn in front of "<part>"` line per part whose drift refusals hold a body (the same opening and bar) that another part holds in the draw order — that layer is not what the painting shows there (none on the five public paintings); and look at `render/recomposite_error_rig.png`. Between the part lines and the totals, one `author-made: part "<part>" (<run>:author:<label>) — …` line per part from a layer the author made (below, *A layer the author made*), then one `cut: "<part>" opaque <n> = "<part>" <kept> + "<piece>" <taken> …` line per part an `assemble.cuts` entry cut (below; it ends `; under <n> px filled, <m> px left empty` when a cut of that part has `under`), then — with `config.limbs` (issue #349) — one `limb cut: "<part>" opaque <n> = "<segment part>" <px> + …` line per part a limb takes and one `limb cap:` line per joint, its cap's pixels from the cap image, from the layer and missing, and its box, followed on a short cap by one `LINT "<part>" cap at [x, y] … short_px left <n>, right <m>: no layer gives them …` line (issue #557) — from the upper segment where it gave a pixel (under `cap_shape: "disc"` always), under `edge: "feather"` the pixels faded, under `cut_band` the line the cut was placed on and the stroke pixels it and the joint line cross (issue #360) (§3, *Limbs: cut at their joints*), then one `fringe pushed back: "<part>" <px> px, where the painting shows "<holder>" <px> px, …` line per part whose fringe was cleared (below) | on the examples: `reference-sample` 0.83 / 98.0 % / 4,359 / 1,185, 259 holes, the largest 94 px; `reference-demo` 2.34 / 95.8 % / 10,340 / 1,564, 453 holes, the largest 70 px (default rule) — many slivers along part edges, no hole a region could hide | one large hole: part of the figure is in no layer — a plan entry is missing, hair left the head crop sideways (reference-demo's `hair_back` is taken from the full run for that reason), or See-through split one garment into two and left the space between them in neither (a skirt as two trouser legs); the `between` parts say where. When neither run holds it at all, an `assemble.patches` entry cuts it from the painting (below) |
|
|
2283
2327
|
| `propose` | `note:` lines, `LINT` lines, the `coverage` lines, `landmarks.png`, `basis.json` | no LINT line: every chain link lies on its mesh's art, and the hip is below the chest and the figure's top quarter; the `coverage:` summary says how many bones that verdict covers — a `not checked` bone was read by no check (its line says why), and a `ratio` or `fallback` bone in `basis.json` is a guess | a link off the art (a bone on the background) — move it onto the layer; `LINT <link> at … runs to … N degrees off the head's down axis …` — a fringe link that does not lean with the head (§3, the fringe in the head's frame): move it along the lock it drives; `LINT hairback_… on mesh '<part>' (side <r\|l>): <N> tree(s) for <M> visible hair mass(es) (mass 0 columns x=<minX>..<maxX>, y=<minY>..<maxY>; …)` — back-hair cloth trees whose count does not match the side's visible hair masses (`max(1, floor(w / (4 * grid)) + 1)` per mass) or whose link or tip leaves its mass's column range (issues #445, #461): omit `chains` on `cloth."back hair"` or draft trees per visible hair mass inside its columns; `LINT <a_limb> and <b_limb> on <part> (<from>) cross at [x, y] with no per-limb split: …` — two limbs sharing one layer cross in an X without a per-limb split (issue #446): declare `config.limbs.<covering>.split` (`{ "line": [[x, y], …] }` or `{ "edge": "painting" }`, §3 *Which limb*); `LINT foot_<s> at [x, y], the <s>_ankle joint and leg_<s>1's tip, lies on none of leg_<s>'s art within 1 px along its joint line (the nearest of it on that line is the pixel [x, y], D px from the joint): …` — an ankle keypoint off its leg's art on the line `assemble` sizes the ankle's cap by (issue #517): `propose` drafts every leg without its ankle cut, the shoe layer stays one part, and nothing is moved onto the art; move that ankle keypoint onto the leg's or the shoe's art and re-run `propose` (`(the line crosses none of it)` when no art lies on that line at all); `LINT stop on <chain> (<firstLink> at [x0, y0]) against <against> (at [ax, ay]) places <chain>_touch at [tx, ty], above <firstLink>'s root (rest R deg, \|rest\| + outward B deg): …` — a stop's contact point `<chain>_touch` lies above `links[0]`'s root in rig px or pushes `\|rest\| + outward` past `180°` (issue #447, §2 `stops`): stop against the descending limb bone below `firstLink`, set `links` to start at a link below `<chain>_touch`, or omit the stop on a rising limb; `LINT hip at [x, y] is not below chest at [x, y]: …` or `LINT hip at [x, y] is above 0.25 of the figure height (figure y T..B, so hip y must be at least L): a hip at the shoulders` — move `hip` down to the waist (and `chest` between it and the neck); a `hanging strand … -- no chain proposed` note — that strand hangs stiff until you add a chain down the x and rows it names (§3); a `no blink: …` or `blink without brows: …` note — the idle will not blink (or its brows will not drop), because no part came from an `eyewhite` (or `eyebrow`) layer; the note names the tags looked for; a `no eyewhite part for eye_<s> …` note — the iris and lash parts it names ride `head` and do not blink, because no `eyewhite-<s>` part made that side's eye bone: take the eyewhite from the other run, or keep them on `head`; a `no face part: face box derived from …` note (always the first) — `head`, `neck` and every face-height scale come from a box guessed off the hair and neck (§3): check `head` and `neck` on `landmarks_head.png` and move them; when it adds `the blink shuts the eyes over no face part`, read `BLINK_NO_HOLE` after `check` — an eye with no face under it can open a hole (the `reference-sample` with only its face removed: 587 px). Under `--keypoints`: the `lint rule set:` line first (joints, or screen and why), then the joint notes — `missing: the rule "…" placed bone X instead` is a bone still guessed; `not used — …` names why an arm's joints did not place its sleeve (for a wrist on no part, the nearest part and the `--wrist-snap` that would bind it); a `wrist snap: …` note is a wrist bound past 15 px by the flag — check that chain's tip on `landmarks.png`; a `one handwear part holds both wrists` note is two chains on one mesh — cut the part with `assemble.cuts` to separate them; `LINT chest at … is not between the neck joint …`, `LINT hip at … is not past chest …`, `LINT hip at … is nearer the neck joint …` and `LINT <chain><i> at … does not advance from <s>_shoulder toward <s>_wrist` are the joint-frame lines: move that bone between, past or along the joints they name |
|
|
2284
2328
|
| `compare` | one line per pair (origin, parent, tip, length, direction — or SKIP and why), then the per-row summary, the unmapped bones of each side, `required:`, each side's roles and the `controls:` line | proposal against the config you corrected: the rows you changed and no others. Config against the `rig.json` `build` writes for it: measured on both examples, every origin within 6.19e-7 px (the rig's offsets are written to 6 places) and every chain link's tip and length within 4.99e-4 px (`length` is written to 3), printed to three places as `0.000` (a signed figure as `+0.000` or `-0.000`); `parent … is the right's ancestor at depth 2, <bone>_ctl between` for every keyed mesh bone, no `DIFFERENT` and no `NOT MAPPED` | `parent DIFFERENT: left a, right b` — a bone hangs from another parent than the other side's; `frames not related` — a rig with no stage (`skeleton.width`/`height`), two configs at different `rig_scale`: the distance rows SKIP, so declare the frame in a `--map` file if the author knows it; `FAIL STRUCTURE_REQUIRED_PRESENT` — a bone the map requires is missing through its pairs |
|
|
2285
2329
|
| `rig` (inside `build`) | one line per mesh: vertices, triangles, bones, influences, `cover`; the `bones` line; the `idle keys` line; then rigc's gate lines (with A15's declared SKIP under `--idle-keys direct`); in `rig.json`, each chain link's (or its `_ctl`'s) `length` and `rotation` | `cover 1.00000` on every mesh, both gate summaries `0 failed` (the compile and the packed pages); every link's `length` the distance to the next link and `rotation` its direction (Spine degrees, counter-clockwise, y up, local to the parent), every offset under it — a child bone's `x, y`, a weight's bind `x, y`, a region's `x, y` — in that turned frame, and a region on a link carrying `rotation` that turns it back upright. Nothing moved: `flattenRig` (`src/rig.ts`) turns every offset back and gives the unturned numbers | `RIG_LATTICE_ONE_LOOP`: change that mesh's `grid` |
|
|
2286
2330
|
| `check` (inside `build`) | the gate lines verbatim, the pack line, `loop:` (and `loop physics:` when the rig declares a physics constraint, §7), `seam:`, the six judgement lines, then — when `motion.json` holds an animation, the idle included — `ANIMATIONS_DO_NOT_FOLD` and one `folds` line per folding mesh, rigc's own (issues #320, #333), then — where a `footwear` part rides a bone that hangs from another — `FEET_STAY_LEVEL` and one `foot` line per such part (issue #348), then — when `parts.json` names a `handwear` part and there is an idle — `STRESS_OFF_CHAIN` (issue #347), then — where `parts.json` holds a limb segment's part — `LIMB_ONE_BONE` and one `limb` line per such part (issue #349), then — where a limb record carries a `range` — `SEAM_OVER_RANGE` and one `joint` line per joint and angle (issue #360), then `SEAM_OVER_MOTION` — a SKIP naming why on a rig that declares no neighbour pair, else the pairs read in every animation and one `WARN seam` line per pair and animation over the one-cell floor (issue #493, a warning and never a bar), then `CLOTH_SETTLES` — a SKIP naming why on a rig with no physics constraint, else the chains read and one `WARN chain` line per chain whose tip comes to rest before the idle's loop length (issue #501, a warning and never a bar), `RECOMPOSITE_HOLES` and, under `--source`, `SETUP_POSE_VS_SOURCE` (§7), `check.json`; the last line says how many of the bars measured — nine, ten with the fold bar, one more each with the feet-level bar, the stress bar, the limb bar and the range bar — and names the ones that said SKIP, then — where `SEAM_OVER_MOTION` read a pair — how many warnings it printed, `; N warning(s) (SEAM_OVER_MOTION, not a bar)` — with `CLOTH_SETTLES` named beside it, and N their sum, where the rig declares a physics constraint — which no bar counts | `check: PASS; 11 of 11 bar(s) measured, 0 skipped` on `demo` and `scarf`, whose sleeves each ride one chain; `check: PASS; 10 of 11 bar(s) measured, 1 skipped (STRESS_OFF_CHAIN)` on `reference-demo` and `reference-sample`, whose one `sleeves` mesh rides both sleeve chains (issue #347) — no example writes `FEET_STAY_LEVEL`, every shoe riding `root`; a judgement line SKIP only where the character lacks what it reads; on a rig spec with no `parts.json` or no `idle` (a merged rig, §7 *Measuring a rig rig-parts did not assemble*), PASS with the skipped bars named | `CHECK_SEAM_WITHIN_BAR` or `CHECK_LOOP_CLOSES` (§6); `CHECK_ANIMATIONS_DO_NOT_FOLD` — a clip turns a mesh over (§6); `CHECK_STRESS_OFF_CHAIN` — a sleeve weighted off its chain (§6); `CHECK_LIMB_ONE_BONE` — a limb part on a second bone (§6); `CHECK_SEAM_OVER_RANGE` — a joint that opens when bent (§6) |
|
|
2287
|
-
| `check --requirements` (and `build --requirements`) | after the lines above, one line per declared requirement, `NAME: PASS`, `FAIL` or `NOT MEASURABLE — …` with its figures, the bar as declared and the worst frame; then `requirements: N declared — M measured (P PASS, F FAIL), K NOT MEASURABLE; not declared: <kinds>`; `check.json`'s `requirements` block; the renders under `requirements/` (§7, *Declared requirements*) | every line PASS and `0 NOT MEASURABLE`; a follow's `released_copy` says whether rigc's consumer-driven door was taken on the throwaway copy; a `stretch` line's `held_by` (issue #321), right after `worst`, names the bones the worst edge's two vertices hang on and their idle chains, in `CHECK_TEXTURE_STRETCH`'s words (§6) and by the same function, on a PASS as on a FAIL | `CHECK_REQUIREMENT_MET` (a figure past its bar; the line names the frame) or `CHECK_REQUIREMENT_MEASURABLE` (the quantity is undefined in the frames: a tip or an axis on a bone of length 0, an aim with no line, a follow no frame of which reaches its least drive); the last line then reads `check: FAIL — B bar(s) not met, R declared requirement(s) not PASS` |
|
|
2331
|
+
| `check --requirements` (and `build --requirements`) | after the lines above, one line per declared requirement, `NAME: PASS`, `FAIL` or `NOT MEASURABLE — …` with its figures, the bar as declared and the worst frame; then `requirements: N declared — M measured (P PASS, F FAIL), K NOT MEASURABLE; not declared: <kinds>`; `check.json`'s `requirements` block, first its `file` record (issue #556); the renders under `requirements/` (§7, *Declared requirements*) — `build` reads `config.requirements` in place of the flag when it is not given | every line PASS and `0 NOT MEASURABLE`; a follow's `released_copy` says whether rigc's consumer-driven door was taken on the throwaway copy; a `stretch` line's `held_by` (issue #321), right after `worst`, names the bones the worst edge's two vertices hang on and their idle chains, in `CHECK_TEXTURE_STRETCH`'s words (§6) and by the same function, on a PASS as on a FAIL | `CHECK_REQUIREMENT_MET` (a figure past its bar; the line names the frame) or `CHECK_REQUIREMENT_MEASURABLE` (the quantity is undefined in the frames: a tip or an axis on a bone of length 0, an aim with no line, a follow no frame of which reaches its least drive); the last line then reads `check: FAIL — B bar(s) not met, R declared requirement(s) not PASS` |
|
|
2288
2332
|
| `compose` | the `[compose]` lines: one per character (its offset, its scale, its placed bounds, the shift and how many first-level bones, regions on `root` and weights bound to `root` it moved, its bone, slot, track and constraint counts, its `rig_scale` and idle), the declared order and the slot count it expands to, rigc's gate lines; then the `[check]` lines as for `check`, and `scene.json` | both gate summaries `0 failed`, `check: PASS` with the bars that measured and the ones that said SKIP named — on a composed rig `4 of 9`: the gate, the loop, `CHAIN_LAG` and `TEXTURE_STRETCH` (there is no `parts.json`; each character's own `build` measured all nine). `scene.json`'s `order.slots` is the order the compiled skeleton draws | a `SCENE_*` refusal (§6, *compose*) — the scene file, a build, or the order; `COMPOSE_RIGC_GREEN` — rigc's own line, quoted |
|
|
2289
2333
|
| `loop` (inside `build --loop`, or `loop --frames … --out …`) | the dropped-duplicate line, or, when the end frame is not frame 0, the jump line: its max \|d\| and px over 40, then why — under `build`, `the rig holds N physics constraint(s), and rigc's render starts every one at rest at frame 0` with the remedy `build --loop --lead-in <n>`, or `the rig holds no physics constraint, so the idle itself does not close` (`CHECK_LOOP_CLOSES`); under `loop --frames`, which reads frames alone, both causes (issue #325); under `build --lead-in`, the lead-in line in its place (the frames kept and the jump at the wrap); each file's line, then `loop: idle.png N B (lossless); idle-indexed.png N B (max …, mean …); idle.gif N B (max …, mean …)` | `f0048.png equals f0000.png byte for byte, so it is dropped` | `LOOP_ENCODE` (§6) |
|
|
2290
2334
|
|
|
@@ -2896,7 +2940,7 @@ says why each requirement exists and what breaks without it.
|
|
|
2896
2940
|
| <a id="PROPOSE_CLOTH_DRAFTED"></a>`PROPOSE_CLOTH_DRAFTED` | with `--cloth` (issue #364): the config's `cloth` block holds a recipe for a tag the proposer drafts no chain on — no part has that tag, or every `back hair` part ends above the shoulders (a bun bone, no chain). A `bottomwear` recipe with no `bottomwear` part names every `topwear` part shaped like a skirt (issue #402) | leave that recipe out, or assemble the layer it is for, or declare the named part in `cloth.bottomwear.part` |
|
|
2897
2941
|
| <a id="PROPOSE_CLOTH_PART"></a>`PROPOSE_CLOTH_PART` | with `--cloth` (issues #402, #437): `cloth.bottomwear.part` (a string) names no part, a part or cut piece whose source is not `topwear` (a `bottomwear` part takes the recipe by its tag already), or a target whose box ends above the hip + 0.25 face heights, the topwear rule's waist line; or `cloth.<tag>.parts` (or `part` as a list, issue #437) names a part not in `parts.json`, a part no link of the drafted tree crosses (`spanCrosses == 0`), or parts out of root-to-tip depth order along the chain | name the `topwear` part or its cut skirt piece that holds the skirt (or leave `part` out), or list only parts in `parts.json` that the drafted tree links cross in root-to-tip order |
|
|
2898
2942
|
| <a id="PROPOSE_WRITE_CONFIG_FRESH"></a>`PROPOSE_WRITE_CONFIG_FRESH` | with `--write-config` (issue #537): the out path exists, or is a file the run writes itself (`proposal.json`, `basis.json` under `--out`); the config is written to a new file, never over the `--cloth` config or an earlier one | name a file that does not exist yet, beside the `--cloth` config |
|
|
2899
|
-
| <a id="PROPOSE_WRITE_CONFIG_CONFLICT"></a>`PROPOSE_WRITE_CONFIG_CONFLICT` | with `--write-config` (issue #552): an entry of `bones`, `constraints` or `motion.tracks` the recipe re-drafts or removes was changed by hand in the `--cloth` config — it equals neither the draft with the recipe nor the draft without it — so the write would drop the hand edit; the object is the entry (`config.constraints[40] "skirt0a_0_physics"` in CL207), the detail names the first field the hand edit holds and what the draft writes there. Also a name the config states twice where the recipe drafts it. Every conflict is named at once and nothing is written | take the draft by removing the hand edit (or the entry), or leave the recipe out for that part (its `cloth` block); state a name once |
|
|
2943
|
+
| <a id="PROPOSE_WRITE_CONFIG_CONFLICT"></a>`PROPOSE_WRITE_CONFIG_CONFLICT` | with `--write-config` (issue #552): an entry of `bones`, `constraints` or `motion.tracks` the recipe re-drafts or removes was changed by hand in the `--cloth` config — it equals neither the draft with the recipe nor the draft without it — so the write would drop the hand edit; the object is the entry (`config.constraints[40] "skirt0a_0_physics"` in CL207), the detail names the first field the hand edit holds and what the draft writes there. With `--from <previous config>` (issue #571) an entry equal to the previous recipe's draft is the recipe's too, and the conflict is an entry that equals neither the draft, the draft without the recipe, nor the previous recipe's draft: the detail says so and reads the first differing field against the previous recipe's draft. Also a name the config states twice where the recipe drafts it. Every conflict is named at once and nothing is written | take the draft by removing the hand edit (or the entry), or leave the recipe out for that part (its `cloth` block); state a name once |
|
|
2900
2944
|
| <a id="PROPOSE_WRITE_CONFIG_SPLICE"></a>`PROPOSE_WRITE_CONFIG_SPLICE` | with `--write-config` (issue #537): the `--cloth` config's text with the drafted sections spliced in does not parse to that config with them set, and the message names the first key that moved — the text states a key twice, so the splice lands on the first and the parse keeps the last | state each key once in the `--cloth` config |
|
|
2901
2945
|
| <a id="PROPOSE_CLOTH_BACK_HAIR_CHAINS"></a>`PROPOSE_CLOTH_BACK_HAIR_CHAINS` | with `--cloth` (issues #390, #445, #461): `cloth."back hair".chains` exceeds what the narrower side's opaque width at the eye-line root row holds at the part's mesh grid (`max(1, min(floor(w_r / grid), floor(w_l / grid)))`), or places a tree root outside the 15 px dilated art mask of the `back hair` part (e.g. an inner twin-tail root over the face where the hair has no pixel); the message names the part, each side's root-row width, the grid spacing, and any off-art root with its pixel alpha | lower `cloth."back hair".chains` to at most the max fit named in the message, or omit `chains` so `propose --cloth` derives the tree count per visible hair mass on each side from its root-row width |
|
|
2902
2946
|
| <a id="PROPOSE_ACCESSORY_BODY"></a>`PROPOSE_ACCESSORY_BODY` | an accessory has nothing above its pendant rows to hang its bone on | that part's plan entry, or author its bones by hand |
|
|
@@ -3134,6 +3178,7 @@ documents do not ship). Each is an input this package built; none is an author's
|
|
|
3134
3178
|
| <a id="CHECK_PACK_PAGE_EDGES"></a>`CHECK_PACK_PAGE_EDGES` | the pack line disagrees with the `--page-edges` the build was run with — its `, page edges free` clause is there under `pot` or missing under `free`, or a `pot` page is not a power of two on both edges | a rigc problem; report it, with `rigc --version` |
|
|
3135
3179
|
| <a id="CHECK_PACK_SHAPE"></a>`CHECK_PACK_SHAPE` | the pack line disagrees with the `--pack-shape` the build was run with — it ends `, shape rect` under `polygon` or `, shape polygon` under `rect`, or it has no shape clause (the 1.5–2.0 form, read as `rect`) under `polygon` | a rigc older than 2.1.0 on `PATH`: rigc 2.0.3 takes `--pack-shape` without a word, packs by rectangles and prints the form with no shape clause, so this refusal is what catches it — `bun install` (this package depends on rig-c ^2.20.4); otherwise a rigc problem, report it with `rigc --version` |
|
|
3136
3180
|
| <a id="BUILD_ARTIFACT_PRESENT"></a>`BUILD_ARTIFACT_PRESENT` | the packed build lacks its `.json`, `.atlas` or page | a rigc problem; report it |
|
|
3181
|
+
| <a id="BUILD_REQUIREMENTS_CONFLICT"></a>`BUILD_REQUIREMENTS_CONFLICT` | `build --requirements <file>` names a file with other bytes than the one `config.requirements` declares (issue #556): the detail names both, each resolved (the flag against the working directory, the declaration against the config's) with its sha256 — or `no such file`. Refused before assemble writes anything. The same file by both, or a copy of its bytes, is not refused: the declaration is read and recorded | drop the flag to build from the config's file, or point `config.requirements` at the flag's |
|
|
3137
3182
|
| <a id="REQUIREMENTS_FILE"></a>`REQUIREMENTS_FILE` | `--requirements` names no file, or one that does not parse as a JSON object. Refused before anything is built (by `build`, before assemble) | the path of a `spine-parts-requirements/1` file |
|
|
3138
3183
|
| <a id="REQUIREMENTS_FIELD"></a>`REQUIREMENTS_FIELD` | a field of the file is missing, of the wrong type, or not one the format reads: `spec`, `fps` (no default), `requirements`, each requirement's `name` (letters, digits, underscores; once each), `kind`, `animation` and its kind's fields — every bar among them (`within_px`, `fraction`, `tolerance`, `least_drive` above 0, `within_degrees` from 0 to 180, `lo_degrees` ≤ `hi_degrees`, `within_ratio` ≥ 1) — and each target's `bone`, `animation` and exactly one of `at` and `keys` (times strictly increasing), and `not_planted`, `not_swinging`, `rises` and `rests` when given (each a non-empty list of part names, each once; no part both in `not_swinging` and in `rises` or `rests`), and `may_fold` when given (a non-empty list of `{ "slot", "animation", "why" }`, every one a non-blank string, each pair once; issue #320). `note`, `*_note` (strings) and `x-…` (any value) are read by nothing, as in the config | write the field; the bar is yours |
|
|
3139
3184
|
| <a id="REQUIREMENTS_RESOLVES"></a>`REQUIREMENTS_RESOLVES` | a bone, an `ik` or `transform` constraint (by name and `constraint_type`, as rig-c resolves it), a slot, a mesh attachment or an animation the file names is not in `rig.json` or `motion.json`, or a seam's part or a `not_planted`, `not_swinging`, `rises` or `rests` name is not in `parts.json` — the detail lists the ones that are; or an animation whose name cannot be a directory. Refused before anything is built | the name as the rig spells it |
|
|
@@ -3334,7 +3379,7 @@ the two examples [observed]:
|
|
|
3334
3379
|
| <a id="FEET_STAY_LEVEL"></a>`FEET_STAY_LEVEL` | issue #348. Each `footwear` part whose slot's bone hangs from another bone (rig.json's `parent`; a part on `root` hangs from nothing and is not read), over every animation, the idle included, from the same `rigc render --folds` run, which then also writes `--geometry`: on each frame where a bone above the part's bone — its parent or any bone over that — has a world rotation other than its setup pose's (no threshold; the nearest is named), the drawing's turn: the least-squares rotation carrying the attachment's setup-pose vertices onto the frame's, both centred (a region's four corners turn exactly with its bone). **This is the reading of "the sole's angle"**: no rig data marks a sole, so level is the drawing's setup angle, the painting's own; a declared sole line would replace it if one ever exists | every read foot within ±10 degrees — HQ's line (rig-c/parts#347 ruling 4), not a figure measured here | not written: the shoes ride `root` | not written: the shoes ride `root` | SKIP when no frame turns a bone above any read foot (not counted as measured); not written at all when no `footwear` part hangs from a bone, or `motion.json` holds no animation, so the examples' `check.json` keep their keys |
|
|
3335
3380
|
| <a id="STRESS_OFF_CHAIN"></a>`STRESS_OFF_CHAIN` | each mesh from a See-through `handwear` layer whose weights ride exactly one chain the idle keys: the chain's first link turned 90°, −90° and 180° from its setup rotation (interim, issue #347: until a config block declares each limb and its joint's range), one `rigc build --profile spine` and one `rigc render --geometry` of a copy with its physics constraints left out; per turn, the part's worst edge as max(ratio, 1/ratio) against the setup pose, at four places, and the bones it is weighted to off the chain. A part riding two chains, or none, or not a weighted mesh, is listed under `not_read` with the reason, and so is a part a `config.limbs` segment made (issue #349): `LIMB_ONE_BONE` holds it to its one bone, so it turns rigidly by construction | 1.0000 — the part turning rigidly with its chain; float32 noise on rigid sleeves measured at most 1.0000090 | SKIP: `sleeves` rides 2 chains | SKIP: `sleeves` rides 2 chains | no part comes from a `handwear` layer or the motion has no idle (the line is not written); every `handwear` part not read (SKIP, each reason) |
|
|
3336
3381
|
| <a id="LIMB_ONE_BONE"></a>`LIMB_ONE_BONE` | issue #349. Each part `parts.json` records as a limb segment's (`limb`), read off `rig.json` alone, nothing rendered: the bones its attachments are bound to — a mesh's weights, or its slot's bone for a region — against its segment's bone (under `config.turn`, that bone's leaf twin counts as the bone) | every limb part bound to its one bone alone, weight 1 | not written: no limbs | not written: no limbs | never: written only when `parts.json` holds a limb part, so the examples' `check.json` keep their keys |
|
|
3337
|
-
| <a id="SEAM_OVER_RANGE"></a>`SEAM_OVER_RANGE` | issue #360. Each limb part `parts.json` records with a `range` (`config.limbs.<limb>.segments[k].range`): a copy of the rig with its physics constraints left out, its joint's bone keyed `rotate` to the range's min, its middle and its max (each angle once, rigc's sense, counter-clockwise on screen), one `rigc build --profile spine` and two `rigc render`s on one grid — one with the joint's own art drawn under the limb (the limb's parts at rest inside the cap's disc, one pixel in from every edge of what is opaque there, on the bone the joint's bone hangs from), one with it hidden (`--hide`); per pose, the seam figures of the second against the first | the rest-pose seam's: mean \|d\| ≤ 1.0 and ≤ 50 rig px over 40 at every pose; a `cap_shape: "disc"` joint also 0 frame px over 40 | not written: no limbs | not written: no limbs | never: written only when `parts.json` holds a limb record with a `range`, so the examples' `check.json` keep their keys |
|
|
3382
|
+
| <a id="SEAM_OVER_RANGE"></a>`SEAM_OVER_RANGE` | issue #360. Each limb part `parts.json` records with a `range` (`config.limbs.<limb>.segments[k].range`): a copy of the rig with its physics constraints left out, its joint's bone keyed `rotate` to the range's min, its middle and its max (each angle once, rigc's sense, counter-clockwise on screen), one `rigc build --profile spine` and two `rigc render`s on one grid — one with the joint's own art drawn under the limb (the limb's parts at rest inside the cap's disc, one pixel in from every edge of what is opaque there, on the bone the joint's bone hangs from), one with it hidden (`--hide`); per pose, the seam figures of the second against the first. Issue #557: per pose also the **contour step**, a reading and never a bar — on the frame with the joint's art hidden, lines across the upper segment (perpendicular to its bone's direction at the setup pose, origin to the joint) one frame pixel apart, from one cap radius before the joint line to one past it; on each, from the axis outward on each side, the outline's extent (the first sample within 40 of the background, out to two radii); the step on a side is the largest change between adjacent lines, in rig px, `left` and `right` as the cap's `short_px` names them. A limb whose outline the bend keeps reads one frame pixel, 1 / s rig px (1.161 at the synthetic fixtures' s 0.861413); the unfilled two-layer knee of the selftest reads 11.609 on the opening side at ±15° and the filled one 1.161. The row prints it; `check.json` carries it (`step_px` on each pose) only for a joint whose cap record carries `short_px` | the rest-pose seam's: mean \|d\| ≤ 1.0 and ≤ 50 rig px over 40 at every pose; a `cap_shape: "disc"` joint also 0 frame px over 40 | not written: no limbs | not written: no limbs | never: written only when `parts.json` holds a limb record with a `range`, so the examples' `check.json` keep their keys |
|
|
3338
3383
|
|
|
3339
3384
|
**`TIP_OVER_ROOT` is measured from geometry, not pixels (issue #118).** Until #118 the
|
|
3340
3385
|
line rendered each part alone at `--max 640` and took, per half of its frame box, the
|
|
@@ -3834,6 +3879,21 @@ unit (the stage box maps to the world by a translation and the y flip,
|
|
|
3834
3879
|
}
|
|
3835
3880
|
```
|
|
3836
3881
|
|
|
3882
|
+
**Where a rebuild finds the file** (issue #556). A rig that passes only under its
|
|
3883
|
+
requirements — a rigid shorts piece in `not_swinging`, a fold the art means in
|
|
3884
|
+
`may_fold` — rebuilds green only if the next caller knows the file. `check.json`'s
|
|
3885
|
+
`requirements` block opens with `file`: `path` as the caller wrote it (`--requirements`
|
|
3886
|
+
as typed, or `config.requirements` as declared — never resolved, so a build moved to
|
|
3887
|
+
another directory writes the same bytes), the `sha256` of the bytes read, and `keys`,
|
|
3888
|
+
the file's top-level keys in its order, so a reader sees what it asked without opening
|
|
3889
|
+
it. `config.requirements` (§3) declares the file beside the config, and `build` reads
|
|
3890
|
+
it when the flag is not given: a build with `--requirements reqs.json`, typed from the
|
|
3891
|
+
config's directory, and a rebuild from a config declaring `"requirements": "reqs.json"`
|
|
3892
|
+
write the same bytes, every file (selftest `BU178`). A flag naming other bytes than the
|
|
3893
|
+
declaration is `BUILD_REQUIREMENTS_CONFLICT` (`BU179`); the same file by both, or a copy
|
|
3894
|
+
of it, builds what the config alone builds (`BU180`). Without either, no `requirements`
|
|
3895
|
+
block is written and no byte moves.
|
|
3896
|
+
|
|
3837
3897
|
**Feet that are not planted** (issue #231). The feet halves of `BREATH_VISIBLE` and
|
|
3838
3898
|
`STILL_REGIONS_DARK` assume a figure that stands: every `footwear` part holds still.
|
|
3839
3899
|
Whether the figure stands is the scene's knowledge, so a scene where it sits and its
|
package/docs/STABILITY.md
CHANGED
|
@@ -53,7 +53,7 @@ defaults are the help's too, and none is guessed from the art.
|
|
|
53
53
|
| `comfy` | `seethrough`: `--image`, `--out`; optional `--resolution`, `--steps`, `--seed`, `--prefix`, `--offload`, `--lama`, `--nf4`, `--host`, `--wait`, `--timeout`, `--poll` |
|
|
54
54
|
| `assemble` | `--propose-plan` with `--source`, `--full`, `--config`, optional `--head`; or `--source`, `--full`, `--config`, `--out`, optional `--head` (without it, one run: issue #359), `--seam` (near-white, silhouette), `--project` (core, visible), `--alt` (repeatable `<name>=<source>:<full>[:<head>]`, issue #454) |
|
|
55
55
|
| `propose` | `--head-box` with `--full`, `--canvas`; optional `--no-back-hair` |
|
|
56
|
-
| `propose` | `--parts`, `--source`, `--out`; optional `--compare` or `--from-config` (one of them), `--keypoints`, `--person` and `--wrist-snap` (each with `--keypoints`), `--full`, `--head` (the turn control's depths; not with `--from-config`), `--grid-rule` (`figure` or `part`, the drafted lattice's spacing; not with `--from-config`), `--cloth` (a config whose `cloth` block is the recipe, issue #364; not with `--from-config`), `--write-config` (a new file, with `--cloth` and not with `--from-config`, issue #537 — additive: without it nothing `propose` writes changes) |
|
|
56
|
+
| `propose` | `--parts`, `--source`, `--out`; optional `--compare` or `--from-config` (one of them), `--keypoints`, `--person` and `--wrist-snap` (each with `--keypoints`), `--full`, `--head` (the turn control's depths; not with `--from-config`), `--grid-rule` (`figure` or `part`, the drafted lattice's spacing; not with `--from-config`), `--cloth` (a config whose `cloth` block is the recipe, issue #364; not with `--from-config`), `--write-config` (a new file, with `--cloth` and not with `--from-config`, issue #537 — additive: without it nothing `propose` writes changes), `--from` (the config the recipe is changed from, only with `--write-config`, issue #571 — additive: without it nothing `--write-config` writes changes) |
|
|
57
57
|
| `compare` | `--left`, `--right`; optional `--map` |
|
|
58
58
|
| `rig` | `--config`, `--parts`, `--out`; optional `--idle-keys` (ctl, direct), `--page-edges` (pot, free), `--pack-shape` (rect, polygon) |
|
|
59
59
|
| `check` | `--rig`, `--out`; optional `--parts`, `--source`, `--page-edges`, `--pack-shape`, `--requirements`, `--seam-pairs`, `--keep-stills`, `--set` or `--all-sets` (issue #454), `--environment` (issue #538, additive) |
|
|
@@ -114,7 +114,7 @@ The fields, object by object (a bold path is where the object sits; `<part>` is
|
|
|
114
114
|
part name, `[i]` an entry of a list):
|
|
115
115
|
|
|
116
116
|
<!-- stable:config -->
|
|
117
|
-
- **config** — required by the full loader, in front of rig and build: `key`, `assemble`, `bones`, `meshes`, `regions`, `motion`; optional: `generation`, `seethrough`, `limbs`, `constraints`, `stops`, `turn`, `scene`, `cloth`, `proposed_rig_scale`
|
|
117
|
+
- **config** — required by the full loader, in front of rig and build: `key`, `assemble`, `bones`, `meshes`, `regions`, `motion`; optional: `generation`, `seethrough`, `limbs`, `constraints`, `stops`, `turn`, `scene`, `cloth`, `proposed_rig_scale`, `requirements` (issue #556, additive: a path beside the config that build reads in place of its requirements flag, whose behaviour is unchanged)
|
|
118
118
|
- **generation** — required: `checkpoint`, `loras`, `trigger`, `identity`, `sampler`, `costume`, `negative_extra`, `style`, `negative_pose`, `latent`, `seed`; optional: `pose`, `control`
|
|
119
119
|
- **generation.loras[i]** — required: `name`, `strength`; optional: `strength_clip`
|
|
120
120
|
- **generation.sampler** — required: `steps`, `cfg`, `sampler`, `scheduler`
|
|
@@ -190,15 +190,15 @@ every number) are AUTHORING §3's tables, and the loader refuses any other by na
|
|
|
190
190
|
|
|
191
191
|
| file | written by | what is stable |
|
|
192
192
|
| --- | --- | --- |
|
|
193
|
-
| `parts.json`, `parts/<name>.png` | `assemble`, `build` | one record per part: `from` (`<run>:<tag>` with a See-through v3 tag, `<run>:author:<label>` for a layer the author made — issue #256, read by no role rule — or `painting:<name>` for a patch), `cut_from` on a cut's piece only (the plan part it was cut from, issue #230), `limb` on a limb segment's part only (issue #349: `name`, `segment`, `of`, `bone`, and below a joint `joint`, `range` when the config segment declares one (issue #360), and `cap` — `at`, `width`, `radius`, `box`, `layer_px`, `image_px` with a cap image, `image_layer` after it when that image was a hidden-art layer — issue #359, `<run>:<layer>:hidden` — `missing_px`, then `shape` and `upper_px` under the segment's `cap_shape
|
|
193
|
+
| `parts.json`, `parts/<name>.png` | `assemble`, `build` | one record per part: `from` (`<run>:<tag>` with a See-through v3 tag, `<run>:author:<label>` for a layer the author made — issue #256, read by no role rule — or `painting:<name>` for a patch), `cut_from` on a cut's piece only (the plan part it was cut from, issue #230), `limb` on a limb segment's part only (issue #349: `name`, `segment`, `of`, `bone`, and below a joint `joint`, `range` when the config segment declares one (issue #360), and `cap` — `at`, `width`, `radius`, `box`, `layer_px`, `image_px` with a cap image, `image_layer` after it when that image was a hidden-art layer — issue #359, `<run>:<layer>:hidden` — `missing_px`, `short_px` (`left`, `right`) after it only when `missing_px` is above 0 (issue #557, additive), then `shape` and `upper_px` under the segment's `cap_shape` — `upper_px` without the shape only when the upper segment gave a pixel (issue #557, additive) — and `edge`, `feather_radius` and `feathered_px` under its `edge`, and `cut_band`, `cut_offset`, `cut_at`, `cut_crossed`, `joint_crossed`, `band_px` and `stroke_luma_max` (when the band has a split) under its `cut_band`, issue #360), the box `x`, `y`, `w`, `h` (rig px), the pixel counts `src/parts.ts` documents (`opaque_px`, `visible_px`, `occluded_px`, `projected_core_px`, `source_px_taken`, `visible_not_projected_px`, `refused_drift_px`, `merged_px`, `seam_override_px`, and `fringe_pushed_back` when not empty); `rig_size`, `scale_rig_per_source`, `ghost_px`, `recomposite`, and `scene` (`figure_alpha_above`, `figure_px`, `figure_mask`) under `config.scene` only, with the figure's mask `figure_rig.png` beside the recomposite (issue #242); `single_run_pad` (`file_size`, `side`, `left`, `top`) last, only for one run whose file is not the `seethrough.resolution` square (issue #366) |
|
|
194
194
|
| `rig/rig.json`, `rig/motion.json`, `rig/images/` | `rig`, `build`, `compose` | rig-c's rig spec and motion spec, `spec` `rigc-rig/1` and `rigc-motion/1`: the format is rig-c's, and this package writes only what rig-c's parser accepts; a bone carries `inherit` only where config.bones declares one, rig-c's mode name as written (issue #348) |
|
|
195
195
|
| `rig/mesh_report.json` | `rig`, `build` | one row per mesh: `part`, `vertices`, `triangles`, `hull`, `bones` (the sorted names the attachment's weights bind in the written `rig.json`, in every mode — since 1.49.1 (issue #536) a rig with `turn` or `stops` names the twins and `<link>_d` bones there, where the row named the segment bones they replace: a fix of a wrong name, not a format change; a rig with neither writes the bytes it wrote), `max_influences`, `mean_influences`, `art_coverage`, then `grid` (a lattice); `mode` "contour" with `params`, `contour`, `regions` (`params.maxEdge` and `contour.outlineCut` only when the mesh declares `contour.maxEdge`; `params.bridges` and `contour.bridges` — `islands`, `units`, `joins`, and `faint` only when an island was left out as faint — only when it declares `contour.bridges`); or `mode` "influence" with `influence` (as declared), `reach` (`farthest`, `at`, `nearest`, `capped`, `widest`) and `lattice` (rig-c's `SegmentsLatticeReport`: `cols`, `rows`, `artCells`, `keptCells`, `passes`, `islands`) (issue #378); or `mode` "auto" with `settings`, `source`, `result`, `residuals`, `worst_residual`, `worst_region`, `motion_amplitude`, `termination`, `weights`, `regions`, `deformation`, `quality_report` (rig-c's `mesh-quality-report/1` document whole), `motion_report`, and, only when they apply, `stray_cleared` (after `source`, when `source.stray` is declared), `skinning_residual` and `replay` (`AutoMeshReport` in `src/rig.ts`); in every mode, `exponent` when the mesh declares one (after `grid`, or after `mode`); `influences`, as declared, when a lattice or contour mesh declares it (after `exponent`, or where `exponent` would be); `stray` and `stray_cleared` when a lattice mesh declares `stray` (after `influences`, or where `influences` would be); `ribs` when a contour or auto mesh declares them (after `exponent`, or after `mode`), and then `contour.ribs` (`source.contour.ribs` in the automatic mode) |
|
|
196
|
-
| `check/check.json` and the rest of `check/` | `check`, `build`, `compose` | the reference's fields in its order (`gate_spine_html_green`, `rigc_entry`, `pack_mode`, `environment` after it under `--environment` only (issue #538, additive: `path` as given, `sha256`, `steps`), `loop_max_diff`, the seam figures — `seam_mean`, `seam_px_over_40`, `seam_px_over_80` and, from issue #216, `seam_frame_scale`, the frame scale the bar divides the count by), `loop_physics` after `loop_max_diff` when the rig declares a physics constraint, `seam_border` after the seam figures when `parts.json` declares a scene (issue #242), `seam_pairs` after the seam figures when the seam bar fails or `--seam-pairs` asks (each row's picture under `check/seam/`; `--keep-stills` leaves the setup-pose still and its `frames.json` under `check/setup_still/`), then the judgement lines (`BREATH_VISIBLE`, `BLINK_NO_HOLE`, `CHAIN_LAG`, `TIP_OVER_ROOT`, `STILL_REGIONS_DARK`, `TEXTURE_STRETCH`), `ANIMATIONS_DO_NOT_FOLD` after them when `motion.json` holds an animation, the idle included — on every rig with an idle since issue #333 (issues #320, #363: `status`, `animations`, `fps`, `physics_left_out`, `folding` — each `animation`, `slot`, `attachment`, `frames`, `worst_frame`, `worst_triangles`, `triangles`, `physics_on`, `physics_off`, `physics_constraints`, `declared`, `line` — `folding_undeclared`, `declared_not_folding`, `bar`), `FEET_STAY_LEVEL` after it when a `footwear` part rides a bone that hangs from another and `motion.json` holds an animation (issue #348: `status`, `reason` on a SKIP only, `animations`, `fps`, `physics_left_out`, `bar_degrees`, `bar`, `feet` — each `part`, `bone`, `hangs_from`, `status`, `frames_posed`, `worst`), `LIMB_ONE_BONE` after it (and after `STRESS_OFF_CHAIN` where that is written) when `parts.json` holds a limb segment's part (issue #349: `status`, `parts` — each `part`, `limb`, `bone`, `status`, `others`), `SEAM_OVER_RANGE` after it when a limb record carries a `range` (issue #360: `status`, `frame_scale`, `physics_left_out`, `bar` — `mean`, `rig_px_over_40`, `level` — and `joints`, each `part`, `limb`, `segment`, `joint`, `bone`, `range`, `at`, `radius`, `under_px`, `status`, `poses` — each `degrees`, `status`, `mean`, `px_over_40`, `px_over_80`, `rig_px_over_40` — and `unread` on a joint not read), `SEAM_OVER_MOTION` after it when `parts.json` holds a limb segment or `--requirements` a `seam` (issue #493, a warning and not a bar: `status` — `WARN`, `CLEAR` or `SKIP` — `reason` on a SKIP only, `fps`, `floor`, `pairs` — each `pair`, `a`, `b`, `declared`, and `unread` on a pair not read — `animations`, `warnings`, `rows` — each `pair`, `animation`, `status`, `drawn`, `banded`, `opens`, `px`, `max_px`, `under_floor`), `CLOTH_SETTLES` after it when the rig declares a physics constraint and has an idle (issue #501, a warning and not a bar: `status` — `WARN` or `CLEAR` — `fps`, `frames`, `duration`, `floor_rig_px_per_s`, `floor`, `levers`, `warnings`, `rows` — each `tip`, `root`, `links`, `point`, `settles_at`, `max_rig_px_per_s`, `min_rig_px_per_s`), `RECOMPOSITE_HOLES` (its first figure `declared_scene` when `parts.json` declares a scene), `SETUP_POSE_VS_SOURCE`, `skipped`, a `requirements` block under `--requirements`, and `PASS`; `check/build/skeleton.json`, `.atlas` and `.png` are the packed artifact rig-c writes |
|
|
196
|
+
| `check/check.json` and the rest of `check/` | `check`, `build`, `compose` | the reference's fields in its order (`gate_spine_html_green`, `rigc_entry`, `pack_mode`, `environment` after it under `--environment` only (issue #538, additive: `path` as given, `sha256`, `steps`), `loop_max_diff`, the seam figures — `seam_mean`, `seam_px_over_40`, `seam_px_over_80` and, from issue #216, `seam_frame_scale`, the frame scale the bar divides the count by), `loop_physics` after `loop_max_diff` when the rig declares a physics constraint, `seam_border` after the seam figures when `parts.json` declares a scene (issue #242), `seam_pairs` after the seam figures when the seam bar fails or `--seam-pairs` asks (each row's picture under `check/seam/`; `--keep-stills` leaves the setup-pose still and its `frames.json` under `check/setup_still/`), then the judgement lines (`BREATH_VISIBLE`, `BLINK_NO_HOLE`, `CHAIN_LAG`, `TIP_OVER_ROOT`, `STILL_REGIONS_DARK`, `TEXTURE_STRETCH`), `ANIMATIONS_DO_NOT_FOLD` after them when `motion.json` holds an animation, the idle included — on every rig with an idle since issue #333 (issues #320, #363: `status`, `animations`, `fps`, `physics_left_out`, `folding` — each `animation`, `slot`, `attachment`, `frames`, `worst_frame`, `worst_triangles`, `triangles`, `physics_on`, `physics_off`, `physics_constraints`, `declared`, `line` — `folding_undeclared`, `declared_not_folding`, `bar`), `FEET_STAY_LEVEL` after it when a `footwear` part rides a bone that hangs from another and `motion.json` holds an animation (issue #348: `status`, `reason` on a SKIP only, `animations`, `fps`, `physics_left_out`, `bar_degrees`, `bar`, `feet` — each `part`, `bone`, `hangs_from`, `status`, `frames_posed`, `worst`), `LIMB_ONE_BONE` after it (and after `STRESS_OFF_CHAIN` where that is written) when `parts.json` holds a limb segment's part (issue #349: `status`, `parts` — each `part`, `limb`, `bone`, `status`, `others`), `SEAM_OVER_RANGE` after it when a limb record carries a `range` (issue #360: `status`, `frame_scale`, `physics_left_out`, `bar` — `mean`, `rig_px_over_40`, `level` — and `joints`, each `part`, `limb`, `segment`, `joint`, `bone`, `range`, `at`, `radius`, `under_px`, `status`, `poses` — each `degrees`, `status`, `mean`, `px_over_40`, `px_over_80`, `rig_px_over_40`, and `step_px` (`left`, `right`) only on a joint whose cap record carries `short_px` (issue #557, additive) — and `unread` on a joint not read), `SEAM_OVER_MOTION` after it when `parts.json` holds a limb segment or `--requirements` a `seam` (issue #493, a warning and not a bar: `status` — `WARN`, `CLEAR` or `SKIP` — `reason` on a SKIP only, `fps`, `floor`, `pairs` — each `pair`, `a`, `b`, `declared`, and `unread` on a pair not read — `animations`, `warnings`, `rows` — each `pair`, `animation`, `status`, `drawn`, `banded`, `opens`, `px`, `max_px`, `under_floor`), `CLOTH_SETTLES` after it when the rig declares a physics constraint and has an idle (issue #501, a warning and not a bar: `status` — `WARN` or `CLEAR` — `fps`, `frames`, `duration`, `floor_rig_px_per_s`, `floor`, `levers`, `warnings`, `rows` — each `tip`, `root`, `links`, `point`, `settles_at`, `max_rig_px_per_s`, `min_rig_px_per_s`), `RECOMPOSITE_HOLES` (its first figure `declared_scene` when `parts.json` declares a scene), `SETUP_POSE_VS_SOURCE`, `skipped`, a `requirements` block under `--requirements` (or `build`'s `config.requirements`) — `file` first from issue #556, additive: `path` as typed or declared, `sha256`, `keys` — and `PASS`; `check/build/skeleton.json`, `.atlas` and `.png` are the packed artifact rig-c writes |
|
|
197
197
|
| `layers.json`, `<index>_<name>.png` | `layers --export` | the wrapper form `layers` reads (issue #359): `width`, `height`, then `layers` — each `name`, `filename`, `left`, `top`, `right`, `bottom`, `depth_median` (the input's own; `null` for a PSD, the manifest's order then being the draw order) — drawn layers in draw order, then the hidden-art layers; a PNG's name is its index and its layer's name, and the manifest, not the file name, says which layer it is |
|
|
198
198
|
| the template `.psd` | `layers --template` | one empty layer per name `templateLayerNames` (`src/layers.ts`) holds, bottom first; the same canvas writes the same bytes |
|
|
199
199
|
| `proposal.json`, `render/landmarks*.png` | `propose` | the config's four rig sections, `constraints` with `--cloth` (issue #364: a physics constraint per tree link named `<bone>_physics`, a dangling end's `<bone>_translate`, and a skirt swing's transforms `<swing>_<tree>`), `turn` with `--full`/`--head`, `proposed_rig_scale` (issue #354), and `notes` |
|
|
200
200
|
| `basis.json` | `propose` | spec `spine-parts-basis/1` |
|
|
201
|
-
| the `--write-config` file | `propose --cloth … --write-config` | the `--cloth` config read, byte for byte, but for the entries the recipe drafts (issue #537), measured against the same parts drafted without it: `meshes.<part>` and `regions.<part>` for each part the recipe moves, and `bones`, `constraints` and `motion.tracks` entry by entry by name (issue #552) — an entry the recipe drafts replaced or inserted, one it replaces removed, every other entry kept with its bytes and its place, and a hand edit to an entry the recipe owns refused by name (`PROPOSE_WRITE_CONFIG_CONFLICT`) rather than dropped; a section the input lacks is inserted |
|
|
201
|
+
| the `--write-config` file | `propose --cloth … --write-config` | the `--cloth` config read, byte for byte, but for the entries the recipe drafts (issue #537), measured against the same parts drafted without it: `meshes.<part>` and `regions.<part>` for each part the recipe moves, and `bones`, `constraints` and `motion.tracks` entry by entry by name (issue #552) — an entry the recipe drafts replaced or inserted, one it replaces removed, every other entry kept with its bytes and its place, and a hand edit to an entry the recipe owns refused by name (`PROPOSE_WRITE_CONFIG_CONFLICT`) rather than dropped; a section the input lacks is inserted; with `--from <previous config>` (issue #571) an entry equal to the previous recipe's draft is the recipe's as well |
|
|
202
202
|
| `config.json`, `mesh_draft.json` | `mesh-draft` | `config.json` is the config read, byte for byte, but for each drafted part's `meshes` entry; `mesh_draft.json` is spec `rig-parts-mesh-draft/1`: `rules`, `lattice_check`, `draft_check`, `figure_overdraw`, and per lattice part `part`, `mode`, `lattice`, `candidate` (with `bridges` — `units`, `joins` of `span` and `area_px2`, `area_px2`, `overdraw`, and `faint` only when an island was left out as faint — only when the candidate is a bridged one, issue #326), `delta` (under `--more-triangles` only), `readings`, `gate` (each line's `reading`, `pass`, `text`, `margin`), `note`; and `not_compared` (issue #307), only when the config holds an `auto` or `contour` entry: per such entry, in config order, `part`, `mode` and `note` — the part was neither drafted nor compared, and a config of lattices alone writes no such key |
|
|
203
203
|
| `rig.json`, `motion.json`, `mesh_report.json`, `images/`, `remesh.json` | `remesh` | the input revision's files, `rig.json` and `mesh_report.json` with the part's attachment and row replaced (under `--delta` the row is the input's with its counts, `bones` and influences recomputed and `mode` "delta"), every other file byte for byte; `remesh.json` is spec `rig-parts-remesh/1`: `request` (`part`, `mesh`, `mesh_sha256`, `idle_keys`, `page_edges`, `pack_shape`; under `--delta`, issue #526: `part`, `delta` — the mesh edit as read — `delta_sha256`, `ops`, `applied` — `moved`, `added`, `removed`, `constrained` — `idle_keys`, `page_edges`, `pack_shape`), `versions` (`parts`, `rigc`), `input` (`rig` — `path`, `bytes`, `sha256` per file — `config_sha256`, `parts_json_sha256`), `baseline` (`reproduced`, `not_compared`; under `--delta` `reproduced` holds one sentence: no config is built, the input is the baseline), `target` (`before`, `after`: `vertices`, `triangles`, `hull`), `preserved` (`identical`, `spliced`), `revision` (per file as `input.rig`), `check` (`input`, `revision`: `pass`, `measured`, `not_met`, `skipped`, `physics`, then `line` and `status` — issue #541, additive, the spec stays `rig-parts-remesh/1`: `line` is the last line `check` prints on that tree, byte for byte, and `status` every block's status as that tree's `check.json` records it, by name in the file's order — `gate`, `loop` and `seam` read from their figures, every other block its own `status`, a block the file does not write absent; `scope`) |
|
|
204
204
|
| `rig.json`, `motion.json`, `mesh_report.json`, `images/`, `retune.json` | `retune` | the input revision's files, `rig.json` with `constraints` and `invariants.detached` replaced and `motion.json` with `animations.idle` replaced by the config's build, every other file byte for byte; `retune.json` is spec `rig-parts-retune/1`: `request` (`idle_keys`, `page_edges`, `pack_shape`), `versions` (`parts`, `rigc`), `input` (`rig` — `path`, `bytes`, `sha256` per file — `config_sha256`, `parts_json_sha256`), `held` (`compared`, `not_compared`), `changed` (`constraints` — each `name`, `type`, `fields` — `added`, `removed`, `idle`: `tracks_changed`, `duration` as before and after), `preserved` (`identical`, `spliced`), `revision` (per file as `input.rig`), `check` (`input`, `revision`: `pass`, `measured`, `not_met`, `skipped`, `physics`, then `line` and `status` — issue #541, additive, the spec stays `rig-parts-retune/1`: `line` is the last line `check` prints on that tree, byte for byte, and `status` every block's status as that tree's `check.json` records it, by name in the file's order — `gate`, `loop` and `seam` read from their figures, every other block its own `status`, a block the file does not write absent; `scope`) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rig-parts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.51.0",
|
|
4
4
|
"description": "AI-authored 2D character parts from one anime painting and its See-through layer decomposition: measured parts, weighted-mesh rig specs, verified through rig-c before anything is written. A CLI for agents that cannot see the image.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|