@rig-c/parts 0.0.0-stage → 1.5.3
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/LICENSE +21 -0
- package/NOTICE.md +134 -0
- package/README.md +431 -2
- package/bin/rig-parts.cjs +43 -0
- package/cli.ts +1240 -0
- package/docs/AUTHORING.md +2387 -0
- package/docs/MIGRATION.md +137 -0
- package/docs/STABILITY.md +262 -0
- package/package.json +70 -4
- package/skills/rig-parts/SKILL.md +167 -0
- package/src/apng.ts +381 -0
- package/src/assemble.ts +2259 -0
- package/src/autoamplitude.ts +194 -0
- package/src/autoenvelope.ts +404 -0
- package/src/automesh.ts +585 -0
- package/src/automotion.ts +447 -0
- package/src/autoreplay.ts +516 -0
- package/src/build.ts +1240 -0
- package/src/check.ts +2942 -0
- package/src/comfy/client.ts +245 -0
- package/src/comfy/index.ts +19 -0
- package/src/comfy/painting.ts +136 -0
- package/src/comfy/seethrough.ts +171 -0
- package/src/config.ts +2283 -0
- package/src/contour.ts +1901 -0
- package/src/coords.ts +26 -0
- package/src/diagnostics.ts +198 -0
- package/src/errors.ts +39 -0
- package/src/gif.ts +213 -0
- package/src/graphs.ts +302 -0
- package/src/headbox.ts +173 -0
- package/src/heat.ts +313 -0
- package/src/inputs.ts +100 -0
- package/src/instruments.ts +1145 -0
- package/src/keypoints.ts +296 -0
- package/src/layers.ts +598 -0
- package/src/localweights.ts +217 -0
- package/src/mesh.ts +362 -0
- package/src/motion.ts +311 -0
- package/src/palette.ts +208 -0
- package/src/parts.ts +410 -0
- package/src/propose.ts +2540 -0
- package/src/pyfmt.ts +135 -0
- package/src/raster/blur.ts +80 -0
- package/src/raster/components.ts +165 -0
- package/src/raster/composite.ts +81 -0
- package/src/raster/index.ts +9 -0
- package/src/raster/morph.ts +116 -0
- package/src/raster/png.ts +82 -0
- package/src/raster/poly.ts +166 -0
- package/src/raster/resize.ts +301 -0
- package/src/raster/types.ts +89 -0
- package/src/raster/warp.ts +121 -0
- package/src/requirements.ts +1240 -0
- package/src/rig.ts +1440 -0
- package/src/round.ts +62 -0
- package/src/scene.ts +1414 -0
- package/src/sheet.ts +128 -0
- package/src/skeleton.ts +400 -0
- package/src/structure.ts +858 -0
- package/src/tags.ts +121 -0
- package/src/weights.ts +124 -0
- package/workflows/seethrough.json +68 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Migrating from 0.16.0
|
|
2
|
+
|
|
3
|
+
0.16.0 was the last version published under the package's former name. This page is
|
|
4
|
+
what changed between it and 1.0.0 for a user of the command, an author of a config
|
|
5
|
+
and a reader of the files a build writes; what 1.0.0 holds stable is
|
|
6
|
+
[STABILITY.md](STABILITY.md). It comes in two parts: 0.16.0 to the release candidate
|
|
7
|
+
1.0.0-rc.1, then what landed between the candidate and 1.0.0. Every figure is quoted
|
|
8
|
+
from the pull request that measured it.
|
|
9
|
+
|
|
10
|
+
## In one paragraph
|
|
11
|
+
|
|
12
|
+
Install `rig-parts`. A config that built on 0.16.0 loads and builds unchanged: every
|
|
13
|
+
config change since is a new, opt-in field inside a new mesh mode. The bytes a
|
|
14
|
+
config without that mode builds moved once, by a declared exception (every mesh
|
|
15
|
+
triangle's vertex order, #133); apart from it, each change since 0.16.0 that touched
|
|
16
|
+
the code was measured against the tree before it on the three public examples'
|
|
17
|
+
builds, and moved no byte of them. Inside the automatic mode, one change after the
|
|
18
|
+
candidate moves declared bytes, named in *Since 1.0.0-rc.1*: the skinning envelope's
|
|
19
|
+
reference (#169).
|
|
20
|
+
|
|
21
|
+
## From 0.16.0 to 1.0.0-rc.1
|
|
22
|
+
|
|
23
|
+
### The package name
|
|
24
|
+
|
|
25
|
+
| | 0.16.0 | 1.0.0-rc.1 and 1.0.0 |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| npm package | the former name | `rig-parts`; the alias `spine-parts` is published beside it at every version, the same files with only the `name` in `package.json` changed |
|
|
28
|
+
| command | the former name | `rig-parts`; the install also keeps the alias `spine-parts` as a second command on the same launcher, for the transition |
|
|
29
|
+
| repository | the former repository name (GitHub redirects it) | `firejune/rig-parts` |
|
|
30
|
+
| selftest variables | the `SPINE_PARTS_` names | `RIG_PARTS_CORPUS`, `RIG_PARTS_SELFTEST_JOBS`, each read first, with the former `SPINE_PARTS_` name read when it is not set |
|
|
31
|
+
| spec ids of the files authors write and this package writes | `spine-parts-requirements/1`, `spine-parts-scene/1`, `spine-parts-keypoints/1`, `spine-parts-bonemap/1`, `spine-parts-basis/1`, `spine-parts-scene-report/1` | unchanged: they name a file format, not the tool, so a file written before the rename still reads |
|
|
32
|
+
| public examples repository | `spine-parts-examples` | unchanged (it keeps the name it was published under) |
|
|
33
|
+
|
|
34
|
+
What to do: install with `npm install -g rig-parts` and write `rig-parts` in scripts.
|
|
35
|
+
A script or a dependant that names the alias `spine-parts` keeps working and keeps
|
|
36
|
+
receiving every release; how long the alias stays is RELEASING.md's *The alias stays
|
|
37
|
+
until its retirement questions have written answers*. No build output carries the
|
|
38
|
+
package name: a grep of all 330 files the three example builds write found neither
|
|
39
|
+
spelling (#142). The console does: the lines that name the tool (5 per build: the
|
|
40
|
+
`build`, `assemble`, `rig` twice and `check` lines) now say `rig-parts`. Where a
|
|
41
|
+
config uses a constraint or `--idle-keys direct`, the `why` prose this package writes
|
|
42
|
+
into `rig.json`'s invariants names `rig-parts` too; that prefix is the one known
|
|
43
|
+
output change of the rename (#142).
|
|
44
|
+
|
|
45
|
+
### rig-c, as this package sees it
|
|
46
|
+
|
|
47
|
+
The dependency is `rig-c` `^2.33.0` at 1.0.0 (`^2.31.0` at 1.0.0-rc.1; the moves
|
|
48
|
+
between the two are in *Since 1.0.0-rc.1*), where 0.16.0 took the same upstream
|
|
49
|
+
package under its former npm name at `^2.15.0`; that name is spelled only in `CHANGELOG.md`.
|
|
50
|
+
The upstream package was renamed on npm at 2.20.4 with the same `exports` map
|
|
51
|
+
(#138), and every import, probe and sentence here names `rig-c`. A project that
|
|
52
|
+
installed the former upstream name beside this package installs nothing more:
|
|
53
|
+
`rig-c` comes as a dependency. No Spine runtime is a dependency, as in 0.16.0.
|
|
54
|
+
|
|
55
|
+
### The config
|
|
56
|
+
|
|
57
|
+
**A config that built on 0.16.0 loads unchanged.** The loader's only change between
|
|
58
|
+
the two is one more optional key, `auto`, on `meshes.<part>`, and the objects under it;
|
|
59
|
+
no key was removed, renamed or made required outside it, and no CLI flag was added or
|
|
60
|
+
removed (`git diff v0.16.0` of `src/config.ts` and `cli.ts`). `grid` and `contour`
|
|
61
|
+
meshes read exactly as before, and `propose` still writes `grid`.
|
|
62
|
+
|
|
63
|
+
What an author who adopts the new mode meets (AUTHORING §3, *An automatic mesh*):
|
|
64
|
+
|
|
65
|
+
- **`meshes.<part>.auto`**, the third mesh mode (#131): the contour mesh at alpha 1
|
|
66
|
+
and above, reduced and locally refined by rig-c's `reduceMesh` under declared
|
|
67
|
+
bounds. Exactly one of `grid`, `contour` and `auto` per mesh.
|
|
68
|
+
- **`motion` is required in it** (#134): at least `maxLocalDeformation`, the bound
|
|
69
|
+
the reduced mesh's motion against its unreduced source on the idle must meet
|
|
70
|
+
before the part is written. A part the idle cannot deform is refused, never
|
|
71
|
+
passed.
|
|
72
|
+
- **`maxOvershoot` and `maxUndercut` take `null`** (#139), in `sourceBounds` and in
|
|
73
|
+
`targets.artFit`: measured and reported, not bounded. Leaving the field out is
|
|
74
|
+
still refused by name.
|
|
75
|
+
- **The acceptance loop** (#141) replays a less-reduced step when the motion gate
|
|
76
|
+
refuses the full reduction; it needs no field. **`motion.selection`** (#151,
|
|
77
|
+
opt-in) replaces its bisection with a budgeted multi-interval search.
|
|
78
|
+
- **The Stage B opt-ins** (#147): `boundaryRuns`, `retriangulate`, `removalOrder`.
|
|
79
|
+
- **`motion.gradation`** (#150, opt-in): the author's G for rig-c's allocation
|
|
80
|
+
contrast row.
|
|
81
|
+
- **`motion.residual`** (#152, opt-in): the skinning residual as a per-step veto.
|
|
82
|
+
|
|
83
|
+
Without any of these the mode's output is what it was before each was added: every
|
|
84
|
+
pull request that added one compared the opt-out run against the tree before it,
|
|
85
|
+
byte for byte.
|
|
86
|
+
|
|
87
|
+
### The bytes a build writes
|
|
88
|
+
|
|
89
|
+
| change | what moved | measured |
|
|
90
|
+
| --- | --- | --- |
|
|
91
|
+
| #131, the automatic mode | nothing for a config without `auto` | 330 of 330 files of the three example builds identical, main at rig-c 2.15.0 against the change at 2.19.0 |
|
|
92
|
+
| #133, the winding | **the declared exception**: every mesh `triangles` triple `[a, b, c]` is written `[a, c, b]` (counter-clockwise in Spine world), in `rig.json`, the compiled `skeleton.json`, `skeleton.model.json` and the render's `geometry.json`; the `TEXTURE_STRETCH` entries in `check.json` that print a triangle's vertices and edge print them in that order; `spine.sha256` follows the skeleton bytes | every rendered PNG byte-identical before and after; the triangle index, the unordered edge, the frame, the ratio and the severity unchanged |
|
|
93
|
+
| #134, #137 to #142, #146, #147, #150, #152 | nothing | 330 of 330 at each, against the tree before it; the console differs in the one `rigc <version>` line per build where rig-c moved |
|
|
94
|
+
| #172 unit 1b, one mask under `stray` | nothing for a part without `auto.source.stray`; a part that declares it now builds where its extra islands at or under the figure refused it (`REDUCE_SOURCE_FAILS_ITS_ART_BOUNDS`): the islands are cleared from the art every reader of the mesh takes, and its row gains `stray_cleared` (islands, pixels, art pixels) and its mesh line a `stray cleared` clause; the written image is the part as assembled | the selftest's `SY01`–`SY06` on a synthetic crumb part; a part without `stray` reads the very mask object it read before (`SY03`) |
|
|
95
|
+
| #151, the multi-interval selection | nothing without `motion.selection` | measured on the selftest's fixture configs, not the example builds: rig.json, motion.json, mesh_report.json and the printed log identical in all six configurations; #152 then measured the example builds against the tree #151 left, 330 of 330 |
|
|
96
|
+
|
|
97
|
+
What to do: a consumer that compares a build with one 0.16.0 wrote, byte for byte,
|
|
98
|
+
expects the #133 exception and nothing else; one that reads the meshes (a renderer,
|
|
99
|
+
a culling pass, rig-c's own orientation rows) now reads every triangle
|
|
100
|
+
counter-clockwise in Spine world, as rig-c writes its own. Spine does not cull, so
|
|
101
|
+
nothing draws differently.
|
|
102
|
+
|
|
103
|
+
## Since 1.0.0-rc.1
|
|
104
|
+
|
|
105
|
+
Every change below is additive to the interface: a field that was refused is now
|
|
106
|
+
accepted, or a build that was refused now builds; nothing a 1.0.0-rc.1 config could
|
|
107
|
+
say is removed or reads differently, outside the declared byte move below. No CLI
|
|
108
|
+
flag was added or removed.
|
|
109
|
+
|
|
110
|
+
- **Density-only regions** (#156, opt-in): an `auto.regions` entry may leave out both
|
|
111
|
+
`bone` and `band` to ask rig-c for density without touching any weight. One without
|
|
112
|
+
the other is refused by name (`CONFIG_REGION_BAND_NEEDS_BONE`,
|
|
113
|
+
`CONFIG_REGION_BONE_NEEDS_BAND`; at 1.0.0-rc.1 the same input was refused
|
|
114
|
+
`CONFIG_FIELD_PRESENT`, naming the missing field), and a region with both reads as
|
|
115
|
+
before. A config without such a region builds as before.
|
|
116
|
+
- **The skinning envelope's reference** (#169), **the declared byte move**: under
|
|
117
|
+
`motion.residual`, the envelope rig-c's reducer is sent is derived against the
|
|
118
|
+
lowest common ancestor of the slot's bone and every bone the part's weights bind,
|
|
119
|
+
where 1.0.0-rc.1 derived it against the slot's bone and, when a bound bone did not
|
|
120
|
+
hang below it, sent no target, so the residual veto did not apply. Such a part's
|
|
121
|
+
reduction, written mesh and `mesh_report.json` row move; a part whose bound bones
|
|
122
|
+
all hang below the slot's bone makes the same call as before. The
|
|
123
|
+
`skinning_residual` row keeps its shape: its `reference` names the bone the envelope
|
|
124
|
+
was derived against, and a part whose reference is not the slot's bone carries a
|
|
125
|
+
second `rule` sentence naming the rule. `ENVELOPE_BONE_NOT_BELOW_REFERENCE` keeps
|
|
126
|
+
its name and its check.
|
|
127
|
+
- **rig-c `^2.33.0`** (#163, #166, #173, from `^2.31.0`): 2.32.1 refuses, by name, a
|
|
128
|
+
refinement insertion whose triangle would read as degenerate (`MQ_DEGENERATE`)
|
|
129
|
+
instead of writing it (rigc#1311); 2.32.2 no longer misrefuses a motion sample on an
|
|
130
|
+
edge two triangles share (`COMPARE_UV_CARRIER_NOT_UNIQUE`, rigc#1323); 2.33.0 adds
|
|
131
|
+
named interior lines, which this package does not send. The three example builds
|
|
132
|
+
are byte-identical across the move (#173).
|
|
133
|
+
|
|
134
|
+
What to do: nothing for a config without `auto`. A config under `auto` that declares
|
|
135
|
+
`motion.residual` may write a different mesh than 1.0.0-rc.1 did, as above; a
|
|
136
|
+
consumer that compares builds byte for byte with 1.0.0-rc.1 expects that move and
|
|
137
|
+
nothing else.
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Interface stability
|
|
2
|
+
|
|
3
|
+
This page states what **1.0.0 holds stable**, and what it does not. Every item is
|
|
4
|
+
read off the tree: the command and flag lists below are held to
|
|
5
|
+
`cli.ts`, and the config field list to the loader in `src/config.ts`, by the
|
|
6
|
+
selftest's `TY13` and `TY14` (the `tree` suite), so neither list can drift from the
|
|
7
|
+
code without a red run. What changed for an author coming from 0.16.0 is
|
|
8
|
+
[MIGRATION.md](MIGRATION.md).
|
|
9
|
+
|
|
10
|
+
## What "stable" means here
|
|
11
|
+
|
|
12
|
+
From 1.0.0 the package follows semantic versioning over the items on this page. A
|
|
13
|
+
stable item is not removed, renamed, or given another meaning inside a major
|
|
14
|
+
version; a new command, flag, optional config field, report key or refusal may
|
|
15
|
+
arrive in a minor version, because a reader written against the old surface still
|
|
16
|
+
reads it. A refusal may be retired in a minor version when what it refused becomes
|
|
17
|
+
accepted (0.13.0 retired two ik refusals that way, when rig-c's parser took them
|
|
18
|
+
over).
|
|
19
|
+
|
|
20
|
+
The list was frozen for review at the release candidate 1.0.0-rc.1, and 1.0.0 was
|
|
21
|
+
promoted from it after the owner's acceptance of the production evidence (issue #126,
|
|
22
|
+
item 7; `docs/evidence/production-trial.md` in the repository). Every interface
|
|
23
|
+
change between the two is additive, and [MIGRATION.md](MIGRATION.md)'s *Since
|
|
24
|
+
1.0.0-rc.1* names each one, with the build bytes that moved.
|
|
25
|
+
|
|
26
|
+
Bytes are a separate promise, and a narrower one: **one version of this package
|
|
27
|
+
with one installed rig-c writes the same bytes for the same inputs** (*Determinism*
|
|
28
|
+
below). A build's bytes are not promised across versions. A later version may move
|
|
29
|
+
them, and when it does, the change that moves them declares which bytes and why (the
|
|
30
|
+
winding change of #133 is the example: [MIGRATION.md](MIGRATION.md)).
|
|
31
|
+
|
|
32
|
+
## Commands and flags
|
|
33
|
+
|
|
34
|
+
Exit codes are part of the interface: **0** the command did what it says, **1** it
|
|
35
|
+
refused its input (every reason a `FAIL` line), **2** a usage error or a command
|
|
36
|
+
this version does not implement. No command is unimplemented at 1.0.0 (`LATER`
|
|
37
|
+
in `cli.ts` is empty). A refusal line has the shape
|
|
38
|
+
` FAIL <RULE>: <object> — <value found>; <value required>`: the rule name is a
|
|
39
|
+
stable identifier, and the detail after it is prose that may be reworded. A command
|
|
40
|
+
also answers to the alias `spine-parts` as long as the install keeps it
|
|
41
|
+
([MIGRATION.md](MIGRATION.md)). `-h`, `help` and `-v` are the short forms of
|
|
42
|
+
`--help` and `--version`. The flags' meanings are `rig-parts --help`'s; their
|
|
43
|
+
defaults are the help's too, and none is guessed from the art.
|
|
44
|
+
|
|
45
|
+
<!-- stable:commands -->
|
|
46
|
+
| command | flags |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `layers` | one positional path: a wrapper directory, a `layers.json` or a `.psd` |
|
|
49
|
+
| `sheet` | `--source`, `--layers` (repeatable), `--out`; optional `--cell`, `--cols` |
|
|
50
|
+
| `inputs` | `--source`, `--config`, `--out` |
|
|
51
|
+
| `comfy` | `paint`: `--config`, `--out`; optional `--seeds`, `--seed0`, `--host`, `--wait`, `--timeout`, `--poll` |
|
|
52
|
+
| `comfy` | `seethrough`: `--image`, `--out`; optional `--resolution`, `--steps`, `--seed`, `--prefix`, `--offload`, `--lama`, `--nf4`, `--host`, `--wait`, `--timeout`, `--poll` |
|
|
53
|
+
| `assemble` | `--propose-plan` with `--source`, `--full`, `--head`, `--config`; or `--source`, `--full`, `--head`, `--config`, `--out`, optional `--seam` (near-white, silhouette), `--project` (core, visible) |
|
|
54
|
+
| `propose` | `--head-box` with `--full`, `--canvas` |
|
|
55
|
+
| `propose` | `--parts`, `--source`, `--out`; optional `--compare` or `--from-config` (one of them), `--keypoints`, `--person` and `--wrist-snap` (each with `--keypoints`) |
|
|
56
|
+
| `compare` | `--left`, `--right`; optional `--map` |
|
|
57
|
+
| `rig` | `--config`, `--parts`, `--out`; optional `--idle-keys` (ctl, direct), `--page-edges` (pot, free), `--pack-shape` (rect, polygon) |
|
|
58
|
+
| `check` | `--rig`, `--out`; optional `--parts`, `--source`, `--page-edges`, `--pack-shape`, `--requirements`, `--seam-pairs`, `--keep-stills` |
|
|
59
|
+
| `loop` | `--frames`, `--out`; optional `--palette` |
|
|
60
|
+
| `build` | `--config`, `--source`, `--full`, `--head`, `--out`; optional `--seam`, `--project`, `--page-edges`, `--pack-shape`, `--loop`, `--requirements`, `--idle-keys` |
|
|
61
|
+
| `compose` | `--scene`, `--out`; optional `--requirements`, `--accept` |
|
|
62
|
+
| (none) | `--version`, `--help` |
|
|
63
|
+
<!-- /stable:commands -->
|
|
64
|
+
|
|
65
|
+
`TY13` holds the first column to the commands `cli.ts` dispatches and the set of
|
|
66
|
+
flags named anywhere in the table to the set of flags `cli.ts` spells. It holds the
|
|
67
|
+
names, not which command takes which flag: that pairing is the CLI's, and the `cli`
|
|
68
|
+
suite's controls read it from the help.
|
|
69
|
+
|
|
70
|
+
## The config contract
|
|
71
|
+
|
|
72
|
+
`src/config.ts` is the schema and the loader, and
|
|
73
|
+
[AUTHORING §3](AUTHORING.md#3-configjson-field-by-field) explains every field. The
|
|
74
|
+
rules that make the contract:
|
|
75
|
+
|
|
76
|
+
- **Every key is known or refused** (`CONFIG_KEY_KNOWN`), a required key that is
|
|
77
|
+
missing is refused by name (`CONFIG_FIELD_PRESENT`), and nothing is defaulted
|
|
78
|
+
from the art. A field absent where absence means "none" (a contour's `stray`, an
|
|
79
|
+
automatic mesh's `minAngle`) is written as that in the report, never filled in.
|
|
80
|
+
- **Two open doors, and nothing reads behind them**: `note` and any key ending in
|
|
81
|
+
`_note` hold a string anywhere an object is; any key beginning `x-` with a name
|
|
82
|
+
after it holds any JSON value in the same places. They are not open in `meshes`,
|
|
83
|
+
`regions` or `motion.blink.still`, whose keys are part names.
|
|
84
|
+
- **Coordinates** in `bones`, `meshes` and `motion` are rig pixels, y down, origin
|
|
85
|
+
top-left.
|
|
86
|
+
- **A mesh is one of three modes**: `grid` (the lattice, what `propose` writes),
|
|
87
|
+
`contour` (the traced outline with declared interior points) or `auto` (the
|
|
88
|
+
automatic mode: the contour mesh at alpha 1 and above reduced by rig-c's
|
|
89
|
+
`reduceMesh` under declared bounds, written only when its motion against the
|
|
90
|
+
unreduced source passes the author's bounds). Two, or none, is
|
|
91
|
+
`CONFIG_MESH_MODE`. The top-level default does not change: `propose` writes
|
|
92
|
+
`grid`, and a config that names no `auto` builds as it did before the mode
|
|
93
|
+
existed.
|
|
94
|
+
- **`constraints`** are rig-c's own rig-spec constraints (`RigConstraint` in
|
|
95
|
+
rig-c's `src/rig.ts`), handed to rigc as written; this loader checks their
|
|
96
|
+
`type`, their `name` and that every bone they name resolves.
|
|
97
|
+
|
|
98
|
+
The fields, object by object (a bold path is where the object sits; `<part>` is a
|
|
99
|
+
part name, `[i]` an entry of a list):
|
|
100
|
+
|
|
101
|
+
<!-- stable:config -->
|
|
102
|
+
- **config** — required by the full loader, in front of rig and build: `key`, `assemble`, `bones`, `meshes`, `regions`, `motion`; optional: `generation`, `seethrough`, `constraints`
|
|
103
|
+
- **generation** — required: `checkpoint`, `loras`, `trigger`, `identity`, `sampler`, `costume`, `negative_extra`, `style`, `negative_pose`, `latent`, `seed`; optional: `pose`, `control`
|
|
104
|
+
- **generation.loras[i]** — required: `name`, `strength`; optional: `strength_clip`
|
|
105
|
+
- **generation.sampler** — required: `steps`, `cfg`, `sampler`, `scheduler`
|
|
106
|
+
- **generation.control** — required: `skeleton`, `strength`, `end_percent`; optional: `model`
|
|
107
|
+
- **generation.control.skeleton**, the pose file it names when it is no built-in — required: `width`, `height`, `points`
|
|
108
|
+
- **seethrough** — required: `resolution`, `steps`, `seed`, `offload`; optional: `head_box`
|
|
109
|
+
- **assemble** — required: `rig_scale`, `plan` (from plain `assemble` on); optional: `extend_below_crop`, `patches`, `cuts`
|
|
110
|
+
- **assemble.extend_below_crop[i]** — required: `part`, `run`, `tag`
|
|
111
|
+
- **assemble.patches[i]** — required: `name`, `box`, `alpha`, `draw`
|
|
112
|
+
- **assemble.patches[i].draw**, when an object — required: `before`
|
|
113
|
+
- **assemble.cuts[i]** — required: `from`, `into`, `polygon`, `draw`, `overlap`; optional: `under`
|
|
114
|
+
- **assemble.cuts[i].draw**, when an object — required: `before`
|
|
115
|
+
- **bones[i]**, a single bone — required: `name`, `parent`, `at`; optional: `tip`
|
|
116
|
+
- **bones[i]**, a chain — required: `chain`, `parent`, `points`, `tip`
|
|
117
|
+
- **meshes.<part>** — exactly one of `grid`, `contour`, `auto`; required in every mode: `r`, `segments`; optional in every mode: `exponent`, `rule`; optional with `contour` or `auto`: `ribs`
|
|
118
|
+
- **meshes.<part>.ribs.<chain>** — required: `stations`
|
|
119
|
+
- **meshes.<part>.contour** — required: `tolerance`, `margin`, `spacing`; optional: `budget`, `stray`, `regions`
|
|
120
|
+
- **meshes.<part>.contour.regions[i]** — required: `name`, `shape`, `bone`, `spacing`, `band`, and `cx`, `cy`, `r` for a circle or `points` for a polygon
|
|
121
|
+
- **meshes.<part>.auto** — required: `source`, `sourceBounds`, `targets`, `influences`, `budget`, `minArtSamples`, `motion`; optional: `protect`, `regions`, the three Stage B opt-ins `boundaryRuns`, `retriangulate`, `removalOrder`, and `stimulus`
|
|
122
|
+
- **meshes.<part>.auto.source** — required: `tolerance`, `margin`, `spacing`; optional: `stray`
|
|
123
|
+
- **meshes.<part>.auto.sourceBounds** and **meshes.<part>.auto.targets.artFit** — required: `minCoverage`, `maxOvershoot`, `maxUndercut` (each of the last two a number or null, the bound declared absent)
|
|
124
|
+
- **meshes.<part>.auto.targets** — required: `artFit`, `maxBoundaryDeviation`; optional: `minAngle`
|
|
125
|
+
- **meshes.<part>.auto.influences** — required: `maxInfluences`, `minWeight`
|
|
126
|
+
- **meshes.<part>.auto.budget** — required: `maxCandidates`
|
|
127
|
+
- **meshes.<part>.auto.motion** — required: `maxLocalDeformation`; optional: `maxStretch`, `minStretch`, `deformMayFold`, `gradation`, `selection`, `residual`
|
|
128
|
+
- **meshes.<part>.auto.motion.selection** — required: `policy`, `maxProbes`
|
|
129
|
+
- **meshes.<part>.auto.motion.residual** — required: `maxResidual`
|
|
130
|
+
- **meshes.<part>.auto.protect** — optional: `hull`, `vertices`, `edges`, `regionBoundaries`, `weightJump`, `influences`
|
|
131
|
+
- **meshes.<part>.auto.regions[i]** — required: `name`, `shape`, `maxEdgeLength`, `transition`, `grade`, `minArtSamples`, and `cx`, `cy`, `r` for a circle or `points` for a polygon; optional: `bone`, `band` (both or neither; with neither the region is density only)
|
|
132
|
+
- **meshes.<part>.auto.boundaryRuns** — required: `maxVertices`
|
|
133
|
+
- **meshes.<part>.auto.stimulus**, or each entry of it when a list — required: `chain`, `degrees`
|
|
134
|
+
- **regions.<part>** — a bone name
|
|
135
|
+
- **motion** — required: `duration`, `tracks`; optional: `blink`, `animations_from`
|
|
136
|
+
- **motion.tracks[i]**, a single track — required: `bone`, `prop`, `amp`, `period`, `phase`; optional: `base`
|
|
137
|
+
- **motion.tracks[i]**, a chain track — required: `chain`, `amps`, `period`, `phase`, `lag`
|
|
138
|
+
- **motion.blink** — required: `t`, `eyes`, `squash`; optional: `brows`, `brow_drop`, `still`
|
|
139
|
+
- **motion.blink.still.<part>** — required: `row`, `bone`
|
|
140
|
+
- **motion.animations_from**, the file it names — required: `spec`, `animations`
|
|
141
|
+
- **proposal.json**, the file propose writes — `bones`, `meshes`, `regions`, `motion` under the rules above, and `notes`
|
|
142
|
+
<!-- /stable:config -->
|
|
143
|
+
|
|
144
|
+
`TY14` holds the set of field names in backticks above to the set of names the
|
|
145
|
+
loader's object checks spell (every `c.object(…)` in `src/config.ts`, with the lists
|
|
146
|
+
they name), in both directions, and refuses an object check whose key list it cannot
|
|
147
|
+
read. It holds the names, not their nesting or which are required: the `config`
|
|
148
|
+
suite's controls hold those, refusal by refusal.
|
|
149
|
+
|
|
150
|
+
The values a field takes (`retriangulate` is "delaunay", `removalOrder`
|
|
151
|
+
"deformation-load", `selection.policy` "multi-interval"; the units and ranges of
|
|
152
|
+
every number) are AUTHORING §3's tables, and the loader refuses any other by name.
|
|
153
|
+
|
|
154
|
+
## Files this package writes
|
|
155
|
+
|
|
156
|
+
| file | written by | what is stable |
|
|
157
|
+
| --- | --- | --- |
|
|
158
|
+
| `parts.json`, `parts/<name>.png` | `assemble`, `build` | one record per part: `from`, 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` |
|
|
159
|
+
| `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 |
|
|
160
|
+
| `rig/mesh_report.json` | `rig`, `build` | one row per mesh: `part`, `vertices`, `triangles`, `hull`, `bones`, `max_influences`, `mean_influences`, `art_coverage`, then `grid` (a lattice); `mode` "contour" with `params`, `contour`, `regions`; 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`); `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) |
|
|
161
|
+
| `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`, `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_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`), `RECOMPOSITE_HOLES`, `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 |
|
|
162
|
+
| `proposal.json`, `render/landmarks*.png` | `propose` | the config's four rig sections and `notes` |
|
|
163
|
+
| `basis.json` | `propose` | spec `spine-parts-basis/1` |
|
|
164
|
+
| the scene report | `compose` | spec `spine-parts-scene-report/1` |
|
|
165
|
+
| `idle.png`, `idle-indexed.png`, `idle.gif` | `loop`, `build --loop` | APNG and GIF encodings of the rendered idle |
|
|
166
|
+
|
|
167
|
+
Files authors write for this package, each with a spec id the reader holds:
|
|
168
|
+
`spine-parts-requirements/1` (`check --requirements`), `spine-parts-scene/1`
|
|
169
|
+
(`compose --scene`), `spine-parts-keypoints/1` (`propose --keypoints`),
|
|
170
|
+
`spine-parts-bonemap/1` (`compare --map`). The spec ids keep the package's former
|
|
171
|
+
name on purpose: they name a file format, not the tool, and a file written before
|
|
172
|
+
the rename still reads. They do not change at 1.0.
|
|
173
|
+
|
|
174
|
+
## Environment
|
|
175
|
+
|
|
176
|
+
The installed package reads two environment variables and no other: `PATH`, where
|
|
177
|
+
the launcher finds Bun and the CLI finds the `rigc` its own `node_modules` holds,
|
|
178
|
+
and `COMFY_HOST`, which `comfy paint` and `comfy seethrough` read when `--host` is
|
|
179
|
+
not given (it has no default). `RIG_PARTS_CORPUS` and `RIG_PARTS_SELFTEST_JOBS`,
|
|
180
|
+
with their former `SPINE_PARTS_` names read when they are not set, are the
|
|
181
|
+
selftest's, a development interface of this repository: the selftest does not ship
|
|
182
|
+
in the package.
|
|
183
|
+
|
|
184
|
+
## rig-c
|
|
185
|
+
|
|
186
|
+
`dependencies` takes `rig-c` `^2.33.0`: 2.33.0 or any later 2.x. Bun 1.2 or later
|
|
187
|
+
runs the package (`engines`). What this package relies on in rig-c, every import
|
|
188
|
+
read off `src/` and `cli.ts`:
|
|
189
|
+
|
|
190
|
+
- the named entries `rig-c/mesh` (the outline functions, `measureAuthoredMeshFit`,
|
|
191
|
+
`reduceMesh`, `skinningEnvelopeBone`, `writeMeshQualityReport` and their types)
|
|
192
|
+
and `rig-c/meshcompare` (`compareMeshesInMotion`);
|
|
193
|
+
- the deep paths its `exports` map carries: `rig-c/src/rig.ts` (`parseRigSpec`,
|
|
194
|
+
`RIG_SPEC_VERSION`, the constraint keys), `rig-c/src/errors.ts`,
|
|
195
|
+
`rig-c/src/png.ts`, `rig-c/src/transform.ts` (the y flip, through
|
|
196
|
+
`src/coords.ts` only), `rig-c/tools/plate.ts` (the PNG codec) and
|
|
197
|
+
`rig-c/tools/font5x7.ts`;
|
|
198
|
+
- the `rigc` command: `build` and `render`, and `--version`, whose `entry:` line
|
|
199
|
+
says which validator gated a build (`check.json`'s `rigc_entry`).
|
|
200
|
+
|
|
201
|
+
A rig-c release that moves any of these breaks this package by name, and the
|
|
202
|
+
install smoke is where that shows first. No Spine runtime is a dependency: an
|
|
203
|
+
install is gated by rigc's own validator, and `@esotericsoftware/spine-core` is a
|
|
204
|
+
development dependency of this repository only.
|
|
205
|
+
|
|
206
|
+
## What is not stable
|
|
207
|
+
|
|
208
|
+
- **The evidence documents** under `docs/evidence/`: their layout, columns and
|
|
209
|
+
figures are a measurement record of one tree on one rig-c, regenerated when the
|
|
210
|
+
tools or rig-c move.
|
|
211
|
+
- **The tools** under `tools/` (the matrix, the surveys, the comparisons) and their
|
|
212
|
+
command lines, and the scripts under `scripts/`.
|
|
213
|
+
- **The selftest**: its control names, counts and line wording.
|
|
214
|
+
- **Console prose** beyond the shapes above: the detail after a rule name, the
|
|
215
|
+
wording of a note, the order of informational lines.
|
|
216
|
+
- **The examples' `expected/` outputs**: they are this repository's regression
|
|
217
|
+
record and move with any change that declares a byte move.
|
|
218
|
+
- **Bytes across versions**, as stated at the top.
|
|
219
|
+
|
|
220
|
+
## Bounded time, and what the checks cost
|
|
221
|
+
|
|
222
|
+
The automatic mode's search is bounded by counts the author declares or the call
|
|
223
|
+
derives, never by a clock (`src/` reads none): rig-c's `reduceMesh` tries at most
|
|
224
|
+
`budget.maxCandidates` steps, the acceptance loop replays at most ⌈log₂(N − I)⌉
|
|
225
|
+
removal steps (N the call's accepted operations, I the refinement's), and the
|
|
226
|
+
multi-interval selection at most `motion.selection.maxProbes`, each replay one
|
|
227
|
+
unpacked gated build and one motion comparison. Wall time is therefore a property of
|
|
228
|
+
the input and the machine. Measured: the evidence tools run every cell under a
|
|
229
|
+
600 s cap and a whole matrix under 2,700 s (`docs/evidence/auto-mesh-matrix.md`,
|
|
230
|
+
*re-running*); one `reduceMesh` call on the public parts took 0.7 s to 10.7 s at
|
|
231
|
+
rig-c 2.23.0 (the same document's quiet timing table, a remote WSL runner, pool,
|
|
232
|
+
load under 2); at rig-c 2.31.0 the whole rig stage of one automatic part, motion
|
|
233
|
+
gate and acceptance loop included, took 1.1 s to 61.6 s on the eight parts the
|
|
234
|
+
surveys switch, demo `bottomwear` the slowest at 12 gated builds, with a run-to-run
|
|
235
|
+
spread of ±15 % on that part (pull request #152's paired exclusive timing, remote
|
|
236
|
+
20-core runner; the surveys print wall time to standard error, not into the
|
|
237
|
+
documents). On CI (`ubuntu-latest`), the last two green runs on `main` took 4 min
|
|
238
|
+
54 s and 8 min 28 s for the full selftest (842 controls over 45 suites at
|
|
239
|
+
`22b2c5a`, with the public examples fetched; the job's limit is 20 minutes) and
|
|
240
|
+
42 s and 41 s for the install smoke (6 cases; limit 10 minutes), at `8be4cd1` and
|
|
241
|
+
`22b2c5a` respectively. None of these figures is a promise: they are what the named
|
|
242
|
+
runs measured.
|
|
243
|
+
|
|
244
|
+
## Determinism
|
|
245
|
+
|
|
246
|
+
The same inputs, with the same version of this package and the same installed
|
|
247
|
+
rig-c, write the same bytes: fixed key order in every JSON written, stable sorts, no
|
|
248
|
+
clock, no randomness and no locale-sensitive formatting. `src/` is pure outside
|
|
249
|
+
`src/comfy/` (`TY06` refuses a clock, randomness or network call anywhere else under
|
|
250
|
+
`src/`). The selftest holds it by running the same thing twice and comparing the bytes:
|
|
251
|
+
`PN01` (the PNG codec), `PT01` (`parts.json` round trip), `AS07` (`assemble`
|
|
252
|
+
from the CLI), `SK04` (the skeleton), `RG03` (two lattice builds), `CW20` and
|
|
253
|
+
`CT20` (a contour rig and a contour mesh), `AM24` (an automatic mesh), `MO11`,
|
|
254
|
+
`MO27`, `MO44`, `MO50`, `MO63` and `MO74` (the motion gate, the acceptance
|
|
255
|
+
loop's replay, every Stage B opt-in, a gradation, the multi-interval selection's
|
|
256
|
+
policy path and the residual veto), `CK02`, `CK33` and `CK79` (`check`, its
|
|
257
|
+
stretch geometry, and `check --requirements`), `DG13` (`basis.json`), `LP08`
|
|
258
|
+
(the indexed APNG) and `ST26` (the `compare` printout). With the public examples
|
|
259
|
+
fetched, the `chain` suite builds each of them and holds `parts.json`
|
|
260
|
+
(`CH02`), `rig.json`, `motion.json` and `mesh_report.json` (`CH03`),
|
|
261
|
+
`check.json` (`CH04`) and the gate file (`CH05`) to its tracked `expected/`,
|
|
262
|
+
field by field, with the tolerances `CH07` plants against.
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rig-c/parts",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.5.3",
|
|
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
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"rig-parts": "./bin/rig-parts.cjs",
|
|
8
|
+
"spine-parts": "./bin/rig-parts.cjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"bun": ">=1.2.0"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "firejune",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/firejune/rig-parts.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/firejune/rig-parts#readme",
|
|
20
|
+
"bugs": "https://github.com/firejune/rig-parts/issues",
|
|
21
|
+
"keywords": [
|
|
22
|
+
"spine",
|
|
23
|
+
"spine2d",
|
|
24
|
+
"spine-2d",
|
|
25
|
+
"ai",
|
|
26
|
+
"ai-agents",
|
|
27
|
+
"rigging",
|
|
28
|
+
"character-rigging",
|
|
29
|
+
"character-parts",
|
|
30
|
+
"layer-decomposition",
|
|
31
|
+
"see-through",
|
|
32
|
+
"anime",
|
|
33
|
+
"live2d-alternative",
|
|
34
|
+
"weighted-mesh",
|
|
35
|
+
"skeletal-animation",
|
|
36
|
+
"psd",
|
|
37
|
+
"cli"
|
|
38
|
+
],
|
|
39
|
+
"files": [
|
|
40
|
+
"bin/rig-parts.cjs",
|
|
41
|
+
"cli.ts",
|
|
42
|
+
"src",
|
|
43
|
+
"workflows",
|
|
44
|
+
"docs/AUTHORING.md",
|
|
45
|
+
"docs/MIGRATION.md",
|
|
46
|
+
"docs/STABILITY.md",
|
|
47
|
+
"skills",
|
|
48
|
+
"NOTICE.md"
|
|
49
|
+
],
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"fetch-examples": "bash scripts/fetch-examples.sh",
|
|
55
|
+
"selftest": "bun selftest.ts",
|
|
56
|
+
"smoke": "bun scripts/install_smoke.ts",
|
|
57
|
+
"typecheck": "bunx tsc --noEmit",
|
|
58
|
+
"lint": "bunx eslint .",
|
|
59
|
+
"prepublishOnly": "bun run typecheck && bun run lint && bun run selftest"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"ag-psd": "^31.0.2",
|
|
63
|
+
"rig-c": "^2.33.0"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@esotericsoftware/spine-core": "4.3.13",
|
|
67
|
+
"@types/bun": "^1.4.2",
|
|
68
|
+
"eslint": "^10.11.0",
|
|
69
|
+
"typescript": "^5.9.3",
|
|
70
|
+
"typescript-eslint": "^8.70.1"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rig-parts
|
|
3
|
+
description: Turn one anime character painting and its See-through layer decomposition into a verified 2D character rig (Spine 4.3 skeleton data) — measured parts, weighted meshes, bone chains and a looping idle — with rig-parts, which gates everything through rig-c before it is written. Use for a request to rig or animate a single character painting, to run or read rig-parts layers, sheet, assemble, propose, rig, check, loop or build, or to write or fix a rig-parts config.json. Not for cutting art into parts by hand, for authoring a rig from loose PNGs (that is the rigc skill), for lip-sync or swapping a part's image, or for running See-through itself.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires Bun 1.2 or later. The tool is the npm package rig-parts (bunx rig-parts, or bun add -d rig-parts); rig-c is installed with it. See-through is run separately.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# rig-parts — a painting to a Spine rig, for agents
|
|
9
|
+
|
|
10
|
+
rig-parts merges See-through's two layer runs over one painting into rig-space
|
|
11
|
+
parts, authors a rig spec and a motion spec over them, and hands those to
|
|
12
|
+
rig-c, which compiles, gates, packs and renders. You cannot see the painting,
|
|
13
|
+
the layers or the rig. The printed lines, `docs/AUTHORING.md` and the files each
|
|
14
|
+
stage writes are the whole interface.
|
|
15
|
+
|
|
16
|
+
## Non-negotiables
|
|
17
|
+
|
|
18
|
+
- **rig-c's gate is never bypassed.** rig-parts writes no Spine data
|
|
19
|
+
itself; `rig` writes only after rigc's `build` gate is green, and `build`'s
|
|
20
|
+
artifact is what rigc wrote. There is no flag that skips it, and none may be added.
|
|
21
|
+
`check.json`'s `rigc_entry` names which gate ran: rigc's own validator in an
|
|
22
|
+
install, the spine-core round trip where the runtime is installed beside rigc.
|
|
23
|
+
- **No value is invented.** A missing config field is a refusal naming it. Take a
|
|
24
|
+
value from the command that proposes it (`propose --head-box`,
|
|
25
|
+
`assemble --propose-plan`, `propose`) or decide it yourself — never guess one
|
|
26
|
+
because the tool refused.
|
|
27
|
+
- **The refusal is the instruction.** `FAIL RULE: object — detail` names the object,
|
|
28
|
+
the value found and the value required; AUTHORING §6 maps every rule to the field
|
|
29
|
+
or input that has to change.
|
|
30
|
+
- **Green is not "looks right".** `check` measures the gates, the seam, the loop and
|
|
31
|
+
six judgement lines (`BREATH_VISIBLE`, `BLINK_NO_HOLE`, `CHAIN_LAG`,
|
|
32
|
+
`TIP_OVER_ROOT`, `STILL_REGIONS_DARK` — its face half in the head's own frame —
|
|
33
|
+
and `TEXTURE_STRETCH`) (AUTHORING §7). A judgement line that says
|
|
34
|
+
SKIP was not verified: report it as such, with its reason, never as passed.
|
|
35
|
+
No line judges a bang over the face or the eyes: `STILL_REGIONS_DARK`'s
|
|
36
|
+
`crossing` reports how deep each one swings, and only an eye can say whether
|
|
37
|
+
that reads right.
|
|
38
|
+
- **What a scene asks is declared, not assumed.** When the request says what the
|
|
39
|
+
motion must do — a hand on a cup, a sleeve taking half an arm's turn, a joint
|
|
40
|
+
inside a range, a fringe that must not part from the face — write it into a `spine-parts-requirements/1` file and pass
|
|
41
|
+
`check --requirements <file>` (or `build --requirements`); every bar in it is the
|
|
42
|
+
requester's, never yours to invent (AUTHORING §7, *Declared requirements*). Each
|
|
43
|
+
line is PASS, FAIL or NOT MEASURABLE; a NOT MEASURABLE is not green, and a kind the
|
|
44
|
+
file does not declare was not measured — say so, never "passed".
|
|
45
|
+
- **A hole in the layers is invisible to every bar.** Painting that no part holds is
|
|
46
|
+
missing from the setup pose and from the flat stack alike, so the seam passes over
|
|
47
|
+
it. `assemble` lists it (`uncovered hole N: <px> px at x,y wxh (between …)`) and
|
|
48
|
+
paints it red in `recomposite_error_rig.png`; `check` copies it into `check.json` as
|
|
49
|
+
`RECOMPOSITE_HOLES`, a REPORTED line with no bar. Read it; never report it as a
|
|
50
|
+
pass.
|
|
51
|
+
|
|
52
|
+
## The loop
|
|
53
|
+
|
|
54
|
+
1. `rig-parts inputs --source <painting> --config config.json --out <dir>` writes
|
|
55
|
+
`st_input_full.png`, the painting on a white square. The config needs only `key`,
|
|
56
|
+
`seethrough` and `assemble.rig_scale` at this point. Run See-through on it — any
|
|
57
|
+
route; the optional `comfy seethrough` adapter only talks to a ComfyUI box.
|
|
58
|
+
2. `rig-parts layers <full run>` — read the table. A `WARN PLAN_LAYER_…` line names
|
|
59
|
+
a layer See-through invented (a translucent haze, or one out of proportion);
|
|
60
|
+
the plan step leaves it out and says so in its `notes`.
|
|
61
|
+
3. `rig-parts propose --head-box --full <full run> --canvas <W>x<H>` → put
|
|
62
|
+
`head_box` in the config, run `inputs` again (it now also writes
|
|
63
|
+
`st_input_head.png`, the crop at that box), and run See-through on the crop.
|
|
64
|
+
4. `rig-parts assemble --propose-plan …` → `config.assemble.plan` and
|
|
65
|
+
`extend_below_crop`.
|
|
66
|
+
5. `rig-parts assemble … --out work` — read the `uncovered hole` lines and look at
|
|
67
|
+
`work/render/recomposite_error_rig.png`; a large red hole between two parts is a
|
|
68
|
+
gap See-through left (a skirt split into two legs), fixed in the plan or the layers,
|
|
69
|
+
not in the rig. Then `rig-parts propose --parts work/rig
|
|
70
|
+
--source <painting> --out work` → copy `bones`, `meshes`, `regions`, `motion`
|
|
71
|
+
from `proposal.json` into the config. `assemble` needs the plan and none of
|
|
72
|
+
those four; do not stub them to get past it (AUTHORING §4 says what each step
|
|
73
|
+
requires). If an `uncovered hole` stays large with the plan right — a piece
|
|
74
|
+
of the figure neither run holds, red in `recomposite_error_rig.png` — add an
|
|
75
|
+
`assemble.patches` entry (a rig-pixel box, `alpha: "silhouette"`, drawn
|
|
76
|
+
`"back"` and reaching under its neighbours, its bone in `regions`) and assemble
|
|
77
|
+
again; never add a part to `rig/` or `parts/` by hand (AUTHORING §5).
|
|
78
|
+
One layer holding two things that must move apart (a scarf end inside
|
|
79
|
+
`topwear`, both arms in one `handwear`): add an `assemble.cuts` entry — a
|
|
80
|
+
polygon in rig pixels read off `work/rig/parts/<part>.png` plus its
|
|
81
|
+
`parts.json` `x`, `y`, a new name, a `draw`, an `overlap` (the band the part
|
|
82
|
+
keeps under the piece's edge; 1 px closed the seam on scarf) — and give the piece its own
|
|
83
|
+
`meshes` entry; the `cut:` line gives the split. At overlap 0 a cut through
|
|
84
|
+
opaque art leaves a seam `check` reads (AUTHORING §5).
|
|
85
|
+
A seated or reclining figure: add `--keypoints <file>` (body-18 joints in
|
|
86
|
+
painting px, each observed, occluded or missing; AUTHORING §3, *A posed
|
|
87
|
+
figure*) so the neck, hip, chest and sleeves follow the pose and LINT reads
|
|
88
|
+
the joints, not screen y. Never write a joint you did not get from an
|
|
89
|
+
estimator or the painting: say `missing` and let the rule stand in.
|
|
90
|
+
6. Correct against `render/landmarks.png` and `note:` lines; a
|
|
91
|
+
`coverage … not checked` line is a bone no check read (the line says why),
|
|
92
|
+
and `basis.json` beside the proposal says what each bone rests on — check
|
|
93
|
+
the `ratio` bones and any with a `fallback` first. `propose …
|
|
94
|
+
--from-config config.json` (with the same `--keypoints`) until it prints no
|
|
95
|
+
`LINT` line. `rig-parts compare
|
|
96
|
+
--left work/proposal.json --right config.json` lists what the correction changed,
|
|
97
|
+
bone by bone — origin, parent, tip, length, direction (AUTHORING §4).
|
|
98
|
+
A constraint the motion needs (an ik reaching a scene target, physics on a
|
|
99
|
+
link) goes in `config.constraints`, in rig-c's own rig-spec shape: the
|
|
100
|
+
loader resolves the bones it names and nothing else, and rigc's gate refuses
|
|
101
|
+
the rest in its words. A scene target is a single bone under `root`. A two-bone
|
|
102
|
+
ik over links the idle keys needs `--idle-keys direct` on `rig` or `build`
|
|
103
|
+
(rigc refuses the pair the link's control splits, and the line names the flag
|
|
104
|
+
on the command that ran; AUTHORING §3).
|
|
105
|
+
7. `rig-parts build --config … --source … --full … --head … --out out --loop`
|
|
106
|
+
(add `--idle-keys direct` when step 6 said so).
|
|
107
|
+
It stops at the first stage that refuses, printing that stage's lines under
|
|
108
|
+
`[assemble]`, `[rig]` or `[check]`. Fix what the FAIL line names and build again.
|
|
109
|
+
8. Read `out/check/check.json` — the six judgement lines the same way as the seam
|
|
110
|
+
and the loop: a FAIL names the field to change (AUTHORING §6);
|
|
111
|
+
`TEXTURE_STRETCH` names the worst mesh triangle (slot, triangle, vertices, edge,
|
|
112
|
+
frame), so quote it even on a PASS. Quote
|
|
113
|
+
`RECOMPOSITE_HOLES` (uncovered px, hole count, the largest hole's box) in the
|
|
114
|
+
report whatever `PASS` says. The artifact is the three paths the build prints
|
|
115
|
+
last: `check/build/skeleton.json`, `skeleton.atlas` and the packed page. Report
|
|
116
|
+
them with the pack line and the check figures verbatim.
|
|
117
|
+
|
|
118
|
+
Several characters in one rig: build each one green on its own, then
|
|
119
|
+
`rig-parts compose --scene scene.json --out scene` (spec `spine-parts-scene/1`:
|
|
120
|
+
the canvas, each character's `build` and `offset`, an optional plate with its
|
|
121
|
+
`provenance`, and the `order` of the characters' slots, back to front). You write
|
|
122
|
+
the order and the offsets; nothing infers them, nothing scales a character, and
|
|
123
|
+
nothing detects or separates people. Report the plate's provenance as you declared
|
|
124
|
+
it and the order as `scene.json` records it (AUTHORING §7, *Composing several
|
|
125
|
+
characters*).
|
|
126
|
+
|
|
127
|
+
`--seam silhouette` repairs more of the seam on white garments than the default
|
|
128
|
+
`near-white` (the demo: 10,340 → 8,644 recomposite error pixels); the default is
|
|
129
|
+
the reference implementation's rule. `--project visible` lets thin visible parts
|
|
130
|
+
(lashes, brows, irises) take the painting's pixels, which the default `core` rule
|
|
131
|
+
erodes away. Name both rules you used in your report, and quote the assemble
|
|
132
|
+
`pixels:` line: its occluded share is hidden art, its "visible but not projected"
|
|
133
|
+
share is synthesis where the painting was there to be taken.
|
|
134
|
+
|
|
135
|
+
## What this will not do
|
|
136
|
+
|
|
137
|
+
- Run See-through or generate the painting itself. The optional `comfy seethrough`
|
|
138
|
+
and `comfy paint` commands drive a ComfyUI box you name; nothing else here reaches
|
|
139
|
+
a GPU or the network.
|
|
140
|
+
- Give a layer two depths: a layer in front of another in one place and behind it in
|
|
141
|
+
another is right in the still and wrong in motion.
|
|
142
|
+
- Propose, key or judge any animation but the looping `idle`, or lip-sync: every slot
|
|
143
|
+
holds one attachment, so nothing swaps a part's image. Expressions and a jiggle are
|
|
144
|
+
yours to build on top (below).
|
|
145
|
+
- Write animated WebP: `loop` writes GIF and APNG.
|
|
146
|
+
- Know what the art does not tag: a swinging element painted inside another layer,
|
|
147
|
+
hair of an unfamiliar shape, whether an accessory swings. Those are yours to add.
|
|
148
|
+
- Promise a success rate. Three public characters and eight private ones check green;
|
|
149
|
+
that is all that has been measured.
|
|
150
|
+
|
|
151
|
+
## Where to read next
|
|
152
|
+
|
|
153
|
+
[docs/AUTHORING.md](https://github.com/firejune/rig-parts/blob/main/docs/AUTHORING.md)
|
|
154
|
+
first — every config field, the command order, what to read after each stage, every
|
|
155
|
+
refusal. It is in the installed package at `node_modules/rig-parts/docs/AUTHORING.md`,
|
|
156
|
+
the copy that matches the version you run. Two recipes there cover what this package
|
|
157
|
+
leaves to you:
|
|
158
|
+
|
|
159
|
+
- An expression or any other named animation: AUTHORING §3, *Recipe: expressions and other
|
|
160
|
+
named animations* (`motion.animations_from`; built and gated with the rig, not measured).
|
|
161
|
+
- A jiggle (a bust, the hips): AUTHORING §3, *Recipe: a soft region driven by physics* (a
|
|
162
|
+
config-only bone, a `contour` region on it, a `physics` constraint; `examples/sample`
|
|
163
|
+
carries one, and its slow idle barely moves it).
|
|
164
|
+
|
|
165
|
+
A `RIG_RIGC_GREEN` or `CHECK_RIGC_GREEN`
|
|
166
|
+
line quotes rig-c's own assertion; rig-c's guide for those is
|
|
167
|
+
`node_modules/rig-c/docs/AUTHORING.md`, and its `rigc` skill covers the compiler.
|