rig-play 1.9.0 → 1.9.2

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 CHANGED
@@ -219,7 +219,10 @@ apart), `pause()` / `resume()` hold and release it, `timeScale` scales every
219
219
  step, and `seek(t)` moves it to a time. A seek is "reopen, then step to the
220
220
  time" in `seekStep` increments (1/60 s by default) — never a jump, because a
221
221
  physics rig has history and its pose at a time depends on the steps that
222
- reached it. `on('event', …)` receives the event keys each step crosses, in the
222
+ reached it. The physics integrates on rig-c's render clock (`physicsClockStep`:
223
+ each step and 2⁻³⁰ of it more), so stepping at a fixed rate — `frame(1/60)`, a
224
+ capture, a test — shows no single-frame spring jump where a frame ends on a
225
+ physics step; the animation, the events and `time` stay on the steps (#103). `on('event', …)` receives the event keys each step crosses, in the
223
226
  runtime's order across a loop's wrap; `on('complete', …)` fires once a step
224
227
  completes a cycle. `skin` (a constructor option) poses under a named skin;
225
228
  without it the rig is posed the way a fresh Spine skeleton is, with no skin
@@ -607,6 +610,12 @@ onto shared pages instead. Both play here, unchanged:
607
610
  mesh once (no reallocation), so it is fine to expose as a user setting.
608
611
  - `renderer.triangleExpand` — how far (canvas px) each triangle edge's clip is
609
612
  moved outward to close antialiased mesh seams (default 0.5). Also re-rasters every mesh once when changed.
613
+ - `renderer.meshSourceRect` — what a canvas2d mesh triangle is drawn from:
614
+ `'page'` (the whole page) or `'triangle'` (a sub-rect covering its clip). Both
615
+ draw the same picture; the default is `'triangle'` on Linux WebKit, which
616
+ garbles whole-page draws, and `'page'` elsewhere, because macOS Safari ran the
617
+ sub-rect 12–15% slower (#25). Also on `CanvasRenderer` for its canvas2d
618
+ fallback. Re-rasters every mesh once when changed.
610
619
  - `renderer.clipping` — apply the clips the frame carries (default `true`).
611
620
  Which slots a clip covers is decided where the frame is made — the player's
612
621
  adapter walks the draw order the way the runtime's draw loop does (one clip in
@@ -872,7 +881,8 @@ scenes (floors 0.585–1.553%, Chromium and WebKit). The DOM tier's two mesh
872
881
  backends get the same A/B (`?backend=canvas2d` against `?backend=webgl`, at most
873
882
  0.5%). Hairline seams are guarded by a deterministic canary (`?expand=0` must
874
883
  change the canvas2d raster), the canvas2d source sub-rect by another (expand 32
875
- against 8), and counter tests pin the dirty-skip / grow-only-backing /
884
+ against 8, forced to the sub-rect), the two source rects by an A/B that must
885
+ match exactly, and counter tests pin the dirty-skip / grow-only-backing /
876
886
  clip-counter invariants plus the region corner order (BL, UL, UR, BR) and the
877
887
  turned-region UVs, read off rig-c's pose against hand-written numbers.
878
888
 
@@ -1,3 +1,4 @@
1
+ import { type MeshSourceRect } from './DomRenderer.js';
1
2
  import type { PosedFrame } from './posedFrame.js';
2
3
  /** What actually drew the last frame of a `CanvasRenderer`. */
3
4
  export type CanvasBackend = 'webgl' | 'canvas2d';
@@ -69,6 +70,8 @@ export declare class CanvasRenderer {
69
70
  viewport: CanvasViewport | null;
70
71
  /** The backend to draw with: 'webgl' (default) through the shared context, or 'canvas2d' to force the fallback. */
71
72
  backend: CanvasBackend;
73
+ /** What the canvas2d fallback draws each mesh triangle from — as `DomRenderer.meshSourceRect`, with the same default. */
74
+ meshSourceRect: MeshSourceRect;
72
75
  /** What drew the last frame (or would have, had it not been reused). */
73
76
  backendActive: CanvasBackend;
74
77
  /** The visible canvas — the renderer's one element in the root. */
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasRenderer.d.ts","sourceRoot":"","sources":["../src/CanvasRenderer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAwB,UAAU,EAAa,MAAM,iBAAiB,CAAC;AAEnF,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,CAAC;AAEjD,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAYD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,cAAc;IAqEvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IArExB;;;;;OAKG;IACH,UAAU,SAA+D;IACzE,6HAA6H;IAC7H,QAAQ,UAAQ;IAChB;;;;OAIG;IACH,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAQ;IACvC,mHAAmH;IACnH,OAAO,EAAE,aAAa,CAAW;IACjC,wEAAwE;IACxE,aAAa,EAAE,aAAa,CAAW;IACvC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEnC,8EAA8E;IAC9E,SAAS,SAAK;IACd,oEAAoE;IACpE,YAAY,SAAK;IACjB,iEAAiE;IACjE,cAAc,SAAK;IACnB,oFAAoF;IACpF,YAAY,SAAK;IACjB,yDAAyD;IACzD,KAAK,SAAK;IACV,wEAAwE;IACxE,kBAAkB,SAAK;IACvB,yCAAyC;IACzC,SAAS,SAAK;IACd,gIAAgI;IAChI,aAAa,SAAK;IAElB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkC;IACtD,gHAAgH;IAChH,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,yGAAyG;IACzG,OAAO,CAAC,GAAG,CAAyB;IACpC,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,QAAQ,CAAiB;IAEjC;;;;;;OAMG;gBAEgB,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAgB/D,uGAAuG;IACvG;;;;;;;;OAQG;IACH,cAAc,IAAI,MAAM;IAKxB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAIlC,uBAAuB;IACvB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAuD/B,+GAA+G;IAC/G,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,OAAO;IAUf,oFAAoF;IACpF,OAAO,CAAC,WAAW;IAkBnB,uGAAuG;IACvG,OAAO,CAAC,gBAAgB;IAoExB,iFAAiF;IACjF,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,MAAM,CAAa;IAE3B;;;OAGG;IACH,OAAO,CAAC,QAAQ;IA4BhB,+CAA+C;IAC/C,OAAO,CAAC,aAAa;IAmErB,OAAO,CAAC,MAAM;CAmEf"}
1
+ {"version":3,"file":"CanvasRenderer.d.ts","sourceRoot":"","sources":["../src/CanvasRenderer.ts"],"names":[],"mappings":"AAEA,OAAO,EAA+C,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGpG,OAAO,KAAK,EAAwB,UAAU,EAAa,MAAM,iBAAiB,CAAC;AAEnF,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,CAAC;AAEjD,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAYD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,cAAc;IAuEvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAvExB;;;;;OAKG;IACH,UAAU,SAA+D;IACzE,6HAA6H;IAC7H,QAAQ,UAAQ;IAChB;;;;OAIG;IACH,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAQ;IACvC,mHAAmH;IACnH,OAAO,EAAE,aAAa,CAAW;IACjC,yHAAyH;IACzH,cAAc,EAAE,cAAc,CAA2B;IACzD,wEAAwE;IACxE,aAAa,EAAE,aAAa,CAAW;IACvC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEnC,8EAA8E;IAC9E,SAAS,SAAK;IACd,oEAAoE;IACpE,YAAY,SAAK;IACjB,iEAAiE;IACjE,cAAc,SAAK;IACnB,oFAAoF;IACpF,YAAY,SAAK;IACjB,yDAAyD;IACzD,KAAK,SAAK;IACV,wEAAwE;IACxE,kBAAkB,SAAK;IACvB,yCAAyC;IACzC,SAAS,SAAK;IACd,gIAAgI;IAChI,aAAa,SAAK;IAElB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkC;IACtD,gHAAgH;IAChH,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,sFAAsF;IACtF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;IACvD,yGAAyG;IACzG,OAAO,CAAC,GAAG,CAAyB;IACpC,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,QAAQ,CAAiB;IAEjC;;;;;;OAMG;gBAEgB,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAgB/D,uGAAuG;IACvG;;;;;;;;OAQG;IACH,cAAc,IAAI,MAAM;IAKxB,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAIlC,uBAAuB;IACvB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAuD/B,+GAA+G;IAC/G,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,OAAO;IAUf,oFAAoF;IACpF,OAAO,CAAC,WAAW;IAkBnB,uGAAuG;IACvG,OAAO,CAAC,gBAAgB;IAqExB,iFAAiF;IACjF,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,MAAM,CAAa;IAE3B;;;OAGG;IACH,OAAO,CAAC,QAAQ;IA4BhB,+CAA+C;IAC/C,OAAO,CAAC,aAAa;IAmErB,OAAO,CAAC,MAAM;CAmEf"}
@@ -2,6 +2,12 @@ import { type RegionImage } from './DomTexture.js';
2
2
  import type { PosedFrame } from './posedFrame.js';
3
3
  /** Rasterizer used for the mesh (deform) tier. */
4
4
  export type MeshBackend = 'canvas2d' | 'webgl';
5
+ /**
6
+ * What a canvas2d mesh triangle is drawn from: `'triangle'`, a source sub-rect
7
+ * of the page covering the triangle's clip, or `'page'`, the whole page. Both
8
+ * draw the same picture under the same clip; they differ in cost by engine.
9
+ */
10
+ export type MeshSourceRect = 'triangle' | 'page';
5
11
  /**
6
12
  * Renders a posed frame (`PosedFrame`) as DOM, split by slot kind:
7
13
  *
@@ -88,6 +94,12 @@ export declare class DomRenderer {
88
94
  * to see them.
89
95
  */
90
96
  triangleExpand: number;
97
+ /**
98
+ * What the canvas2d mesh backend draws each triangle from (`MeshSourceRect`):
99
+ * by default the sub-rect on Linux WebKit and the whole page elsewhere.
100
+ * Re-rasters every mesh once when changed.
101
+ */
102
+ meshSourceRect: MeshSourceRect;
91
103
  /**
92
104
  * Mesh-canvas backing-store pixels per CSS pixel. Defaults to the device
93
105
  * pixel ratio. If the caller scales the root element, fold that scale in
@@ -1 +1 @@
1
- {"version":3,"file":"DomRenderer.d.ts","sourceRoot":"","sources":["../src/DomRenderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DomRenderer.d.ts","sourceRoot":"","sources":["../src/DomRenderer.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { type CanvasBackend, CanvasRenderer, type CanvasViewport } from './CanvasRenderer.js';
2
- export { DomRenderer, type MeshBackend } from './DomRenderer.js';
2
+ export { DomRenderer, type MeshBackend, type MeshSourceRect } from './DomRenderer.js';
3
3
  export { type PageLayout, type PageRegion, type RegionEncoding, type RegionImage, revokeRegions, type UnpackRegionsOptions, unpackRegions } from './DomTexture.js';
4
4
  export { type LoadModelOptions, loadModel, type ModelAssets, type ModelDocument, type RegionLoading } from './loadModel.js';
5
5
  export { type AdjustableBones, type BoneAdjust, type BoneLocals, type BoneWorld, type PlayOptions, type PoseBounds, type QueueOptions, type RenderMode, type RigComplete, type RigEvent, RigPlayer, type RigPlayerOptions, type SlotFilter, type TrackEntry } from './player.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnK,OAAO,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5H,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACjR,YAAY,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnK,OAAO,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5H,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACjR,YAAY,EACV,SAAS,EACT,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,SAAS,GACV,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -4927,6 +4927,17 @@ function setupPosed(doc, plant, mode) {
4927
4927
  if (world === null || shown === null || setup.slots === null || setup.drawOrder === null) throw new CoreInputError("the raw setup pose was not posed");
4928
4928
  return { world, shown, slots: setup.slots, drawOrder: setup.drawOrder };
4929
4929
  }
4930
+ const PHYSICS_CLOCK_LEAD = 2 ** -30;
4931
+ function physicsClockStep(step) {
4932
+ return step + step * PHYSICS_CLOCK_LEAD;
4933
+ }
4934
+ function checkedClock(clock, who) {
4935
+ return (dt) => {
4936
+ const moved = clock(dt);
4937
+ if (typeof moved !== "number" || !Number.isFinite(moved) || moved < 0) throw new CoreInputError(`${who} clock moved the physics by ${String(moved)} for a step of ${dt}, not a finite time at or above 0`);
4938
+ return moved;
4939
+ };
4940
+ }
4930
4941
  function loopedTime(trackTime, duration) {
4931
4942
  return duration === 0 ? 0 : trackTime % duration;
4932
4943
  }
@@ -5031,7 +5042,10 @@ function openTrack(doc, animation, options, plant = {}) {
5031
5042
  if (typeof options !== "object" || options === null || typeof options.loop !== "boolean") throw new CoreInputError(`the live track's options.loop is ${JSON.stringify(options?.loop)}, not true or false`);
5032
5043
  if (options.reset !== "animation" && options.reset !== "setup") throw new CoreInputError(`the live track's options.reset is ${JSON.stringify(options.reset)}, not "animation" or "setup"`);
5033
5044
  if (options.adjust !== void 0 && typeof options.adjust !== "function") throw new CoreInputError(`the live track's options.adjust is ${typeof options.adjust}, not a function`);
5034
- const { track, first } = openRawTrack(doc, animation, plant, options.reset, options.loop ? LOOPED : HELD, options.adjust);
5045
+ if (options.clock !== void 0 && typeof options.clock !== "function") throw new CoreInputError(`the live track's options.clock is ${typeof options.clock}, not a function`);
5046
+ const mode = options.loop ? LOOPED : HELD;
5047
+ const clock = options.clock === void 0 ? void 0 : checkedClock(options.clock, "the live track's");
5048
+ const { track, first } = openRawTrack(doc, animation, plant, options.reset, clock === void 0 ? mode : { ...mode, clock: (dt) => clock(dt) }, options.adjust);
5035
5049
  return new Track(track, first);
5036
5050
  }
5037
5051
  class Track {
@@ -5953,13 +5967,16 @@ function delayOf(v, call) {
5953
5967
  function openTracks(doc, options, plant = {}) {
5954
5968
  if (typeof options !== "object" || options === null || options.reset !== "animation" && options.reset !== "setup") throw new CoreInputError(`the live tracks' options.reset is ${JSON.stringify(options?.reset)}, not "animation" or "setup"`);
5955
5969
  if (options.adjust !== void 0 && typeof options.adjust !== "function") throw new CoreInputError(`the live tracks' options.adjust is ${typeof options.adjust}, not a function`);
5956
- return new Tracks(doc, options.reset, options.adjust, plant, openRawTracksPath(doc, plant));
5970
+ if (options.clock !== void 0 && typeof options.clock !== "function") throw new CoreInputError(`the live tracks' options.clock is ${typeof options.clock}, not a function`);
5971
+ const clock = options.clock === void 0 ? void 0 : checkedClock(options.clock, "the live tracks'");
5972
+ return new Tracks(doc, options.reset, options.adjust, clock, plant, openRawTracksPath(doc, plant));
5957
5973
  }
5958
5974
  class Tracks {
5959
- constructor(doc, reset, adjust, plant, path) {
5975
+ constructor(doc, reset, adjust, clock, plant, path) {
5960
5976
  this.doc = doc;
5961
5977
  this.reset = reset;
5962
5978
  this.adjust = adjust;
5979
+ this.clock = clock;
5963
5980
  this.plant = plant;
5964
5981
  this.path = path;
5965
5982
  this.started = false;
@@ -6064,7 +6081,7 @@ class Tracks {
6064
6081
  const { doc, path } = this;
6065
6082
  const ctx = path.ctx;
6066
6083
  const before = ctx.time;
6067
- ctx.time += dt;
6084
+ ctx.time += this.clock === void 0 ? dt : this.clock(dt);
6068
6085
  const pose = new Pose(doc, this.plant);
6069
6086
  const animationTime = this.mixer.apply(pose);
6070
6087
  const mixed = new Map(doc.slots.map((s, k) => [s.name, { deform: pose.slots[k].deform, seen: pose.slots[k].seen }]));
@@ -6842,6 +6859,10 @@ function getMeshGlBlitter() {
6842
6859
  }
6843
6860
  return shared && !shared.lost ? shared : null;
6844
6861
  }
6862
+ function defaultMeshSourceRect(userAgent = typeof navigator === "object" ? navigator.userAgent : "") {
6863
+ const linuxWebKit = /AppleWebKit/.test(userAgent) && /Linux|X11/.test(userAgent) && !/Android|Chrome|Chromium|CriOS|Edg/.test(userAgent);
6864
+ return linuxWebKit ? "triangle" : "page";
6865
+ }
6845
6866
  const regionVertices = new Float32Array(8);
6846
6867
  const SVG_NS = "http://www.w3.org/2000/svg";
6847
6868
  let tintFilterSeq = 0;
@@ -6965,6 +6986,12 @@ class DomRenderer {
6965
6986
  * to see them.
6966
6987
  */
6967
6988
  triangleExpand = 0.5;
6989
+ /**
6990
+ * What the canvas2d mesh backend draws each triangle from (`MeshSourceRect`):
6991
+ * by default the sub-rect on Linux WebKit and the whole page elsewhere.
6992
+ * Re-rasters every mesh once when changed.
6993
+ */
6994
+ meshSourceRect = defaultMeshSourceRect();
6968
6995
  /**
6969
6996
  * Mesh-canvas backing-store pixels per CSS pixel. Defaults to the device
6970
6997
  * pixel ratio. If the caller scales the root element, fold that scale in
@@ -7238,7 +7265,7 @@ class DomRenderer {
7238
7265
  const ratio = this.pixelRatio;
7239
7266
  const uvs = slot.uvs;
7240
7267
  const triangles = slot.triangles;
7241
- let dirty = view.meshUvs !== uvs || view.meshTriangles !== triangles || view.meshPage !== page || view.meshSequenceIndex !== sequenceIndex || view.meshExpand !== this.triangleExpand || view.meshVertexCount !== count || view.meshBackendDrawn !== this.meshBackendActive;
7268
+ let dirty = view.meshUvs !== uvs || view.meshTriangles !== triangles || view.meshPage !== page || view.meshSequenceIndex !== sequenceIndex || view.meshExpand !== this.triangleExpand || view.meshSourceRect !== this.meshSourceRect || view.meshVertexCount !== count || view.meshBackendDrawn !== this.meshBackendActive;
7242
7269
  const needW = Math.max(1, Math.round(w * ratio));
7243
7270
  const needH = Math.max(1, Math.round(h * ratio));
7244
7271
  const ratioChanged = view.meshRatio !== ratio;
@@ -7278,6 +7305,7 @@ class DomRenderer {
7278
7305
  view.meshPage = page;
7279
7306
  view.meshSequenceIndex = sequenceIndex;
7280
7307
  view.meshExpand = this.triangleExpand;
7308
+ view.meshSourceRect = this.meshSourceRect;
7281
7309
  view.meshVertexCount = count;
7282
7310
  view.meshBackendDrawn = this.meshBackendActive;
7283
7311
  if (this.meshBackendActive === "webgl") {
@@ -7410,7 +7438,7 @@ class DomRenderer {
7410
7438
  * class of offset the `uv * size` addressing removes.
7411
7439
  */
7412
7440
  drawTriangle(ctx, img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) {
7413
- drawTexturedTriangle(ctx, img, this.triangleExpand, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
7441
+ drawTexturedTriangle(ctx, img, this.triangleExpand, this.meshSourceRect, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
7414
7442
  }
7415
7443
  // --- clipping tier ---------------------------------------------------------
7416
7444
  /**
@@ -7636,6 +7664,7 @@ class DomRenderer {
7636
7664
  meshPage: null,
7637
7665
  meshSequenceIndex: -1,
7638
7666
  meshExpand: -1,
7667
+ meshSourceRect: "",
7639
7668
  meshVertexCount: -1,
7640
7669
  meshBackendDrawn: "",
7641
7670
  meshVertices: new Float64Array(0),
@@ -7654,7 +7683,7 @@ class DomRenderer {
7654
7683
  this.setClipPath(view, "");
7655
7684
  }
7656
7685
  }
7657
- function drawTexturedTriangle(ctx, img, expand, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) {
7686
+ function drawTexturedTriangle(ctx, img, expand, sourceRect, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) {
7658
7687
  const corners = offsetTriangle(x0, y0, x1, y1, x2, y2, expand);
7659
7688
  const px0 = corners[0], py0 = corners[1];
7660
7689
  const px1 = corners[2], py1 = corners[3];
@@ -7677,6 +7706,14 @@ function drawTexturedTriangle(ctx, img, expand, x0, y0, u0, v0, x1, y1, u1, v1,
7677
7706
  const d = (eu1 * ey2 - eu2 * ey1) * det;
7678
7707
  const e = x0 - a * u0 - c * v0;
7679
7708
  const f = y0 - b * u0 - d * v0;
7709
+ if (sourceRect === "page") {
7710
+ ctx.save();
7711
+ ctx.transform(a, b, c, d, e, f);
7712
+ ctx.clip();
7713
+ ctx.drawImage(img, 0, 0);
7714
+ ctx.restore();
7715
+ return;
7716
+ }
7680
7717
  let minU = Math.min(u0, u1, u2);
7681
7718
  let maxU = Math.max(u0, u1, u2);
7682
7719
  let minV = Math.min(v0, v1, v2);
@@ -7768,6 +7805,8 @@ class CanvasRenderer {
7768
7805
  viewport = null;
7769
7806
  /** The backend to draw with: 'webgl' (default) through the shared context, or 'canvas2d' to force the fallback. */
7770
7807
  backend = "webgl";
7808
+ /** What the canvas2d fallback draws each mesh triangle from — as `DomRenderer.meshSourceRect`, with the same default. */
7809
+ meshSourceRect = defaultMeshSourceRect();
7771
7810
  /** What drew the last frame (or would have, had it not been reused). */
7772
7811
  backendActive = "webgl";
7773
7812
  /** The visible canvas — the renderer's one element in the root. */
@@ -7941,7 +7980,8 @@ class CanvasRenderer {
7941
7980
  this.nextSig = grown;
7942
7981
  }
7943
7982
  };
7944
- need(8);
7983
+ need(9);
7984
+ sig[n++] = this.meshSourceRect === "triangle" ? 1 : 0;
7945
7985
  sig[n++] = this.left;
7946
7986
  sig[n++] = this.top;
7947
7987
  sig[n++] = this.backingW;
@@ -8156,6 +8196,7 @@ class CanvasRenderer {
8156
8196
  ctx,
8157
8197
  source,
8158
8198
  0.5,
8199
+ this.meshSourceRect,
8159
8200
  X(vertices[i0]),
8160
8201
  Y(vertices[i0 + 1]),
8161
8202
  uvs[i0] * uw,
@@ -8558,7 +8599,7 @@ class RigPlayer {
8558
8599
  if (this.tracks === null && plain && !this.trackMode) {
8559
8600
  this.animation = name;
8560
8601
  this.loop = loop;
8561
- this.track = openTrack(this.view, name, { loop, reset: "animation", adjust: this.adjustHook });
8602
+ this.track = openTrack(this.view, name, { loop, reset: "animation", adjust: this.adjustHook, clock: physicsClockStep });
8562
8603
  this.pose = this.track.first;
8563
8604
  return;
8564
8605
  }
@@ -8649,7 +8690,7 @@ class RigPlayer {
8649
8690
  */
8650
8691
  compose() {
8651
8692
  if (this.tracks !== null) return this.tracks;
8652
- const tracks = openTracks(this.view, { reset: "animation", adjust: this.adjustHook });
8693
+ const tracks = openTracks(this.view, { reset: "animation", adjust: this.adjustHook, clock: physicsClockStep });
8653
8694
  const single = this.track;
8654
8695
  const time = single?.trackTime ?? 0;
8655
8696
  if (single !== null && this.animation !== null) {
@@ -8689,14 +8730,14 @@ class RigPlayer {
8689
8730
  /** Whatever is open, opened again with track 0's animation as `play` last set it, at pose 0: the single track, or the tracks under `tracks: true`. */
8690
8731
  reopen() {
8691
8732
  if (this.tracks !== null) {
8692
- const tracks = openTracks(this.view, { reset: "animation", adjust: this.adjustHook });
8733
+ const tracks = openTracks(this.view, { reset: "animation", adjust: this.adjustHook, clock: physicsClockStep });
8693
8734
  tracks.setAnimation(0, this.animation, { loop: this.loop, mixDuration: 0 });
8694
8735
  this.trackCount = 1;
8695
8736
  this.tracks = tracks;
8696
8737
  this.pose = tracks.start();
8697
8738
  return;
8698
8739
  }
8699
- this.track = openTrack(this.view, this.animation, { loop: this.loop, reset: "animation", adjust: this.adjustHook });
8740
+ this.track = openTrack(this.view, this.animation, { loop: this.loop, reset: "animation", adjust: this.adjustHook, clock: physicsClockStep });
8700
8741
  this.pose = this.track.first;
8701
8742
  }
8702
8743
  /** Steps whatever is open forward to `time` in `seekStep` increments, the last one shorter. */
@@ -8724,7 +8765,11 @@ class RigPlayer {
8724
8765
  * Steps the track by `dt × timeScale` seconds and fires the step's listeners,
8725
8766
  * without drawing. A paused player, or a step of zero, keeps the pose it
8726
8767
  * holds without re-posing it, so a held rig costs the renderer's dirty
8727
- * checks and nothing else.
8768
+ * checks and nothing else. The physics clock moves by `physicsClockStep`
8769
+ * of the step — the step and 2⁻³⁰ of it more, rig-c's render clock — so a
8770
+ * caller stepping at a fixed rate whose frame is a whole number of physics
8771
+ * steps (`frame(1/60)`, a capture) shows no spring jump; the animation time,
8772
+ * the events and `time` stay on the steps themselves (#103).
8728
8773
  */
8729
8774
  advance(dt) {
8730
8775
  if (this.pose === null) return;