spine-rigc 0.35.0 โ 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/AUTHORING.md +161 -97
- package/docs/FACE.md +3 -1
- package/docs/INGEST.md +10 -13
- package/docs/SPEC_COVERAGE.md +15 -14
- package/package.json +1 -1
- package/src/compile.ts +224 -236
- package/src/diff.ts +59 -0
- package/src/ingest.ts +26 -148
- package/src/rig.ts +48 -8
- package/src/timelines.ts +23 -8
- package/src/types.ts +14 -13
- package/src/validate.ts +9 -3
- package/tools/editor_roundtrip.ts +13 -4
package/docs/AUTHORING.md
CHANGED
|
@@ -1045,6 +1045,15 @@ page:
|
|
|
1045
1045
|
| leaves a remaining **tie in the order your file declares it** | `turn` before `Turn`; `Mango` before `mango` โ each given in that order and returned in it |
|
|
1046
1046
|
| writes **leaves then folders at the root**, and **sub-folders then leaves inside a folder** | `h` before `f/sub1/deep/q`; `f/sub1/x` before `f/leafA` |
|
|
1047
1047
|
|
|
1048
|
+
๐ธ **One clause of the rule is not from those files.** Before comparing, the
|
|
1049
|
+
comparator reads U+3000 IDEOGRAPHIC SPACE as a space and the full-width digits
|
|
1050
|
+
U+FF10โU+FF19 as `0`โ`9`. No probe carried either; the fold was measured on a
|
|
1051
|
+
production skin's slot keys ([#791](https://github.com/firejune/rigc/issues/791),
|
|
1052
|
+
ยง10.6b says what was measured and why it is those two classes and not NFKC), and
|
|
1053
|
+
it applies here because R10, R11 and a skin's slot keys are one comparator. So
|
|
1054
|
+
`shot๏ผ` sorts before `shot10`, and a pair an ideographic space decides is
|
|
1055
|
+
ordered rather than refused as `separator`.
|
|
1056
|
+
|
|
1048
1057
|
โญ **A tie is not an ambiguity, and that is what retired most of this rule's
|
|
1049
1058
|
refusals.** Two names the comparator cannot separate come back in the order the
|
|
1050
1059
|
file gave them, so the order rigc emits for such a pair is **your own declaration
|
|
@@ -1094,12 +1103,14 @@ names the same comparator puts ahead of it โ `default` before `2`, `default`
|
|
|
1094
1103
|
before `A` โ so renaming a skin away from `default` makes it an ordinary name that
|
|
1095
1104
|
sorts like one.
|
|
1096
1105
|
|
|
1097
|
-
**R12 โ
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1106
|
+
**R12 โ An attachment's `name` is written exactly when the spec states it, and
|
|
1107
|
+
the `default` skin may not share a placeholder with a named skin.** rigc derives
|
|
1108
|
+
no name. A placeholder several skins fill is emitted under that placeholder in
|
|
1109
|
+
each skin, carrying the `name` each entry states and none where it states none โ
|
|
1110
|
+
which is the shape the editor itself exports (ยง3.4.2). Until
|
|
1111
|
+
[#796](https://github.com/firejune/rigc/issues/796) rigc composed
|
|
1112
|
+
`"<skin>/<placeholder>"` there, which renamed every such attachment at runtime.
|
|
1113
|
+
What you *do* author is where the shared art lives: a
|
|
1103
1114
|
placeholder the `default` skin shares with a named skin is a **compile error**,
|
|
1104
1115
|
because the Spine editor has no representation for it in either spelling (#567,
|
|
1105
1116
|
measured on 4.3.26 โ named, the export re-keys it and the default skin draws
|
|
@@ -1323,25 +1334,26 @@ the default `type`:
|
|
|
1323
1334
|
| Field | Meaning |
|
|
1324
1335
|
| --- | --- |
|
|
1325
1336
|
| `type` | `"region"`, or omit |
|
|
1337
|
+
| `name` | the attachment's **own name**, when it is not the placeholder: what the runtime calls it (`Attachment.name`, which is what `slot.attachment.name` returns) and what `path` defaults to. Optional โ absent, the runtime names the attachment by its placeholder. Written **verbatim**, as the attachment's first key, exactly when you state it; rigc never makes one up (R12, ยง3.4.2). Nothing resolves an attachment *by* it: a slot's setup `attachment`, every timeline and a linked mesh's `source` use the placeholder. Every type takes it. Not a string is refused โ `"name" is 7, which is not a string` |
|
|
1326
1338
|
| `image` | **rigc extension.** A PNG relative to the rig's `images` directory; rigc measures it (R5) |
|
|
1327
1339
|
| `width`, `height` | required by the format โ give them, or give an `image` |
|
|
1328
|
-
| `path` | the atlas region to resolve; defaults to the attachment's
|
|
1340
|
+
| `path` | the atlas region to resolve; defaults to the attachment's name โ its `name`, else the placeholder. rigc sets it for you when the PNG basename differs from that name. **One rule, both kinds** โ see the note under *Mesh attachment* |
|
|
1329
1341
|
| `x`, `y` | offset from the bone, in the bone's local space |
|
|
1330
1342
|
| `rotation` | degrees; cancels a rotated bone for a plate authored screen-upright |
|
|
1331
1343
|
| `scaleX`, `scaleY`, `color` | as Spine |
|
|
1332
|
-
| `sequence` | a **numbered image series** instead of one region: `{ "count", "start"?, "digits"?, "setup"? }`, and `path` (or the placeholder) is the series' stem. No `image` beside it โ the frames are the images. ยง3.4.3 |
|
|
1344
|
+
| `sequence` | a **numbered image series** instead of one region: `{ "count", "start"?, "digits"?, "setup"? }`, and `path` (or, with none, the `name`, or the placeholder) is the series' stem. No `image` beside it โ the frames are the images. ยง3.4.3 |
|
|
1333
1345
|
|
|
1334
1346
|
**Mesh attachment** ([Spine: meshes](http://esotericsoftware.com/spine-meshes)) โ
|
|
1335
1347
|
either authored geometry (`uvs` + `triangles` + geometry) **or** a `generator`,
|
|
1336
1348
|
never both. `hull`, `edges`, `width` and `height` may be stated; whichever is
|
|
1337
1349
|
omitted, rigc derives โ `hull` and `edges` from the triangles, the size from the
|
|
1338
|
-
PNG โ and the rules are a few paragraphs down. `type`, `image`, `path`,
|
|
1339
|
-
`sequence` mean exactly what they mean on a region (a sequence mesh takes authored
|
|
1350
|
+
PNG โ and the rules are a few paragraphs down. `type`, `name`, `image`, `path`,
|
|
1351
|
+
`color` and `sequence` mean exactly what they mean on a region (a sequence mesh takes authored
|
|
1340
1352
|
geometry, never a `generator` โ ยง3.4.3).
|
|
1341
1353
|
|
|
1342
1354
|
๐ **`path` is one rule for both kinds.** A mesh derives it from `image` the way a
|
|
1343
1355
|
region does: stated wins, otherwise the PNG's basename when that differs from the
|
|
1344
|
-
placeholder
|
|
1356
|
+
attachment's name โ its `name`, else the placeholder โ otherwise nothing. The parser reads `path` off both with the same line
|
|
1345
1357
|
(`getValue(map, "path", name)`, `SkeletonJson.ts:541` and `:570`), and `path`
|
|
1346
1358
|
defaults to the attachment's **name** rather than to the placeholder โ so a mesh
|
|
1347
1359
|
with `image: hair_short.png` under a placeholder called `hair` resolves the region
|
|
@@ -1506,11 +1518,11 @@ them (`SkeletonJson.ts:568-569`, `:582`), so rigc reads them the same way.
|
|
|
1506
1518
|
|
|
1507
1519
|
| Field | Meaning |
|
|
1508
1520
|
| --- | --- |
|
|
1509
|
-
| `source` | **required.** The **placeholder** of the mesh whose geometry this one draws โ the key it is filed under in its skin, not its `name`. A miss is refused naming the skin, the slot and what that slot holds |
|
|
1521
|
+
| `source` | **required.** The **placeholder** of the mesh whose geometry this one draws โ the key it is filed under in its skin, not its `name`. A miss is refused naming the skin, the slot and what that slot holds; a `source` that spells the source's `name` instead is that miss, because the runtime looks the source up by skin, slot and key and never by name โ measured, it throws `Source mesh not found` |
|
|
1510
1522
|
| `slot` | the slot the source lives in. Default: **this attachment's own slot**. Resolved by name against the rig's slots |
|
|
1511
1523
|
| `skin` | the skin the source lives in. Default: **`default`** โ the default skin, *not* the skin this link is written in. Resolved by name |
|
|
1512
1524
|
| `timelines` | default **`true`**: the link plays the source's `deform` keys. `false` makes it its own timeline target, so only keys written against the link move it |
|
|
1513
|
-
| `image`, `path`, `width`, `height`, `color` | exactly as on a mesh โ the link resolves **its own** region, which is the point of the type |
|
|
1525
|
+
| `name`, `image`, `path`, `width`, `height`, `color` | exactly as on a mesh โ the link resolves **its own** region, which is the point of the type |
|
|
1514
1526
|
|
|
1515
1527
|
```json
|
|
1516
1528
|
"skins": {
|
|
@@ -1596,6 +1608,7 @@ region, a trigger volume โ that moves with the skeleton and draws nothing.
|
|
|
1596
1608
|
| Field | Meaning |
|
|
1597
1609
|
| --- | --- |
|
|
1598
1610
|
| `type` | `"boundingbox"`. **Required**: an omitted `type` is `"region"`, and a region has nowhere to put these keys โ measured, the refusal reads `attachment "mask" (region) has 2 keys this compiler does not read: "vertexCount", "vertices"` |
|
|
1611
|
+
| `name` | as on a region: the runtime's name for the attachment, written only when stated. A polygon resolves no region, so here it is the name and nothing else |
|
|
1599
1612
|
| `vertexCount` | **required**, 3 or more. No default โ the paragraph above is why |
|
|
1600
1613
|
| `vertices` | the unweighted `x, y` run, in the slot bone's local space; or the index-encoded weighted run, behind `boneIndexing` |
|
|
1601
1614
|
| `weights` | the by-name form: one entry per vertex, each a list of `{ "bone": โฆ, "x": โฆ, "y": โฆ, "weight": โฆ }`, each pair in that bone's local space. Never beside `vertices` |
|
|
@@ -1610,7 +1623,7 @@ attachment rather than a second set of art.
|
|
|
1610
1623
|
| Field | Meaning |
|
|
1611
1624
|
| --- | --- |
|
|
1612
1625
|
| `type` | `"clipping"`. **Required** |
|
|
1613
|
-
| `vertexCount`, `vertices`, `weights`, `boneIndexing`, `color` | exactly as on a bounding box |
|
|
1626
|
+
| `name`, `vertexCount`, `vertices`, `weights`, `boneIndexing`, `color` | exactly as on a bounding box |
|
|
1614
1627
|
| `end` | the last slot the clip applies to, **by name**. Absent is the parser's own encoding for *clip everything after this one*, which is why a typo cannot be told from an omission once the file is loaded: `findSlot` returns null on a miss and the parser assigns that null without a word, so the clip runs to the bottom of the draw order and takes every slot below it with it. rigc refuses a name the rig does not declare โ `end names slot "X", which this rig does not declare` โ and `A33` refuses it again on a skeleton rigc did not write |
|
|
1615
1628
|
| `convex` | default **false**. True tells the runtime the polygon is convex so it can clip without triangulating it, and a polygon that deforms concave is clipped by its convex hull instead (`ClippingAttachment.convex`). Nothing here checks that the polygon is in fact convex |
|
|
1616
1629
|
| `inverse` | default **false**. True makes everything **outside** the polygon visible instead of everything inside, and inverse clipping is always treated as convex (`ClippingAttachment.inverse`) |
|
|
@@ -1628,7 +1641,7 @@ other vertex attachment.
|
|
|
1628
1641
|
| Field | Meaning |
|
|
1629
1642
|
| --- | --- |
|
|
1630
1643
|
| `type` | `"path"`. **Required** |
|
|
1631
|
-
| `vertexCount`, `vertices`, `weights`, `boneIndexing`, `color` | as on a bounding box โ except that these vertices are knots **and** their handles, which the count rule below is about |
|
|
1644
|
+
| `name`, `vertexCount`, `vertices`, `weights`, `boneIndexing`, `color` | as on a bounding box โ except that these vertices are knots **and** their handles, which the count rule below is about |
|
|
1632
1645
|
| `closed` | default **false**. True joins the last knot back to the first |
|
|
1633
1646
|
| `constantSpeed` | default **true** โ note the direction. Leaving it out asks for the expensive-and-correct traversal, in which the runtime re-measures the path every frame and `lengths` is never read. `false` makes the runtime trust the emitted `lengths` instead: cheaper, exact only while the path holds its setup shape, and the reason a deformed path wants the default |
|
|
1634
1647
|
| `lengths` | ๐ซ **refused by name.** rigc measures the setup length of each curve off the geometry and emits it, the way it measures a region's size off its PNG: `"lengths" is not authored โ rigc measures the setup arc length of each curveโฆ`. The field is declared only so the refusal can say that rather than report a misspelt key. What the numbers are โ and why *arc length* is the wrong name for them โ is ยง10.6 |
|
|
@@ -2303,41 +2316,64 @@ beside them is refused rather than ignored (an ignored slot is an attachment tha
|
|
|
2303
2316
|
vanishes), and a rig with a *slot* of one of those names is refused too, because
|
|
2304
2317
|
there the two forms are genuinely ambiguous. Rename the slot.
|
|
2305
2318
|
|
|
2306
|
-
#### 3.4.2 Two skins, one placeholder โ the `name`
|
|
2307
|
-
|
|
2308
|
-
Two skins putting different art under one placeholder is what a skin is *for*, and
|
|
2309
|
-
it is the one shape rigc emitted wrongly until
|
|
2310
|
-
[#541](https://github.com/firejune/rigc/issues/541). Without a `name` field an
|
|
2311
|
-
attachment's name **is** its placeholder (`SkeletonJson.ts:526`), so four skins
|
|
2312
|
-
filling `patch` are four different attachments all called `patch`. spine-core never
|
|
2313
|
-
notices โ its skin table is keyed by placeholder, so the two never meet โ and the
|
|
2314
|
-
whole gate is green. The Spine editor refuses the import outright:
|
|
2315
|
-
|
|
2316
|
-
```
|
|
2317
|
-
ERROR: Unable to import skeleton.
|
|
2318
|
-
[error] Error reading skeleton: skins
|
|
2319
|
-
Cause: [error] Error reading attachment: patch (MOw)
|
|
2320
|
-
Cause: [error] Multiple attachments have the same name: patch patch
|
|
2321
|
-
```
|
|
2319
|
+
#### 3.4.2 Two skins, one placeholder โ and the `name` you may state
|
|
2322
2320
|
|
|
2323
|
-
|
|
2324
|
-
|
|
2321
|
+
Two skins putting different art under one placeholder is what a skin is *for*. Each
|
|
2322
|
+
entry is its own attachment, filed under that placeholder in its own skin, and with
|
|
2323
|
+
no `name` field the runtime names every one of them by the placeholder
|
|
2324
|
+
(`getValue(map, "name", placeholder)`, `SkeletonJson.js:526`). That is legal Spine
|
|
2325
|
+
data, and it is the shape the editor exports: rigc emits it exactly as you wrote it.
|
|
2325
2326
|
|
|
2326
2327
|
```json
|
|
2327
2328
|
"skins": {
|
|
2328
2329
|
"default": { "block": { "block": { "image": "block.png" } } },
|
|
2329
2330
|
"base": { "patch": { "patch": { "image": "patch_a.png" } } },
|
|
2330
|
-
"zulu": { "patch": { "patch": { "image": "
|
|
2331
|
+
"zulu": { "patch": { "patch": { "image": "patch_b.png", "x": 4 } } }
|
|
2331
2332
|
}
|
|
2332
2333
|
```
|
|
2333
2334
|
|
|
2334
|
-
emits
|
|
2335
|
+
emits two `patch` attachments in slot `patch`, one per skin, each with the `path` its
|
|
2336
|
+
image gives it (`patch_a`, `patch_b`) and **no `name`** โ both answer to `patch` at
|
|
2337
|
+
runtime, and each is the one its skin shows.
|
|
2338
|
+
|
|
2339
|
+
๐ **State a `name` when the attachment's own name is not its placeholder.** A
|
|
2340
|
+
transcription of an export that carries one โ `ingest` writes it for you โ or any
|
|
2341
|
+
rig whose consumer reads `slot.attachment.name`. It is written verbatim, and `path`
|
|
2342
|
+
defaults to it, so an image named after it needs no `path`:
|
|
2335
2343
|
|
|
2336
2344
|
```json
|
|
2337
|
-
{ "
|
|
2338
|
-
{ "name": "zulu/patch", "path": "patch", "width": 64, "height": 64, "x": 4 }
|
|
2345
|
+
"base": { "patch": { "patch": { "name": "patch-base", "image": "patch-base.png" } } }
|
|
2339
2346
|
```
|
|
2340
2347
|
|
|
2348
|
+
emits `"name": "patch-base"` first and no `path`, and the runtime draws region
|
|
2349
|
+
`patch-base` for an attachment it calls `patch-base`, filed under `patch`.
|
|
2350
|
+
|
|
2351
|
+
๐ฌ **Until [#796](https://github.com/firejune/rigc/issues/796) rigc composed a name
|
|
2352
|
+
here, and the reason it did was measured wrong.**
|
|
2353
|
+
[#541](https://github.com/firejune/rigc/issues/541) read the editor's refusal of a
|
|
2354
|
+
four-skin rig โ `Multiple attachments have the same name: patch patch` โ as "one
|
|
2355
|
+
name over several attachments, because a linked mesh resolves its parent by name",
|
|
2356
|
+
and [#552](https://github.com/firejune/rigc/issues/552) wrote
|
|
2357
|
+
`"<skin>/<placeholder>"` on every contested entry. Both halves fail a measurement:
|
|
2358
|
+
|
|
2359
|
+
- **A linked mesh finds its source by skin, slot and KEY.** Through spine-core
|
|
2360
|
+
4.3.13, two skins each fill `C` with a different mesh and no `name`, both load
|
|
2361
|
+
named `C`, and a link with `source: "C"` binds the mesh of the skin its own
|
|
2362
|
+
`skin` names. A `source` that spells a source's `name` instead throws
|
|
2363
|
+
`Source mesh not found` โ which rigc refuses by name before that (ยง3.4, *Linked
|
|
2364
|
+
mesh*).
|
|
2365
|
+
- **The editor imports the uncomposed shape.** A production rig whose placeholders
|
|
2366
|
+
are each filled by two named skins, meshes and linked meshes among them, imported
|
|
2367
|
+
through Spine 4.3.26 with every composed name stripped. It is the file that editor
|
|
2368
|
+
exported.
|
|
2369
|
+
|
|
2370
|
+
What #541 had bisected was a rig whose **default** skin filled the contested
|
|
2371
|
+
placeholder beside the named ones โ its smallest refusing variant was `default` plus
|
|
2372
|
+
one named skin โ and that shape is refused on measurements of its own, below. The
|
|
2373
|
+
composition renamed every contested attachment of every multi-skin export at
|
|
2374
|
+
runtime, which `slot.attachment.name` shows a consumer and no gate could see; `diff`
|
|
2375
|
+
now reads it as `attachments.runtime_name`.
|
|
2376
|
+
|
|
2341
2377
|
๐จ **Every skin that shares a placeholder has to be a named one โ the default
|
|
2342
2378
|
skin may not be among them, and rigc refuses the rig if it is.** That is not a
|
|
2343
2379
|
style rule; it is the editor's model, and two round trips through Spine
|
|
@@ -2368,18 +2404,9 @@ style rule; it is the editor's model, and two round trips through Spine
|
|
|
2368
2404
|
are the same namespace, and both are `patch`.
|
|
2369
2405
|
|
|
2370
2406
|
โ **The rule: move the shared art into a named skin.** Call it `base`. Every
|
|
2371
|
-
filler of that placeholder is then a named skin,
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
`zulu/patch` and `mike/patch` are three names. That shape is the one the editor
|
|
2375
|
-
does hold: the same three fillers in named skins imported, exported and measured
|
|
2376
|
-
**0.00 mean MAE** with names and paths intact.
|
|
2377
|
-
|
|
2378
|
-
๐ **The earlier reading, kept because it was reasonable and wrong.** Between the
|
|
2379
|
-
two trips this guide said *compose off the default skin only* โ keep the default
|
|
2380
|
-
skin's entry as its placeholder and name the others. Trip 7 supported it and trip
|
|
2381
|
-
8 refuted it: that is the spelling the editor refuses at the door. There is no
|
|
2382
|
-
third spelling, which is why this is a refusal rather than a naming scheme.
|
|
2407
|
+
filler of that placeholder is then a named skin, which is the shape the editor
|
|
2408
|
+
holds. Stating a `name` on the default skin's entry does not lift the refusal: that
|
|
2409
|
+
is the first of the two spellings above.
|
|
2383
2410
|
|
|
2384
2411
|
What to know about it, and nothing to author:
|
|
2385
2412
|
|
|
@@ -2399,39 +2426,27 @@ What to know about it, and nothing to author:
|
|
|
2399
2426
|
restated as the join the renderer actually performs it was a tautology over
|
|
2400
2427
|
the resolve check beside it
|
|
2401
2428
|
([#574](https://github.com/firejune/rigc/issues/574)).
|
|
2402
|
-
-
|
|
2403
|
-
**name**, not to its placeholder, so an entry
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
skin, the slot, the placeholder and the path
|
|
2407
|
-
([#589](https://github.com/firejune/rigc/issues/589))
|
|
2408
|
-
reported it in the parser's own words until then, and now defers to A08.
|
|
2409
|
-
- **Only contested placeholders are touched.** One skin filling a placeholder, or
|
|
2410
|
-
two skins filling a slot under *different* placeholders, emit exactly what they
|
|
2411
|
-
always did โ every rig in this repository is byte-identical across the change.
|
|
2412
|
-
- **A composed name that collides is a compile error, not a surprise.** If some
|
|
2413
|
-
other placeholder in the same slot is literally called `zulu/patch`, rigc refuses
|
|
2414
|
-
and names both sites rather than emitting two attachments with one name again.
|
|
2415
|
-
The walk covers every *uncontested* entry's plain name too, the default skin's
|
|
2416
|
-
included โ a name that composed nothing can still be the one another skin
|
|
2417
|
-
composes.
|
|
2418
|
-
(`/` is the separator because it appears in **0** of the 160 placeholder names and
|
|
2419
|
-
159 atlas region names in `examples/` and `gallery/`, where `-` appears in 85 and
|
|
2420
|
-
`_` in 37.)
|
|
2429
|
+
- **A stated `name` with no `path` resolves the region the name spells.** `path`
|
|
2430
|
+
defaults to the attachment's **name**, not to its placeholder, so an entry naming
|
|
2431
|
+
`patch-base` and drawing `patch_a.png` needs a `path` โ and gets one, because the
|
|
2432
|
+
image basename differs from the name. `A08_REGION_NAMES_MATCH_ATTACHMENTS` names
|
|
2433
|
+
the skin, the slot, the placeholder and the path if the region is not there
|
|
2434
|
+
([#589](https://github.com/firejune/rigc/issues/589)).
|
|
2421
2435
|
- **Each skin's art is measured and atlased on its own.** The example above points
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
โ ๏ธ **
|
|
2431
|
-
which the editor wrote, gives the name `head` to a region in
|
|
2432
|
-
bounding box in slot `head-bb`, and reuses `hoverglow-small`
|
|
2433
|
-
|
|
2434
|
-
|
|
2436
|
+
the two skins at two PNGs, so there are two regions, each attachment's `path`
|
|
2437
|
+
resolving to the file that attachment named and its `width`/`height` measured off
|
|
2438
|
+
that file. Until [#555](https://github.com/firejune/rigc/issues/555) only the
|
|
2439
|
+
first skin's PNG was ever opened, and the second skin's art reached neither the
|
|
2440
|
+
atlas nor the measurement โ so name the two files **distinctly**, because the
|
|
2441
|
+
region name is the basename and `a/patch.png` beside `b/patch.png` is refused
|
|
2442
|
+
(R5).
|
|
2443
|
+
|
|
2444
|
+
โ ๏ธ **Nothing measured says the editor wants names unique within a slot.**
|
|
2445
|
+
`spineboy-pro.json`, which the editor wrote, gives the name `head` to a region in
|
|
2446
|
+
slot `head` and to a bounding box in slot `head-bb`, and reuses `hoverglow-small`
|
|
2447
|
+
across eight slots; the production rig above holds same-named attachments in one
|
|
2448
|
+
slot across its named skins. The one refusal the editor was measured making is the
|
|
2449
|
+
default-skin share, and that is the rule rigc enforces.
|
|
2435
2450
|
|
|
2436
2451
|
๐จ **Once a rig has named skins, no instrument here can see them until you say
|
|
2437
2452
|
which one** ([#571](https://github.com/firejune/rigc/issues/571)). `render` and
|
|
@@ -2497,11 +2512,18 @@ other than what was written (measured on spine-core 4.3.13,
|
|
|
2497
2512
|
only on the three kinds that draw a region, so it would be dropped in silence. The
|
|
2498
2513
|
refusal names region, mesh and linkedmesh.
|
|
2499
2514
|
|
|
2500
|
-
`width` and `height` are the attachment's one size, every frame drawn into it.
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2515
|
+
`width` and `height` are the attachment's one size, every frame drawn into it. The
|
|
2516
|
+
frames **may differ in size**: the runtime scales each frame's region into the
|
|
2517
|
+
attachment's size (`RegionAttachment.computeUVs`, `width / region.originalWidth`), so a
|
|
2518
|
+
stated size is emitted as stated and compared with no frame, on the loose route and
|
|
2519
|
+
under `--atlas-in` alike. That is what an editor exports for a series that mixes image
|
|
2520
|
+
sizes โ the setup frame's size, the other frames as they are
|
|
2521
|
+
([#795](https://github.com/firejune/rigc/issues/795)). Omit them and rigc takes the
|
|
2522
|
+
frames' size โ **only when every frame measures the same**; frames of different sizes
|
|
2523
|
+
are refused until you state the size, because picking one of them would be the
|
|
2524
|
+
compiler choosing a value. โ ๏ธ One region is different: its `width` is its image's size
|
|
2525
|
+
in every editor export, so under `--atlas-in` a stated size that disagrees with its
|
|
2526
|
+
packed region is still refused.
|
|
2505
2527
|
`A46_SEQUENCE_ATTACHMENTS_SHOW_THE_FRAME_THE_FILE_STATES` (ยง5.2) holds the block and
|
|
2506
2528
|
every frame the timelines show against the file.
|
|
2507
2529
|
|
|
@@ -3542,7 +3564,7 @@ a delta from the constraint's own setting.
|
|
|
3542
3564
|
infinite inverse mass โ the constraint stops moving.
|
|
3543
3565
|
- **Four of the seven are bounded, and a key outside its bound is a compile
|
|
3544
3566
|
error** ([#610](https://github.com/firejune/rigc/issues/610)). `mass` must be
|
|
3545
|
-
`> 0`, `damping` must be
|
|
3567
|
+
`> 0`, `damping` must be inside the closed `[0, 1]`, and `mix` and `strength`
|
|
3546
3568
|
must be `0` or more. `A23_PHYSICS_CONSTRAINT_EFFECTIVE` applies the same four to
|
|
3547
3569
|
a file rigc did not write, naming the animation, the constraint, the key time
|
|
3548
3570
|
and the value โ so the compiler is where a spec you wrote is refused, and the
|
|
@@ -3555,9 +3577,19 @@ a delta from the constraint's own setting.
|
|
|
3555
3577
|
whole number the same negative is raised to a fractional power, which is NaN.
|
|
3556
3578
|
[measured] one planted `damping` key of โ0.5 on the generated physics fixture
|
|
3557
3579
|
stays finite at 60 fps and at 30 (exponent 2), and is NaN within three steps of
|
|
3558
|
-
the key at 45 and at 120. `1`
|
|
3559
|
-
rate. The refusal names the exponent and the rate for this
|
|
3560
|
-
holds it to the two-rate measurement.
|
|
3580
|
+
the key at 45 and at 120. Above `1` every velocity grows on every step and
|
|
3581
|
+
diverges at every rate. The refusal names the exponent and the rate for this
|
|
3582
|
+
reason, and `T101` holds it to the two-rate measurement.
|
|
3583
|
+
- โ
**Both ends of `damping` are inside the bound**
|
|
3584
|
+
([#794](https://github.com/firejune/rigc/issues/794)). `1 ** x` is 1 and
|
|
3585
|
+
`0 ** x` is 0 for every positive exponent, so neither depends on `fps`: at `1`
|
|
3586
|
+
the velocity never decays and the jiggle holds for as long as it runs, and at
|
|
3587
|
+
`0` every velocity is zeroed on every step, so the offset follows the bone with
|
|
3588
|
+
no overshoot. Both are finite, at rest and keyed โ [measured] 120 steps from
|
|
3589
|
+
`Physics.reset` at 60, 45 and 30 fps on the generated physics fixture, which
|
|
3590
|
+
`T109`โ`T111` hold. โ ๏ธ `1` is also what a 4.2 file means by saying nothing:
|
|
3591
|
+
4.2's parser reads an omitted `damping` as `1` where 4.3's reads `0.85`
|
|
3592
|
+
(ยง4.6), so a rig migrated from 4.2 that keys "the default" keys `1`.
|
|
3561
3593
|
- ๐ซ **`inertia`, `wind` and `gravity` are bounded nowhere, and neither is the top
|
|
3562
3594
|
of `mix`.** The runtime documents no range for the first three, and
|
|
3563
3595
|
`PhysicsConstraintPose` documents `mix` as "a percentage (0+)" โ so a negative
|
|
@@ -3962,11 +3994,16 @@ key times. One lag, one place.
|
|
|
3962
3994
|
mass?, wind?, gravity?, mix?, fps?, limit? }`. These are emitted into the 4.3
|
|
3963
3995
|
`constraints` array. Seven of them โ the six tuning numbers and `mix` โ can also
|
|
3964
3996
|
be **keyed over time** as `tracks` entries naming this constraint (ยง4.4); this
|
|
3965
|
-
table is the value at rest, and a timeline overrides it while it plays. `mass: 0` becomes an infinite inverse mass and `damping
|
|
3997
|
+
table is the value at rest, and a timeline overrides it while it plays. `mass: 0` becomes an infinite inverse mass and a `damping` above 1
|
|
3966
3998
|
never settles โ both are `A23`, here and on every timeline key that states them
|
|
3967
|
-
([#610](https://github.com/firejune/rigc/issues/610)); a `damping`
|
|
3968
|
-
is refused as well, and
|
|
3969
|
-
([#748](https://github.com/firejune/rigc/issues/748)).
|
|
3999
|
+
([#610](https://github.com/firejune/rigc/issues/610)); a `damping` below 0
|
|
4000
|
+
is refused as well, and whether it is NaN depends on `fps` โ ยง4.4
|
|
4001
|
+
([#748](https://github.com/firejune/rigc/issues/748)). `damping` is `[0, 1]`
|
|
4002
|
+
with both ends in: `1` never decays and `0` zeroes the velocity on every step,
|
|
4003
|
+
both finite at every rate ([#794](https://github.com/firejune/rigc/issues/794)).
|
|
4004
|
+
โ ๏ธ An omitted `damping` is `0.85` to 4.3's parser (`SkeletonJson.js:308` in
|
|
4005
|
+
4.3.13) and `1` to 4.2's (`SkeletonJson.js:242` in 4.2.120), so a constraint
|
|
4006
|
+
migrated from 4.2 that stated nothing may arrive stating `1` โ which builds. โ ๏ธ `strength: 0` is `A23` **here and not on a key**:
|
|
3970
4007
|
at rest it is a constraint nothing pulls back, and on a key it is a release somebody
|
|
3971
4008
|
asked for, which ยง4.4 states with the measurement behind it
|
|
3972
4009
|
([#727](https://github.com/firejune/rigc/issues/727)). A negative `strength` is
|
|
@@ -5441,7 +5478,7 @@ or the key's position in its own track. These are the frequent ones, verbatim:
|
|
|
5441
5478
|
| `physics constraint "*": the name is reserved โ โฆ` / `` `physics."*"` names a physics constraint "*", and that name is reserved โฆ `` | ยง3.5 โ `"*"` is the target of the timeline that names no constraint; rename the constraint |
|
|
5442
5479
|
| `animation "A": group "G" lists "*", which is not a constraint but the target that names none โฆ` | ยง4.4 โ write `"*"` as the track's `physics` field |
|
|
5443
5480
|
| `animation "A" bone "X" translatex: key value must be an array of 1 number(s)` | the value shape must match the property (ยง4.4) |
|
|
5444
|
-
| `animation "A" physics constraint "C" mass key at t=โฆ is 0 (massInverse Infinity); must be > 0 โ โฆ` | ยง4.4 โ a keyed physics value the runtime cannot use. The message names the bound and the `PhysicsConstraint.js` lines that make it one: `mass` is `> 0`, `damping` is inside `
|
|
5481
|
+
| `animation "A" physics constraint "C" mass key at t=โฆ is 0 (massInverse Infinity); must be > 0 โ โฆ` | ยง4.4 โ a keyed physics value the runtime cannot use. The message names the bound and the `PhysicsConstraint.js` lines that make it one: `mass` is `> 0`, `damping` is inside `[0, 1]`, both ends included ([#794](https://github.com/firejune/rigc/issues/794)), `mix` and `strength` are `0` or more, and `inertia`/`wind`/`gravity` are bounded nowhere ([#610](https://github.com/firejune/rigc/issues/610)). โ ๏ธ Those are the bounds a **key** is held to. A setup `strength` of `0` is refused too, but by `A23` rather than here, and with its own sentence โ `physics "C" has strength 0; nothing pulls it back` ([#727](https://github.com/firejune/rigc/issues/727)); a setup `strength` below 0 says the offset is pushed away and grows, the same arm this message quotes for a negative key ([#748](https://github.com/firejune/rigc/issues/748)). A `damping` key's sentence names the exponent `60 * step` and why a negative is NaN at any `fps` where `60 / fps` is not whole (ยง4.4) |
|
|
5445
5482
|
| `a key carries both a named easing and a raw curve; pick one` | R6 |
|
|
5446
5483
|
| `last key carries an easing but has nothing to ease to` | drop `ease`/`curve` from the final key |
|
|
5447
5484
|
| `key times must strictly increase (at t=โฆ)` | including after `lag` and `stagger` |
|
|
@@ -5516,7 +5553,7 @@ or the key's position in its own track. These are the frequent ones, verbatim:
|
|
|
5516
5553
|
| `N pair(s) of animation names have no one order: โฆ "Fx/a" / "fx/b" (folder) โ "Fx/a" and "fx/b" sit in the sibling folders "Fx" and "fx", which the comparator leaves in one place โฆ; rename one of the two folders so they differ by more than letter case, spacing or a leading zero` | **R10** โ rename until no pair is left. The kind in brackets says which of the three things the five stored round trips leave open decides the pair: `number` (two digit runs that are each one number written twice, pointing opposite ways), `separator` (a whitespace character that is not a space) or `folder` (two sibling folders the comparator cannot separate). rigc keys `animations` in the editor's own comparator, read off `fixtures/editor-order/probe{1..5}.{in,out}.json` ([#728](https://github.com/firejune/rigc/issues/728)) โ so a pair those files settle is emitted rather than refused, **including a pair that differs only in case**, whose order is then the one your spec declared. On the three that are left, the editor's re-key repoints every slider whose animation moves index ([#535](https://github.com/firejune/rigc/issues/535)) |
|
|
5517
5554
|
| `N pair(s) of skin names have no one order: โฆ "Fx/a" / "fx/b" (folder) โ โฆ` | **R11** โ rename until no pair is left. The same shape and the same three kinds as the row above, because it is the same comparator: two of the five round trips carried one name list as both collections and both came back in one order ([#728](https://github.com/firejune/rigc/issues/728)). โ ๏ธ This row was **wider** than R10's until then โ `Zulu`/`mike` and `mike10`/`mike2` built as animation names and were refused as skin names ([#541](https://github.com/firejune/rigc/issues/541)) โ and both build now |
|
|
5518
5555
|
| `slot "patch": placeholder "patch" is filled by the "default" skin AND by skins "zulu", "mike", and the Spine editor has no way to hold that โฆ Move the default skin's entry for this slot into a named skin โ call it "base"` | **R12** โ do what it says: move that entry out of `default` into a named skin. The editor has no representation for a placeholder the default skin shares with a named one, in either spelling, and ยง3.4.2 has both measurements. Renaming the placeholder does not help; the shape is what is refused |
|
|
5519
|
-
| `
|
|
5556
|
+
| `skin "S" slot "X" attachment "P": "name" is V, which is not a string. An attachment's name is the runtime's `Attachment.name` โฆ` | ยง3.4 โ write the name as a string, or leave the key out and the attachment is named by its placeholder. It is written verbatim and `path` defaults to it, so a number there would reach the atlas as a region name nobody spelled |
|
|
5520
5557
|
|
|
5521
5558
|
โ ๏ธ **One refusal in this section is not a `CompileError`, and it is `explain`'s.**
|
|
5522
5559
|
`explain` prints the `DEFORM` block by **posing** the rig, and a pose resolves every
|
|
@@ -5630,7 +5667,7 @@ Fix A00 and run it again ([#568](https://github.com/firejune/rigc/issues/568)).
|
|
|
5630
5667
|
| `A20_MESH_WEIGHTS_COHERENT` | both โ | a weighted vertex with no bone, a negative weight, a bone index out of range, or weights that do not sum to 1. Under `spine-html` also: an unweighted mesh, a binding at weight 0, or **a bone the mesh declares that no vertex binds** โ `mesh "x" declares bone "grip_b" and none of its 25 vertices binds it; the weights reference "box", "grip_a"`. Those three are one sentence about rigc's own generators: the bone set a generated mesh declares is the bone set its weights reference, so a `controls` or `chain` name that moves nothing is a defect where a foreign mesh's is not ([#684](https://github.com/firejune/rigc/issues/684)). Fix the rig spec's `controls`/`chain`, or the manifest's `control_bones`. **SKIP** when the skeleton carries no mesh attachment ([#580](https://github.com/firejune/rigc/issues/580)) |
|
|
5631
5668
|
| `A21_MESH_RIM_PINNED` | archetype | a generated ring's rim, a ribbon's entry row, or a contour's outline (which is all of it) is not pinned to its anchor bone at weight 1 |
|
|
5632
5669
|
| `A22_MESH_UVS_IN_UNIT_RANGE` | both | a mesh UV outside its region, or a UV array that disagrees with the vertex count. **SKIP** when the skeleton carries no mesh attachment ([#580](https://github.com/firejune/rigc/issues/580)) |
|
|
5633
|
-
| `A23_PHYSICS_CONSTRAINT_EFFECTIVE` | both | a physics constraint that drives no component, rests at `mix: 0` with **no timeline in any animation keying that `mix` above 0**, has `mass: 0`, has `strength` at or below 0 โ `0` says `nothing pulls it back`, below 0 says the offset `is pushed away and grows with every step`, both read off the row's `outside` arms, which the key's refusal quotes too ([#748](https://github.com/firejune/rigc/issues/748)) โ or has `damping` outside `
|
|
5670
|
+
| `A23_PHYSICS_CONSTRAINT_EFFECTIVE` | both | a physics constraint that drives no component, rests at `mix: 0` with **no timeline in any animation keying that `mix` above 0**, has `mass: 0`, has `strength` at or below 0 โ `0` says `nothing pulls it back`, below 0 says the offset `is pushed away and grows with every step`, both read off the row's `outside` arms, which the key's refusal quotes too ([#748](https://github.com/firejune/rigc/issues/748)) โ or has `damping` outside `[0, 1]`, which says `physics "C" has damping 1.5; must be inside [0, 1] โ above 1 every velocity grows on every step, and below 0 it is NaN at any fps where 60 / fps is not whole`, the bound read off the row the key's refusal reads; `1` and `0` are inside, since both are finite at every rate ([#794](https://github.com/firejune/rigc/issues/794)) โ **at rest, and on every physics timeline key** ([#610](https://github.com/firejune/rigc/issues/610), [#743](https://github.com/firejune/rigc/issues/743)). The timeline arm reads each key through the runtime's own `PhysicsConstraint*Timeline.set`, so a keyed `mass` is judged as the `massInverse` it becomes, and the detail names the animation, the constraint, the key time, the value and the bound. Two differences between the two arms, and the runtime is the reason for both: a **key** of `mix: 0` is accepted, because `update` opens with `if (mix === 0) return;` and muting a constraint for a stretch is what a mix timeline is for โ the editor's own `sack-pro` example keys it there on 24 of its 36 mix keys โ and a **key** of `strength: 0` is accepted, because it releases the constraint for the span with `damping` and `inertia` still applied and the next key pulls the offset back, measured through spine-core at no NaN, a coast to a limit and a return in 54 steps ([#727](https://github.com/firejune/rigc/issues/727)). As a **setup** value `strength: 0` is still refused by the arm above, and `mix: 0` is refused only when nothing keys it above 0. The `mix` branch above is why `mix` is the one setup value a key can answer for: at rest the constraint is **inert** rather than broken, so a rig that rests muted and is keyed above 0 is refused by nothing, while a rig resting at `mass: 0` is `massInverse` Infinity before anything plays and no key reaches back into that. The detail of the refusal says both halves and how many animations were searched: `physics "C" has mix 0 and none of the 3 animations keys its mix above 0; it is muted โ rest it above 0, or key its mix above 0 in an animation`. The search counts the unnamed global timeline for every constraint whose own `mixGlobal` is set, reads each key through the runtime's accessor, counts every sample of a Bezier between two keys as a value the timeline poses โ so two keys of 0 joined by a curve lifted above 0 are a rescue, measured to move the bone โ and takes an animation a slider applies like any other. It is the one reading `A36` and `A37` use as well ([#752](https://github.com/firejune/rigc/issues/752)). `inertia`, `wind`, `gravity` and the top of `mix` are bounded nowhere, at rest or keyed. `ingest` does not carry a constraint that drives no component into the spec it writes: it omits it with its timelines and reports `PHYSICS_DRIVES_NOTHING` ([INGEST ยง2.0](INGEST.md), [#731](https://github.com/firejune/rigc/issues/731)), so this sentence is met on a file, never on a decompiled rebuild. **SKIP** when the skeleton declares no physics constraint ([#580](https://github.com/firejune/rigc/issues/580)) โ the same sentence `A36` and `A37` have always printed for their own constraint types |
|
|
5634
5671
|
| `A24_AXIS_SPACE_STROKE` | archetype | a bone under the rig's `axisBone` was keyed with a screen-space Y component, or the axis bone itself was keyed. **SKIP** when the rig declares no axis bone, and also when no animation keys that bone or anything under it ([#580](https://github.com/firejune/rigc/issues/580)) |
|
|
5635
5672
|
| `A25_DETACHED_BONE_PARENTAGE` | archetype | a bone the rig declares `detached` is a descendant of the bone it must never hang under |
|
|
5636
5673
|
| `A26_SLOT_DRAW_ORDER` | archetype | the emitted slots are not the rig's slot table โ a slot is out of order, is not in the table at all, or is in the table and missing from the skeleton (ยง3.3). **SKIP** when the rig declares no canonical slot order. โ ๏ธ A skeleton with **no** slot beside a rig that declares some is **not** a skip, and it is the one rule in this family where an empty loop is not a vacuous pass ([#580](https://github.com/firejune/rigc/issues/580)): the completeness clause reads it as every declared slot lost and names them, which is the maximal case of what [#575](https://github.com/firejune/rigc/issues/575) filed |
|
|
@@ -8161,6 +8198,33 @@ says which.**
|
|
|
8161
8198
|
t=0, so the editor wrote them `value` alone, and that rule would have moved
|
|
8162
8199
|
`time` โ first in every other key kind the editor writes โ behind `value`.
|
|
8163
8200
|
|
|
8201
|
+
๐ฌ **Two positions and one fold are measured on a production set, not on
|
|
8202
|
+
`examples/`** ([#791](https://github.com/firejune/rigc/issues/791)). The twelve
|
|
8203
|
+
exports carry no mesh `path` or `color` and no slot name outside ASCII โ `IG84`
|
|
8204
|
+
and `IG85` count both on every run with a corpus โ so the table cannot learn
|
|
8205
|
+
either, and what rigc writes for them was read off 42 production exports
|
|
8206
|
+
instead:
|
|
8207
|
+
|
|
8208
|
+
- **A mesh attachment writes `path` and `color` right after `type`, `path` before `color` โ measured on a production set (#791), not on `examples/`.**
|
|
8209
|
+
18 meshes whose `path` differs from their name wrote it second, and 1 with a
|
|
8210
|
+
`color` wrote that second; no mesh carried both. The row does not list them,
|
|
8211
|
+
so the position is the constructor's โ `meshTextureKeys` in
|
|
8212
|
+
[`src/compile.ts`](../src/compile.ts), which every mesh route spreads right
|
|
8213
|
+
after `type` (`S104`). A region's `path` and a linked mesh's keys stay where
|
|
8214
|
+
they were: neither was in the set, and an analogy is not a measurement.
|
|
8215
|
+
- **A skin's slot keys are compared after `foldBeforeComparing`, which reads U+3000 as U+0020 and U+FF10โU+FF19 as U+0030โU+0039** โ
|
|
8216
|
+
the ideographic space as a space, the full-width digits as `0`โ`9`
|
|
8217
|
+
(`EDITOR_NAME_FOLD`). One map of 95 slot keys, 7 of them carrying those
|
|
8218
|
+
characters, came back in an order this reproduces 95 of 95 and neither a
|
|
8219
|
+
codepoint sort nor the comparator without the fold does (`S105`). It is **not**
|
|
8220
|
+
`normalize('NFKC')`, though NFKC folds both the same way: NFKC, a classifier
|
|
8221
|
+
that reads every Unicode digit as a digit and every space separator as a space,
|
|
8222
|
+
and a width fold alone all reproduce that map and disagree past it (on `๏ฌ`,
|
|
8223
|
+
`ยฒ`, `ูฃ`, `๏ผก`, a no-break space), and what all three agree on is exactly
|
|
8224
|
+
these two classes. The comparator is R10's, so animation and skin names are
|
|
8225
|
+
compared after the fold too. A pair the fold does not close โ a tab, a
|
|
8226
|
+
no-break space โ still keeps the map in rigc's order, whole (`S106`).
|
|
8227
|
+
|
|
8164
8228
|
๐ธ **An object keyed by NAMES is not a field order**, and the table does not
|
|
8165
8229
|
touch one. A bone's or a slot's timelines, and a transform constraint's
|
|
8166
8230
|
`properties` and each `to` inside them, are read into the runtime's arrays in the
|
package/docs/FACE.md
CHANGED
|
@@ -1474,7 +1474,9 @@ is the card for having left the sentence standing:
|
|
|
1474
1474
|
names. โ ๏ธ **The editor was never silent**: it named the section, the attachment
|
|
1475
1475
|
and the rule, and `tools/editor_roundtrip.ts` had discarded its stdout and
|
|
1476
1476
|
stderr. What changed is [#552](https://github.com/firejune/rigc/issues/552) โ
|
|
1477
|
-
the composed `<skin>/<placeholder>` name, with `default` pinned first
|
|
1477
|
+
the composed `<skin>/<placeholder>` name, with `default` pinned first; the
|
|
1478
|
+
composition was retired by [#796](https://github.com/firejune/rigc/issues/796),
|
|
1479
|
+
which measured that it was never what the editor objected to โ and what
|
|
1478
1480
|
still binds is [#567](https://github.com/firejune/rigc/issues/567): a
|
|
1479
1481
|
`CompileError` when the default skin shares a placeholder with a named one. โ
|
|
1480
1482
|
Skins are not the reason to stay at one, and every figure on this page was
|
package/docs/INGEST.md
CHANGED
|
@@ -621,7 +621,6 @@ is the one failure a comparison of two sets cannot show you.
|
|
|
621
621
|
| `ANIMATION_GROUP` | `BLOCK` | 1 | the animation carries a group the motion spec has no home for. The detail names the ten it does carry. `drawOrderFolder` is the group to know about: the runtime reads it and builds a timeline from it, and no export in this corpus carries one | transcribe that group by hand (ยง2), or accept that the rebuild does not carry it |
|
|
622
622
|
| `ATTACHMENT_<TYPE>` | `BLOCK` | 1 | an attachment of a type rigc does not emit; the code is composed from the type, so on the one type left it reads `ATTACHMENT_POINT`. rigc emits region, mesh, linkedmesh, boundingbox, clipping and path โ `linkedmesh` since [#691](https://github.com/firejune/rigc/issues/691), and `point` is the remaining deferred type | the rebuild will not have that attachment at all. `docs/SPEC_COVERAGE.md` part 1-6 says what a deferred type would carry |
|
|
623
623
|
| `ATTACHMENT_LINK_GEOMETRY` | `LOSS` | 0 | a **linked mesh** that also states `uvs`, `triangles`, `vertices`, `hull` or `edges`. The parser returns from the `source` branch before `readVertices` (`SkeletonJson.ts:582-586`), so those keys are read by nothing at all and the attachment draws the geometry its `source` names; the rig spec has no home for them either, because `build` refuses geometry on a link by name. The detail lists the keys and the source. Until [#710](https://github.com/firejune/rigc/issues/710) the rebuild dropped them with no line at all, so an `ingest` that normalised somebody's file said nothing about it | nothing. The rebuild is the mesh the runtime was already drawing โ and if those keys were the geometry you meant, take `source` off and author it as a mesh of its own. `A44_LINKED_MESH_STATES_NO_GEOMETRY_OF_ITS_OWN` is the same fact at the gate |
|
|
624
|
-
| `ATTACHMENT_NAME` | `LOSS` | 0 | the rebuilt attachment answers to a different name than the source's. **Two shapes, one comparison.** Where only **one** skin fills the placeholder, any stated `name` is lost: rigc writes none โ it composes `<skin>/<placeholder>` exactly where a placeholder is contested. Where the placeholder **is** contested, rigc composes that name, and the source's name โ what it states, or its placeholder where it states none (`SkeletonJson.js:526`) โ is compared with it: equal is rigc's own emit and prints nothing, different is a rename and the detail states **both strings**. Until [#746](https://github.com/firejune/rigc/issues/746) the contested half printed nothing at all. A contested placeholder the **default** skin fills gets no line โ the compiler composes nothing there and refuses the rebuild by name. ๐จ **The name is also the ATLAS REGION KEY**, and the detail says what became of it: `readAttachment` reads `name = getValue(map, "name", placeholder)` and then `path = getValue(map, "path", name)`, so `path` defaults to the **name** and not to the placeholder. A name that differs from the placeholder is therefore **kept as `path`** on an attachment that resolves a region โ region, mesh, linked mesh โ and the detail names the region. The three shapes that keep nothing say which they are: the source stated its own `path` (carried unchanged), the name **is** the placeholder (same region either way), or the type resolves no region at all (`boundingbox`, `clipping`, `path`). Until [#742](https://github.com/firejune/rigc/issues/742) nothing was written, so the rebuild asked the atlas for the placeholder and `A08_REGION_NAMES_MATCH_ATTACHMENTS` refused it | nothing about the art, which is carried. The **name** is what is gone, so this matters where something downstream looks that attachment up by the name the source gave it |
|
|
625
624
|
| `ATTACHMENT_SEQUENCE` | `BLOCK` | 1 | a `sequence` block โ a numbered image series โ that the rig spec cannot say **as written**. Since [#729](https://github.com/firejune/rigc/issues/729) a well-formed block on a region, mesh or linked mesh is carried field for field, with no `image` on the loose route (the frames `<path><number>` are the art), and a `sequence` timeline with it; what is left here is a block the parser reads into a series other than the one written โ no `count` (0 regions), a `setup` past the end (clamped), a fraction โ or one on a `boundingbox`, `clipping` or `path`, where the parser never reads it. The detail quotes the block and says which | the rebuild draws the single region the attachment names. Fix the block in the source โ a `count` is the usual one โ and ingest again |
|
|
626
625
|
| `ATTACHMENT_TIMELINE` | `BLOCK` | 1 | an attachment timeline that is neither `deform` nor `sequence`. Both are carried since [#729](https://github.com/firejune/rigc/issues/729), and `readAnimation` tests an attachment timeline for exactly those two names and ignores anything else (`SkeletonJson.js:1147-1201`) โ so what reaches this line is a name outside the format, which no player plays either | fix the timeline's name in the source, or accept that the rebuild does not carry it |
|
|
627
626
|
| `BONE_FIELD` | `BLOCK` | 1 | a bone field with no rig-spec field, so it is dropped. A 4.0/4.1 export spelling `transform` where 4.3 spells `inherit` lands here; so does a misspelling | check the name against AUTHORING ยง3 first โ a typo and an unsupported field read exactly the same |
|
|
@@ -651,18 +650,16 @@ is the one failure a comparison of two sets cannot show you.
|
|
|
651
650
|
| `TIMELINE_KEY_RESTATED` | `LOSS` | 0 | an editor omits a channel that equals the parser's default, and the motion spec's `v` is positional, so the omission is written out at that default **in the spec** โ and the line is printed only where the **file** will carry it too. It was the commonest line in a real run until [#716](https://github.com/firejune/rigc/issues/716): the emitter now leaves a channel out wherever it is the one the parser reads without it ([AUTHORING ยง10.6c](AUTHORING.md)), so on every key kind with a row the rebuild is the source's own text and nothing is said โ measured on the twelve exports, 341 tracks printed it before and 0 after. What still prints it is a timeline whose keys have no row (`shearx`, `alpha`, path `spacing`, โฆ), and an `inherit` key: one that omits the mode is written as `normal` โ the parser's default โ and one spelled with a capital first letter (`NoScale`) as the editor's `noScale`, the same mode either way | nothing. The same values the runtime reads, spelled out โ a larger file and the same animation |
|
|
652
651
|
| `TRANSFORM_KEY_FIELD` | `BLOCK` | 1 | as `IK_KEY_FIELD`, on a `transform` timeline | as `IK_KEY_FIELD` |
|
|
653
652
|
|
|
654
|
-
โ ๏ธ **
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
regions, because every row can name a region the pack has and still be one region doing
|
|
665
|
-
the work of two.
|
|
653
|
+
โ ๏ธ **An attachment's `name` has no row, because nothing about it is lost any more.**
|
|
654
|
+
Until [#796](https://github.com/firejune/rigc/issues/796) the rig spec had no field for
|
|
655
|
+
one, so `ATTACHMENT_NAME` reported it as a `LOSS` in two shapes: a stated name on a
|
|
656
|
+
placeholder one skin fills was kept only as `path` and the rebuild answered to the
|
|
657
|
+
placeholder, and a contested placeholder was renamed `<skin>/<placeholder>` by the
|
|
658
|
+
compiler. The field exists now, `ingest` carries a stated `name` verbatim โ equal to its
|
|
659
|
+
key or not, exactly as the source spells it โ and writes none where the source states
|
|
660
|
+
none, and `compile` emits exactly what the spec states. The code went with the loss it
|
|
661
|
+
named; `IG86`โ`IG89` in `bun run selftest` hold the carry, the rebuild's loaded names and
|
|
662
|
+
regions, and the two-skin shape with a link in each.
|
|
666
663
|
|
|
667
664
|
### Transcription โ the route that made a foreign skeleton yours
|
|
668
665
|
|
package/docs/SPEC_COVERAGE.md
CHANGED
|
@@ -633,20 +633,21 @@ with the member's own `skin: true` โ either half alone is refused, because `Sk
|
|
|
633
633
|
| `clipping` | โ
under `--profile spine` ยท ๐ซ under `spine-html` | `end` (refused when it names no slot), `convex`, `inverse`, `vertexCount`, geometry, `color`. **A33**, and **A11_NO_CLIPPING_ATTACHMENTS** is the renderer-profile refusal |
|
|
634
634
|
| `sequence` block | โ
| on a region, a mesh or a linked mesh: `count` (required โ the parser's 0 loads no region), `start`, `digits`, `setup`, emitted as stated. The frames are the regions `<path><start + i>` zero-padded to `digits`, each atlased by name โ the loose route's PNG of that name, or `--atlas-in`'s region โ and a missing frame is refused with its number and the name looked for. A `setup` past the end (clamped), a fraction, an `image` or a `generator` beside it, and a `sequence` on any other kind are refused by name. **A46_SEQUENCE_ATTACHMENTS_SHOW_THE_FRAME_THE_FILE_STATES** ([#729](https://github.com/firejune/rigc/issues/729)) |
|
|
635
635
|
|
|
636
|
-
Across all
|
|
637
|
-
|
|
638
|
-
Part 1-5 above states why it matters
|
|
639
|
-
`name`
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
636
|
+
Across all six types rigc emits, the attachment's own **`name`** is written exactly when the rig
|
|
637
|
+
spec states it, verbatim, as the attachment's first key โ and never derived
|
|
638
|
+
([#796](https://github.com/firejune/rigc/issues/796)). Part 1-5 above states why it matters:
|
|
639
|
+
`name` defaults to the placeholder and `path` defaults to `name`, so it is the runtime's
|
|
640
|
+
`Attachment.name` and, on a type that draws, the region it resolves; nothing resolves an
|
|
641
|
+
attachment by it. From [#541](https://github.com/firejune/rigc/issues/541) to #796 rigc composed
|
|
642
|
+
`<skin>/<placeholder>` for a placeholder several skins fill, on the reading that a linked mesh
|
|
643
|
+
resolves its source by name; it resolves it by skin, slot and key, and the editor imports the
|
|
644
|
+
uncomposed shape. โ ๏ธ The **`default` skin may not be one of the skins sharing a placeholder**, and
|
|
645
|
+
that is a `CompileError` rather than an emission rule: the editor holds no placeholder the default
|
|
646
|
+
skin shares with a named one in either spelling โ named, the export re-keys the attachment by its
|
|
647
|
+
name and the slot's setup attachment stops resolving; unnamed, the import is refused with
|
|
648
|
+
`Multiple attachments have the same name` ([#567](https://github.com/firejune/rigc/issues/567),
|
|
649
|
+
Spine 4.3.26, round trips 7 and 8). Of the twelve editor exports in `examples/`, **0**
|
|
650
|
+
attachments state a `name`, because all twelve declare one skin.
|
|
650
651
|
|
|
651
652
|
Mesh geometry is generated by exactly three procedural generators (`mesh.ts`): `buildRingMesh`
|
|
652
653
|
(three concentric rings + hub, outer two pinned), `buildRibbonMesh` (a two-wide strip along a bone
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spine-rigc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Rig compiler for Spine โ declarative rig specs in, Spine 4.3 skeleton data out, verified by a spine-core round-trip. Built so AI agents can author rigs and check their own work; the output imports into the Spine editor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|