@rig-c/parts 0.0.0-stage → 1.5.4
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 +433 -2
- package/bin/rig-parts.cjs +43 -0
- package/cli.ts +1240 -0
- package/docs/AUTHORING.md +2387 -0
- package/docs/MIGRATION.md +150 -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,150 @@
|
|
|
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-c/parts` (the package's name after 1.5.3; *After 1.5.3* below). A
|
|
13
|
+
config that built on 0.16.0 loads and builds unchanged: every config change since is
|
|
14
|
+
a new, opt-in field inside a new mesh mode. The bytes a config without that mode
|
|
15
|
+
builds moved once, by a declared exception (every mesh triangle's vertex order,
|
|
16
|
+
#133); apart from it, each change since 0.16.0 that touched the code was measured
|
|
17
|
+
against the tree before it on the three public examples' builds, and moved no byte
|
|
18
|
+
of them. Inside the automatic mode, one change after the candidate moves declared
|
|
19
|
+
bytes, named in *Since 1.0.0-rc.1*: the skinning envelope's 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-c/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.
|
|
138
|
+
|
|
139
|
+
## After 1.5.3: the scoped name
|
|
140
|
+
|
|
141
|
+
| | 1.0.0 to 1.5.3 | after 1.5.3 |
|
|
142
|
+
| --- | --- | --- |
|
|
143
|
+
| npm package | `rig-parts` | `@rig-c/parts`; `rig-parts` and the alias `spine-parts` are published beside it at every version as aliases, the same files with only the `name` in `package.json` changed |
|
|
144
|
+
| command | `rig-parts`, and the alias `spine-parts` on the same launcher | unchanged |
|
|
145
|
+
| repository | `firejune/rig-parts` (GitHub redirects it) | `rig-c/parts`, beside `rig-c/core` (npm `rig-c`) and `rig-c/play` |
|
|
146
|
+
| spec ids, the config, the bytes a build writes | | unchanged |
|
|
147
|
+
|
|
148
|
+
What to do: install with `npm i -D @rig-c/parts` (or `npm install -g @rig-c/parts`);
|
|
149
|
+
command lines do not change. A dependant that names `rig-parts` keeps receiving
|
|
150
|
+
every release under it (#222).
|
|
@@ -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.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
|
+
"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/rig-c/parts.git"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/rig-c/parts#readme",
|
|
20
|
+
"bugs": "https://github.com/rig-c/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
|
+
}
|