rig-play 0.8.0 → 1.1.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/NOTICE.md +50 -23
- package/README.md +511 -456
- package/dist/CanvasRenderer.d.ts +139 -0
- package/dist/CanvasRenderer.d.ts.map +1 -0
- package/dist/{SpineHtmlRenderer.d.ts → DomRenderer.d.ts} +70 -65
- package/dist/DomRenderer.d.ts.map +1 -0
- package/dist/DomTexture.d.ts +34 -14
- package/dist/DomTexture.d.ts.map +1 -1
- package/dist/MeshGlBlitter.d.ts +67 -1
- package/dist/MeshGlBlitter.d.ts.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7470 -5
- package/dist/index.js.map +1 -1
- package/dist/loadModel.d.ts +92 -0
- package/dist/loadModel.d.ts.map +1 -0
- package/dist/player.d.ts +198 -0
- package/dist/player.d.ts.map +1 -0
- package/dist/posedFrame.d.ts +99 -0
- package/dist/posedFrame.d.ts.map +1 -0
- package/package.json +13 -19
- package/dist/DomTexture.js +0 -520
- package/dist/DomTexture.js.map +0 -1
- package/dist/MeshGlBlitter.js +0 -365
- package/dist/MeshGlBlitter.js.map +0 -1
- package/dist/SpineHtmlRenderer.d.ts.map +0 -1
- package/dist/SpineHtmlRenderer.js +0 -1107
- package/dist/SpineHtmlRenderer.js.map +0 -1
- package/dist/binary.d.ts +0 -48
- package/dist/binary.d.ts.map +0 -1
- package/dist/binary.js +0 -29
- package/dist/binary.js.map +0 -1
- package/dist/coreCompat.d.ts +0 -153
- package/dist/coreCompat.d.ts.map +0 -1
- package/dist/coreCompat.js +0 -136
- package/dist/coreCompat.js.map +0 -1
- package/dist/loadAtlasAssets.d.ts +0 -73
- package/dist/loadAtlasAssets.d.ts.map +0 -1
- package/dist/loadAtlasAssets.js +0 -75
- package/dist/loadAtlasAssets.js.map +0 -1
- package/dist/loadSkeletonAssets.d.ts +0 -88
- package/dist/loadSkeletonAssets.d.ts.map +0 -1
- package/dist/loadSkeletonAssets.js +0 -79
- package/dist/loadSkeletonAssets.js.map +0 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type RegionImage } from './DomTexture.js';
|
|
2
|
+
/**
|
|
3
|
+
* Loads a rig built by `rigc build`: the compiled model document
|
|
4
|
+
* (`skeleton.model.json`, spec `rigc-compiled/3`) and the page images its
|
|
5
|
+
* `pages` section names, cut into region bitmaps once.
|
|
6
|
+
*
|
|
7
|
+
* The document states everything the player reads — the skeleton, the
|
|
8
|
+
* animations, and where every region sits on its page — so the `.atlas` and
|
|
9
|
+
* `skeleton.json` the build writes beside it are not fetched. A Spine export
|
|
10
|
+
* (`.json`, `.skel`) is refused by name: this package poses the compiled model
|
|
11
|
+
* through `rig-c/core` and reads nothing else.
|
|
12
|
+
*/
|
|
13
|
+
export interface LoadModelOptions {
|
|
14
|
+
/** URL of the compiled model document (`skeleton.model.json`). */
|
|
15
|
+
modelUrl: string;
|
|
16
|
+
/**
|
|
17
|
+
* Maps a page name from the document's `pages` section to the URL its image
|
|
18
|
+
* lives at. Defaults to resolving the name against the model URL's
|
|
19
|
+
* directory: a build writes page names as paths relative to its own
|
|
20
|
+
* directory, which is where the document sits.
|
|
21
|
+
*/
|
|
22
|
+
resolvePage?: (pageName: string, modelUrl: string) => string;
|
|
23
|
+
/**
|
|
24
|
+
* crossOrigin attribute for the page images. Needed when the images come
|
|
25
|
+
* from another origin: the region cut reads them into a canvas, and a
|
|
26
|
+
* tainted canvas cannot be exported (SecurityError from toBlob).
|
|
27
|
+
*/
|
|
28
|
+
crossOrigin?: string;
|
|
29
|
+
/** fetch implementation, for custom headers or a test double. */
|
|
30
|
+
fetch?: typeof globalThis.fetch;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* What `new RigPlayer(root, assets)` draws from. The caller owns it: one load
|
|
34
|
+
* can back any number of players, and nothing a player does disposes it.
|
|
35
|
+
*/
|
|
36
|
+
export interface ModelAssets {
|
|
37
|
+
/** The document's spec, e.g. `rigc-compiled/3`. */
|
|
38
|
+
readonly spec: string;
|
|
39
|
+
/** Every animation the document carries, in its order, with the runtime's duration. */
|
|
40
|
+
readonly animations: ReadonlyArray<{
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly duration: number;
|
|
43
|
+
}>;
|
|
44
|
+
/** Every skin the document declares, in its order. */
|
|
45
|
+
readonly skins: readonly string[];
|
|
46
|
+
/**
|
|
47
|
+
* The setup pose's box in world units (Y up) as the document states it —
|
|
48
|
+
* the rig's own framing, for laying out a stage — or null where it states
|
|
49
|
+
* none.
|
|
50
|
+
*/
|
|
51
|
+
readonly stage: {
|
|
52
|
+
readonly x: number;
|
|
53
|
+
readonly y: number;
|
|
54
|
+
readonly width: number;
|
|
55
|
+
readonly height: number;
|
|
56
|
+
} | null;
|
|
57
|
+
/** Unpacked per-region bitmaps, keyed by region name — the rigid tier's. */
|
|
58
|
+
readonly regionImages: Map<string, RegionImage>;
|
|
59
|
+
/** Page images, keyed by the document's page names — the mesh tier's. */
|
|
60
|
+
readonly pageImages: Map<string, HTMLImageElement>;
|
|
61
|
+
/**
|
|
62
|
+
* The document as `rig-c/core` read it. Opaque to callers: the player poses
|
|
63
|
+
* it, and its shape is rig-c's, not this package's.
|
|
64
|
+
*/
|
|
65
|
+
readonly document: ModelDocument;
|
|
66
|
+
/**
|
|
67
|
+
* Frees the blob URLs this load created (see revokeRegions). Idempotent.
|
|
68
|
+
* Call it after the players drawing from these assets are disposed — a live
|
|
69
|
+
* <img> would be left pointing at a dead URL.
|
|
70
|
+
*/
|
|
71
|
+
dispose(): void;
|
|
72
|
+
}
|
|
73
|
+
/** The read document, held for the player. Deliberately opaque. */
|
|
74
|
+
export interface ModelDocument {
|
|
75
|
+
readonly spec: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Loads a rig built by `rigc build`.
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* const assets = await loadModel({ modelUrl: '/rigs/walk/skeleton.model.json' });
|
|
82
|
+
* const player = new RigPlayer(root, assets);
|
|
83
|
+
* player.play('walk');
|
|
84
|
+
* // each frame: player.frame(dt)
|
|
85
|
+
* // …later: player.dispose(); assets.dispose();
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* Page images load in parallel. If anything fails part-way, no blob URL is
|
|
89
|
+
* left behind.
|
|
90
|
+
*/
|
|
91
|
+
export declare function loadModel(options: LoadModelOptions): Promise<ModelAssets>;
|
|
92
|
+
//# sourceMappingURL=loadModel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadModel.d.ts","sourceRoot":"","sources":["../src/loadModel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAgC,MAAM,iBAAiB,CAAC;AAEjF;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7D;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzF,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnH,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAChD,yEAAyE;IACzE,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACnD;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC;;;;OAIG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAgED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAqC/E"}
|
package/dist/player.d.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { CanvasRenderer } from './CanvasRenderer.js';
|
|
2
|
+
import { DomRenderer, type MeshBackend } from './DomRenderer.js';
|
|
3
|
+
import type { ModelAssets } from './loadModel.js';
|
|
4
|
+
import { type PosedFrame } from './posedFrame.js';
|
|
5
|
+
/**
|
|
6
|
+
* Plays a rig built by `rigc build` on a DOM root.
|
|
7
|
+
*
|
|
8
|
+
* The player owns the track and the renderer: `play` opens an animation on a
|
|
9
|
+
* live track (`openTrack` from `rig-c/core`), each `frame(dt)` steps it by
|
|
10
|
+
* `dt × timeScale`, turns the pose into a `PosedFrame` and hands that to its
|
|
11
|
+
* renderer — a `DomRenderer` (`mode: 'dom'`, the default) or a
|
|
12
|
+
* `CanvasRenderer` (`mode: 'canvas'`). Everything the pose holds is computed by
|
|
13
|
+
* the core from the compiled model document; this class schedules and draws.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* How a player draws: `'dom'` — elements, the rigid tier as `<img>` and the
|
|
17
|
+
* mesh tier on per-part canvases (`DomRenderer`); `'canvas'` — the whole frame
|
|
18
|
+
* into one `<canvas>` through the shared WebGL context (`CanvasRenderer`).
|
|
19
|
+
*/
|
|
20
|
+
export type RenderMode = 'dom' | 'canvas';
|
|
21
|
+
export interface RigPlayerOptions {
|
|
22
|
+
/**
|
|
23
|
+
* The skin to pose under. Absent is the runtime's "no skin set" — a fresh
|
|
24
|
+
* skeleton whose `setSkin` was never called (`underNoSkin`): no skin's bones
|
|
25
|
+
* or constraints applied, every slot resolved through the default skin.
|
|
26
|
+
*/
|
|
27
|
+
skin?: string;
|
|
28
|
+
/** How the player draws (see `RenderMode`). Default `'dom'`. Can be changed later through `mode`. */
|
|
29
|
+
mode?: RenderMode;
|
|
30
|
+
/** The mesh tier's rasterizer (see `DomRenderer.meshBackend`) — the DOM mode only. */
|
|
31
|
+
meshBackend?: MeshBackend;
|
|
32
|
+
/**
|
|
33
|
+
* The step `seek` walks the track forward with, in seconds. A seek is
|
|
34
|
+
* "reopen, then step to the time", never a jump: a physics rig has history,
|
|
35
|
+
* and the pose at a time depends on the steps taken to reach it.
|
|
36
|
+
*/
|
|
37
|
+
seekStep?: number;
|
|
38
|
+
}
|
|
39
|
+
/** What `on('event', …)` hands a listener: one event key the step crossed. */
|
|
40
|
+
export interface RigEvent {
|
|
41
|
+
name: string;
|
|
42
|
+
/** The key's time in the animation. */
|
|
43
|
+
time: number;
|
|
44
|
+
int: number;
|
|
45
|
+
float: number;
|
|
46
|
+
string: string | null;
|
|
47
|
+
}
|
|
48
|
+
type Listener<T> = (payload: T) => void;
|
|
49
|
+
/**
|
|
50
|
+
* One rig on one root.
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* const player = new RigPlayer(root, assets);
|
|
54
|
+
* player.play('walk');
|
|
55
|
+
* requestAnimationFrame(function tick(now) { player.frame(dt); requestAnimationFrame(tick); });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* Where a bone is in the pose the player holds — world units, Y up, the
|
|
60
|
+
* numbers `rig-c/core` posed (`RawBone`): the world matrix `a b c d`, the
|
|
61
|
+
* world position, the world rotation of each axis in degrees and the world
|
|
62
|
+
* scale of each, and whether the bone is active under the player's skin.
|
|
63
|
+
*/
|
|
64
|
+
export interface BoneWorld {
|
|
65
|
+
name: string;
|
|
66
|
+
active: boolean;
|
|
67
|
+
x: number;
|
|
68
|
+
y: number;
|
|
69
|
+
a: number;
|
|
70
|
+
b: number;
|
|
71
|
+
c: number;
|
|
72
|
+
d: number;
|
|
73
|
+
rotationX: number;
|
|
74
|
+
rotationY: number;
|
|
75
|
+
scaleX: number;
|
|
76
|
+
scaleY: number;
|
|
77
|
+
}
|
|
78
|
+
/** A box in world units, Y up: `y` is the bottom edge. */
|
|
79
|
+
export interface PoseBounds {
|
|
80
|
+
x: number;
|
|
81
|
+
y: number;
|
|
82
|
+
width: number;
|
|
83
|
+
height: number;
|
|
84
|
+
}
|
|
85
|
+
export declare class RigPlayer {
|
|
86
|
+
/**
|
|
87
|
+
* The renderer this player draws through — its knobs and counters are the
|
|
88
|
+
* caller's to read and set. A `DomRenderer` in the DOM mode, a
|
|
89
|
+
* `CanvasRenderer` in the canvas mode; a new object after `mode` changes.
|
|
90
|
+
*/
|
|
91
|
+
get renderer(): DomRenderer | CanvasRenderer;
|
|
92
|
+
/** Multiplies every step. 0 holds the pose (nothing is re-posed); negative is refused by the track. */
|
|
93
|
+
timeScale: number;
|
|
94
|
+
/** The player's whole-rig colour, r g b a — multiplied into every slot's tint. Not a document value. */
|
|
95
|
+
color: [number, number, number, number];
|
|
96
|
+
private active;
|
|
97
|
+
private readonly root;
|
|
98
|
+
private readonly assets;
|
|
99
|
+
private readonly meshBackend;
|
|
100
|
+
private readonly view;
|
|
101
|
+
private readonly source;
|
|
102
|
+
private readonly seekStep;
|
|
103
|
+
private track;
|
|
104
|
+
private animation;
|
|
105
|
+
private loop;
|
|
106
|
+
private paused;
|
|
107
|
+
private pose;
|
|
108
|
+
private setup;
|
|
109
|
+
private readonly listeners;
|
|
110
|
+
constructor(root: HTMLElement, assets: ModelAssets, options?: RigPlayerOptions);
|
|
111
|
+
/**
|
|
112
|
+
* How the player draws. Setting it swaps the renderer without reloading
|
|
113
|
+
* anything: the old one is disposed (its elements removed, its GPU pages
|
|
114
|
+
* handed back), the new one is created over the same root and the same
|
|
115
|
+
* assets, `pixelRatio` and `clipping` carry over, and the pose the player
|
|
116
|
+
* holds is drawn again at once.
|
|
117
|
+
*/
|
|
118
|
+
get mode(): RenderMode;
|
|
119
|
+
set mode(mode: RenderMode);
|
|
120
|
+
private create;
|
|
121
|
+
/** The animation the track is playing, or null before `play`. */
|
|
122
|
+
get current(): string | null;
|
|
123
|
+
/** The track time — the running sum of the steps since `play` (or the last `seek`). */
|
|
124
|
+
get time(): number;
|
|
125
|
+
/**
|
|
126
|
+
* Opens `name` on the track at its first pose, the physics reset there. The
|
|
127
|
+
* pose is drawn on the next `frame`.
|
|
128
|
+
*/
|
|
129
|
+
play(name: string, options?: {
|
|
130
|
+
loop?: boolean;
|
|
131
|
+
}): void;
|
|
132
|
+
/** Stops stepping; `frame` keeps drawing the pose it holds. */
|
|
133
|
+
pause(): void;
|
|
134
|
+
/** Resumes stepping after `pause`. */
|
|
135
|
+
resume(): void;
|
|
136
|
+
/**
|
|
137
|
+
* Moves the track to `time`: the animation is reopened and stepped forward
|
|
138
|
+
* in `seekStep` increments (the last one shorter) until the track time
|
|
139
|
+
* reaches `time`. Events and completes crossed on the way are not fired.
|
|
140
|
+
*/
|
|
141
|
+
seek(time: number): void;
|
|
142
|
+
/** Adds a listener; returns a function that removes it. */
|
|
143
|
+
on(type: 'event', listener: Listener<RigEvent>): () => void;
|
|
144
|
+
on(type: 'complete', listener: Listener<{
|
|
145
|
+
animation: string;
|
|
146
|
+
}>): () => void;
|
|
147
|
+
/**
|
|
148
|
+
* Advances the track by `dt × timeScale` seconds and draws the pose —
|
|
149
|
+
* `advance(dt)` then `draw()`.
|
|
150
|
+
*/
|
|
151
|
+
frame(dt: number): void;
|
|
152
|
+
/**
|
|
153
|
+
* Steps the track by `dt × timeScale` seconds and fires the step's listeners,
|
|
154
|
+
* without drawing. A paused player, or a step of zero, keeps the pose it
|
|
155
|
+
* holds without re-posing it, so a held rig costs the renderer's dirty
|
|
156
|
+
* checks and nothing else.
|
|
157
|
+
*/
|
|
158
|
+
advance(dt: number): void;
|
|
159
|
+
/** Draws the pose the player holds. */
|
|
160
|
+
draw(): void;
|
|
161
|
+
/**
|
|
162
|
+
* Where `name` is in the pose the player holds — the pose of the last
|
|
163
|
+
* `advance`/`frame`/`seek`, or the setup pose before `play`. Read off the
|
|
164
|
+
* core's pose, so it is the same in `dom` and `canvas` mode and costs nothing
|
|
165
|
+
* until called. An unknown bone is refused by name.
|
|
166
|
+
*/
|
|
167
|
+
bone(name: string): BoneWorld;
|
|
168
|
+
/**
|
|
169
|
+
* The box of what the pose the player holds draws, in world units, Y up:
|
|
170
|
+
* every region's four corners and every mesh's vertices, in the same frame
|
|
171
|
+
* record the renderer takes (`posedFrame`). A slot under a clip counts only
|
|
172
|
+
* inside the clip polygon's own box (an inverse clip removes nothing from
|
|
173
|
+
* the count); bounding boxes, paths and points are not drawn and do not
|
|
174
|
+
* count. `null` when nothing draws. The same numbers in `dom` and `canvas`
|
|
175
|
+
* mode; nothing is computed until called.
|
|
176
|
+
*/
|
|
177
|
+
bounds(): PoseBounds | null;
|
|
178
|
+
/** The pose the reads above see: the track's, or the setup pose before `play` (posed once). */
|
|
179
|
+
private posed;
|
|
180
|
+
/** The pose the player holds, as the frame record the renderer draws. */
|
|
181
|
+
posedFrame(): PosedFrame;
|
|
182
|
+
/** Removes the renderer's elements and hands its GPU pages back. The assets stay the caller's. */
|
|
183
|
+
dispose(): void;
|
|
184
|
+
private open;
|
|
185
|
+
/**
|
|
186
|
+
* The step's events, then its complete. The core fires the keys
|
|
187
|
+
* (`pose.events`, in the runtime's order across a wrap) and leaves
|
|
188
|
+
* `complete` to the player, which derives it from the track time and the
|
|
189
|
+
* duration: on a looping track, once on a step whose whole cycles rose past
|
|
190
|
+
* 0 (rig-c `src/core/track.ts`, *Across the wrap*); on a held one, on the
|
|
191
|
+
* step that reaches the duration. The runtime queues a looping complete
|
|
192
|
+
* between the keys before the wrap and the keys after it; this player
|
|
193
|
+
* dispatches it after all of the step's keys.
|
|
194
|
+
*/
|
|
195
|
+
private dispatch;
|
|
196
|
+
}
|
|
197
|
+
export {};
|
|
198
|
+
//# sourceMappingURL=player.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../src/player.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The record the DOM tier draws: one posed moment of a rig, every slot the
|
|
3
|
+
* renderer shows, in draw order.
|
|
4
|
+
*
|
|
5
|
+
* The renderer never needed a skeleton. Per slot it needs the kind, four world
|
|
6
|
+
* corners or world vertices with page UVs and triangles, the bitmap or the
|
|
7
|
+
* page image with its alpha convention, a tint, a blend mode, a clip polygon
|
|
8
|
+
* and a stacking position — and every one of those is a field of a pose that
|
|
9
|
+
* `rig-c/core` computes from the compiled model document, plus that document's
|
|
10
|
+
* `pages` section. This module is the adapter from one to the other
|
|
11
|
+
* (`frameOf`), and these types are the whole of what crosses it.
|
|
12
|
+
*
|
|
13
|
+
* Coordinates are world space, Y up, exactly as the poser computed them; the
|
|
14
|
+
* renderer does the Y flip. Nothing here is rounded or re-ordered.
|
|
15
|
+
*/
|
|
16
|
+
export interface PosedFrame {
|
|
17
|
+
/** Every slot that draws, in draw order. */
|
|
18
|
+
order: PosedSlot[];
|
|
19
|
+
}
|
|
20
|
+
/** The four blend modes, spelled as the runtime's enum names them. */
|
|
21
|
+
export type BlendMode = 'Normal' | 'Additive' | 'Multiply' | 'Screen';
|
|
22
|
+
/**
|
|
23
|
+
* A clip polygon in world space and whether it keeps what is outside it.
|
|
24
|
+
*
|
|
25
|
+
* One object per clip in force: every slot a clip covers carries the *same*
|
|
26
|
+
* object, which is how the renderer tells a clip that covers the whole frame
|
|
27
|
+
* (one `clip-path` on the root) from one that covers a range of it.
|
|
28
|
+
*/
|
|
29
|
+
export interface PosedClip {
|
|
30
|
+
/** Flat x, y pairs, world space. */
|
|
31
|
+
polygon: number[];
|
|
32
|
+
inverse: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* The clipping attachment's `convex` flag: a polygon that is not convex is
|
|
35
|
+
* clipped against its hull rather than decomposed. The DOM tier's CSS
|
|
36
|
+
* `clip-path` takes the polygon as authored and does not read it; the canvas
|
|
37
|
+
* mode's triangle cut does (`clipThrough` in `rig-c/core`).
|
|
38
|
+
*/
|
|
39
|
+
convex: boolean;
|
|
40
|
+
}
|
|
41
|
+
interface PosedSlotCommon {
|
|
42
|
+
/** The slot's name — the renderer keys its element on it. */
|
|
43
|
+
slot: string;
|
|
44
|
+
/** The slot's index in the full draw order (hidden slots included): its z-index. */
|
|
45
|
+
z: number;
|
|
46
|
+
blend: BlendMode;
|
|
47
|
+
/** Slot colour × attachment colour × the player's own colour, r g b a in [0, 1]. */
|
|
48
|
+
tint: [number, number, number, number];
|
|
49
|
+
/** The slot's dark (two-colour) tint, where it carries one. The DOM tier cannot draw it. */
|
|
50
|
+
dark?: [number, number, number];
|
|
51
|
+
/** The clip in force over this slot, where one is. */
|
|
52
|
+
clip?: PosedClip;
|
|
53
|
+
}
|
|
54
|
+
/** A rigid slot: an unpacked region bitmap posed by its four world corners. */
|
|
55
|
+
export interface PosedRegion extends PosedSlotCommon {
|
|
56
|
+
kind: 'region';
|
|
57
|
+
/** The region drawn — the key into the region bitmap map (a sequence frame's own name). */
|
|
58
|
+
region: string;
|
|
59
|
+
/** Four world corners, bottom-left, upper-left, upper-right, bottom-right: x0 y0 … x3 y3. */
|
|
60
|
+
corners: number[];
|
|
61
|
+
/**
|
|
62
|
+
* The page the region sits on — the key into the page image map. The DOM tier
|
|
63
|
+
* draws the region's own bitmap and never reads it; the canvas mode samples
|
|
64
|
+
* the page through `uvs`.
|
|
65
|
+
*/
|
|
66
|
+
page: string;
|
|
67
|
+
/** Whether the page's texels are premultiplied by their alpha. */
|
|
68
|
+
pma: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* The region's page UVs at its four corners, in the corners' order (u, v
|
|
71
|
+
* pairs, the page spanning [0, 1]) — the runtime's region UVs, a 90°-packed
|
|
72
|
+
* region's turn included. The same array object from frame to frame for the
|
|
73
|
+
* same region.
|
|
74
|
+
*/
|
|
75
|
+
uvs: number[];
|
|
76
|
+
}
|
|
77
|
+
/** A deform slot: world vertices over page UVs, rastered from the page image. */
|
|
78
|
+
export interface PosedMesh extends PosedSlotCommon {
|
|
79
|
+
kind: 'mesh';
|
|
80
|
+
/** The page drawn — the key into the page image map. */
|
|
81
|
+
page: string;
|
|
82
|
+
/** Whether the page's texels are premultiplied by their alpha. */
|
|
83
|
+
pma: boolean;
|
|
84
|
+
/** World vertices, flat x, y pairs. */
|
|
85
|
+
vertices: number[];
|
|
86
|
+
/**
|
|
87
|
+
* Page UVs, flat u, v pairs, the page spanning [0, 1]. The same array object
|
|
88
|
+
* from frame to frame for the same region and attachment, so the renderer
|
|
89
|
+
* can tell a mesh whose texture did not change by identity.
|
|
90
|
+
*/
|
|
91
|
+
uvs: number[];
|
|
92
|
+
/** Triangle indices into `vertices`, three per triangle. Stable by identity like `uvs`. */
|
|
93
|
+
triangles: number[];
|
|
94
|
+
/** The sequence frame drawn (0 for an attachment with no series). */
|
|
95
|
+
sequence: number;
|
|
96
|
+
}
|
|
97
|
+
export type PosedSlot = PosedRegion | PosedMesh;
|
|
98
|
+
export {};
|
|
99
|
+
//# sourceMappingURL=posedFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"posedFrame.d.ts","sourceRoot":"","sources":["../src/posedFrame.ts"],"names":[],"mappings":"AAiBA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,sEAAsE;AACtE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,oCAAoC;IACpC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,eAAe;IACvB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,oFAAoF;IACpF,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,SAAS,CAAC;IACjB,oFAAoF;IACpF,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,4FAA4F;IAC5F,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,sDAAsD;IACtD,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,+EAA+E;AAC/E,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,IAAI,EAAE,QAAQ,CAAC;IACf,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,GAAG,EAAE,OAAO,CAAC;IACb;;;;;OAKG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAU,SAAQ,eAAe;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,GAAG,EAAE,OAAO,CAAC;IACb,uCAAuC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,2FAA2F;IAC3F,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rig-play",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Plays skeleton.model.json written by rigc build as plain DOM elements — rigid slots as <img> posed by CSS matrix, deform meshes on small per-part canvases — or as one canvas.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "firejune",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/firejune/
|
|
10
|
+
"url": "https://github.com/firejune/rig-play.git"
|
|
11
11
|
},
|
|
12
|
-
"homepage": "https://github.com/firejune/
|
|
13
|
-
"
|
|
12
|
+
"homepage": "https://github.com/firejune/rig-play#readme",
|
|
13
|
+
"funding": {
|
|
14
|
+
"type": "github",
|
|
15
|
+
"url": "https://github.com/sponsors/firejune"
|
|
16
|
+
},
|
|
17
|
+
"bugs": "https://github.com/firejune/rig-play/issues",
|
|
14
18
|
"keywords": [
|
|
15
|
-
"
|
|
16
|
-
"
|
|
19
|
+
"rigc",
|
|
20
|
+
"rig-c",
|
|
17
21
|
"skeletal-animation",
|
|
18
22
|
"mesh-deformation",
|
|
19
23
|
"dom",
|
|
@@ -29,10 +33,6 @@
|
|
|
29
33
|
".": {
|
|
30
34
|
"types": "./dist/index.d.ts",
|
|
31
35
|
"import": "./dist/index.js"
|
|
32
|
-
},
|
|
33
|
-
"./binary": {
|
|
34
|
-
"types": "./dist/binary.d.ts",
|
|
35
|
-
"import": "./dist/binary.js"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
@@ -45,9 +45,7 @@
|
|
|
45
45
|
"dev": "vite",
|
|
46
46
|
"prebuild": "bash scripts/fetch-assets.sh",
|
|
47
47
|
"build": "tsc --noEmit && vite build",
|
|
48
|
-
"
|
|
49
|
-
"build:pages": "vite build",
|
|
50
|
-
"build:lib": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
48
|
+
"build:lib": "rm -rf dist && node scripts/build-lib.mjs dist",
|
|
51
49
|
"prepublishOnly": "npm run build:lib",
|
|
52
50
|
"preview": "vite preview",
|
|
53
51
|
"test": "playwright test",
|
|
@@ -56,14 +54,10 @@
|
|
|
56
54
|
"bench:build": "bash scripts/fetch-assets.sh && vite build --config bench/vite.config.ts",
|
|
57
55
|
"fetch-assets": "bash scripts/fetch-assets.sh"
|
|
58
56
|
},
|
|
59
|
-
"peerDependencies": {
|
|
60
|
-
"@esotericsoftware/spine-core": ">=4.0.0 <4.4.0"
|
|
61
|
-
},
|
|
62
57
|
"devDependencies": {
|
|
63
|
-
"@esotericsoftware/spine-core": "^4.3.13",
|
|
64
|
-
"@esotericsoftware/spine-webgl": "4.3.13",
|
|
65
58
|
"@playwright/test": "1.62.1",
|
|
66
59
|
"@types/node": "^22",
|
|
60
|
+
"rig-c": "2.35.0",
|
|
67
61
|
"typescript": "^5.6.0",
|
|
68
62
|
"vite": "^6.0.0"
|
|
69
63
|
}
|