spine-rigc 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.ts +82 -43
- package/docs/AUTHORING.md +13 -7
- package/package.json +1 -1
- package/src/atlas.ts +26 -16
- package/src/check.ts +37 -39
- package/src/compile.ts +59 -74
- package/src/core/constraints_path.ts +60 -38
- package/src/core/constraints_physics.ts +22 -4
- package/src/core/index.ts +95 -10
- package/src/core/uvs.ts +25 -5
- package/src/core/world.ts +79 -24
- package/src/deformmeasure.ts +6 -3
- package/src/emit.ts +17 -6
- package/src/ingest.ts +18 -13
- package/src/keyorder.ts +2 -2
- package/src/model.ts +109 -11
- package/src/render.ts +405 -47
- package/src/render_core.ts +115 -18
- package/src/transform.ts +62 -126
- package/src/types.ts +6 -5
- package/src/validate.ts +51 -29
package/src/model.ts
CHANGED
|
@@ -82,10 +82,12 @@
|
|
|
82
82
|
* they are the atlas emitter's constants, and the model does not carry them.
|
|
83
83
|
*
|
|
84
84
|
* 📄 **It is written as a document** (issue #922, cut 1f): `modelDocument` below
|
|
85
|
-
* spells it as `rigc-compiled/1
|
|
86
|
-
* `skeleton.model.json` beside the
|
|
85
|
+
* spells it as `rigc-compiled/2` (`/1` until issue #1016 added `pages`), and
|
|
86
|
+
* `build` writes that text into `--out` as `skeleton.model.json` beside the
|
|
87
|
+
* Spine files, after the gate, like them.
|
|
87
88
|
*/
|
|
88
89
|
import { createHash } from 'node:crypto';
|
|
90
|
+
import { parseAtlasText } from './atlas.ts';
|
|
89
91
|
import { CompileError } from './errors.ts';
|
|
90
92
|
import type { BoneTransform } from './transform.ts';
|
|
91
93
|
import type { RigSkinConstraintKey } from './rig.ts';
|
|
@@ -211,10 +213,12 @@ export interface ModelSequence {
|
|
|
211
213
|
* (#931: the atlas's `rotate` transposed into the corners was exact on 2018 of
|
|
212
214
|
* 3000 probes, ignored on 3000 of 3000). The trim and the original size do not
|
|
213
215
|
* move under either: rigc's packer never trims or rotates (`src/atlas.ts`).
|
|
214
|
-
* The draw, which does need the four — a region's page and page UVs —
|
|
216
|
+
* The draw, which does need the four — a region's page and page UVs — read
|
|
215
217
|
* them off the atlas written beside this document, as a second input
|
|
216
|
-
* (`src/core/uvs.ts`, issue #967)
|
|
217
|
-
*
|
|
218
|
+
* (`src/core/uvs.ts`, issue #967), until issue #1016 gave the document a
|
|
219
|
+
* `pages` section spelled from the atlas text `build` writes (`pagesOfAtlas`
|
|
220
|
+
* below): the four are still not this record's, because they are the written
|
|
221
|
+
* arrangement's, and the section moves with it.
|
|
218
222
|
*/
|
|
219
223
|
export interface ModelAtlasRect {
|
|
220
224
|
width: number;
|
|
@@ -613,11 +617,17 @@ export interface CompiledModel extends CarriedFromCompileResult {
|
|
|
613
617
|
}
|
|
614
618
|
|
|
615
619
|
// ---------------------------------------------------------------------------
|
|
616
|
-
// the document: `rigc-compiled/
|
|
620
|
+
// the document: `rigc-compiled/2` (issue #922, cut 1f; `pages` and `/2`, issue #1016)
|
|
617
621
|
// ---------------------------------------------------------------------------
|
|
618
622
|
|
|
619
|
-
/**
|
|
620
|
-
|
|
623
|
+
/**
|
|
624
|
+
* The document's `spec` value. `/2` since issue #1016 added the `pages`
|
|
625
|
+
* section: a `/1` reader (`readModel` of rigc 1.6) refuses a section it does
|
|
626
|
+
* not know by name, so the same spec over a new section would be refused by
|
|
627
|
+
* every reader already installed rather than read wrongly — a new spec says so
|
|
628
|
+
* before the first section is opened. `readModel` reads both.
|
|
629
|
+
*/
|
|
630
|
+
export const MODEL_DOCUMENT_SPEC = 'rigc-compiled/2';
|
|
621
631
|
|
|
622
632
|
/** The file `build` writes the document to, in `--out` beside `skeleton.json` and `skeleton.atlas`. */
|
|
623
633
|
export const MODEL_DOCUMENT_FILE = 'skeleton.model.json';
|
|
@@ -809,7 +819,7 @@ const MODEL_DOCUMENT_FIELDS: readonly string[] = [
|
|
|
809
819
|
const MODEL_DOCUMENT_LEFT_OUT: readonly string[] = ['setupWorld'];
|
|
810
820
|
|
|
811
821
|
/**
|
|
812
|
-
* The compiled model as a document: `rigc-compiled/
|
|
822
|
+
* The compiled model as a document: `rigc-compiled/2`, `JSON.stringify(doc,
|
|
813
823
|
* null, 2)` and a newline — the text `build` writes to `skeleton.model.json`,
|
|
814
824
|
* and the record rigc's own posing core reads (`readModel` in
|
|
815
825
|
* `src/core/index.ts`, issue #380, step 2). Its cost in a build is measured in
|
|
@@ -820,7 +830,9 @@ const MODEL_DOCUMENT_LEFT_OUT: readonly string[] = ['setupWorld'];
|
|
|
820
830
|
* `constraints`, `events`, `animations` — then the fields carried from `CompileResult` in
|
|
821
831
|
* `CarriedFromCompileResult`'s order: `images`, `pageGrids`, `droppedStates`,
|
|
822
832
|
* `absentParts`, `meshBones`, `meshes`, `physics`, `deformTransforms`,
|
|
823
|
-
* `trackDerivations`, `rig`;
|
|
833
|
+
* `trackDerivations`, `rig`; then `pages`, where each region sits on its page
|
|
834
|
+
* in the atlas written beside it (`pagesOfAtlas`, issue #1016), which is why
|
|
835
|
+
* the atlas text is the third argument; and last `spine`, the digest of the
|
|
824
836
|
* `skeleton.json` written beside it (`spineFileSha256`, issue #968), which is
|
|
825
837
|
* why the Spine text is the second argument. Inside a model record, its interface's field
|
|
826
838
|
* order (`ModelBone`, `ModelSlot`, `ModelSkin`, each attachment kind,
|
|
@@ -894,7 +906,7 @@ const MODEL_DOCUMENT_LEFT_OUT: readonly string[] = ['setupWorld'];
|
|
|
894
906
|
* What the Spine emitter adds (`emitSkeleton`'s header, its spellings, its
|
|
895
907
|
* orders and omissions) is not in the model and so not here.
|
|
896
908
|
*/
|
|
897
|
-
export function modelDocument(model: CompiledModel, skeletonText: string): string {
|
|
909
|
+
export function modelDocument(model: CompiledModel, skeletonText: string, atlasText: string): string {
|
|
898
910
|
for (const key of Object.keys(model)) {
|
|
899
911
|
if (!MODEL_DOCUMENT_FIELDS.includes(key) && !MODEL_DOCUMENT_LEFT_OUT.includes(key)) {
|
|
900
912
|
throw new CompileError(`internal: the model document has no place for the model's field "${key}"; it writes [${MODEL_DOCUMENT_FIELDS.join(', ')}] and leaves out [${MODEL_DOCUMENT_LEFT_OUT.join(', ')}]`);
|
|
@@ -921,11 +933,97 @@ export function modelDocument(model: CompiledModel, skeletonText: string): strin
|
|
|
921
933
|
deformTransforms: plain(model.deformTransforms, 'deformTransforms'),
|
|
922
934
|
trackDerivations: plain(model.trackDerivations, 'trackDerivations'),
|
|
923
935
|
rig: plain(model.rig, 'rig'),
|
|
936
|
+
pages: plain(pagesOfAtlas(atlasText), 'pages'),
|
|
924
937
|
spine: { sha256: spineFileSha256(skeletonText) },
|
|
925
938
|
};
|
|
926
939
|
return `${JSON.stringify(doc, null, 2)}\n`;
|
|
927
940
|
}
|
|
928
941
|
|
|
942
|
+
// --- #1016 where each region sits on its page: begin ---
|
|
943
|
+
/**
|
|
944
|
+
* One region of a page, as the document's `pages` section states it: the
|
|
945
|
+
* region's name exactly as the atlas line spells it (untrimmed — the core finds
|
|
946
|
+
* a region by that spelling, `./core/uvs.ts`), its rectangle's top-left `x`,
|
|
947
|
+
* `y` on the page (y down) and `width`, `height` in the drawing's orientation,
|
|
948
|
+
* the trim (`offsetX` from the drawing's left, `offsetY` from its bottom) and
|
|
949
|
+
* the untrimmed size, its turn in `degrees`, and its `index:` field — every
|
|
950
|
+
* number in the page's texels, exactly as `parseAtlasText` reads it.
|
|
951
|
+
*/
|
|
952
|
+
export interface ModelPageRegion {
|
|
953
|
+
name: string;
|
|
954
|
+
x: number;
|
|
955
|
+
y: number;
|
|
956
|
+
width: number;
|
|
957
|
+
height: number;
|
|
958
|
+
offsetX: number;
|
|
959
|
+
offsetY: number;
|
|
960
|
+
originalWidth: number;
|
|
961
|
+
originalHeight: number;
|
|
962
|
+
degrees: number;
|
|
963
|
+
index: number;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/** One page: its name (a path from the directory `build` writes into, trimmed), its `size`, and its regions in file order. */
|
|
967
|
+
export interface ModelPage {
|
|
968
|
+
name: string;
|
|
969
|
+
width: number;
|
|
970
|
+
height: number;
|
|
971
|
+
regions: ModelPageRegion[];
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/** The fields of a page and of a region, in the order the document writes them — `readModel` mirrors both lists. */
|
|
975
|
+
export const MODEL_PAGE_FIELDS = ['name', 'width', 'height', 'regions'] as const;
|
|
976
|
+
export const MODEL_PAGE_REGION_FIELDS = ['name', 'x', 'y', 'width', 'height', 'offsetX', 'offsetY', 'originalWidth', 'originalHeight', 'degrees', 'index'] as const;
|
|
977
|
+
|
|
978
|
+
/**
|
|
979
|
+
* The document's `pages` section (issue #1016): every page of `atlasText` and
|
|
980
|
+
* every region on it, in file order, with the numbers the draw reads — where
|
|
981
|
+
* each drawing sits, which `./core/uvs.ts` turns into page UVs. `atlasText`
|
|
982
|
+
* is the atlas `build` writes beside the document, the one that run's gate
|
|
983
|
+
* last read: after `--pack` the packed text, after `--copy-images` the text
|
|
984
|
+
* with the copies' page names.
|
|
985
|
+
*
|
|
986
|
+
* ⭐ **Why it is a function of the written atlas rather than a model field.**
|
|
987
|
+
* Issue #939 left the page, `x`, `y` and `rotate` out of `ModelAtlasRect`
|
|
988
|
+
* because `--pack` moves them after `compile` returns and `--copy-images`
|
|
989
|
+
* renames every page — a value the model held from `compile` would state a
|
|
990
|
+
* place the written atlas does not have. The section is spelled from the
|
|
991
|
+
* atlas text instead, so it moves exactly when that text does, and `build`
|
|
992
|
+
* spells the document from the text it writes (`cli.ts`): the document a pack
|
|
993
|
+
* writes is spelled from the packed text and gated by the packed pass, where
|
|
994
|
+
* `A18` compares it with a second compile's document spelled from a second,
|
|
995
|
+
* independent pack.
|
|
996
|
+
*
|
|
997
|
+
* 🔸 **What it leaves out.** The page's `format`, `filter`, `repeat`, `pma`
|
|
998
|
+
* and `scale:` lines: nothing that draws reads them (the rasteriser samples
|
|
999
|
+
* one way, `src/render.ts`'s header; the pose reads only the ratios the
|
|
1000
|
+
* trimmed and original sizes make, #939's decision 2). Every region of every
|
|
1001
|
+
* page is written, drawn or not: which regions a rig draws is the core's
|
|
1002
|
+
* lookup rule (`./core/uvs.ts`, *Which region, on which page*), and a writer
|
|
1003
|
+
* choosing a subset would restate it.
|
|
1004
|
+
*/
|
|
1005
|
+
export function pagesOfAtlas(atlasText: string): ModelPage[] {
|
|
1006
|
+
return parseAtlasText(atlasText).pages.map((page) => ({
|
|
1007
|
+
name: page.name,
|
|
1008
|
+
width: page.width,
|
|
1009
|
+
height: page.height,
|
|
1010
|
+
regions: page.regions.map((r) => ({
|
|
1011
|
+
name: r.name,
|
|
1012
|
+
x: r.x,
|
|
1013
|
+
y: r.y,
|
|
1014
|
+
width: r.width,
|
|
1015
|
+
height: r.height,
|
|
1016
|
+
offsetX: r.offsetX,
|
|
1017
|
+
offsetY: r.offsetY,
|
|
1018
|
+
originalWidth: r.originalWidth,
|
|
1019
|
+
originalHeight: r.originalHeight,
|
|
1020
|
+
degrees: r.degrees,
|
|
1021
|
+
index: r.index,
|
|
1022
|
+
})),
|
|
1023
|
+
}));
|
|
1024
|
+
}
|
|
1025
|
+
// --- #1016 where each region sits on its page: end ---
|
|
1026
|
+
|
|
929
1027
|
// --- #968 the Spine file the document was written beside: begin ---
|
|
930
1028
|
/**
|
|
931
1029
|
* The document's last section, `spine`: `{ "sha256": "<64 lowercase hex>" }`,
|