spine-rigc 0.35.1 โ 0.36.1
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/README.md +6 -5
- package/cli.ts +15 -1
- package/docs/AUTHORING.md +236 -118
- package/docs/FACE.md +3 -1
- package/docs/INGEST.md +10 -14
- package/docs/SPEC_COVERAGE.md +16 -15
- package/package.json +1 -1
- package/src/atlas.ts +41 -3
- package/src/compile.ts +297 -259
- package/src/diff.ts +59 -0
- package/src/ingest.ts +34 -161
- package/src/rig.ts +72 -18
- package/src/timelines.ts +246 -22
- package/src/transform.ts +141 -13
- package/src/types.ts +34 -22
- package/src/validate.ts +51 -11
- package/tools/editor_roundtrip.ts +88 -10
package/docs/AUTHORING.md
CHANGED
|
@@ -505,6 +505,18 @@ because the text passes through by line; regions the rig does not use stay in th
|
|
|
505
505
|
file, because a real pack is shared between cuts and an importer that quietly
|
|
506
506
|
dropped half of one would make `--out` disagree with the pack it was built from.
|
|
507
507
|
|
|
508
|
+
๐ธ **The one thing not passed through is the pack's blank lines**
|
|
509
|
+
([#803](https://github.com/firejune/rigc/issues/803)). They are written in the
|
|
510
|
+
shape rigc writes its own packs in: none before the first page, exactly one between
|
|
511
|
+
two page blocks, one trailing newline. Every non-blank line keeps its bytes and its
|
|
512
|
+
order, so a pack already in that shape โ every editor export in the example corpus,
|
|
513
|
+
and every pack `--pack` writes โ is emitted byte for byte as before. What this
|
|
514
|
+
changes is a pack from a 3.8-era packer, which begins with a blank line: the
|
|
515
|
+
runtime reads a run of blank lines before the first page as nothing, so the pack
|
|
516
|
+
loads, and until #803 `build` re-emitted the blank and refused its own emission as
|
|
517
|
+
`A07_ATLAS_TEXT_SHAPE: line 1: consecutive blank lines`. A run of blank lines
|
|
518
|
+
between two page blocks reads as one to the runtime, and is written as one.
|
|
519
|
+
|
|
508
520
|
Five things are refused rather than warned about, because each of them otherwise
|
|
509
521
|
**loads clean and draws wrong** โ or, the last, cannot be read back at all:
|
|
510
522
|
|
|
@@ -607,7 +619,6 @@ bun cli.ts ingest hero.json --out specs/ --images parts/
|
|
|
607
619
|
# .. art loose
|
|
608
620
|
# .. images ../parts/ (the rig spec's own, from /abs/path/specs)
|
|
609
621
|
# JUDGE DURATION: animation "idle" โ skeleton JSON carries no duration; the largest key time (2.667) is used โฆ
|
|
610
|
-
# LOSS PATH_LENGTHS: skin "default" slot "track" attachment "track" โ the source states `lengths`; rigc RE-MEASURES it โฆ
|
|
611
622
|
# rigc: wrote /abs/path/specs/rig.json
|
|
612
623
|
# rigc: wrote /abs/path/specs/motion.json
|
|
613
624
|
# rigc: wrote /abs/path/specs/findings.json
|
|
@@ -698,7 +709,7 @@ the first:
|
|
|
698
709
|
| --- | --- |
|
|
699
710
|
| `BLOCK` | the spec format cannot say it, so the rebuild will **not** be the file that was read โ `point`, a `sequence` block the parser would read as some other series, an unknown field on a bone, slot or constraint, a timeline family the motion spec has no track for. The command exits non-zero **and still writes both specs**, because a spec plus a list of what is missing from it beats no spec |
|
|
700
711
|
| `JUDGE` | the skeleton cannot answer and somebody has to: the stage, and each animation's duration |
|
|
701
|
-
| `LOSS` | the skeleton's spelling and rigc's differ, on purpose, and the line says how
|
|
712
|
+
| `LOSS` | the skeleton's spelling and rigc's differ, on purpose, and the line says how: `HEADER_BOOKKEEPING` for a field the spec has no home for, `HEADER_REDERIVED` for the version string, `HEADER_ORIGIN` for an origin the source left to the format and the rebuild writes out (#622) |
|
|
702
713
|
|
|
703
714
|
โ **It reads one generation of the format, and a file from another one ends loud.**
|
|
704
715
|
Spine data is locked to the generation that exported it and a mismatch does not
|
|
@@ -1103,12 +1114,14 @@ names the same comparator puts ahead of it โ `default` before `2`, `default`
|
|
|
1103
1114
|
before `A` โ so renaming a skin away from `default` makes it an ordinary name that
|
|
1104
1115
|
sorts like one.
|
|
1105
1116
|
|
|
1106
|
-
**R12 โ
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1117
|
+
**R12 โ An attachment's `name` is written exactly when the spec states it, and
|
|
1118
|
+
the `default` skin may not share a placeholder with a named skin.** rigc derives
|
|
1119
|
+
no name. A placeholder several skins fill is emitted under that placeholder in
|
|
1120
|
+
each skin, carrying the `name` each entry states and none where it states none โ
|
|
1121
|
+
which is the shape the editor itself exports (ยง3.4.2). Until
|
|
1122
|
+
[#796](https://github.com/firejune/rigc/issues/796) rigc composed
|
|
1123
|
+
`"<skin>/<placeholder>"` there, which renamed every such attachment at runtime.
|
|
1124
|
+
What you *do* author is where the shared art lives: a
|
|
1112
1125
|
placeholder the `default` skin shares with a named skin is a **compile error**,
|
|
1113
1126
|
because the Spine editor has no representation for it in either spelling (#567,
|
|
1114
1127
|
measured on 4.3.26 โ named, the export re-keys it and the default skin draws
|
|
@@ -1279,8 +1292,8 @@ setup pose as `null`.
|
|
|
1279
1292
|
|
|
1280
1293
|
### 3.4 `skins` โ placeholder โ attachment maps
|
|
1281
1294
|
|
|
1282
|
-
`skins` is `skinName โ slotName โ placeholderName โ attachment`.
|
|
1283
|
-
`default
|
|
1295
|
+
`skins` is `skinName โ slotName โ placeholderName โ attachment`. A skin called
|
|
1296
|
+
`default` becomes the skeleton's default skin. (No rung of the benchmark ladder
|
|
1284
1297
|
uses a named skin โ all twelve official example skeletons have exactly one skin,
|
|
1285
1298
|
called `default`.)
|
|
1286
1299
|
|
|
@@ -1288,11 +1301,25 @@ A skin can also say which bones and constraints it **switches on**, and that nee
|
|
|
1288
1301
|
one more level, so a skin entry has a second spelling โ see ยง3.4.1. The short one
|
|
1289
1302
|
above is unchanged and is what almost every rig wants.
|
|
1290
1303
|
|
|
1291
|
-
๐ธ **`default` is a name, not a requirement
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1304
|
+
๐ธ **`default` is a name, not a requirement, and rigc writes one exactly when the
|
|
1305
|
+
spec has one** ([#801](https://github.com/firejune/rigc/issues/801)). A rig may put
|
|
1306
|
+
every attachment in named skins and declare no `default` at all, which is what an
|
|
1307
|
+
editor export of a multi-skin character gives back: the 4.3.26 editor took a build
|
|
1308
|
+
declaring `skins: [default, alt, base]` with `default` **empty** and exported
|
|
1309
|
+
`[alt, base]`. So the emitted file carries a `default` skin when `skins` has the
|
|
1310
|
+
key โ `"default": {}` included, which is written back empty โ or when a manifest
|
|
1311
|
+
part files its states under it, and **none otherwise**. spine-core loads both
|
|
1312
|
+
spellings alike (`SkeletonData.defaultSkin` is null or an empty skin, and neither
|
|
1313
|
+
fills a slot), and the binary format has no way to hold an empty default skin at
|
|
1314
|
+
all. Until #801 rigc wrote an empty `default` into every build whether the spec
|
|
1315
|
+
had one or not, so a rebuild of such an export read `attachments.skins 1/2`
|
|
1316
|
+
against it. Two things change for a rig with no default skin, and both are
|
|
1317
|
+
named: a linked mesh that states no `skin` looks for its source in the default
|
|
1318
|
+
skin and is refused (the error table in ยง5.1), and `rigc explain` says the
|
|
1319
|
+
skeleton declares no default skin above its slot list instead of printing
|
|
1320
|
+
`attachments=[]` on every slot. An animation keying such a slot resolves its
|
|
1321
|
+
attachment names against every skin there is โ ยง4.4 states that rule and ยง5.1 the
|
|
1322
|
+
one refusal left.
|
|
1296
1323
|
|
|
1297
1324
|
๐ธ **A skin may fill no slot with anything that needs art, and that build is
|
|
1298
1325
|
green.** The atlas is built out of what the skins reference, so a rig whose skins
|
|
@@ -1332,25 +1359,26 @@ the default `type`:
|
|
|
1332
1359
|
| Field | Meaning |
|
|
1333
1360
|
| --- | --- |
|
|
1334
1361
|
| `type` | `"region"`, or omit |
|
|
1362
|
+
| `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` |
|
|
1335
1363
|
| `image` | **rigc extension.** A PNG relative to the rig's `images` directory; rigc measures it (R5) |
|
|
1336
1364
|
| `width`, `height` | required by the format โ give them, or give an `image` |
|
|
1337
|
-
| `path` | the atlas region to resolve; defaults to the attachment's
|
|
1365
|
+
| `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* |
|
|
1338
1366
|
| `x`, `y` | offset from the bone, in the bone's local space |
|
|
1339
1367
|
| `rotation` | degrees; cancels a rotated bone for a plate authored screen-upright |
|
|
1340
1368
|
| `scaleX`, `scaleY`, `color` | as Spine |
|
|
1341
|
-
| `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 |
|
|
1369
|
+
| `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 |
|
|
1342
1370
|
|
|
1343
1371
|
**Mesh attachment** ([Spine: meshes](http://esotericsoftware.com/spine-meshes)) โ
|
|
1344
1372
|
either authored geometry (`uvs` + `triangles` + geometry) **or** a `generator`,
|
|
1345
1373
|
never both. `hull`, `edges`, `width` and `height` may be stated; whichever is
|
|
1346
1374
|
omitted, rigc derives โ `hull` and `edges` from the triangles, the size from the
|
|
1347
|
-
PNG โ and the rules are a few paragraphs down. `type`, `image`, `path`,
|
|
1348
|
-
`sequence` mean exactly what they mean on a region (a sequence mesh takes authored
|
|
1375
|
+
PNG โ and the rules are a few paragraphs down. `type`, `name`, `image`, `path`,
|
|
1376
|
+
`color` and `sequence` mean exactly what they mean on a region (a sequence mesh takes authored
|
|
1349
1377
|
geometry, never a `generator` โ ยง3.4.3).
|
|
1350
1378
|
|
|
1351
1379
|
๐ **`path` is one rule for both kinds.** A mesh derives it from `image` the way a
|
|
1352
1380
|
region does: stated wins, otherwise the PNG's basename when that differs from the
|
|
1353
|
-
placeholder
|
|
1381
|
+
attachment's name โ its `name`, else the placeholder โ otherwise nothing. The parser reads `path` off both with the same line
|
|
1354
1382
|
(`getValue(map, "path", name)`, `SkeletonJson.ts:541` and `:570`), and `path`
|
|
1355
1383
|
defaults to the attachment's **name** rather than to the placeholder โ so a mesh
|
|
1356
1384
|
with `image: hair_short.png` under a placeholder called `hair` resolves the region
|
|
@@ -1515,11 +1543,11 @@ them (`SkeletonJson.ts:568-569`, `:582`), so rigc reads them the same way.
|
|
|
1515
1543
|
|
|
1516
1544
|
| Field | Meaning |
|
|
1517
1545
|
| --- | --- |
|
|
1518
|
-
| `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 |
|
|
1546
|
+
| `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` |
|
|
1519
1547
|
| `slot` | the slot the source lives in. Default: **this attachment's own slot**. Resolved by name against the rig's slots |
|
|
1520
1548
|
| `skin` | the skin the source lives in. Default: **`default`** โ the default skin, *not* the skin this link is written in. Resolved by name |
|
|
1521
1549
|
| `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 |
|
|
1522
|
-
| `image`, `path`, `width`, `height`, `color` | exactly as on a mesh โ the link resolves **its own** region, which is the point of the type |
|
|
1550
|
+
| `name`, `image`, `path`, `width`, `height`, `color` | exactly as on a mesh โ the link resolves **its own** region, which is the point of the type |
|
|
1523
1551
|
|
|
1524
1552
|
```json
|
|
1525
1553
|
"skins": {
|
|
@@ -1605,6 +1633,7 @@ region, a trigger volume โ that moves with the skeleton and draws nothing.
|
|
|
1605
1633
|
| Field | Meaning |
|
|
1606
1634
|
| --- | --- |
|
|
1607
1635
|
| `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"` |
|
|
1636
|
+
| `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 |
|
|
1608
1637
|
| `vertexCount` | **required**, 3 or more. No default โ the paragraph above is why |
|
|
1609
1638
|
| `vertices` | the unweighted `x, y` run, in the slot bone's local space; or the index-encoded weighted run, behind `boneIndexing` |
|
|
1610
1639
|
| `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` |
|
|
@@ -1619,7 +1648,7 @@ attachment rather than a second set of art.
|
|
|
1619
1648
|
| Field | Meaning |
|
|
1620
1649
|
| --- | --- |
|
|
1621
1650
|
| `type` | `"clipping"`. **Required** |
|
|
1622
|
-
| `vertexCount`, `vertices`, `weights`, `boneIndexing`, `color` | exactly as on a bounding box |
|
|
1651
|
+
| `name`, `vertexCount`, `vertices`, `weights`, `boneIndexing`, `color` | exactly as on a bounding box |
|
|
1623
1652
|
| `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 |
|
|
1624
1653
|
| `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 |
|
|
1625
1654
|
| `inverse` | default **false**. True makes everything **outside** the polygon visible instead of everything inside, and inverse clipping is always treated as convex (`ClippingAttachment.inverse`) |
|
|
@@ -1637,10 +1666,10 @@ other vertex attachment.
|
|
|
1637
1666
|
| Field | Meaning |
|
|
1638
1667
|
| --- | --- |
|
|
1639
1668
|
| `type` | `"path"`. **Required** |
|
|
1640
|
-
| `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 |
|
|
1669
|
+
| `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 |
|
|
1641
1670
|
| `closed` | default **false**. True joins the last knot back to the first |
|
|
1642
1671
|
| `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 |
|
|
1643
|
-
| `lengths` |
|
|
1672
|
+
| `lengths` | **stated or measured** ([#804](https://github.com/firejune/rigc/issues/804)). The cumulative length at the end of each curve, and exactly **`vertexCount / 3`** entries on an open path and a closed one alike โ the parser's own allocation, which on an open path is one more than its curves: the last entry is the wrap-around curve's cumulative, which the editor writes and nothing reads. **Stated**, it is emitted as stated (float32, like every number in the file) โ which is what `ingest` writes from an export, and the only way to carry the editor's number, because the editor measures the pose the first update gives the path constraint, *constraints applied*, and rigc does not pose. A stated array of the wrong count is refused with both counts, `"lengths" has N entry(ies) where the parser sizes M`, and a non-finite entry or one below its predecessor by index. **Left out**, rigc measures it off the geometry: weighted vertices through their bones' setup world transforms, scale, shear and `inherit` included, on the **unconstrained** setup pose โ so a path whose bones a constraint moves at rest gets a different figure from the editor's. Only `constantSpeed: false` reads the field at all. What the numbers are โ and why *arc length* is the wrong name for them โ is ยง10.6 |
|
|
1644
1673
|
|
|
1645
1674
|
๐จ **`vertexCount` counts knots AND handles, and it has to be a multiple of 3.**
|
|
1646
1675
|
The parser hands `vertexCount << 1` to `readVertices` and then walks the result in
|
|
@@ -1660,7 +1689,8 @@ and `vertexCount is N and an open path needs at least 6`.
|
|
|
1660
1689
|
|
|
1661
1690
|
Nine points are two curves. The outer handles at `x = -30` and `x = 210` are
|
|
1662
1691
|
dropped, so the chain runs from `x = 0` to `x = 180` and rigc emits
|
|
1663
|
-
`"lengths": [90, 180]` beside it โ measured, not stated
|
|
1692
|
+
`"lengths": [90, 180, 360]` beside it โ measured, not stated, and the third entry
|
|
1693
|
+
is the wrap-around curve from `x = 180` back to `x = 0`, which nothing reads. That is the path
|
|
1664
1694
|
ยง3.5.1's constraint example rides: with `position: 0.25` its `cart` bone poses at
|
|
1665
1695
|
`worldX = 45.000000`.
|
|
1666
1696
|
|
|
@@ -2312,41 +2342,64 @@ beside them is refused rather than ignored (an ignored slot is an attachment tha
|
|
|
2312
2342
|
vanishes), and a rig with a *slot* of one of those names is refused too, because
|
|
2313
2343
|
there the two forms are genuinely ambiguous. Rename the slot.
|
|
2314
2344
|
|
|
2315
|
-
#### 3.4.2 Two skins, one placeholder โ the `name`
|
|
2316
|
-
|
|
2317
|
-
Two skins putting different art under one placeholder is what a skin is *for*, and
|
|
2318
|
-
it is the one shape rigc emitted wrongly until
|
|
2319
|
-
[#541](https://github.com/firejune/rigc/issues/541). Without a `name` field an
|
|
2320
|
-
attachment's name **is** its placeholder (`SkeletonJson.ts:526`), so four skins
|
|
2321
|
-
filling `patch` are four different attachments all called `patch`. spine-core never
|
|
2322
|
-
notices โ its skin table is keyed by placeholder, so the two never meet โ and the
|
|
2323
|
-
whole gate is green. The Spine editor refuses the import outright:
|
|
2345
|
+
#### 3.4.2 Two skins, one placeholder โ and the `name` you may state
|
|
2324
2346
|
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
```
|
|
2331
|
-
|
|
2332
|
-
โ rigc now writes each of those entries a name of its own, composed from the two
|
|
2333
|
-
names you already gave it:
|
|
2347
|
+
Two skins putting different art under one placeholder is what a skin is *for*. Each
|
|
2348
|
+
entry is its own attachment, filed under that placeholder in its own skin, and with
|
|
2349
|
+
no `name` field the runtime names every one of them by the placeholder
|
|
2350
|
+
(`getValue(map, "name", placeholder)`, `SkeletonJson.js:526`). That is legal Spine
|
|
2351
|
+
data, and it is the shape the editor exports: rigc emits it exactly as you wrote it.
|
|
2334
2352
|
|
|
2335
2353
|
```json
|
|
2336
2354
|
"skins": {
|
|
2337
2355
|
"default": { "block": { "block": { "image": "block.png" } } },
|
|
2338
2356
|
"base": { "patch": { "patch": { "image": "patch_a.png" } } },
|
|
2339
|
-
"zulu": { "patch": { "patch": { "image": "
|
|
2357
|
+
"zulu": { "patch": { "patch": { "image": "patch_b.png", "x": 4 } } }
|
|
2340
2358
|
}
|
|
2341
2359
|
```
|
|
2342
2360
|
|
|
2343
|
-
emits
|
|
2361
|
+
emits two `patch` attachments in slot `patch`, one per skin, each with the `path` its
|
|
2362
|
+
image gives it (`patch_a`, `patch_b`) and **no `name`** โ both answer to `patch` at
|
|
2363
|
+
runtime, and each is the one its skin shows.
|
|
2364
|
+
|
|
2365
|
+
๐ **State a `name` when the attachment's own name is not its placeholder.** A
|
|
2366
|
+
transcription of an export that carries one โ `ingest` writes it for you โ or any
|
|
2367
|
+
rig whose consumer reads `slot.attachment.name`. It is written verbatim, and `path`
|
|
2368
|
+
defaults to it, so an image named after it needs no `path`:
|
|
2344
2369
|
|
|
2345
2370
|
```json
|
|
2346
|
-
{ "
|
|
2347
|
-
{ "name": "zulu/patch", "path": "patch", "width": 64, "height": 64, "x": 4 }
|
|
2371
|
+
"base": { "patch": { "patch": { "name": "patch-base", "image": "patch-base.png" } } }
|
|
2348
2372
|
```
|
|
2349
2373
|
|
|
2374
|
+
emits `"name": "patch-base"` first and no `path`, and the runtime draws region
|
|
2375
|
+
`patch-base` for an attachment it calls `patch-base`, filed under `patch`.
|
|
2376
|
+
|
|
2377
|
+
๐ฌ **Until [#796](https://github.com/firejune/rigc/issues/796) rigc composed a name
|
|
2378
|
+
here, and the reason it did was measured wrong.**
|
|
2379
|
+
[#541](https://github.com/firejune/rigc/issues/541) read the editor's refusal of a
|
|
2380
|
+
four-skin rig โ `Multiple attachments have the same name: patch patch` โ as "one
|
|
2381
|
+
name over several attachments, because a linked mesh resolves its parent by name",
|
|
2382
|
+
and [#552](https://github.com/firejune/rigc/issues/552) wrote
|
|
2383
|
+
`"<skin>/<placeholder>"` on every contested entry. Both halves fail a measurement:
|
|
2384
|
+
|
|
2385
|
+
- **A linked mesh finds its source by skin, slot and KEY.** Through spine-core
|
|
2386
|
+
4.3.13, two skins each fill `C` with a different mesh and no `name`, both load
|
|
2387
|
+
named `C`, and a link with `source: "C"` binds the mesh of the skin its own
|
|
2388
|
+
`skin` names. A `source` that spells a source's `name` instead throws
|
|
2389
|
+
`Source mesh not found` โ which rigc refuses by name before that (ยง3.4, *Linked
|
|
2390
|
+
mesh*).
|
|
2391
|
+
- **The editor imports the uncomposed shape.** A production rig whose placeholders
|
|
2392
|
+
are each filled by two named skins, meshes and linked meshes among them, imported
|
|
2393
|
+
through Spine 4.3.26 with every composed name stripped. It is the file that editor
|
|
2394
|
+
exported.
|
|
2395
|
+
|
|
2396
|
+
What #541 had bisected was a rig whose **default** skin filled the contested
|
|
2397
|
+
placeholder beside the named ones โ its smallest refusing variant was `default` plus
|
|
2398
|
+
one named skin โ and that shape is refused on measurements of its own, below. The
|
|
2399
|
+
composition renamed every contested attachment of every multi-skin export at
|
|
2400
|
+
runtime, which `slot.attachment.name` shows a consumer and no gate could see; `diff`
|
|
2401
|
+
now reads it as `attachments.runtime_name`.
|
|
2402
|
+
|
|
2350
2403
|
๐จ **Every skin that shares a placeholder has to be a named one โ the default
|
|
2351
2404
|
skin may not be among them, and rigc refuses the rig if it is.** That is not a
|
|
2352
2405
|
style rule; it is the editor's model, and two round trips through Spine
|
|
@@ -2377,18 +2430,9 @@ style rule; it is the editor's model, and two round trips through Spine
|
|
|
2377
2430
|
are the same namespace, and both are `patch`.
|
|
2378
2431
|
|
|
2379
2432
|
โ **The rule: move the shared art into a named skin.** Call it `base`. Every
|
|
2380
|
-
filler of that placeholder is then a named skin,
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
`zulu/patch` and `mike/patch` are three names. That shape is the one the editor
|
|
2384
|
-
does hold: the same three fillers in named skins imported, exported and measured
|
|
2385
|
-
**0.00 mean MAE** with names and paths intact.
|
|
2386
|
-
|
|
2387
|
-
๐ **The earlier reading, kept because it was reasonable and wrong.** Between the
|
|
2388
|
-
two trips this guide said *compose off the default skin only* โ keep the default
|
|
2389
|
-
skin's entry as its placeholder and name the others. Trip 7 supported it and trip
|
|
2390
|
-
8 refuted it: that is the spelling the editor refuses at the door. There is no
|
|
2391
|
-
third spelling, which is why this is a refusal rather than a naming scheme.
|
|
2433
|
+
filler of that placeholder is then a named skin, which is the shape the editor
|
|
2434
|
+
holds. Stating a `name` on the default skin's entry does not lift the refusal: that
|
|
2435
|
+
is the first of the two spellings above.
|
|
2392
2436
|
|
|
2393
2437
|
What to know about it, and nothing to author:
|
|
2394
2438
|
|
|
@@ -2408,39 +2452,27 @@ What to know about it, and nothing to author:
|
|
|
2408
2452
|
restated as the join the renderer actually performs it was a tautology over
|
|
2409
2453
|
the resolve check beside it
|
|
2410
2454
|
([#574](https://github.com/firejune/rigc/issues/574)).
|
|
2411
|
-
-
|
|
2412
|
-
**name**, not to its placeholder, so an entry
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
skin, the slot, the placeholder and the path
|
|
2416
|
-
([#589](https://github.com/firejune/rigc/issues/589))
|
|
2417
|
-
reported it in the parser's own words until then, and now defers to A08.
|
|
2418
|
-
- **Only contested placeholders are touched.** One skin filling a placeholder, or
|
|
2419
|
-
two skins filling a slot under *different* placeholders, emit exactly what they
|
|
2420
|
-
always did โ every rig in this repository is byte-identical across the change.
|
|
2421
|
-
- **A composed name that collides is a compile error, not a surprise.** If some
|
|
2422
|
-
other placeholder in the same slot is literally called `zulu/patch`, rigc refuses
|
|
2423
|
-
and names both sites rather than emitting two attachments with one name again.
|
|
2424
|
-
The walk covers every *uncontested* entry's plain name too, the default skin's
|
|
2425
|
-
included โ a name that composed nothing can still be the one another skin
|
|
2426
|
-
composes.
|
|
2427
|
-
(`/` is the separator because it appears in **0** of the 160 placeholder names and
|
|
2428
|
-
159 atlas region names in `examples/` and `gallery/`, where `-` appears in 85 and
|
|
2429
|
-
`_` in 37.)
|
|
2455
|
+
- **A stated `name` with no `path` resolves the region the name spells.** `path`
|
|
2456
|
+
defaults to the attachment's **name**, not to its placeholder, so an entry naming
|
|
2457
|
+
`patch-base` and drawing `patch_a.png` needs a `path` โ and gets one, because the
|
|
2458
|
+
image basename differs from the name. `A08_REGION_NAMES_MATCH_ATTACHMENTS` names
|
|
2459
|
+
the skin, the slot, the placeholder and the path if the region is not there
|
|
2460
|
+
([#589](https://github.com/firejune/rigc/issues/589)).
|
|
2430
2461
|
- **Each skin's art is measured and atlased on its own.** The example above points
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
โ ๏ธ **
|
|
2440
|
-
which the editor wrote, gives the name `head` to a region in
|
|
2441
|
-
bounding box in slot `head-bb`, and reuses `hoverglow-small`
|
|
2442
|
-
|
|
2443
|
-
|
|
2462
|
+
the two skins at two PNGs, so there are two regions, each attachment's `path`
|
|
2463
|
+
resolving to the file that attachment named and its `width`/`height` measured off
|
|
2464
|
+
that file. Until [#555](https://github.com/firejune/rigc/issues/555) only the
|
|
2465
|
+
first skin's PNG was ever opened, and the second skin's art reached neither the
|
|
2466
|
+
atlas nor the measurement โ so name the two files **distinctly**, because the
|
|
2467
|
+
region name is the basename and `a/patch.png` beside `b/patch.png` is refused
|
|
2468
|
+
(R5).
|
|
2469
|
+
|
|
2470
|
+
โ ๏ธ **Nothing measured says the editor wants names unique within a slot.**
|
|
2471
|
+
`spineboy-pro.json`, which the editor wrote, gives the name `head` to a region in
|
|
2472
|
+
slot `head` and to a bounding box in slot `head-bb`, and reuses `hoverglow-small`
|
|
2473
|
+
across eight slots; the production rig above holds same-named attachments in one
|
|
2474
|
+
slot across its named skins. The one refusal the editor was measured making is the
|
|
2475
|
+
default-skin share, and that is the rule rigc enforces.
|
|
2444
2476
|
|
|
2445
2477
|
๐จ **Once a rig has named skins, no instrument here can see them until you say
|
|
2446
2478
|
which one** ([#571](https://github.com/firejune/rigc/issues/571)). `render` and
|
|
@@ -2449,7 +2481,10 @@ skin alone and the art you just moved into `base`, `zulu` and `mike` draws
|
|
|
2449
2481
|
nothing at all. `check` then compares blank against blank and reports a perfect
|
|
2450
2482
|
`0.0000` โ about the very placeholder this subsection is about. Pass
|
|
2451
2483
|
`--skin <name>` to both, once per skin (**ยง9**); `tools/editor_roundtrip.ts`
|
|
2452
|
-
loops over every skin the build
|
|
2484
|
+
loops over every skin the build and the export both declare for the same reason,
|
|
2485
|
+
and names a skin only one of them declares as **lost** (or **added**) **by the
|
|
2486
|
+
export**, quoting `diff`'s `attachments.skins`, without rendering it on either side
|
|
2487
|
+
([#801](https://github.com/firejune/rigc/issues/801)).
|
|
2453
2488
|
|
|
2454
2489
|
#### 3.4.3 `sequence` โ a numbered image series on one attachment
|
|
2455
2490
|
|
|
@@ -2506,11 +2541,18 @@ other than what was written (measured on spine-core 4.3.13,
|
|
|
2506
2541
|
only on the three kinds that draw a region, so it would be dropped in silence. The
|
|
2507
2542
|
refusal names region, mesh and linkedmesh.
|
|
2508
2543
|
|
|
2509
|
-
`width` and `height` are the attachment's one size, every frame drawn into it.
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2544
|
+
`width` and `height` are the attachment's one size, every frame drawn into it. The
|
|
2545
|
+
frames **may differ in size**: the runtime scales each frame's region into the
|
|
2546
|
+
attachment's size (`RegionAttachment.computeUVs`, `width / region.originalWidth`), so a
|
|
2547
|
+
stated size is emitted as stated and compared with no frame, on the loose route and
|
|
2548
|
+
under `--atlas-in` alike. That is what an editor exports for a series that mixes image
|
|
2549
|
+
sizes โ the setup frame's size, the other frames as they are
|
|
2550
|
+
([#795](https://github.com/firejune/rigc/issues/795)). Omit them and rigc takes the
|
|
2551
|
+
frames' size โ **only when every frame measures the same**; frames of different sizes
|
|
2552
|
+
are refused until you state the size, because picking one of them would be the
|
|
2553
|
+
compiler choosing a value. โ ๏ธ One region is different: its `width` is its image's size
|
|
2554
|
+
in every editor export, so under `--atlas-in` a stated size that disagrees with its
|
|
2555
|
+
packed region is still refused.
|
|
2514
2556
|
`A46_SEQUENCE_ATTACHMENTS_SHOW_THE_FRAME_THE_FILE_STATES` (ยง5.2) holds the block and
|
|
2515
2557
|
every frame the timelines show against the file.
|
|
2516
2558
|
|
|
@@ -3548,14 +3590,48 @@ a delta from the constraint's own setting.
|
|
|
3548
3590
|
somebody else's file means **0**.
|
|
3549
3591
|
- โ ๏ธ `mass` is the one whose keyed number is not what the runtime stores. The
|
|
3550
3592
|
key states a mass and the pose holds `1 / mass`, so a `mass` key of `0` is an
|
|
3551
|
-
infinite inverse mass โ the
|
|
3593
|
+
infinite inverse mass โ every velocity and offset is NaN from the first step.
|
|
3552
3594
|
- **Four of the seven are bounded, and a key outside its bound is a compile
|
|
3553
3595
|
error** ([#610](https://github.com/firejune/rigc/issues/610)). `mass` must be
|
|
3554
|
-
`> 0`, `damping` must be
|
|
3596
|
+
`> 0`, `damping` must be inside the closed `[0, 1]`, and `mix` and `strength`
|
|
3555
3597
|
must be `0` or more. `A23_PHYSICS_CONSTRAINT_EFFECTIVE` applies the same four to
|
|
3556
3598
|
a file rigc did not write, naming the animation, the constraint, the key time
|
|
3557
3599
|
and the value โ so the compiler is where a spec you wrote is refused, and the
|
|
3558
3600
|
assertion is where an import is.
|
|
3601
|
+
- ๐ **Each way out of a bound has a basis, and the refusal says which**
|
|
3602
|
+
([#798](https://github.com/firejune/rigc/issues/798)). **arithmetic** means the
|
|
3603
|
+
runtime cannot compute the value โ an expression in the integrator is
|
|
3604
|
+
non-finite at it โ and the sentence names the expression and its lines;
|
|
3605
|
+
**behavioural** means the runtime runs it, finitely, and the rig runs wrongly,
|
|
3606
|
+
so refusing it is rigc's call and the sentence says so and says what the value
|
|
3607
|
+
does. Two of the eight ways out are arithmetic. The table is the
|
|
3608
|
+
`PHYSICS_POSE_RULES` rows' own `basis`, verbatim, and `CUR100` holds it to them;
|
|
3609
|
+
every basis is re-measured through spine-core by `T113` on every run.
|
|
3610
|
+
|
|
3611
|
+
| field | at rest | on a key | basis |
|
|
3612
|
+
| --- | --- | --- | --- |
|
|
3613
|
+
| `mix` | `> 0` | `>= 0` | behavioural: below 0 the jiggle is applied inverted, on `x` and `y` exactly the offset a positive mix of the same size applies, mirrored (`PhysicsConstraint.js:172,174`), and `PhysicsConstraintPose` documents mix as "a percentage (0+)" where a transform constraint documents its own as "unbounded"; behavioural: at 0 `update` returns before it does anything (`PhysicsConstraint.js:109-111`), so the constraint is muted |
|
|
3614
|
+
| `mass` | `> 0` | `> 0` | arithmetic: at 0 `massInverse = 1 / mass` is Infinity and `m = t * massInverse` multiplies every velocity update, so the first step takes every velocity and offset to NaN (`SkeletonJson.js:309, Animation.js:2140, PhysicsConstraint.js:149,156,211`); behavioural: below 0 `massInverse` is a finite negative, which flips the sign of every force the velocity update applies, so the restoring force pushes the offset away and it grows with every step |
|
|
3615
|
+
| `strength` | `> 0` | `>= 0` | behavioural: below 0 the restoring term is ADDED to the offset instead of taken out of it, so the offset is pushed away and grows with every step; behavioural: nothing pulls it back |
|
|
3616
|
+
| `damping` | `inside [0, 1]` | `inside [0, 1]` | behavioural: above 1 every velocity grows on every step and the offset diverges; arithmetic: at any fps where `60 / fps` is not whole it is a negative number raised to a fractional power, which is NaN (`PhysicsConstraint.js:148,210`) |
|
|
3617
|
+
|
|
3618
|
+
โ ๏ธ The line between the two is **non-finite within the walk that measures
|
|
3619
|
+
it**, not "non-finite eventually": [measured] on the generated physics
|
|
3620
|
+
fixture at 60 fps, a setup `damping` of 2 is finite for 1,064 steps before its
|
|
3621
|
+
velocity overflows, and a `mass` of โ1 runs the offset to 2.7e6 in 120 steps
|
|
3622
|
+
finite on every one. Every run-away overflows at some horizon, which is why
|
|
3623
|
+
`damping` above 1 is behavioural although it diverges.
|
|
3624
|
+
- โ๏ธ **A negative `mix` is refused on a physics constraint and accepted on a
|
|
3625
|
+
transform constraint, and neither is the runtime's arithmetic**
|
|
3626
|
+
([#798](https://github.com/firejune/rigc/issues/798)). [measured] both are a
|
|
3627
|
+
finite, mirrored scale: a physics constraint resting at `mix` โ0.5 moves its
|
|
3628
|
+
bone by exactly the opposite of +0.5 on every step, and a transform constraint
|
|
3629
|
+
at `mixRotate` โ0.5 rotates its bone by the negative of +0.5's. What differs is
|
|
3630
|
+
the range the runtime documents for each field โ `PhysicsConstraintPose.mix` is
|
|
3631
|
+
"a percentage (0+)", `TransformConstraintPose.mixRotate` "a percentage
|
|
3632
|
+
(unbounded)" โ and each rule follows its own. `T114` holds the mirror and both
|
|
3633
|
+
documented ranges against the runtime; `T105` holds the transform side's
|
|
3634
|
+
acceptance.
|
|
3559
3635
|
- โ ๏ธ **`damping`'s bound depends on the constraint's `fps`, and a rig played at
|
|
3560
3636
|
60 fps hides it** ([#748](https://github.com/firejune/rigc/issues/748)). The
|
|
3561
3637
|
decay is `damping ** (60 * step)` with `step` = `1 / fps`, so the exponent is
|
|
@@ -3564,9 +3640,19 @@ a delta from the constraint's own setting.
|
|
|
3564
3640
|
whole number the same negative is raised to a fractional power, which is NaN.
|
|
3565
3641
|
[measured] one planted `damping` key of โ0.5 on the generated physics fixture
|
|
3566
3642
|
stays finite at 60 fps and at 30 (exponent 2), and is NaN within three steps of
|
|
3567
|
-
the key at 45 and at 120. `1`
|
|
3568
|
-
rate. The refusal names the exponent and the rate for this
|
|
3569
|
-
holds it to the two-rate measurement.
|
|
3643
|
+
the key at 45 and at 120. Above `1` every velocity grows on every step and
|
|
3644
|
+
diverges at every rate. The refusal names the exponent and the rate for this
|
|
3645
|
+
reason, and `T101` holds it to the two-rate measurement.
|
|
3646
|
+
- โ
**Both ends of `damping` are inside the bound**
|
|
3647
|
+
([#794](https://github.com/firejune/rigc/issues/794)). `1 ** x` is 1 and
|
|
3648
|
+
`0 ** x` is 0 for every positive exponent, so neither depends on `fps`: at `1`
|
|
3649
|
+
the velocity never decays and the jiggle holds for as long as it runs, and at
|
|
3650
|
+
`0` every velocity is zeroed on every step, so the offset follows the bone with
|
|
3651
|
+
no overshoot. Both are finite, at rest and keyed โ [measured] 120 steps from
|
|
3652
|
+
`Physics.reset` at 60, 45 and 30 fps on the generated physics fixture, which
|
|
3653
|
+
`T109`โ`T111` hold. โ ๏ธ `1` is also what a 4.2 file means by saying nothing:
|
|
3654
|
+
4.2's parser reads an omitted `damping` as `1` where 4.3's reads `0.85`
|
|
3655
|
+
(ยง4.6), so a rig migrated from 4.2 that keys "the default" keys `1`.
|
|
3570
3656
|
- ๐ซ **`inertia`, `wind` and `gravity` are bounded nowhere, and neither is the top
|
|
3571
3657
|
of `mix`.** The runtime documents no range for the first three, and
|
|
3572
3658
|
`PhysicsConstraintPose` documents `mix` as "a percentage (0+)" โ so a negative
|
|
@@ -3971,11 +4057,16 @@ key times. One lag, one place.
|
|
|
3971
4057
|
mass?, wind?, gravity?, mix?, fps?, limit? }`. These are emitted into the 4.3
|
|
3972
4058
|
`constraints` array. Seven of them โ the six tuning numbers and `mix` โ can also
|
|
3973
4059
|
be **keyed over time** as `tracks` entries naming this constraint (ยง4.4); this
|
|
3974
|
-
table is the value at rest, and a timeline overrides it while it plays. `mass: 0` becomes an infinite inverse mass and `damping
|
|
4060
|
+
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
|
|
3975
4061
|
never settles โ both are `A23`, here and on every timeline key that states them
|
|
3976
|
-
([#610](https://github.com/firejune/rigc/issues/610)); a `damping`
|
|
3977
|
-
is refused as well, and
|
|
3978
|
-
([#748](https://github.com/firejune/rigc/issues/748)).
|
|
4062
|
+
([#610](https://github.com/firejune/rigc/issues/610)); a `damping` below 0
|
|
4063
|
+
is refused as well, and whether it is NaN depends on `fps` โ ยง4.4
|
|
4064
|
+
([#748](https://github.com/firejune/rigc/issues/748)). `damping` is `[0, 1]`
|
|
4065
|
+
with both ends in: `1` never decays and `0` zeroes the velocity on every step,
|
|
4066
|
+
both finite at every rate ([#794](https://github.com/firejune/rigc/issues/794)).
|
|
4067
|
+
โ ๏ธ An omitted `damping` is `0.85` to 4.3's parser (`SkeletonJson.js:308` in
|
|
4068
|
+
4.3.13) and `1` to 4.2's (`SkeletonJson.js:242` in 4.2.120), so a constraint
|
|
4069
|
+
migrated from 4.2 that stated nothing may arrive stating `1` โ which builds. โ ๏ธ `strength: 0` is `A23` **here and not on a key**:
|
|
3979
4070
|
at rest it is a constraint nothing pulls back, and on a key it is a release somebody
|
|
3980
4071
|
asked for, which ยง4.4 states with the measurement behind it
|
|
3981
4072
|
([#727](https://github.com/firejune/rigc/issues/727)). A negative `strength` is
|
|
@@ -5414,6 +5505,7 @@ or the key's position in its own track. These are the frequent ones, verbatim:
|
|
|
5414
5505
|
| `a linked mesh states "uvs", "triangles", โฆ, and a linked mesh has no geometry of its own` | ยง3.4 โ remove them, or remove `source` and author this as a mesh. The parser returns before `readVertices`, so those keys are read by nothing at all |
|
|
5415
5506
|
| `"source" is "X", and skin "S" โฆ slot "L" โฆ holds 2: "a", "b"` | ยง3.4 โ `source` is the PLACEHOLDER the source is filed under, not its `name`. A clause after the skin and after the slot says whether each was stated or taken from the parser's default โ **the default skin** and **this attachment's own slot**, which is the pair that surprises |
|
|
5416
5507
|
| `"slot" is "X", which the rig does not declare as a slot` / `"skin" is "X", โฆ the rig declares no such skin` | ยง3.4 โ a link resolves both by name. Left to the round trip these are the runtime's `Source mesh slot not found` and `Skin not found`, which name neither the attachment nor where it looked |
|
|
5508
|
+
| `no "skin" is stated, so the parser looks for the source "X" in the default skin โ and this rig declares no default skin` | ยง3.4 โ state the `skin` the source is filed under. A link with no `skin` resolves through `SkeletonData.defaultSkin`, which is null in a file with no default skin, and the runtime reads `getAttachment` off it with a `TypeError` naming nothing. Before [#801](https://github.com/firejune/rigc/issues/801) every build carried an empty `default`, so the same link failed at the source instead |
|
|
5417
5509
|
| `"source" is "X", which is itself a linked mesh, and a chain of them is refused` | ยง3.4 โ point `source` at the mesh. A chain resolves in file order and loads nothing at all in one of the two orders, silently |
|
|
5418
5510
|
| `"source" is "X", which is a "region" attachment and not a mesh` | ยง3.4 โ a link takes another MESH's geometry; off any other type the runtime reads `undefined` and says nothing |
|
|
5419
5511
|
| `โฆ is a boundingbox and states a "sequence". A sequence is a numbered series of atlas regions, and only the 3 kinds that draw a region carry one โ region, mesh, linkedmesh โฆ` | ยง3.4.3 โ put the series on a region or a mesh, or remove it |
|
|
@@ -5450,7 +5542,7 @@ or the key's position in its own track. These are the frequent ones, verbatim:
|
|
|
5450
5542
|
| `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 |
|
|
5451
5543
|
| `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 |
|
|
5452
5544
|
| `animation "A" bone "X" translatex: key value must be an array of 1 number(s)` | the value shape must match the property (ยง4.4) |
|
|
5453
|
-
| `animation "A" physics constraint "C" mass key at t=โฆ is 0 (massInverse Infinity); must be > 0 โ โฆ` | ยง4.4 โ a keyed physics value
|
|
5545
|
+
| `animation "A" physics constraint "C" mass key at t=โฆ is 0 (massInverse Infinity); must be > 0 โ โฆ` | ยง4.4 โ a keyed physics value outside its row's bound. The message names the bound and then its basis ([#798](https://github.com/firejune/rigc/issues/798)): where the runtime's arithmetic fails, the expression and its lines (`mass` at 0 is the one here, and `damping` below 0); where the value runs and runs wrongly, that refusing it is rigc's call and what the value does. The bounds: `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) |
|
|
5454
5546
|
| `a key carries both a named easing and a raw curve; pick one` | R6 |
|
|
5455
5547
|
| `last key carries an easing but has nothing to ease to` | drop `ease`/`curve` from the final key |
|
|
5456
5548
|
| `key times must strictly increase (at t=โฆ)` | including after `lag` and `stagger` |
|
|
@@ -5494,7 +5586,8 @@ or the key's position in its own track. These are the frequent ones, verbatim:
|
|
|
5494
5586
|
| `deform โฆ (t=โฆ): transform <kind> states โฆ, and every one of this attachment's N vertices evaluates to an offset of 0` | ยง4.11.1 โ the parameters state a deformation and the geometry sampled it to nothing; the message names the measured cause. A key that means the setup pose states the identity in its parameters, or carries no run |
|
|
5495
5587
|
| `vertexCount is N, which is not a multiple of 3` | ยง3.4 โ a path's vertices are knots and handles read in groups of three: `3(K + 1)` open, `3K` closed |
|
|
5496
5588
|
| `vertexCount is N and an open path needs at least 6` | ยง3.4 โ an open path drops its first and last point, so it needs six for one curve |
|
|
5497
|
-
| `"lengths"
|
|
5589
|
+
| `"lengths" has N entry(ies) where the parser sizes M โ vertexCount / 3 on โฆ` | ยง3.4 โ `vertexCount / 3` entries on either shape; give the array the source states, or leave the field out and rigc measures it |
|
|
5590
|
+
| `"lengths"[i] is V, below โฆ` / `"lengths"[i] is "โฆ"; every entry is a finite cumulative length` | ยง3.4 โ the array is cumulative, so each entry is at least the one before it |
|
|
5498
5591
|
| `rig constraint "X": slot "Y" has no path attachment in any skin` | ยง3.5.1 โ give that slot a `"type": "path"` attachment, or aim the constraint at the slot that has one |
|
|
5499
5592
|
| `rig constraint "X": rotateMode is "CHAINSCALE"; known: Tangent, Chain, ChainScale` | ยง3.5.1 โ only the first letter's case is free; anything else resolves to `undefined` in the parser |
|
|
5500
5593
|
| `rig constraint "X": applies animation "Y", which the motion spec does not declare (it declares: โฆ)` | ยง3.5.2 โ fix the slider's `animation`, or add it to the motion spec |
|
|
@@ -5525,7 +5618,7 @@ or the key's position in its own track. These are the frequent ones, verbatim:
|
|
|
5525
5618
|
| `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)) |
|
|
5526
5619
|
| `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 |
|
|
5527
5620
|
| `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 |
|
|
5528
|
-
| `
|
|
5621
|
+
| `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 |
|
|
5529
5622
|
|
|
5530
5623
|
โ ๏ธ **One refusal in this section is not a `CompileError`, and it is `explain`'s.**
|
|
5531
5624
|
`explain` prints the `DEFORM` block by **posing** the rig, and a pose resolves every
|
|
@@ -5623,7 +5716,7 @@ Fix A00 and run it again ([#568](https://github.com/firejune/rigc/issues/568)).
|
|
|
5623
5716
|
| `A04_MESH_TRIANGLES_AND_ENCODING` | both | authored mesh geometry: triangle count not a multiple of 3, an index out of range, or a `vertices` length that disagrees with `uvs` (the weighted/unweighted trap) **SKIP** when the skeleton carries no mesh attachment ([#580](https://github.com/firejune/rigc/issues/580)) |
|
|
5624
5717
|
| `A05_CURVE_ARRAY_LENGTH` | both | a raw `curve` with the wrong number of values, a non-finite number in one, or a curve on a timeline that cannot take one. Four numbers **per value channel**. **SKIP** when no animation carries a timeline at all ([#580](https://github.com/firejune/rigc/issues/580)). Timelines with no `curve` on any key still PASS: every timeline name is checked against the channel table whether or not a curve sits on one |
|
|
5625
5718
|
| `A06_ATLAS_PAGE_SIZE_MATCHES_PNG` | both โ | the atlas `size:` disagrees with the PNG on disk โ the message names the ratio it measured on **each** axis and the header that states the same art truthfully, and ยง0.2 has the whole of it ([#715](https://github.com/firejune/rigc/issues/715)): a runtime maps a region as a fraction of the DECLARED size and never reads the texture's own, so such a page draws, and what it breaks is every reader that addresses the page in texels. A uniform ratio is a `size:`/`scale:` pair away from honest and the message prints it; two ratios are not, because `scale:` carries one number, and the message says so rather than offering a header that would not work. **Or** a region's rectangle is not inside the page it names โ rotation honoured, so a region at `rotate: 90` or `270` occupies `height x width` of the page and a region that fits only because it is turned is inside it. The message names the region, the rectangle it occupies, the page and the page's size. That clause is **validity** and runs under both profiles ([#694](https://github.com/firejune/rigc/issues/694)): a rectangle outside its page makes `u2 > 1` and samples whatever the wrap mode returns, and `--atlas-in` already refuses the same rectangle at compile time (ยง0.2). Under `spine-html` also: `pma`, rotation, and two regions on one page over the same texels โ a packed page must be **one part covering it exactly** (the unpacked convention) or a **tiling** ([#266](https://github.com/firejune/rigc/issues/266)), and what that message names is the pair that shares texels. **Or** the page file is not a PNG at all, and then nothing about its size is measured: the message carries the page's path and the size the atlas declares, and names what the file is by its first bytes โ one of WebP, JPEG, GIF, KTX, KTX2 by its signature, or no image format rigc recognises, the bytes in hex either way โ or calls it **truncated** when it begins as a PNG and runs out before its `IEND` (ยง0.2, [#732](https://github.com/firejune/rigc/issues/732)). That clause is validity too: nothing in rigc can read such a page back. **SKIP** when the atlas declares no page ([#580](https://github.com/firejune/rigc/issues/580)) |
|
|
5626
|
-
| `A07_ATLAS_TEXT_SHAPE` | both | atlas text: a region name with stray whitespace, or a blank line splitting a page block. rigc writes the atlas, so this means a hand-edited file. โ ๏ธ An atlas with **no page block at all** โ no non-blank line โ is not one of those: its subject is absent, so this reports **SKIP** naming the byte count it read, and so do the four rules below whose subject is a page ([#608](https://github.com/firejune/rigc/issues/608)). A rig whose skins need no art writes exactly that file (ยง3.4), and before #608 this row refused it with two findings naming a page block that was not there. What an empty atlas does **not** excuse is an attachment that wants a region out of it โ that is `A08` |
|
|
5719
|
+
| `A07_ATLAS_TEXT_SHAPE` | both | atlas text: a region name with stray whitespace, or a blank line splitting a page block. rigc writes the atlas, so this means a hand-edited file. Two sentences are about blank lines and name two different repairs ([#803](https://github.com/firejune/rigc/issues/803)): `line 1: the file begins with a blank line` (or `with N blank lines` for a run, one finding) is a blank before the first page name โ delete it; `line N: consecutive blank lines` is two blank lines side by side after the first page โ delete one. rigc writes neither: under `--atlas-in` the pack's blank lines are put in rigc's shape on re-emission (ยง0.2), so either sentence means a file rigc did not write, handed to `validate`. โ ๏ธ An atlas with **no page block at all** โ no non-blank line โ is not one of those: its subject is absent, so this reports **SKIP** naming the byte count it read, and so do the four rules below whose subject is a page ([#608](https://github.com/firejune/rigc/issues/608)). A rig whose skins need no art writes exactly that file (ยง3.4), and before #608 this row refused it with two findings naming a page block that was not there. What an empty atlas does **not** excuse is an attachment that wants a region out of it โ that is `A08` |
|
|
5627
5720
|
| `A08_REGION_NAMES_MATCH_ATTACHMENTS` | both | three things, and the message says which: an attachment whose `path` names **no region** of this atlas; a `path` carrying **stray whitespace**, printed quoted so you can see it; an **atlas region name** carrying stray whitespace (`A07` names that same line with its line number). The first two are read off the raw file **before** the loader is asked, so the miss is named here with the skin, the slot, the placeholder and the attachment's own name โ the four things `AtlasAttachmentLoader`'s own `Region not found in atlas: <path> (attachment: <name>)` does not carry. Until [#589](https://github.com/firejune/rigc/issues/589) they were unreachable: the loader threw first and the miss arrived as `A00_ROUNDTRIP_PARSE`. There is no `spine-html` clause here any more โ a placeholder is free to differ from the region its `path` names ([#574](https://github.com/firejune/rigc/issues/574)) **SKIP** when no attachment names a region *and* the atlas declares none โ both of its subjects at once ([#580](https://github.com/firejune/rigc/issues/580)) |
|
|
5628
5721
|
| `A09_ANIMATION_DURATION_MATCHES_SPEC` | both | the loaded duration โ the declared one, or the two sides disagree about which animations exist (R7). Asymmetric by design: a frame of slack for an animation that ends early, and none worth the name for a key *past* the declared end, which is the same rule ยง4.5 states at compile time โ held here against a skeleton the compiler never saw. **SKIP** when neither side has an animation at all โ a static rig has no duration |
|
|
5629
5722
|
| `A10_NO_NAN_AFTER_STEPPING` | both | stepping the animation produced a `NaN` pose. Look for a degenerate curve or a zero scale. ๐ฆด **It also poses every bone `inherit` key at its own time** ([#733](https://github.com/firejune/rigc/issues/733)): the runtime resolves a mode by folding the case of its first letter and nothing else, and a spelling that misses is stored as **NaN** โ the world position stays finite, `updateWorldTransform` matches no mode, and the bone keeps the rotation, scale and shear it had. The detail names the animation, the bone, the key's time and its spelling, beside the five. A bone whose *setup* spelling misses poses no mode at all, and is named the same way from the stepping loop. Neither is reachable from a rig spec โ `build` refuses both spellings by name (ยง5.1) โ so on a green build this clause is about files rigc did not write. Which mode a correct spelling poses is not judged here, because the lookup that resolved it is the one that would be checked **SKIP** when the skeleton carries no animation ([#580](https://github.com/firejune/rigc/issues/580)): the NaN is produced by stepping, and a static rig is never stepped โ the same subject `A09` skips on |
|
|
@@ -5639,7 +5732,7 @@ Fix A00 and run it again ([#568](https://github.com/firejune/rigc/issues/568)).
|
|
|
5639
5732
|
| `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)) |
|
|
5640
5733
|
| `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 |
|
|
5641
5734
|
| `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)) |
|
|
5642
|
-
| `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 `
|
|
5735
|
+
| `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] โ the per-step decay is `damping ** (60 * step)`, and the runtime runs this value finitely, so refusing it is rigc's call rather than the runtime's: above 1 every velocity grows on every step and the offset diverges ``, 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; the runtime runs this value finitely, so refusing it is rigc's call rather than the runtime's: at 0 `update` returns before it does anything (`PhysicsConstraint.js:109-111`), so the constraint is muted โ rest it above 0, or key its mix above 0 in an animation ``. โ ๏ธ Every reason A23 prints for a setup value is that value's row `basis` arm (ยง4.4's table, [#798](https://github.com/firejune/rigc/issues/798)) โ an arithmetic arm names its expression (`physics "C" has massInverse Infinity; mass must be > 0 โ at 0 โฆ`), a behavioural one says it is rigc's call and what the value does. A setup `mix` **below** 0 is told the jiggle is applied inverted, not that it is muted: until #798 it read "it is muted", of a constraint measured moving its bone by exactly the opposite of a positive mix (`T115`). 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 |
|
|
5643
5736
|
| `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)) |
|
|
5644
5737
|
| `A25_DETACHED_BONE_PARENTAGE` | archetype | a bone the rig declares `detached` is a descendant of the bone it must never hang under |
|
|
5645
5738
|
| `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 |
|
|
@@ -5700,7 +5793,6 @@ are `CompileError`s, and they name what the format actually defines
|
|
|
5700
5793
|
| attachment `type` of anything else โ `sequence`, a typo | `attachment type "X" is not one of the 7 the Spine 4.3 format defines (region, mesh, linkedmesh, boundingbox, path, point, clipping). โฆ the attachment is dropped from the skeleton without a word` โ a **`CompileError`**, not a deferral: rigc is not going to implement a name the format does not have. (`sequence` is a key on a region or a mesh, not a type of its own.) |
|
|
5701
5794
|
| `"type": null` | `"type" is null, which is not a name. โฆ PRESENT-and-null is not absent: getValue(map, "type", "region") takes the default only when the key is missing, so this map matches no case, readAttachment returns null, and the attachment is dropped from the skeleton without a word. Remove the key, or name a type.` Leaving the key **out** is legal and reads as `region`; writing it as `null` is not the same thing ([#577](https://github.com/firejune/rigc/issues/577)) |
|
|
5702
5795
|
| constraint `type` of anything else | `constraint type "X" is not one Spine 4.3 knows. The five are: ik, transform, path, physics, slider.` โ all five are emitted, so this is a typo, and a typo is what the parser drops in silence |
|
|
5703
|
-
| a path attachment's `lengths` | `"lengths" is not authored โ rigc measures the setup arc length of each curve off the geometry` (ยง3.4). Not a deferral: a second copy of a number the vertices already fix |
|
|
5704
5796
|
| any key neither format has, anywhere in either file | `<object> has a key this compiler does not read: "x" (did you mean "y"?) โฆ Known here: โฆ` (ยง5.1). Not a deferral either: a key nothing reads is a value you wrote and the emitted skeleton does not contain |
|
|
5705
5797
|
|
|
5706
5798
|
Two more limits that are not errors but will shape what you can attempt:
|
|
@@ -8025,8 +8117,10 @@ evidence that the format will carry what you write.
|
|
|
8025
8117
|
so do its `position`, `spacing` and three-channel `mix` timelines โ all three
|
|
8026
8118
|
channels of every `mix` key, and all twelve curve numbers on each key that
|
|
8027
8119
|
carries a curve. โ ๏ธ Its `lengths` did **not**, which is the last bullet โ and
|
|
8028
|
-
since [#560](https://github.com/firejune/rigc/issues/560) they do
|
|
8029
|
-
|
|
8120
|
+
since [#560](https://github.com/firejune/rigc/issues/560) they do on that rig,
|
|
8121
|
+
because rigc emits the computation the editor runs rather than one near it.
|
|
8122
|
+
What they are computed ON is a second question, which the round trip could not
|
|
8123
|
+
ask and #804 did: see the end of this section.
|
|
8030
8124
|
- ๐ฌ **`physics.mix` and `physics.reset` timelines survive**, the `reset` key
|
|
8031
8125
|
included โ a key that carries a time and no value at all โ and so does the
|
|
8032
8126
|
physics constraint's setup `mix`.
|
|
@@ -8079,9 +8173,33 @@ out of the artifact.
|
|
|
8079
8173
|
|
|
8080
8174
|
๐ฌ **And the editor always writes `vertexCount / 3` entries, computing the
|
|
8081
8175
|
wrap-around curve even on an open path** โ that open path's fourth entry,
|
|
8082
|
-
`2136.228`, is the closed-chain cumulative.
|
|
8083
|
-
|
|
8084
|
-
|
|
8176
|
+
`2136.228`, is the closed-chain cumulative. The parser allocates `vertexCount / 3`
|
|
8177
|
+
and copies whatever is there, and `PathConstraint` reads at most
|
|
8178
|
+
`lengths[curveCount]`, so the trailing entry is never read โ and since
|
|
8179
|
+
[#804](https://github.com/firejune/rigc/issues/804) rigc writes it too, measured
|
|
8180
|
+
over the closed chain, so the `gallery/ride` build ends on the same `2136.228`.
|
|
8181
|
+
|
|
8182
|
+
๐จ **"Every digit the editor printed" was true of two rigs and false in
|
|
8183
|
+
production** ([#804](https://github.com/firejune/rigc/issues/804)). Both rigs above
|
|
8184
|
+
are unweighted, unscaled and unconstrained, and the computation is only half of
|
|
8185
|
+
the number โ the other half is the geometry it is fed, and there the editor and
|
|
8186
|
+
rigc differed twice:
|
|
8187
|
+
|
|
8188
|
+
- **Scale.** rigc blended weighted vertices through setup matrices that ignored
|
|
8189
|
+
bone scale, shear and `inherit`: a 50/50-weighted probe path over a bone at
|
|
8190
|
+
scale 2 measured 0.752ร the runtime's own `curves`. The matrices are the
|
|
8191
|
+
runtime's now, and an omitted `lengths` measures within 1e-4 of `curves`
|
|
8192
|
+
(`PS186`).
|
|
8193
|
+
- **Constraints.** The editor measures the pose the first update hands the path
|
|
8194
|
+
constraint, with every constraint ordered before it applied; a transform
|
|
8195
|
+
constraint on the path's slot bone ordered after it moves nothing. rigc does
|
|
8196
|
+
not pose, so it cannot reproduce that โ an omitted `lengths` is the
|
|
8197
|
+
**unconstrained** setup figure (`PS190`), and on a path a constraint moves at
|
|
8198
|
+
rest that is not the editor's number.
|
|
8199
|
+
|
|
8200
|
+
โ **A stated `lengths` is carried as stated**, and `ingest` writes the source's
|
|
8201
|
+
array into the spec, so a rebuilt export is its export on this field. What rigc
|
|
8202
|
+
still measures is an array you left out of a spec you wrote.
|
|
8085
8203
|
|
|
8086
8204
|
โ **What this means for you.** `lengths` is the one number in a path rig you
|
|
8087
8205
|
cannot check by looking: `diff` does not compare it, and `A33` asks only that it
|