spine-html 0.1.0 → 0.3.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/README.md +110 -12
- package/dist/MeshGlBlitter.d.ts +69 -0
- package/dist/MeshGlBlitter.d.ts.map +1 -0
- package/dist/MeshGlBlitter.js +265 -0
- package/dist/MeshGlBlitter.js.map +1 -0
- package/dist/SpineHtmlRenderer.d.ts +54 -6
- package/dist/SpineHtmlRenderer.d.ts.map +1 -1
- package/dist/SpineHtmlRenderer.js +241 -33
- package/dist/SpineHtmlRenderer.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/banner.svg" alt="spine-html - DOM-first Spine 2D runtime" width="100%" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/spine-html"><img src="https://img.shields.io/npm/v/spine-html.svg?style=flat-square&color=FF6B4A" alt="npm version" /></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/spine-html"><img src="https://img.shields.io/npm/dm/spine-html.svg?style=flat-square&color=EC4899" alt="npm downloads" /></a>
|
|
8
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-38BDF8.svg?style=flat-square" alt="license" /></a>
|
|
9
|
+
</p>
|
|
2
10
|
|
|
3
11
|
Render [Spine](https://esotericsoftware.com/) skeletal animations as **plain DOM** — one
|
|
4
12
|
absolutely-positioned `<img>` per slot, posed with a single CSS `matrix()` write per frame.
|
|
@@ -17,16 +25,43 @@ The idea has been floated on the official forum three times since 2014 and was n
|
|
|
17
25
|
built — the blockers named were meshes, clipping, and DOM update overhead. This project
|
|
18
26
|
is the experiment: how far does the DOM actually go, and how cheap is it?
|
|
19
27
|
|
|
20
|
-
Measured so far (PoC,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
Measured so far (PoC, Apple silicon — headless and on-device numbers are labeled,
|
|
29
|
+
they do **not** substitute for each other):
|
|
30
|
+
|
|
31
|
+
- Rigid only (spineboy-ess), headless Chromium: 10 skeletons / 180 slot images at
|
|
32
|
+
**~0.03 ms skeleton math + ~0.22 ms DOM writes per frame** — about 1.5% of a
|
|
33
|
+
60 fps frame budget. On-device Safari: 10 rigid skeletons hold **60 fps**.
|
|
34
|
+
- With meshes (spineboy-pro), headless Chromium: 1 skeleton = **~0.05 ms + ~0.5 ms
|
|
35
|
+
render** (8 mesh canvases, 323 triangles); 10 running skeletons = **~3.5 ms/frame**
|
|
36
|
+
total, smooth.
|
|
37
|
+
- Dirty-skip: 10 *static* skeletons (pose held) = **~0.4 ms/frame** headless and
|
|
38
|
+
**~0.6 ms** on-device Safari — unchanged meshes reuse their raster, so idle or
|
|
39
|
+
held parts cost nothing anywhere.
|
|
40
|
+
- Real Safari (on-device), canvas2d mesh backend: in-callback JS stays **~4–5
|
|
41
|
+
ms/frame** for 10 running meshed skeletons — but the rAF rate tells the real
|
|
42
|
+
story: **meshed ×1 = 37 fps, meshed ×10 = 3–4 fps** (rigid-only ×10 = 60 fps).
|
|
43
|
+
The cost lives outside the frame callback, in the compositor/GPU process:
|
|
44
|
+
Safari antialiases canvas2d **clip paths**, so every triangle pays for an AA
|
|
45
|
+
mask. Chromium doesn't antialias clips and stays smooth. This is what the
|
|
46
|
+
optional WebGL mesh backend (below) removes.
|
|
47
|
+
- Real Safari (on-device), **webgl mesh backend**: meshed ×1 holds **60 fps**
|
|
48
|
+
(vs 37 on canvas2d), and the meshed ×10 stress scene jumps **3–4 → 45 fps** —
|
|
49
|
+
80 mesh canvases / 3230 triangles redrawn every frame (0 reused, the worst
|
|
50
|
+
case), in-callback JS ~5.8 ms at dpr=1. The per-triangle clip-AA tax is gone;
|
|
51
|
+
the remaining gap to 60 is the blit/compositing cost of a 10-skeleton stress
|
|
52
|
+
scene, not a per-triangle cost.
|
|
53
|
+
- Headless-WebKit numbers are a **software rasterizer** and measured up to 28×
|
|
54
|
+
off real Safari in both directions — useful for visual regression only, never
|
|
55
|
+
as Safari perf evidence.
|
|
26
56
|
|
|
27
57
|
## Status
|
|
28
58
|
|
|
29
|
-
**
|
|
59
|
+
**Production.** The questions this started as a PoC to answer — how far does the
|
|
60
|
+
DOM actually go, and how cheap is it — are answered with on-device numbers: the
|
|
61
|
+
practical scenario (a character or two, mostly holding pose, a few parts
|
|
62
|
+
deforming) holds **60 fps on every engine measured**, and the 10-skeleton
|
|
63
|
+
stress scene holds 45 fps on the weakest one (Safari, webgl backend). Ships
|
|
64
|
+
with a self-contained test suite (backend visual parity + invariants) and CI.
|
|
30
65
|
|
|
31
66
|
- ✅ Region attachments (rigid parts): exact affine mapping, draw-order via `z-index`,
|
|
32
67
|
attachment swaps, alpha
|
|
@@ -40,12 +75,37 @@ Measured so far (PoC, Chromium on Apple silicon):
|
|
|
40
75
|
clip polygon is expanded 0.5px from its centroid so neighbours overlap — the
|
|
41
76
|
texture is continuous across shared edges, so the overlap is invisible
|
|
42
77
|
(`?expand=0` shows the cracks for comparison)
|
|
78
|
+
- ✅ RGB tinting (skeleton × slot × attachment color) via an SVG `feColorMatrix`
|
|
79
|
+
reference filter per element — an exact channel multiply that works identically on
|
|
80
|
+
`<img>` and `<canvas>` without touching the raster (needs reference-filter support,
|
|
81
|
+
Safari 15+; verified pixel-level on Chromium and WebKit). Dark/two-color tint is
|
|
82
|
+
not expressible this way and stays out of scope
|
|
83
|
+
- ✅ DPR-aware mesh canvas backing store: `renderer.pixelRatio` (defaults to
|
|
84
|
+
`devicePixelRatio`; if you scale the root element, fold that scale in)
|
|
85
|
+
- ✅ Dirty-skip: a mesh whose canvas-space vertices didn't change reuses last frame's
|
|
86
|
+
raster — the CSS translate still tracks it, so parts that hold a pose (or move by
|
|
87
|
+
whole pixels) pay zero raster. 10 frozen spineboys: WebKit ~141 → ~0.5 ms/frame
|
|
43
88
|
- ⬜ Clipping — deliberately unsupported (counted and skipped); layered transparent
|
|
44
89
|
parts + `overflow: hidden` cover the practical cases
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
90
|
+
- ✅ Safari mesh cost root-caused by on-device triangulation (two corrections deep):
|
|
91
|
+
the early "~15× slower per-triangle path" was a **headless-WebKit artifact**
|
|
92
|
+
(software rasterization), and the follow-up "on par with Chromium" held only for
|
|
93
|
+
in-callback JS time. Real-Safari rAF rates — rigid ×10 = 60 fps, meshed ×1 =
|
|
94
|
+
37 fps, meshed ×10 = 3–4 fps with JS flat at ~4–5 ms — put the real cost in the
|
|
95
|
+
GPU process: Safari antialiases canvas2d **clip paths**, so the per-triangle clip
|
|
96
|
+
mapping pays a per-triangle AA-mask tax (the same AA that caused the seam cracks)
|
|
97
|
+
- ✅ Optional WebGL blit backend for the mesh tier: `renderer.meshBackend =
|
|
98
|
+
'webgl'` (default stays `'canvas2d'`). All dirty meshes are shelf-packed into
|
|
99
|
+
**one shared offscreen WebGL context** (module-level — browsers cap contexts at
|
|
100
|
+
~16), drawn as textured triangles with premultiplied alpha, then rect-blitted
|
|
101
|
+
onto the same per-part canvases with an unclipped `drawImage` — cheap on Safari.
|
|
102
|
+
Everything element-level is unchanged: z-index interleave, tint filter,
|
|
103
|
+
`mix-blend-mode`, dirty-skip, grow-only backing. GL rasterizes shared triangle
|
|
104
|
+
edges seamlessly, so this path needs no crack overdraw. Falls back to canvas2d
|
|
105
|
+
when WebGL is unavailable or the context is lost. Backend parity verified by
|
|
106
|
+
headless Chromium+WebKit screenshot diffs (glow / clipping / tint scenes;
|
|
107
|
+
sub-pixel edge differences only). On-device Safari, meshed ×10 with every mesh
|
|
108
|
+
redrawn per frame: **3–4 fps (canvas2d) → 45 fps (webgl)**
|
|
49
109
|
|
|
50
110
|
## Install
|
|
51
111
|
|
|
@@ -75,6 +135,13 @@ const skeleton = new Skeleton(data);
|
|
|
75
135
|
const state = new AnimationState(new AnimationStateData(data));
|
|
76
136
|
state.setAnimation(0, 'walk', true);
|
|
77
137
|
const renderer = new SpineHtmlRenderer(rootElement, regionImages);
|
|
138
|
+
// Mesh canvases raster at devicePixelRatio by default; if you scale the
|
|
139
|
+
// root element, fold that scale in so the raster matches the screen:
|
|
140
|
+
// renderer.pixelRatio = devicePixelRatio * rootScale;
|
|
141
|
+
// Mesh rasterizer: 'canvas2d' (default) or 'webgl' — same output, but on
|
|
142
|
+
// Safari heavy deforming scenes should use 'webgl' (see Measured above).
|
|
143
|
+
// Falls back to canvas2d automatically when WebGL is unavailable.
|
|
144
|
+
// renderer.meshBackend = 'webgl';
|
|
78
145
|
|
|
79
146
|
function frame(delta: number) {
|
|
80
147
|
state.update(delta);
|
|
@@ -99,6 +166,37 @@ The official spineboy example assets are downloaded automatically on first `dev`
|
|
|
99
166
|
(they are owned by Esoteric Software and not redistributed in this repository — see
|
|
100
167
|
[NOTICE.md](NOTICE.md)); `bun run fetch-assets` runs the same idempotent step manually.
|
|
101
168
|
|
|
169
|
+
Debug knobs (query string): `?skel=pro|ess` `?anim=walk` `?count=10` pick the scene,
|
|
170
|
+
`?tint=ff8080` tints the whole skeleton, `?dpr=2` overrides the mesh-canvas backing
|
|
171
|
+
ratio, `?timescale=0` freezes the pose (every mesh should report "reused"),
|
|
172
|
+
`?expand=0` disables the crack-closing clip overdraw, `?backend=webgl` rasterizes
|
|
173
|
+
meshes through the shared WebGL blitter (also a live header select; the stats line
|
|
174
|
+
names the active backend), and `?time=1.2` seeks every instance to the same pose
|
|
175
|
+
for deterministic captures.
|
|
176
|
+
|
|
177
|
+
## Tests
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
bun run test # builds + serves the demo, then runs chromium + webkit
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Playwright drives the demo (`tests/`, config in `playwright.config.ts`; CI
|
|
184
|
+
runs the same suite on ubuntu). The visual check is **A/B within one run**:
|
|
185
|
+
no golden snapshots are committed (they rot across platforms/GPUs) — instead
|
|
186
|
+
the same deterministic pose (`?time` + `?timescale=0`) is screenshotted with
|
|
187
|
+
`?backend=canvas2d` and `?backend=webgl` in the same engine and the buffers
|
|
188
|
+
are diffed directly with a shift-tolerant comparison, so missing parts,
|
|
189
|
+
wrong colors, and tint/blend divergence fail regardless of platform.
|
|
190
|
+
Hairline seams are guarded by a deterministic canary (`?expand=0` must
|
|
191
|
+
change the canvas2d raster), and counter tests pin the dirty-skip /
|
|
192
|
+
grow-only-backing / clip-skip invariants plus spine-core's region corner
|
|
193
|
+
order (BL, UL, UR, BR).
|
|
194
|
+
|
|
195
|
+
Standing rule: **headless numbers are never Safari performance evidence** —
|
|
196
|
+
nothing in the suite asserts timing, and headless-WebKit fps/ms readings do
|
|
197
|
+
not transfer (software rasterizer, measured up to 28× off real Safari). The
|
|
198
|
+
perf oracle is the demo's stats line on a real device.
|
|
199
|
+
|
|
102
200
|
## How it works
|
|
103
201
|
|
|
104
202
|
1. `@esotericsoftware/spine-core` loads the skeleton and drives `AnimationState`,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared offscreen WebGL rasterizer for the mesh (deform) tier.
|
|
3
|
+
*
|
|
4
|
+
* One module-level context serves every renderer instance: browsers cap live
|
|
5
|
+
* WebGL contexts (16 on Chrome/Safari) and a page can hold many renderers, so
|
|
6
|
+
* per-renderer contexts would evict each other. Per flush, every dirty mesh is
|
|
7
|
+
* shelf-packed into a rect of the offscreen canvas, its triangles are drawn
|
|
8
|
+
* textured (atlas page texture, premultiplied alpha), and each rect is blitted
|
|
9
|
+
* onto the mesh's per-part 2d canvas with an unclipped drawImage rect copy.
|
|
10
|
+
*
|
|
11
|
+
* Why this exists: Safari antialiases canvas2d clip paths, so the standard
|
|
12
|
+
* per-triangle clip+transform+drawImage mapping pays a per-triangle AA-mask
|
|
13
|
+
* cost in the GPU process — invisible to in-callback JS timing, but it
|
|
14
|
+
* rAF-limits heavy scenes. GL rasterizes shared triangle edges seamlessly
|
|
15
|
+
* (no clip, no crack overdraw needed), and the remaining canvas2d work is a
|
|
16
|
+
* plain rect blit.
|
|
17
|
+
*
|
|
18
|
+
* The offscreen buffer is scratch space: rects are scissor-cleared and
|
|
19
|
+
* redrawn every flush and read back in the same task, so neither
|
|
20
|
+
* preserveDrawingBuffer nor cross-frame content is relied on. The buffer
|
|
21
|
+
* grows quantized and never shrinks, mirroring the per-part backing policy
|
|
22
|
+
* (reallocating GPU surfaces per frame is a Safari killer).
|
|
23
|
+
*/
|
|
24
|
+
export interface MeshBlitJob {
|
|
25
|
+
/** Destination per-part canvas; the blit clears its full backing first. */
|
|
26
|
+
canvas: HTMLCanvasElement;
|
|
27
|
+
/** Atlas page image the mesh samples (cached as a GL texture on first use). */
|
|
28
|
+
page: HTMLImageElement;
|
|
29
|
+
/** Bbox-relative vertices in CSS px, x/y interleaved (indexed via `triangles`). */
|
|
30
|
+
vertices: Float64Array;
|
|
31
|
+
/** Normalized page UVs aligned with `vertices`. */
|
|
32
|
+
uvs: ArrayLike<number>;
|
|
33
|
+
/** Triangle index list into vertex/UV pairs. */
|
|
34
|
+
triangles: ArrayLike<number>;
|
|
35
|
+
/** Backing-store pixels per CSS px. */
|
|
36
|
+
ratio: number;
|
|
37
|
+
/** Rasterized region in device px — the packed rect and the blit both use it. */
|
|
38
|
+
width: number;
|
|
39
|
+
height: number;
|
|
40
|
+
}
|
|
41
|
+
declare class MeshGlBlitter {
|
|
42
|
+
lost: boolean;
|
|
43
|
+
private readonly canvas;
|
|
44
|
+
private readonly gl;
|
|
45
|
+
private readonly uResolution;
|
|
46
|
+
private readonly textures;
|
|
47
|
+
private readonly maxSize;
|
|
48
|
+
private vertexData;
|
|
49
|
+
/** Per-job packed rect origins, filled by flush(). */
|
|
50
|
+
private packX;
|
|
51
|
+
private packY;
|
|
52
|
+
constructor();
|
|
53
|
+
/**
|
|
54
|
+
* Rasterize every job into the offscreen buffer, then blit each rect onto
|
|
55
|
+
* its per-part canvas. Returns false when the context is lost (or the jobs
|
|
56
|
+
* cannot fit) so the caller can rasterize the batch on the canvas2d path.
|
|
57
|
+
*/
|
|
58
|
+
flush(jobs: MeshBlitJob[]): boolean;
|
|
59
|
+
private compile;
|
|
60
|
+
private textureFor;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The module-level blitter, created on first use. Returns null when WebGL is
|
|
64
|
+
* unavailable or the shared context has been lost — callers then stay on the
|
|
65
|
+
* canvas2d path.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getMeshGlBlitter(): MeshGlBlitter | null;
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=MeshGlBlitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeshGlBlitter.d.ts","sourceRoot":"","sources":["../src/MeshGlBlitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,MAAM,EAAE,iBAAiB,CAAC;IAC1B,+EAA+E;IAC/E,IAAI,EAAE,gBAAgB,CAAC;IACvB,mFAAmF;IACnF,QAAQ,EAAE,YAAY,CAAC;IACvB,mDAAmD;IACnD,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACvB,gDAAgD;IAChD,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7B,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AA4BD,cAAM,aAAa;IACjB,IAAI,UAAS;IAEb,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAC3D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAwB;IAC3C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,UAAU,CAA0B;IAC5C,sDAAsD;IACtD,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,KAAK,CAAgB;;IAoD7B;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO;IAwGnC,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,UAAU;CAmBnB;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CASvD"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared offscreen WebGL rasterizer for the mesh (deform) tier.
|
|
3
|
+
*
|
|
4
|
+
* One module-level context serves every renderer instance: browsers cap live
|
|
5
|
+
* WebGL contexts (16 on Chrome/Safari) and a page can hold many renderers, so
|
|
6
|
+
* per-renderer contexts would evict each other. Per flush, every dirty mesh is
|
|
7
|
+
* shelf-packed into a rect of the offscreen canvas, its triangles are drawn
|
|
8
|
+
* textured (atlas page texture, premultiplied alpha), and each rect is blitted
|
|
9
|
+
* onto the mesh's per-part 2d canvas with an unclipped drawImage rect copy.
|
|
10
|
+
*
|
|
11
|
+
* Why this exists: Safari antialiases canvas2d clip paths, so the standard
|
|
12
|
+
* per-triangle clip+transform+drawImage mapping pays a per-triangle AA-mask
|
|
13
|
+
* cost in the GPU process — invisible to in-callback JS timing, but it
|
|
14
|
+
* rAF-limits heavy scenes. GL rasterizes shared triangle edges seamlessly
|
|
15
|
+
* (no clip, no crack overdraw needed), and the remaining canvas2d work is a
|
|
16
|
+
* plain rect blit.
|
|
17
|
+
*
|
|
18
|
+
* The offscreen buffer is scratch space: rects are scissor-cleared and
|
|
19
|
+
* redrawn every flush and read back in the same task, so neither
|
|
20
|
+
* preserveDrawingBuffer nor cross-frame content is relied on. The buffer
|
|
21
|
+
* grows quantized and never shrinks, mirroring the per-part backing policy
|
|
22
|
+
* (reallocating GPU surfaces per frame is a Safari killer).
|
|
23
|
+
*/
|
|
24
|
+
const VERTEX_SHADER = `
|
|
25
|
+
attribute vec2 aPos;
|
|
26
|
+
attribute vec2 aUV;
|
|
27
|
+
uniform vec2 uResolution;
|
|
28
|
+
varying vec2 vUV;
|
|
29
|
+
void main() {
|
|
30
|
+
// aPos is in offscreen-canvas device px, top-left origin (matching the
|
|
31
|
+
// top-left-origin drawImage read of the same rect).
|
|
32
|
+
vec2 clip = aPos / uResolution * 2.0 - 1.0;
|
|
33
|
+
gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);
|
|
34
|
+
vUV = aUV;
|
|
35
|
+
}`;
|
|
36
|
+
const FRAGMENT_SHADER = `
|
|
37
|
+
precision mediump float;
|
|
38
|
+
uniform sampler2D uTex;
|
|
39
|
+
varying vec2 vUV;
|
|
40
|
+
void main() {
|
|
41
|
+
gl_FragColor = texture2D(uTex, vUV);
|
|
42
|
+
}`;
|
|
43
|
+
/** Gap between packed rects; blits are 1:1 unfiltered, so 1px is plenty. */
|
|
44
|
+
const GUTTER = 1;
|
|
45
|
+
/** Drawing-buffer growth quantum (device px). */
|
|
46
|
+
const GROW_STEP = 256;
|
|
47
|
+
class MeshGlBlitter {
|
|
48
|
+
lost = false;
|
|
49
|
+
canvas = document.createElement('canvas');
|
|
50
|
+
gl;
|
|
51
|
+
uResolution;
|
|
52
|
+
textures = new Map();
|
|
53
|
+
maxSize;
|
|
54
|
+
vertexData = new Float32Array(8192);
|
|
55
|
+
/** Per-job packed rect origins, filled by flush(). */
|
|
56
|
+
packX = [];
|
|
57
|
+
packY = [];
|
|
58
|
+
constructor() {
|
|
59
|
+
const gl = this.canvas.getContext('webgl', {
|
|
60
|
+
alpha: true,
|
|
61
|
+
premultipliedAlpha: true,
|
|
62
|
+
antialias: false,
|
|
63
|
+
depth: false,
|
|
64
|
+
stencil: false,
|
|
65
|
+
preserveDrawingBuffer: false,
|
|
66
|
+
});
|
|
67
|
+
if (!gl)
|
|
68
|
+
throw new Error('WebGL unavailable');
|
|
69
|
+
this.gl = gl;
|
|
70
|
+
// No restore attempt: on loss the renderer falls back to canvas2d and the
|
|
71
|
+
// backend signature re-dirties every mesh, so frames stay complete.
|
|
72
|
+
this.canvas.addEventListener('webglcontextlost', () => {
|
|
73
|
+
this.lost = true;
|
|
74
|
+
});
|
|
75
|
+
const program = gl.createProgram();
|
|
76
|
+
if (!program)
|
|
77
|
+
throw new Error('createProgram failed');
|
|
78
|
+
gl.attachShader(program, this.compile(gl.VERTEX_SHADER, VERTEX_SHADER));
|
|
79
|
+
gl.attachShader(program, this.compile(gl.FRAGMENT_SHADER, FRAGMENT_SHADER));
|
|
80
|
+
gl.linkProgram(program);
|
|
81
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
82
|
+
throw new Error(`program link failed: ${gl.getProgramInfoLog(program)}`);
|
|
83
|
+
}
|
|
84
|
+
gl.useProgram(program);
|
|
85
|
+
const uResolution = gl.getUniformLocation(program, 'uResolution');
|
|
86
|
+
if (!uResolution)
|
|
87
|
+
throw new Error('uResolution not found');
|
|
88
|
+
this.uResolution = uResolution;
|
|
89
|
+
gl.uniform1i(gl.getUniformLocation(program, 'uTex'), 0);
|
|
90
|
+
// Static state: this context does exactly one thing, set it up once.
|
|
91
|
+
// Interleaved [x, y, u, v] vertices in a single dynamic buffer.
|
|
92
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
|
93
|
+
const aPos = gl.getAttribLocation(program, 'aPos');
|
|
94
|
+
const aUV = gl.getAttribLocation(program, 'aUV');
|
|
95
|
+
gl.enableVertexAttribArray(aPos);
|
|
96
|
+
gl.enableVertexAttribArray(aUV);
|
|
97
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
98
|
+
gl.vertexAttribPointer(aUV, 2, gl.FLOAT, false, 16, 8);
|
|
99
|
+
// Premultiplied source-over, matching canvas2d triangle compositing.
|
|
100
|
+
gl.enable(gl.BLEND);
|
|
101
|
+
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
102
|
+
gl.enable(gl.SCISSOR_TEST);
|
|
103
|
+
gl.clearColor(0, 0, 0, 0);
|
|
104
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
105
|
+
this.maxSize = Math.min(gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) || 4096, 8192);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Rasterize every job into the offscreen buffer, then blit each rect onto
|
|
109
|
+
* its per-part canvas. Returns false when the context is lost (or the jobs
|
|
110
|
+
* cannot fit) so the caller can rasterize the batch on the canvas2d path.
|
|
111
|
+
*/
|
|
112
|
+
flush(jobs) {
|
|
113
|
+
const gl = this.gl;
|
|
114
|
+
if (this.lost || gl.isContextLost())
|
|
115
|
+
return false;
|
|
116
|
+
// Shelf-pack, tallest first (indices keep job order for the draw pass).
|
|
117
|
+
let width = Math.max(512, this.canvas.width);
|
|
118
|
+
for (const job of jobs)
|
|
119
|
+
width = Math.max(width, job.width + GUTTER * 2);
|
|
120
|
+
if (width > this.maxSize)
|
|
121
|
+
return false;
|
|
122
|
+
const order = jobs.map((_, i) => i).sort((a, b) => jobs[b].height - jobs[a].height);
|
|
123
|
+
const packX = (this.packX = new Array(jobs.length));
|
|
124
|
+
const packY = (this.packY = new Array(jobs.length));
|
|
125
|
+
let shelfX = GUTTER;
|
|
126
|
+
let shelfY = GUTTER;
|
|
127
|
+
let shelfH = 0;
|
|
128
|
+
let height = GUTTER;
|
|
129
|
+
for (const i of order) {
|
|
130
|
+
const job = jobs[i];
|
|
131
|
+
if (shelfX + job.width + GUTTER > width) {
|
|
132
|
+
shelfY += shelfH + GUTTER;
|
|
133
|
+
shelfX = GUTTER;
|
|
134
|
+
shelfH = 0;
|
|
135
|
+
}
|
|
136
|
+
packX[i] = shelfX;
|
|
137
|
+
packY[i] = shelfY;
|
|
138
|
+
shelfX += job.width + GUTTER;
|
|
139
|
+
if (job.height > shelfH)
|
|
140
|
+
shelfH = job.height;
|
|
141
|
+
if (shelfY + job.height + GUTTER > height)
|
|
142
|
+
height = shelfY + job.height + GUTTER;
|
|
143
|
+
}
|
|
144
|
+
if (height > this.maxSize)
|
|
145
|
+
return false;
|
|
146
|
+
// Grow-only quantized drawing buffer. Resizing clears it, which is fine:
|
|
147
|
+
// every rect below is cleared and redrawn anyway.
|
|
148
|
+
if (width > this.canvas.width || height > this.canvas.height) {
|
|
149
|
+
this.canvas.width = Math.min(this.maxSize, Math.ceil(width / GROW_STEP) * GROW_STEP);
|
|
150
|
+
this.canvas.height = Math.min(this.maxSize, Math.ceil(Math.max(height, this.canvas.height) / GROW_STEP) * GROW_STEP);
|
|
151
|
+
}
|
|
152
|
+
const bufW = this.canvas.width;
|
|
153
|
+
const bufH = this.canvas.height;
|
|
154
|
+
gl.viewport(0, 0, bufW, bufH);
|
|
155
|
+
gl.uniform2f(this.uResolution, bufW, bufH);
|
|
156
|
+
// Build one interleaved vertex array for the whole batch (unindexed —
|
|
157
|
+
// meshes are a few hundred triangles, expansion is cheaper than managing
|
|
158
|
+
// index buffers).
|
|
159
|
+
let floats = 0;
|
|
160
|
+
for (const job of jobs)
|
|
161
|
+
floats += job.triangles.length * 4;
|
|
162
|
+
if (this.vertexData.length < floats) {
|
|
163
|
+
this.vertexData = new Float32Array(1 << Math.ceil(Math.log2(floats)));
|
|
164
|
+
}
|
|
165
|
+
const data = this.vertexData;
|
|
166
|
+
let f = 0;
|
|
167
|
+
for (let i = 0; i < jobs.length; i++) {
|
|
168
|
+
const { vertices, uvs, triangles, ratio } = jobs[i];
|
|
169
|
+
const ox = packX[i];
|
|
170
|
+
const oy = packY[i];
|
|
171
|
+
for (let t = 0; t < triangles.length; t++) {
|
|
172
|
+
const vi = triangles[t] * 2;
|
|
173
|
+
data[f++] = ox + vertices[vi] * ratio;
|
|
174
|
+
data[f++] = oy + vertices[vi + 1] * ratio;
|
|
175
|
+
data[f++] = uvs[vi];
|
|
176
|
+
data[f++] = uvs[vi + 1];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
gl.bufferData(gl.ARRAY_BUFFER, data.subarray(0, floats), gl.DYNAMIC_DRAW);
|
|
180
|
+
let boundPage = null;
|
|
181
|
+
let first = 0;
|
|
182
|
+
for (let i = 0; i < jobs.length; i++) {
|
|
183
|
+
const job = jobs[i];
|
|
184
|
+
if (job.page !== boundPage) {
|
|
185
|
+
gl.bindTexture(gl.TEXTURE_2D, this.textureFor(job.page));
|
|
186
|
+
boundPage = job.page;
|
|
187
|
+
}
|
|
188
|
+
// Scissor is bottom-left origin; pack coords are top-left origin.
|
|
189
|
+
gl.scissor(packX[i], bufH - packY[i] - job.height, job.width, job.height);
|
|
190
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
191
|
+
gl.drawArrays(gl.TRIANGLES, first, job.triangles.length);
|
|
192
|
+
first += job.triangles.length;
|
|
193
|
+
}
|
|
194
|
+
// If the context died mid-batch the draws above were no-ops; report it
|
|
195
|
+
// before blitting stale/blank rects onto the part canvases.
|
|
196
|
+
if (gl.isContextLost()) {
|
|
197
|
+
this.lost = true;
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
// Blit each rect onto its per-part canvas: same-task read (no
|
|
201
|
+
// preserveDrawingBuffer needed), 1:1 device px (no filtering).
|
|
202
|
+
for (let i = 0; i < jobs.length; i++) {
|
|
203
|
+
const job = jobs[i];
|
|
204
|
+
const ctx = job.canvas.getContext('2d');
|
|
205
|
+
if (!ctx)
|
|
206
|
+
continue;
|
|
207
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
208
|
+
// Clear the full backing: the previous raster may have been larger.
|
|
209
|
+
ctx.clearRect(0, 0, job.canvas.width, job.canvas.height);
|
|
210
|
+
ctx.drawImage(this.canvas, packX[i], packY[i], job.width, job.height, 0, 0, job.width, job.height);
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
compile(type, source) {
|
|
215
|
+
const gl = this.gl;
|
|
216
|
+
const shader = gl.createShader(type);
|
|
217
|
+
if (!shader)
|
|
218
|
+
throw new Error('createShader failed');
|
|
219
|
+
gl.shaderSource(shader, source);
|
|
220
|
+
gl.compileShader(shader);
|
|
221
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
222
|
+
throw new Error(`shader compile failed: ${gl.getShaderInfoLog(shader)}`);
|
|
223
|
+
}
|
|
224
|
+
return shader;
|
|
225
|
+
}
|
|
226
|
+
textureFor(page) {
|
|
227
|
+
let texture = this.textures.get(page);
|
|
228
|
+
if (texture)
|
|
229
|
+
return texture;
|
|
230
|
+
const gl = this.gl;
|
|
231
|
+
texture = gl.createTexture();
|
|
232
|
+
if (!texture)
|
|
233
|
+
throw new Error('createTexture failed');
|
|
234
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
235
|
+
// Premultiply at upload so blending and the premultiplied canvas agree.
|
|
236
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
|
|
237
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
|
|
238
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, page);
|
|
239
|
+
// Linear, no mips, clamped — NPOT-safe in WebGL1.
|
|
240
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
241
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
242
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
243
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
244
|
+
this.textures.set(page, texture);
|
|
245
|
+
return texture;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
let shared;
|
|
249
|
+
/**
|
|
250
|
+
* The module-level blitter, created on first use. Returns null when WebGL is
|
|
251
|
+
* unavailable or the shared context has been lost — callers then stay on the
|
|
252
|
+
* canvas2d path.
|
|
253
|
+
*/
|
|
254
|
+
export function getMeshGlBlitter() {
|
|
255
|
+
if (shared === undefined) {
|
|
256
|
+
try {
|
|
257
|
+
shared = new MeshGlBlitter();
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
shared = null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return shared && !shared.lost ? shared : null;
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=MeshGlBlitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeshGlBlitter.js","sourceRoot":"","sources":["../src/MeshGlBlitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type Skeleton } from '@esotericsoftware/spine-core';
|
|
2
2
|
import type { RegionImage } from './DomTexture';
|
|
3
|
+
/** Rasterizer used for the mesh (deform) tier. */
|
|
4
|
+
export type MeshBackend = 'canvas2d' | 'webgl';
|
|
3
5
|
/**
|
|
4
6
|
* Renders a spine-core Skeleton as DOM, split by slot type:
|
|
5
7
|
*
|
|
@@ -7,13 +9,20 @@ import type { RegionImage } from './DomTexture';
|
|
|
7
9
|
* posed with a single CSS matrix() write per frame — exact, since bone
|
|
8
10
|
* transforms are affine.
|
|
9
11
|
* - Mesh attachments (deform parts) each get a small per-part <canvas> sized
|
|
10
|
-
* to the mesh's world bounding box, redrawn per frame with the
|
|
11
|
-
* per-triangle clip+transform+drawImage mapping
|
|
12
|
+
* to the mesh's world bounding box, redrawn per frame — either with the
|
|
13
|
+
* standard per-triangle clip+transform+drawImage mapping (default), or via
|
|
14
|
+
* a shared offscreen WebGL canvas that rect-blits into the same per-part
|
|
15
|
+
* canvases (meshBackend = 'webgl'). Frames where the canvas-space vertices
|
|
16
|
+
* are unchanged reuse the previous raster on both backends.
|
|
12
17
|
*
|
|
13
18
|
* Both element kinds share one stacking context, so draw order interleaves
|
|
14
19
|
* freely via z-index (rear hair canvas < torso img < front hair canvas).
|
|
15
|
-
*
|
|
16
|
-
*
|
|
20
|
+
* RGB tint (skeleton × slot × attachment color) is applied per element with
|
|
21
|
+
* an SVG feColorMatrix reference filter — exact channel multiply, works the
|
|
22
|
+
* same on <img> and <canvas>. Dark (two-color) tint is not expressible that
|
|
23
|
+
* way and is unsupported. Clipping attachments are deliberately unsupported
|
|
24
|
+
* (transparent layered parts make them unnecessary); they are counted in
|
|
25
|
+
* clipSkipCount.
|
|
17
26
|
*
|
|
18
27
|
* Coordinate mapping: Spine is Y-up, CSS is Y-down — world Y is negated.
|
|
19
28
|
* spine-core computes everything (bones, constraints, physics, deformed
|
|
@@ -24,8 +33,16 @@ export declare class SpineHtmlRenderer {
|
|
|
24
33
|
private readonly regionImages;
|
|
25
34
|
/** Clipping attachments encountered (visible but unsupported). */
|
|
26
35
|
clipSkipCount: number;
|
|
27
|
-
/** Mesh canvases
|
|
36
|
+
/** Mesh canvases rasterized last frame. */
|
|
28
37
|
meshCount: number;
|
|
38
|
+
/** Mesh canvases that reused their previous raster last frame. */
|
|
39
|
+
meshReuseCount: number;
|
|
40
|
+
/**
|
|
41
|
+
* Mesh canvas backing stores (re)allocated last frame. Should drop to zero
|
|
42
|
+
* once an animation reaches its steady state; a persistent nonzero value
|
|
43
|
+
* means GPU surfaces are being recreated per frame (a Safari killer).
|
|
44
|
+
*/
|
|
45
|
+
canvasReallocCount: number;
|
|
29
46
|
/** Triangles rasterized last frame. */
|
|
30
47
|
triangleCount: number;
|
|
31
48
|
/**
|
|
@@ -34,8 +51,35 @@ export declare class SpineHtmlRenderer {
|
|
|
34
51
|
* set to 0 to see them.
|
|
35
52
|
*/
|
|
36
53
|
triangleExpand: number;
|
|
54
|
+
/**
|
|
55
|
+
* Mesh-canvas backing-store pixels per CSS pixel. Defaults to the device
|
|
56
|
+
* pixel ratio. If the caller scales the root element, fold that scale in
|
|
57
|
+
* (e.g. devicePixelRatio * rootScale) so the raster matches the on-screen
|
|
58
|
+
* resolution instead of over- or under-sampling.
|
|
59
|
+
*/
|
|
60
|
+
pixelRatio: number;
|
|
61
|
+
/**
|
|
62
|
+
* Rasterizer for the mesh (deform) tier. 'canvas2d' (default) maps each
|
|
63
|
+
* triangle with clip+transform+drawImage directly on the per-part canvas.
|
|
64
|
+
* 'webgl' rasterizes every dirty mesh into one shared offscreen WebGL
|
|
65
|
+
* canvas and rect-blits each mesh back onto its per-part canvas — the DOM
|
|
66
|
+
* structure and all element-level behavior (z-index interleave, tint
|
|
67
|
+
* filter, mix-blend-mode, dirty-skip) are identical, only the raster step
|
|
68
|
+
* changes. Motivation: Safari antialiases canvas2d clip paths, so the
|
|
69
|
+
* per-triangle clip mapping pays a per-triangle AA-mask cost in the GPU
|
|
70
|
+
* process that rAF-limits heavy scenes; GL rasterizes shared edges
|
|
71
|
+
* seamlessly (no clip, no crack overdraw) and the blit is an unclipped
|
|
72
|
+
* rect copy. Falls back to 'canvas2d' when WebGL is unavailable or the
|
|
73
|
+
* shared context is lost — see meshBackendActive.
|
|
74
|
+
*/
|
|
75
|
+
meshBackend: MeshBackend;
|
|
76
|
+
/** Backend that actually rasterized the mesh tier during the last render(). */
|
|
77
|
+
meshBackendActive: MeshBackend;
|
|
37
78
|
private readonly views;
|
|
38
|
-
private
|
|
79
|
+
private readonly pendingJobs;
|
|
80
|
+
private readonly pendingViews;
|
|
81
|
+
private scratchVertices;
|
|
82
|
+
private tintDefs;
|
|
39
83
|
/**
|
|
40
84
|
* @param root Positioned element (e.g. position:absolute) that becomes the
|
|
41
85
|
* skeleton origin. The renderer only appends slot elements to it — layout
|
|
@@ -47,6 +91,8 @@ export declare class SpineHtmlRenderer {
|
|
|
47
91
|
dispose(): void;
|
|
48
92
|
private renderRegion;
|
|
49
93
|
private renderMesh;
|
|
94
|
+
/** The canvas2d raster path: clear the backing, map each triangle. */
|
|
95
|
+
private rasterizeMesh2d;
|
|
50
96
|
/**
|
|
51
97
|
* Standard canvas triangle texture mapping (same math as the official
|
|
52
98
|
* spine-canvas renderer): derive the affine that sends the triangle's
|
|
@@ -60,7 +106,9 @@ export declare class SpineHtmlRenderer {
|
|
|
60
106
|
* with no visible cost. The texture-mapping affine itself stays exact.
|
|
61
107
|
*/
|
|
62
108
|
private drawTriangle;
|
|
109
|
+
private setTransform;
|
|
63
110
|
private applyCommon;
|
|
111
|
+
private tintMatrixFor;
|
|
64
112
|
private view;
|
|
65
113
|
private hide;
|
|
66
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpineHtmlRenderer.d.ts","sourceRoot":"","sources":["../src/SpineHtmlRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,QAAQ,EAId,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"SpineHtmlRenderer.d.ts","sourceRoot":"","sources":["../src/SpineHtmlRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,QAAQ,EAId,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,kDAAkD;AAClD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC;AAiE/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,iBAAiB;IA2D1B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,YAAY;IA3D/B,kEAAkE;IAClE,aAAa,SAAK;IAClB,2CAA2C;IAC3C,SAAS,SAAK;IACd,kEAAkE;IAClE,cAAc,SAAK;IACnB;;;;OAIG;IACH,kBAAkB,SAAK;IACvB,uCAAuC;IACvC,aAAa,SAAK;IAClB;;;;OAIG;IACH,cAAc,SAAO;IACrB;;;;;OAKG;IACH,UAAU,SAA+D;IACzE;;;;;;;;;;;;;OAaG;IACH,WAAW,EAAE,WAAW,CAAc;IACtC,+EAA+E;IAC/E,iBAAiB,EAAE,WAAW,CAAc;IAE5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IACnD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAA8B;IAE9C;;;;;OAKG;gBAEgB,IAAI,EAAE,WAAW,EACjB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC;IAGzD,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IA4ChC,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,YAAY;IA8CpB,OAAO,CAAC,UAAU;IAsIlB,sEAAsE;IACtE,OAAO,CAAC,eAAe;IA+BvB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,YAAY;IAwCpB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAmDnB,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,IAAI;IA+CZ,OAAO,CAAC,IAAI;CAOb"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { BlendMode, ClippingAttachment, MeshAttachment, RegionAttachment, } from '@esotericsoftware/spine-core';
|
|
2
|
+
import { getMeshGlBlitter } from './MeshGlBlitter';
|
|
2
3
|
const regionVertices = new Float32Array(8);
|
|
4
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
5
|
+
/** Unique tint-filter ids across renderer instances (ids are document-global). */
|
|
6
|
+
let tintFilterSeq = 0;
|
|
3
7
|
/** Push a point away from (cx, cy) by `amount` pixels. */
|
|
4
8
|
function expandPoint(x, y, cx, cy, amount) {
|
|
5
9
|
const dx = x - cx;
|
|
@@ -23,13 +27,20 @@ const BLEND_CSS = {
|
|
|
23
27
|
* posed with a single CSS matrix() write per frame — exact, since bone
|
|
24
28
|
* transforms are affine.
|
|
25
29
|
* - Mesh attachments (deform parts) each get a small per-part <canvas> sized
|
|
26
|
-
* to the mesh's world bounding box, redrawn per frame with the
|
|
27
|
-
* per-triangle clip+transform+drawImage mapping
|
|
30
|
+
* to the mesh's world bounding box, redrawn per frame — either with the
|
|
31
|
+
* standard per-triangle clip+transform+drawImage mapping (default), or via
|
|
32
|
+
* a shared offscreen WebGL canvas that rect-blits into the same per-part
|
|
33
|
+
* canvases (meshBackend = 'webgl'). Frames where the canvas-space vertices
|
|
34
|
+
* are unchanged reuse the previous raster on both backends.
|
|
28
35
|
*
|
|
29
36
|
* Both element kinds share one stacking context, so draw order interleaves
|
|
30
37
|
* freely via z-index (rear hair canvas < torso img < front hair canvas).
|
|
31
|
-
*
|
|
32
|
-
*
|
|
38
|
+
* RGB tint (skeleton × slot × attachment color) is applied per element with
|
|
39
|
+
* an SVG feColorMatrix reference filter — exact channel multiply, works the
|
|
40
|
+
* same on <img> and <canvas>. Dark (two-color) tint is not expressible that
|
|
41
|
+
* way and is unsupported. Clipping attachments are deliberately unsupported
|
|
42
|
+
* (transparent layered parts make them unnecessary); they are counted in
|
|
43
|
+
* clipSkipCount.
|
|
33
44
|
*
|
|
34
45
|
* Coordinate mapping: Spine is Y-up, CSS is Y-down — world Y is negated.
|
|
35
46
|
* spine-core computes everything (bones, constraints, physics, deformed
|
|
@@ -40,8 +51,16 @@ export class SpineHtmlRenderer {
|
|
|
40
51
|
regionImages;
|
|
41
52
|
/** Clipping attachments encountered (visible but unsupported). */
|
|
42
53
|
clipSkipCount = 0;
|
|
43
|
-
/** Mesh canvases
|
|
54
|
+
/** Mesh canvases rasterized last frame. */
|
|
44
55
|
meshCount = 0;
|
|
56
|
+
/** Mesh canvases that reused their previous raster last frame. */
|
|
57
|
+
meshReuseCount = 0;
|
|
58
|
+
/**
|
|
59
|
+
* Mesh canvas backing stores (re)allocated last frame. Should drop to zero
|
|
60
|
+
* once an animation reaches its steady state; a persistent nonzero value
|
|
61
|
+
* means GPU surfaces are being recreated per frame (a Safari killer).
|
|
62
|
+
*/
|
|
63
|
+
canvasReallocCount = 0;
|
|
45
64
|
/** Triangles rasterized last frame. */
|
|
46
65
|
triangleCount = 0;
|
|
47
66
|
/**
|
|
@@ -50,8 +69,35 @@ export class SpineHtmlRenderer {
|
|
|
50
69
|
* set to 0 to see them.
|
|
51
70
|
*/
|
|
52
71
|
triangleExpand = 0.5;
|
|
72
|
+
/**
|
|
73
|
+
* Mesh-canvas backing-store pixels per CSS pixel. Defaults to the device
|
|
74
|
+
* pixel ratio. If the caller scales the root element, fold that scale in
|
|
75
|
+
* (e.g. devicePixelRatio * rootScale) so the raster matches the on-screen
|
|
76
|
+
* resolution instead of over- or under-sampling.
|
|
77
|
+
*/
|
|
78
|
+
pixelRatio = typeof devicePixelRatio === 'number' ? devicePixelRatio : 1;
|
|
79
|
+
/**
|
|
80
|
+
* Rasterizer for the mesh (deform) tier. 'canvas2d' (default) maps each
|
|
81
|
+
* triangle with clip+transform+drawImage directly on the per-part canvas.
|
|
82
|
+
* 'webgl' rasterizes every dirty mesh into one shared offscreen WebGL
|
|
83
|
+
* canvas and rect-blits each mesh back onto its per-part canvas — the DOM
|
|
84
|
+
* structure and all element-level behavior (z-index interleave, tint
|
|
85
|
+
* filter, mix-blend-mode, dirty-skip) are identical, only the raster step
|
|
86
|
+
* changes. Motivation: Safari antialiases canvas2d clip paths, so the
|
|
87
|
+
* per-triangle clip mapping pays a per-triangle AA-mask cost in the GPU
|
|
88
|
+
* process that rAF-limits heavy scenes; GL rasterizes shared edges
|
|
89
|
+
* seamlessly (no clip, no crack overdraw) and the blit is an unclipped
|
|
90
|
+
* rect copy. Falls back to 'canvas2d' when WebGL is unavailable or the
|
|
91
|
+
* shared context is lost — see meshBackendActive.
|
|
92
|
+
*/
|
|
93
|
+
meshBackend = 'canvas2d';
|
|
94
|
+
/** Backend that actually rasterized the mesh tier during the last render(). */
|
|
95
|
+
meshBackendActive = 'canvas2d';
|
|
53
96
|
views = new Map();
|
|
54
|
-
|
|
97
|
+
pendingJobs = [];
|
|
98
|
+
pendingViews = [];
|
|
99
|
+
scratchVertices = new Float32Array(256);
|
|
100
|
+
tintDefs = null;
|
|
55
101
|
/**
|
|
56
102
|
* @param root Positioned element (e.g. position:absolute) that becomes the
|
|
57
103
|
* skeleton origin. The renderer only appends slot elements to it — layout
|
|
@@ -65,9 +111,12 @@ export class SpineHtmlRenderer {
|
|
|
65
111
|
render(skeleton) {
|
|
66
112
|
this.clipSkipCount = 0;
|
|
67
113
|
this.meshCount = 0;
|
|
114
|
+
this.meshReuseCount = 0;
|
|
115
|
+
this.canvasReallocCount = 0;
|
|
68
116
|
this.triangleCount = 0;
|
|
117
|
+
const blitter = this.meshBackend === 'webgl' ? getMeshGlBlitter() : null;
|
|
118
|
+
this.meshBackendActive = blitter ? 'webgl' : 'canvas2d';
|
|
69
119
|
const drawOrder = skeleton.drawOrder.appliedPose;
|
|
70
|
-
const skeletonAlpha = skeleton.color.a;
|
|
71
120
|
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
|
72
121
|
const slot = drawOrder[i];
|
|
73
122
|
const pose = slot.appliedPose;
|
|
@@ -77,10 +126,10 @@ export class SpineHtmlRenderer {
|
|
|
77
126
|
continue;
|
|
78
127
|
}
|
|
79
128
|
if (attachment instanceof RegionAttachment) {
|
|
80
|
-
this.renderRegion(slot, pose, attachment, i
|
|
129
|
+
this.renderRegion(skeleton, slot, pose, attachment, i);
|
|
81
130
|
}
|
|
82
131
|
else if (attachment instanceof MeshAttachment) {
|
|
83
|
-
this.renderMesh(skeleton, slot, pose, attachment, i
|
|
132
|
+
this.renderMesh(skeleton, slot, pose, attachment, i);
|
|
84
133
|
}
|
|
85
134
|
else {
|
|
86
135
|
if (attachment instanceof ClippingAttachment)
|
|
@@ -88,14 +137,29 @@ export class SpineHtmlRenderer {
|
|
|
88
137
|
this.hide(slot);
|
|
89
138
|
}
|
|
90
139
|
}
|
|
140
|
+
if (this.pendingJobs.length) {
|
|
141
|
+
if (!blitter || !blitter.flush(this.pendingJobs)) {
|
|
142
|
+
// Context lost mid-frame: rasterize this batch on the 2d path so the
|
|
143
|
+
// frame stays complete; the next render() re-selects the backend.
|
|
144
|
+
for (let i = 0; i < this.pendingJobs.length; i++) {
|
|
145
|
+
const job = this.pendingJobs[i];
|
|
146
|
+
this.pendingViews[i].meshBackendDrawn = 'canvas2d';
|
|
147
|
+
this.rasterizeMesh2d(job.canvas, job.page, job.vertices, job.uvs, job.triangles, job.ratio);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
this.pendingJobs.length = 0;
|
|
151
|
+
this.pendingViews.length = 0;
|
|
152
|
+
}
|
|
91
153
|
}
|
|
92
154
|
dispose() {
|
|
93
155
|
for (const view of this.views.values())
|
|
94
156
|
view.el.remove();
|
|
95
157
|
this.views.clear();
|
|
158
|
+
this.tintDefs?.remove();
|
|
159
|
+
this.tintDefs = null;
|
|
96
160
|
}
|
|
97
161
|
// --- rigid tier -----------------------------------------------------------
|
|
98
|
-
renderRegion(slot, pose, attachment, zIndex
|
|
162
|
+
renderRegion(skeleton, slot, pose, attachment, zIndex) {
|
|
99
163
|
const sequence = attachment.sequence;
|
|
100
164
|
const region = sequence.regions[sequence.resolveIndex(pose)];
|
|
101
165
|
const regionImage = region && this.regionImages.get(region.name);
|
|
@@ -125,11 +189,11 @@ export class SpineHtmlRenderer {
|
|
|
125
189
|
const b = (ury - uly) / w;
|
|
126
190
|
const c = (blx - ulx) / h;
|
|
127
191
|
const d = (bly - uly) / h;
|
|
128
|
-
|
|
129
|
-
this.applyCommon(view, slot,
|
|
192
|
+
this.setTransform(view, `matrix(${a},${b},${c},${d},${ulx},${uly})`);
|
|
193
|
+
this.applyCommon(view, slot, pose, attachment.color, skeleton, zIndex);
|
|
130
194
|
}
|
|
131
195
|
// --- deform tier ----------------------------------------------------------
|
|
132
|
-
renderMesh(skeleton, slot, pose, attachment, zIndex
|
|
196
|
+
renderMesh(skeleton, slot, pose, attachment, zIndex) {
|
|
133
197
|
const sequence = attachment.sequence;
|
|
134
198
|
const sequenceIndex = sequence.resolveIndex(pose);
|
|
135
199
|
const region = sequence.regions[sequenceIndex];
|
|
@@ -139,9 +203,9 @@ export class SpineHtmlRenderer {
|
|
|
139
203
|
return;
|
|
140
204
|
}
|
|
141
205
|
const count = attachment.worldVerticesLength;
|
|
142
|
-
if (this.
|
|
143
|
-
this.
|
|
144
|
-
const vertices = this.
|
|
206
|
+
if (this.scratchVertices.length < count)
|
|
207
|
+
this.scratchVertices = new Float32Array(count);
|
|
208
|
+
const vertices = this.scratchVertices;
|
|
145
209
|
attachment.computeWorldVertices(skeleton, slot, 0, count, vertices, 0, 2);
|
|
146
210
|
// World bounds (in CSS coords: Y negated).
|
|
147
211
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
@@ -169,32 +233,110 @@ export class SpineHtmlRenderer {
|
|
|
169
233
|
}
|
|
170
234
|
const view = this.view(slot, 'canvas');
|
|
171
235
|
const canvas = view.el;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
view.
|
|
176
|
-
view.
|
|
177
|
-
|
|
178
|
-
|
|
236
|
+
const ratio = this.pixelRatio;
|
|
237
|
+
let dirty = view.meshAttachment !== attachment ||
|
|
238
|
+
view.meshSequenceIndex !== sequenceIndex ||
|
|
239
|
+
view.meshExpand !== this.triangleExpand ||
|
|
240
|
+
view.meshVertexCount !== count ||
|
|
241
|
+
view.meshBackendDrawn !== this.meshBackendActive;
|
|
242
|
+
// The backing store only grows, in 32-device-px steps. Setting
|
|
243
|
+
// canvas.width recreates the GPU surface, and a deforming mesh changes
|
|
244
|
+
// its bbox every frame — reallocating every mesh canvas per frame
|
|
245
|
+
// stalled real Safari to ~3 fps while the JS split showed ~4 ms (the
|
|
246
|
+
// cost lives in the compositor, invisible to in-callback timing). With
|
|
247
|
+
// grow-only quantized backing, steady-state animation reallocates
|
|
248
|
+
// nothing. The CSS size mirrors the whole backing so the pixel mapping
|
|
249
|
+
// stays 1:1; the mesh draws into the top-left w×h logical region and
|
|
250
|
+
// the rest stays transparent.
|
|
251
|
+
const needW = Math.max(1, Math.round(w * ratio));
|
|
252
|
+
const needH = Math.max(1, Math.round(h * ratio));
|
|
253
|
+
if (needW > view.canvasW || needH > view.canvasH || view.meshRatio !== ratio) {
|
|
254
|
+
// 25% slack: at low fps the animation is sampled sparsely, so new bbox
|
|
255
|
+
// maxima keep being discovered for many seconds — allocate ahead of the
|
|
256
|
+
// curve instead of chasing it.
|
|
257
|
+
const step = 32;
|
|
258
|
+
view.canvasW = Math.ceil(Math.max(needW * 1.25, view.canvasW) / step) * step;
|
|
259
|
+
view.canvasH = Math.ceil(Math.max(needH * 1.25, view.canvasH) / step) * step;
|
|
260
|
+
view.meshRatio = ratio;
|
|
261
|
+
canvas.width = view.canvasW;
|
|
262
|
+
canvas.height = view.canvasH;
|
|
263
|
+
canvas.style.width = `${view.canvasW / ratio}px`;
|
|
264
|
+
canvas.style.height = `${view.canvasH / ratio}px`;
|
|
265
|
+
this.canvasReallocCount++;
|
|
266
|
+
dirty = true;
|
|
267
|
+
}
|
|
268
|
+
// Canvas-space vertices: identical values mean last frame's raster is
|
|
269
|
+
// still exact (static pose, or the part moved by whole pixels), so the
|
|
270
|
+
// per-triangle redraw can be skipped — the CSS translate below keeps
|
|
271
|
+
// tracking the part. This is the main WebKit cost lever: idle skeletons
|
|
272
|
+
// stop paying the raster entirely.
|
|
273
|
+
if (view.meshVertices.length < count) {
|
|
274
|
+
view.meshVertices = new Float64Array(count);
|
|
275
|
+
dirty = true;
|
|
276
|
+
}
|
|
277
|
+
const rel = view.meshVertices;
|
|
278
|
+
for (let v = 0; v < count; v += 2) {
|
|
279
|
+
const x = vertices[v] - minX;
|
|
280
|
+
const y = vertices[v + 1] - minY;
|
|
281
|
+
if (rel[v] !== x || rel[v + 1] !== y)
|
|
282
|
+
dirty = true;
|
|
283
|
+
rel[v] = x;
|
|
284
|
+
rel[v + 1] = y;
|
|
285
|
+
}
|
|
286
|
+
this.setTransform(view, `translate(${minX}px,${minY}px)`);
|
|
287
|
+
if (!dirty) {
|
|
288
|
+
this.meshReuseCount++;
|
|
179
289
|
}
|
|
180
|
-
|
|
290
|
+
else {
|
|
291
|
+
view.meshAttachment = attachment;
|
|
292
|
+
view.meshSequenceIndex = sequenceIndex;
|
|
293
|
+
view.meshExpand = this.triangleExpand;
|
|
294
|
+
view.meshVertexCount = count;
|
|
295
|
+
view.meshBackendDrawn = this.meshBackendActive;
|
|
296
|
+
const uvs = sequence.getUVs(sequenceIndex);
|
|
297
|
+
const triangles = attachment.triangles;
|
|
298
|
+
if (this.meshBackendActive === 'webgl') {
|
|
299
|
+
// Queued, not drawn: render() flushes the whole batch through the
|
|
300
|
+
// shared GL context once the slot loop is done. `rel` is this view's
|
|
301
|
+
// own signature array — nothing mutates it before the flush.
|
|
302
|
+
this.pendingJobs.push({
|
|
303
|
+
canvas,
|
|
304
|
+
page,
|
|
305
|
+
vertices: rel,
|
|
306
|
+
uvs,
|
|
307
|
+
triangles,
|
|
308
|
+
ratio,
|
|
309
|
+
width: Math.min(view.canvasW, Math.ceil(w * ratio)),
|
|
310
|
+
height: Math.min(view.canvasH, Math.ceil(h * ratio)),
|
|
311
|
+
});
|
|
312
|
+
this.pendingViews.push(view);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
this.rasterizeMesh2d(canvas, page, rel, uvs, triangles, ratio);
|
|
316
|
+
}
|
|
317
|
+
this.meshCount++;
|
|
318
|
+
this.triangleCount += triangles.length / 3;
|
|
319
|
+
}
|
|
320
|
+
this.applyCommon(view, slot, pose, attachment.color, skeleton, zIndex);
|
|
321
|
+
}
|
|
322
|
+
/** The canvas2d raster path: clear the backing, map each triangle. */
|
|
323
|
+
rasterizeMesh2d(canvas, page, vertices, uvs, triangles, ratio) {
|
|
181
324
|
const ctx = canvas.getContext('2d');
|
|
182
325
|
if (!ctx)
|
|
183
326
|
return;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
327
|
+
// Clear the full backing: the previous frame's bbox (and so its drawn
|
|
328
|
+
// region) may have been larger than today's.
|
|
329
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
330
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
331
|
+
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
|
|
187
332
|
const uw = page.width - 1;
|
|
188
333
|
const uh = page.height - 1;
|
|
189
334
|
for (let t = 0; t < triangles.length; t += 3) {
|
|
190
335
|
const i0 = triangles[t] * 2;
|
|
191
336
|
const i1 = triangles[t + 1] * 2;
|
|
192
337
|
const i2 = triangles[t + 2] * 2;
|
|
193
|
-
this.drawTriangle(ctx, page, vertices[i0]
|
|
338
|
+
this.drawTriangle(ctx, page, vertices[i0], vertices[i0 + 1], uvs[i0] * uw, uvs[i0 + 1] * uh, vertices[i1], vertices[i1 + 1], uvs[i1] * uw, uvs[i1 + 1] * uh, vertices[i2], vertices[i2 + 1], uvs[i2] * uw, uvs[i2 + 1] * uh);
|
|
194
339
|
}
|
|
195
|
-
this.meshCount++;
|
|
196
|
-
this.triangleCount += triangles.length / 3;
|
|
197
|
-
this.applyCommon(view, slot, zIndex, skeletonAlpha * pose.color.a * attachment.color.a);
|
|
198
340
|
}
|
|
199
341
|
/**
|
|
200
342
|
* Standard canvas triangle texture mapping (same math as the official
|
|
@@ -242,16 +384,43 @@ export class SpineHtmlRenderer {
|
|
|
242
384
|
ctx.restore();
|
|
243
385
|
}
|
|
244
386
|
// --- shared plumbing -------------------------------------------------------
|
|
245
|
-
|
|
387
|
+
setTransform(view, transform) {
|
|
388
|
+
if (view.transform !== transform) {
|
|
389
|
+
view.transform = transform;
|
|
390
|
+
view.el.style.transform = transform;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
applyCommon(view, slot, pose, attachmentColor, skeleton, zIndex) {
|
|
394
|
+
const sc = skeleton.color;
|
|
395
|
+
const pc = pose.color;
|
|
246
396
|
if (view.zIndex !== zIndex) {
|
|
247
397
|
view.zIndex = zIndex;
|
|
248
398
|
view.el.style.zIndex = String(zIndex);
|
|
249
399
|
}
|
|
250
|
-
|
|
400
|
+
const alpha = sc.a * pc.a * attachmentColor.a;
|
|
251
401
|
if (view.opacity !== alpha) {
|
|
252
402
|
view.opacity = alpha;
|
|
253
403
|
view.el.style.opacity = alpha === 1 ? '' : String(alpha);
|
|
254
404
|
}
|
|
405
|
+
// RGB tint (uniform per slot) rides an feColorMatrix reference filter:
|
|
406
|
+
// scaling the channels is an exact multiply, applies to <img> and
|
|
407
|
+
// <canvas> alike, and never touches the raster. Needs reference-filter
|
|
408
|
+
// support (Safari 15+).
|
|
409
|
+
const r = sc.r * pc.r * attachmentColor.r;
|
|
410
|
+
const g = sc.g * pc.g * attachmentColor.g;
|
|
411
|
+
const b = sc.b * pc.b * attachmentColor.b;
|
|
412
|
+
if (view.tintR !== r || view.tintG !== g || view.tintB !== b) {
|
|
413
|
+
view.tintR = r;
|
|
414
|
+
view.tintG = g;
|
|
415
|
+
view.tintB = b;
|
|
416
|
+
if (r === 1 && g === 1 && b === 1) {
|
|
417
|
+
view.el.style.filter = '';
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
this.tintMatrixFor(view).setAttribute('values', `${r} 0 0 0 0 0 ${g} 0 0 0 0 0 ${b} 0 0 0 0 0 1 0`);
|
|
421
|
+
view.el.style.filter = `url(#${view.tintId})`;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
255
424
|
const blendMode = slot.data.blendMode;
|
|
256
425
|
if (view.blendMode !== blendMode) {
|
|
257
426
|
view.blendMode = blendMode;
|
|
@@ -262,10 +431,36 @@ export class SpineHtmlRenderer {
|
|
|
262
431
|
view.el.style.display = '';
|
|
263
432
|
}
|
|
264
433
|
}
|
|
434
|
+
tintMatrixFor(view) {
|
|
435
|
+
if (view.tintMatrix)
|
|
436
|
+
return view.tintMatrix;
|
|
437
|
+
if (!this.tintDefs) {
|
|
438
|
+
const svg = document.createElementNS(SVG_NS, 'svg');
|
|
439
|
+
svg.setAttribute('width', '0');
|
|
440
|
+
svg.setAttribute('height', '0');
|
|
441
|
+
svg.style.position = 'absolute';
|
|
442
|
+
this.root.appendChild(svg);
|
|
443
|
+
this.tintDefs = svg;
|
|
444
|
+
}
|
|
445
|
+
const filter = document.createElementNS(SVG_NS, 'filter');
|
|
446
|
+
view.tintId = `spine-html-tint-${tintFilterSeq++}`;
|
|
447
|
+
filter.setAttribute('id', view.tintId);
|
|
448
|
+
// Filter math must happen in sRGB to match Spine's color multiply
|
|
449
|
+
// (SVG filters default to linearRGB).
|
|
450
|
+
filter.setAttribute('color-interpolation-filters', 'sRGB');
|
|
451
|
+
const matrix = document.createElementNS(SVG_NS, 'feColorMatrix');
|
|
452
|
+
matrix.setAttribute('in', 'SourceGraphic');
|
|
453
|
+
matrix.setAttribute('type', 'matrix');
|
|
454
|
+
filter.appendChild(matrix);
|
|
455
|
+
this.tintDefs.appendChild(filter);
|
|
456
|
+
view.tintMatrix = matrix;
|
|
457
|
+
return matrix;
|
|
458
|
+
}
|
|
265
459
|
view(slot, kind) {
|
|
266
460
|
let view = this.views.get(slot);
|
|
267
461
|
if (view && view.kind !== kind) {
|
|
268
462
|
view.el.remove();
|
|
463
|
+
view.tintMatrix?.parentElement?.remove();
|
|
269
464
|
view = undefined;
|
|
270
465
|
}
|
|
271
466
|
if (!view) {
|
|
@@ -287,8 +482,21 @@ export class SpineHtmlRenderer {
|
|
|
287
482
|
zIndex: -1,
|
|
288
483
|
opacity: 1,
|
|
289
484
|
blendMode: BlendMode.Normal,
|
|
485
|
+
transform: '',
|
|
486
|
+
tintR: 1,
|
|
487
|
+
tintG: 1,
|
|
488
|
+
tintB: 1,
|
|
489
|
+
tintId: '',
|
|
490
|
+
tintMatrix: null,
|
|
290
491
|
canvasW: 0,
|
|
291
492
|
canvasH: 0,
|
|
493
|
+
meshRatio: -1,
|
|
494
|
+
meshAttachment: null,
|
|
495
|
+
meshSequenceIndex: -1,
|
|
496
|
+
meshExpand: -1,
|
|
497
|
+
meshVertexCount: -1,
|
|
498
|
+
meshBackendDrawn: '',
|
|
499
|
+
meshVertices: new Float64Array(0),
|
|
292
500
|
};
|
|
293
501
|
this.views.set(slot, view);
|
|
294
502
|
this.root.appendChild(el);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpineHtmlRenderer.js","sourceRoot":"","sources":["../src/SpineHtmlRenderer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SpineHtmlRenderer.js","sourceRoot":"","sources":["../src/SpineHtmlRenderer.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAoB,MAAM,cAAc,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spine-html",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Render Spine skeletal animations as plain DOM — rigid slots as <img> posed by CSS matrix, deform meshes on small per-part canvases, interleaved in one stacking context.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"build:lib": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
45
45
|
"prepublishOnly": "npm run build:lib",
|
|
46
46
|
"preview": "vite preview",
|
|
47
|
+
"test": "playwright test",
|
|
47
48
|
"fetch-assets": "bash scripts/fetch-assets.sh"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
@@ -51,6 +52,8 @@
|
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@esotericsoftware/spine-core": "^4.3.13",
|
|
55
|
+
"@playwright/test": "1.62.1",
|
|
56
|
+
"@types/node": "^22",
|
|
54
57
|
"typescript": "^5.6.0",
|
|
55
58
|
"vite": "^6.0.0"
|
|
56
59
|
}
|