@moku-labs/game 0.15.6 → 0.15.7

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.
@@ -1,7 +1,7 @@
1
- import { Jn as FeaturePlugin, Sr as Json, Xn as AnyFlow, dr as NodeFx, gr as FakeClock, mr as ClockSource, nr as NodeTable, or as Descriptor, ur as Hint } from "./types-DnttyLeu.mjs";
2
- import { t as createApp } from "./index-DytzVJFz.mjs";
3
- import { b as saveOf, v as WithGameState, y as memory } from "./types-CRgEt4wq.mjs";
4
- import { a as createHeadless, i as ReproResult, n as HeadlessGame, o as runRepro, r as Repro, s as stepFrames, t as HeadlessApp } from "./headless-DDkRwLnJ.mjs";
1
+ import { Cr as Json, Yn as FeaturePlugin, Zn as AnyFlow, _r as FakeClock, dr as Hint, fr as NodeFx, hr as ClockSource, rr as NodeTable, sr as Descriptor } from "./types-C4D9UVgb.mjs";
2
+ import { t as createApp } from "./index-CU4Oc2Qv.mjs";
3
+ import { b as saveOf, v as WithGameState, y as memory } from "./types-MocH_igX.mjs";
4
+ import { a as createHeadless, i as ReproResult, n as HeadlessGame, o as runRepro, r as Repro, s as stepFrames, t as HeadlessApp } from "./headless-DobgwTKK.mjs";
5
5
  import { AnyPluginInstance } from "@moku-labs/core";
6
6
 
7
7
  //#region src/plugins/clock/fake.d.ts
package/dist/testing.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { an as exit, cn as type, in as refuseStart, m as flattenFeatures, t as createApp } from "./src-DWJabPi4.mjs";
1
+ import { an as exit, cn as type, in as refuseStart, m as flattenFeatures, t as createApp } from "./src-nJYt0LMr.mjs";
2
2
  import { n as saveOf, t as memory } from "./memory-CWlqhS7l.mjs";
3
3
  import { t as fakeClock } from "./fake-6mazmHK3.mjs";
4
4
  import { i as stepFrames, r as runRepro, t as createHeadless } from "./headless-BA6ffzqD.mjs";
@@ -1,5 +1,5 @@
1
- import { A as PixiSprite, An as TrackSegment, Hr as Api$1, Mn as Api$2, Nt as FilterCache, O as PixiFilter, On as ReducedMotion, Ot as FilterSlot, Qr as Require, Rr as Events$5, Sr as Json, T as Api$4, Tn as NumericFields, Zr as Events$2, Zt as Api$3, an as ComponentHandle, ar as TypeTag, in as AnyComponentValue, j as PixiTexture, jt as Point, k as PixiModule, kn as TrackOptions, kt as FilterSlotInputs, ln as Entity, nn as AnyComponent, or as Descriptor, s as Events$1, sn as ComponentType, t as Api$5, v as Events$4, wn as MotionHandle, xn as Ease, xr as Events$3, yr as Api$6 } from "./types-DnttyLeu.mjs";
2
- import { I as I18nApi, J as StylesState, S as TextApi, c as UiNode, i as Finding, j as InputApi, n as ElementChange, o as JsxState, r as ElementMotion } from "./types-CWSMo70I.mjs";
1
+ import { $r as Require, A as PixiModule, An as TrackOptions, At as FilterSlotInputs, Cr as Json, E as Api$4, En as NumericFields, M as PixiTexture, Mt as Point, Nn as Api$2, Pt as FilterCache, Qr as Events$2, Qt as Api$3, Sn as Ease, Sr as Events$3, Tn as MotionHandle, Ur as Api$1, an as AnyComponentValue, br as Api$6, cn as ComponentType, j as PixiSprite, jn as TrackSegment, k as PixiFilter, kn as ReducedMotion, kt as FilterSlot, on as ComponentHandle, or as TypeTag, rn as AnyComponent, s as Events$1, sr as Descriptor, t as Api$5, un as Entity, v as Events$4, zr as Events$5 } from "./types-C4D9UVgb.mjs";
2
+ import { I as I18nApi, J as StylesState, S as TextApi, c as UiNode, i as Finding, j as InputApi, n as ElementChange, o as JsxState, r as ElementMotion } from "./types-CZGuMhV8.mjs";
3
3
  import { Log } from "@moku-labs/common/browser";
4
4
  import { PluginCtx } from "@moku-labs/core";
5
5
  import { Node, Yoga } from "yoga-layout/load";
@@ -1358,15 +1358,17 @@ type FilterArea = readonly [x: number, y: number, width: number, height: number]
1358
1358
  *
1359
1359
  * @example
1360
1360
  * ```ts
1361
- * // A Memory Missing's frost: the body reads a blurred copy of the scene through sampleBlur(uv).
1361
+ * // A Memory Missing's frost on the layer of its panels: the body reads a blurred copy of the scene drawn under them.
1362
1362
  * const Frost = defineFilter("Frost", {
1363
1363
  * wgsl: FROST_WGSL,
1364
1364
  * glsl: FROST_GLSL,
1365
1365
  * uniforms: { view: [0, 0, 1], rectA: [0, 0, 0, 0], strength: 16, vivid: 1.2 },
1366
- * inputs: { blur: { stages: [FrostBox4, FrostHalf, FrostGauss], chain: frostChain } },
1366
+ * backdrop: true,
1367
+ * inputs: { blur: { from: "back", stages: [FrostBox4, FrostHalf, FrostGauss], chain: frostChain } },
1368
+ * area: value => [value.rectA[0] ?? 0, value.rectA[1] ?? 0, value.rectA[2] ?? 0, value.rectA[3] ?? 0],
1367
1369
  * fallback: FrostVeil
1368
1370
  * });
1369
- * Frost.filter.fallback?.id; // "FrostVeil"
1371
+ * [Frost.filter.backdrop, Frost.filter.cache, Frost.filter.inputs[0]?.from]; // [true, "screen", "back"]
1370
1372
  * ```
1371
1373
  */
1372
1374
  type FilterSpec<Uniforms extends Record<string, UniformDeclaration>> = {
@@ -1415,6 +1417,15 @@ type FilterSpec<Uniforms extends Record<string, UniformDeclaration>> = {
1415
1417
  * `scale` sizes it.
1416
1418
  */
1417
1419
  readonly resolution?: number;
1420
+ /**
1421
+ * `true` for a filter that reads what was drawn under its view, inside its box (the view's bounds, or its `area`):
1422
+ * Pixi copies that part of the canvas before the view draws, the body reads it through `sampleBack(uv)`, and an input
1423
+ * may start from it (`from: "back"`). Its output is laid over the canvas like the view's own pixels: where the body
1424
+ * answers transparent the canvas stays as it is. A backdrop is drawn live in every frame, never kept (`cache` may only
1425
+ * be left out or `false`), has no padding, and is no stage; its fallback may be one. On WebGL the renderer then draws
1426
+ * every frame into Pixi's back buffer. Default `false`.
1427
+ */
1428
+ readonly backdrop?: boolean;
1418
1429
  };
1419
1430
  /**
1420
1431
  * How one uniform travels to the GPU: its name, its WGSL type and the form it was declared in.
@@ -1460,7 +1471,8 @@ type FilterDefinition = {
1460
1471
  */
1461
1472
  readonly origin: UniformSpec | undefined; /** The rectangle outside of which the filter draws nothing, from the value; present only when the spec gave one. */
1462
1473
  readonly area?: (value: Readonly<FilterFields>) => FilterArea | undefined; /** The texels per CSS px it draws at; 0 for the resolution of the canvas. */
1463
- readonly resolution: number;
1474
+ readonly resolution: number; /** True for a filter that reads what was drawn under its view: Pixi's `blendRequired`, and `sampleBack` in its body. */
1475
+ readonly backdrop: boolean;
1464
1476
  };
1465
1477
  /**
1466
1478
  * A filter a chain may draw: any component `defineFilter` made. Listed in an input's `stages` and named by its steps.
@@ -1528,6 +1540,12 @@ type FilterChainContext = {
1528
1540
  * ```
1529
1541
  */
1530
1542
  type FilterInput<Value> = {
1543
+ /**
1544
+ * Where the first step reads: `"input"` (the default), the view's own input; `"back"`, what was drawn under the
1545
+ * view inside its box, for a backdrop filter only. A chain from back runs at the resolution of the surface under the
1546
+ * view, which `context.resolution` then holds.
1547
+ */
1548
+ readonly from?: "input" | "back";
1531
1549
  readonly stages: readonly FilterStage[];
1532
1550
  /**
1533
1551
  * The steps of the second texture for this value and resolution. Pure: no state, no randomness; the context object
@@ -1551,12 +1569,13 @@ type FilterInput<Value> = {
1551
1569
  * @example
1552
1570
  * ```ts
1553
1571
  * const [blur] = Frost.filter.inputs;
1554
- * [blur?.texture, blur?.sampler, blur?.scale.name, blur?.clamp.name, blur?.sample];
1555
- * // ["blurTexture", "blurSampler", "blurScale", "blurClamp", "sampleBlur"]
1572
+ * [blur?.texture, blur?.sampler, blur?.scale.name, blur?.clamp.name, blur?.sample, blur?.from];
1573
+ * // ["blurTexture", "blurSampler", "blurScale", "blurClamp", "sampleBlur", "back"]
1556
1574
  * ```
1557
1575
  */
1558
1576
  type FilterInputDefinition = {
1559
- readonly name: string;
1577
+ readonly name: string; /** Where its first step reads: the view's own input, or what was drawn under the view. */
1578
+ readonly from: "input" | "back";
1560
1579
  readonly texture: string;
1561
1580
  readonly sampler: string;
1562
1581
  readonly scale: UniformSpec;
@@ -1864,8 +1883,11 @@ type Place = {
1864
1883
  * pictures through.
1865
1884
  */
1866
1885
  type InputsState = {
1867
- /** A uniform of the value changed since the last evaluation (set by `writeFilter`). */stale: boolean; /** The resolution of the last evaluation. */
1868
- resolution: number; /** Changes whenever what the stages draw changes; 1 after the first evaluation. */
1886
+ /** A uniform of the value changed since the last evaluation (set by `writeFilter`). */stale: boolean; /** The resolution of the view's input at the last evaluation. */
1887
+ resolution: number; /** The resolution of what was drawn under the view at the last evaluation; the input's for a filter that reads none. */
1888
+ backResolution: number; /** An input starts from the view's own input: a new resolution of the input runs the chains again. */
1889
+ readonly fromInput: boolean; /** An input starts from what was drawn under the view: a new resolution of the back runs the chains again. */
1890
+ readonly fromBack: boolean; /** Changes whenever what the stages draw changes; 1 after the first evaluation. */
1869
1891
  version: number; /** The object `chain` receives, reused: its `resolution` is written before each call. */
1870
1892
  readonly context: {
1871
1893
  resolution: number;
@@ -189,7 +189,7 @@ type ThermalStatus = "none" | "light" | "moderate" | "severe" | "critical" | "em
189
189
  *
190
190
  * @example
191
191
  * ```ts
192
- * app.time.rate(); // { fps: 60, mode: "auto", reason: "missed", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null }
192
+ * app.time.rate(); // { fps: 60, mode: "auto", reason: "missed", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null, scale: 0.75 }
193
193
  * ```
194
194
  */
195
195
  type FrameRate = {
@@ -220,13 +220,20 @@ type FrameRate = {
220
220
  * unknown.
221
221
  */
222
222
  heldBy: "panel" | null;
223
+ /**
224
+ * The share of its resolution the canvas draws at for the adaptive rule: 1, or a step of 0.85, 0.75, 0.6 and 0.5
225
+ * down to the floor the renderer allows on a GPU-bound screen. Always 1 without `adaptive`, outside mode `"auto"` and
226
+ * while the renderer allows no scale.
227
+ */
228
+ scale: number;
223
229
  };
224
230
  /**
225
- * Payload of `time:rate`: a change of the loop's rate or of its mode, with the evidence the rule read.
231
+ * Payload of `time:rate`: a change of the loop's rate, of its mode or of the render scale, with the evidence the rule
232
+ * read. A change of the scale alone has `from` equal to `to`.
226
233
  *
227
234
  * @example
228
235
  * ```ts
229
- * const change: RateChange = { from: 120, to: 60, reason: "missed", mode: "auto", displayHz: 120, thermal: "none", window: { drawn: 41, missed: 9, heavy: 0 }, dwellMs: 5000 };
236
+ * const change: RateChange = { from: 120, to: 120, reason: "missed", mode: "auto", displayHz: 120, thermal: "none", window: { drawn: 41, missed: 9, heavy: 0 }, dwellMs: 5000, scale: 0.85 };
230
237
  * ```
231
238
  */
232
239
  type RateChange = {
@@ -240,8 +247,9 @@ type RateChange = {
240
247
  drawn: number;
241
248
  missed: number;
242
249
  heavy: number;
243
- }; /** How long a return must now wait at the lower rate, ms; 0 without `adaptive`. */
244
- dwellMs: number;
250
+ }; /** How long a return must now wait at the lower rate, ms (twice that for a step up of the scale); 0 without `adaptive`. */
251
+ dwellMs: number; /** The render scale after the change, as `FrameRate.scale`. */
252
+ scale: number;
245
253
  };
246
254
  /**
247
255
  * What `time` measured of one frame, handed to the measure listeners after the `render` phase. One object, rewritten
@@ -338,8 +346,8 @@ type Events$7 = {
338
346
  */
339
347
  "time:thermal": ThermalReading;
340
348
  /**
341
- * The loop's frame rate or its mode changed (the adaptive rule, the display, the thermal input or `setRate`).
342
- * Never per frame, never at start.
349
+ * The loop's frame rate, its mode or the render scale changed (the adaptive rule, the display, the thermal input or
350
+ * `setRate`). Never per frame, never at start.
343
351
  */
344
352
  "time:rate": RateChange;
345
353
  };
@@ -457,7 +465,8 @@ type DisplayState = {
457
465
  * The loop's frame rate and what decides it. Not public: exported for `rate.ts`.
458
466
  */
459
467
  type RateState = {
460
- /** The loop's rate now; `maxFps` at creation. */fps: number; /** `"auto"` with `adaptive`, else `"fixed"`, until `setRate` forces a number. */
468
+ /** The loop's rate now; `maxFps` at creation. */fps: number; /** The render scale the adaptive rule chose; 1 at creation. */
469
+ scale: number; /** `"auto"` with `adaptive`, else `"fixed"`, until `setRate` forces a number. */
461
470
  mode: RateMode; /** The reason of the last change; `"start"` at creation. */
462
471
  reason: RateReason; /** `frameDrawn()` was called during the running frame. */
463
472
  drawnNow: boolean; /** `frameProbed()` was called during the running frame. */
@@ -474,7 +483,8 @@ type RateState = {
474
483
  */
475
484
  type Governor = {
476
485
  /** The lowest rate the rule may choose. */floor: number; /** The rates the rule chooses from, highest first, frozen; empty until the display rate is known. */
477
- ladder: readonly number[]; /** The shell's last thermal status; `null` before the first reading. */
486
+ ladder: readonly number[]; /** The render scales the rule steps through before a rate, highest first, frozen; empty while the renderer allows none. */
487
+ scales: readonly number[]; /** The shell's last thermal status; `null` before the first reading. */
478
488
  thermal: ThermalStatus | null; /** The frame that ran last was drawn. */
479
489
  lastDrawn: boolean; /** The frame that ran last ran under the idle cap. */
480
490
  lastIdle: boolean; /** The frame that ran last drew warm-up probes. */
@@ -482,18 +492,20 @@ type Governor = {
482
492
  lastWorkMs: number; /** The rate the frame that ran last ran at. */
483
493
  lastFps: number; /** The next interval is not judged: set at creation, at every switch and at `resume()`. */
484
494
  skipNext: boolean; /** Timestamp of each sample, a ring of `RING`. */
485
- sampleAt: Float64Array; /** Flags of each sample: bit 0 missed, bit 1 heavy. */
495
+ sampleAt: Float64Array; /** Flags of each sample: bit 0 missed, bit 1 heavy, bit 2 missed and busy. */
486
496
  sampleFlags: Uint8Array; /** Samples written since creation: the next slot is `written % RING`. */
487
497
  written: number; /** The oldest sample of the drop window. */
488
498
  dropTail: number; /** Samples in the drop window. */
489
499
  dropDrawn: number; /** Late samples in the drop window. */
490
- dropMissed: number; /** The oldest sample of the return window. */
500
+ dropMissed: number; /** Late samples in the drop window whose frame was busy on the main thread. */
501
+ dropBusy: number; /** The oldest sample of the return window. */
491
502
  returnTail: number; /** Samples in the return window. */
492
503
  returnDrawn: number; /** Late samples in the return window. */
493
504
  returnMissed: number; /** Heavy samples in the return window. */
494
505
  returnHeavy: number; /** When the rate or its mode last changed. */
495
506
  switchedAt: number; /** When the rule last returned a step up; -Infinity before the first return. */
496
- lastReturnAt: number; /** How long a return waits after a switch, ms. */
507
+ lastReturnAt: number; /** The last step of the rule was a return: its first drop judges it. */
508
+ climbed: boolean; /** How long a return waits after a switch, ms. */
497
509
  dwellMs: number; /** The rate last asked of the shell. */
498
510
  requested: number; /** Sequence number of the last request: an answer to an older one is stale. */
499
511
  requestSeq: number;
@@ -695,8 +707,8 @@ type Api$7 = {
695
707
  chargeAgent(ms: number): void;
696
708
  /**
697
709
  * The loop's frame rate now: the rate, who decides it, why it is what it is, the display rate and the ladder the
698
- * adaptive rule chooses from, and the native shell's thermal status. One frozen object, the same until something in
699
- * it changes: cheap to read every frame.
710
+ * adaptive rule chooses from, the native shell's thermal status and the render scale. One frozen object, the same
711
+ * until something in it changes: cheap to read every frame.
700
712
  *
701
713
  * `fps` is the rate the loop really runs at; `asked` the rate it is told to hold outside the adaptive rule, and
702
714
  * `heldBy: "panel"` says the panel is slower than that.
@@ -705,11 +717,11 @@ type Api$7 = {
705
717
  * @example
706
718
  * ```ts
707
719
  * // The settings screen shows the rate the game runs at on this phone.
708
- * app.time.rate(); // { fps: 120, mode: "auto", reason: "start", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null }
720
+ * app.time.rate(); // { fps: 120, mode: "auto", reason: "start", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null, scale: 1 }
709
721
  * // on the memory screen of a weak phone, a second later:
710
- * app.time.rate(); // { fps: 60, mode: "auto", reason: "missed", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null }
722
+ * app.time.rate(); // { fps: 60, mode: "auto", reason: "missed", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null, scale: 0.75 }
711
723
  * // a game with maxFps 120 and no adaptive, on a 60 Hz phone:
712
- * app.time.rate(); // { fps: 60, mode: "fixed", reason: "start", displayHz: 60, ladder: [], thermal: null, asked: 120, heldBy: "panel" }
724
+ * app.time.rate(); // { fps: 60, mode: "fixed", reason: "start", displayHz: 60, ladder: [], thermal: null, asked: 120, heldBy: "panel", scale: 1 }
713
725
  * ```
714
726
  */
715
727
  rate(): Readonly<FrameRate>;
@@ -717,8 +729,9 @@ type Api$7 = {
717
729
  * Forces the frame rate, or gives it back with `"auto"`. A number is the cap from now on, like a `maxFps` of that
718
730
  * value (never above `maxFps`): the adaptive rule and the thermal input leave it alone. `"auto"` hands the rate back
719
731
  * to the config: the top of the adaptive ladder (a step lower while the shell reports heat), or `maxFps` without
720
- * `adaptive`. A choice equal to the current one changes nothing, so a game may apply its player's setting on every
721
- * commit. Every change emits `time:rate` and asks the native shell for the panel rate.
732
+ * `adaptive`. Both start the render scale over at 1. A choice equal to the current one changes nothing, so a game may
733
+ * apply its player's setting on every commit. Every change emits `time:rate` and asks the native shell for the panel
734
+ * rate.
722
735
  *
723
736
  * @param choice - `"auto"`, 30, 60 or 120.
724
737
  * @returns The frame rate after the call.
@@ -726,14 +739,49 @@ type Api$7 = {
726
739
  * @example
727
740
  * ```ts
728
741
  * // The player picked "60" in the settings to save battery.
729
- * app.time.setRate(60); // { fps: 60, mode: "forced", reason: "forced", displayHz: 120, ladder: [120, 60], thermal: "none", asked: 60, heldBy: null }
742
+ * app.time.setRate(60); // { fps: 60, mode: "forced", reason: "forced", displayHz: 120, ladder: [120, 60], thermal: "none", asked: 60, heldBy: null, scale: 1 }
730
743
  * // …and later "Auto" again, on a 120 Hz phone:
731
- * app.time.setRate("auto"); // { fps: 120, mode: "auto", reason: "auto", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null }
744
+ * app.time.setRate("auto"); // { fps: 120, mode: "auto", reason: "auto", displayHz: 120, ladder: [120, 60], thermal: "none", asked: null, heldBy: null, scale: 1 }
732
745
  * // A pin of 120 on a 60 Hz phone runs at the panel's rate:
733
- * app.time.setRate(120); // { fps: 60, mode: "forced", reason: "forced", displayHz: 60, ladder: [60], thermal: "none", asked: 120, heldBy: "panel" }
746
+ * app.time.setRate(120); // { fps: 60, mode: "forced", reason: "forced", displayHz: 60, ladder: [60], thermal: "none", asked: 120, heldBy: "panel", scale: 1 }
734
747
  * ```
735
748
  */
736
749
  setRate(choice: RateChoice): Readonly<FrameRate>;
750
+ /**
751
+ * Lets the adaptive frame rate lower the render scale before it lowers the rate. When the late frames of a window
752
+ * kept the main thread no longer than their frame (from their timestamp, a stall that held the callback included) the
753
+ * screen is GPU-bound: the rule steps the scale down through 0.85, 0.75, 0.6 and 0.5 to `floor` (at the lowest rate
754
+ * too), and only then drops the rate. The way back is the reverse: the rate first, at the scale it dropped at, then
755
+ * the scale, a step after twice the dwell. A late window busy on the main thread skips the scale. For engine
756
+ * plugins: the renderer calls it at start with the floor of its `adaptiveScale`, with 1 while a player's resolution
757
+ * holds, and with the floor again after. A scale under a new floor goes up to it at once, without `time:rate`.
758
+ * Without `adaptive` nothing changes.
759
+ *
760
+ * @param floor - The lowest share of its resolution the canvas may draw at; 1 allows no scale.
761
+ * @returns The frame rate after the call.
762
+ * @example
763
+ * ```ts
764
+ * // The renderer on a phone, at start:
765
+ * ctx.require(timePlugin).allowScale(0.75); // { fps: 120, …, scale: 1 }
766
+ * // on the memory screen of a weak phone, half a second later:
767
+ * app.time.rate(); // { fps: 120, mode: "auto", reason: "missed", …, scale: 0.75 }
768
+ * // the player picked a resolution in the settings: the renderer takes the scale away from the rule
769
+ * ctx.require(timePlugin).allowScale(1); // { fps: 120, …, scale: 1 }
770
+ * ```
771
+ */
772
+ allowScale(floor: number): Readonly<FrameRate>;
773
+ /**
774
+ * Tells the adaptive frame rate that a new scene stands: the back-off of failed returns starts over at a dwell of
775
+ * 5 s, and the new screen is judged on its own frames (both windows start empty, the first interval is skipped). The
776
+ * rate and the scale stay. For engine plugins: `scenes` calls it when a switch has built the new scene.
777
+ *
778
+ * @example
779
+ * ```ts
780
+ * // scenes, once the new scene stands:
781
+ * ctx.require(timePlugin).sceneChanged(); // the next return waits 5 s, not the 40 s three failed returns had grown
782
+ * ```
783
+ */
784
+ sceneChanged(): void;
737
785
  /**
738
786
  * Tells the clock that the frame running now was drawn. For engine plugins: the renderer calls it from its `render`
739
787
  * phase after Pixi drew; a frame without it — a still screen under `onDemand` — never counts for the adaptive
@@ -9004,9 +9052,10 @@ type PerfLongFrameLine = PerfLine<"longFrame"> & LongFrameEntry & {
9004
9052
  * The names of `event` lines (`"devtools"` is the editor's overlay event, in 2b because the editor's page agent emits
9005
9053
  * it on the 2b debug build; `"pool-trim"` is the pool trim of spec 25, detail `PoolTrimDetail`; `"warm"` is the end of
9006
9054
  * a pipeline warm-up run of spec 27, detail `WarmDetail`; `"sections"` is a switch of the monitor's sections, detail
9007
- * `{ on, off }`: the names of the sections on and off, in the order of `MONITOR_SECTIONS`).
9055
+ * `{ on, off }`: the names of the sections on and off, in the order of `MONITOR_SECTIONS`; `"scale"` is a move of the
9056
+ * render scale of the adaptive frame rate, detail `{ from, to, reason, fps }`).
9008
9057
  */
9009
- type PerfEventName = "scene" | "overlay" | "bundle" | "compile" | "upload" | "resolution" | "device-lost" | "device-restored" | "pause" | "resume" | "switch" | "display" | "command" | "recorder" | "rate" | "devtools" | "pool-trim" | "warm" | "shader" | "problem" | "debug" | "sections";
9058
+ type PerfEventName = "scene" | "overlay" | "bundle" | "compile" | "upload" | "resolution" | "device-lost" | "device-restored" | "pause" | "resume" | "switch" | "display" | "command" | "recorder" | "rate" | "devtools" | "pool-trim" | "warm" | "shader" | "problem" | "debug" | "sections" | "scale";
9010
9059
  /**
9011
9060
  * What an `overlay` event line says happened to an overlay (spec 22 O10.2): it opened, landed (its enter motion is
9012
9061
  * over), started to leave, is gone, or its range went live or was kept again (the live fallback).
@@ -9244,23 +9293,26 @@ type PerfLogLine = PerfHeaderLine | PerfStartupLine | PerfSampleLine | PerfSpike
9244
9293
  //#endregion
9245
9294
  //#region src/plugins/renderer/host/resolution.d.ts
9246
9295
  /**
9247
- * Why the resolution changed. Exported: `HostInternal` and spec 14's demand subscriber use it (11-I14).
9296
+ * Why the resolution changed: the device pixels, a setting, the debug switch, the render scale of the adaptive frame
9297
+ * rate. Exported: `HostInternal` and spec 14's demand subscriber use it (11-I14).
9248
9298
  */
9249
- type ResolutionReason = "dpr" | "setting" | "debug";
9299
+ type ResolutionReason = "dpr" | "setting" | "debug" | "rate";
9250
9300
  //#endregion
9251
9301
  //#region src/plugins/renderer/host/types.d.ts
9252
9302
  /**
9253
- * Where the drawing resolution comes from (contract C-d): the device pixels, the cap, the switch
9254
- * that overrides both, and the change the next frame applies. Not public.
9303
+ * Where the drawing resolution comes from (contract C-d): the device pixels, the cap, the render scale of the adaptive
9304
+ * frame rate, the switch that overrides them, and the change the next frame applies. Not public.
9255
9305
  */
9256
9306
  type ResolutionState = {
9257
9307
  /** The last `devicePixelRatio` seen; 1 without a window. */dpr: number; /** `maxResolution` of the config. */
9258
- cap: number; /** Set by `monitor.setResolution`; `undefined` hands the choice back to `dpr` and `cap`. */
9308
+ cap: number; /** Set by `monitor.setResolution`; `undefined` hands the choice back to `dpr`, `cap` and `scale`. */
9259
9309
  override: number | undefined; /** A change asked for and not applied yet: the next frame resizes with it. */
9260
9310
  pending: {
9261
9311
  value: number;
9262
9312
  reason: ResolutionReason;
9263
- } | undefined;
9313
+ } | undefined; /** The render scale the adaptive frame rate chose, a share of `min(dpr, cap)`; 1 at start. */
9314
+ scale: number; /** The lowest scale `adaptiveScale` allows on this device, read at init; 1 allows none. */
9315
+ floor: number;
9264
9316
  };
9265
9317
  /**
9266
9318
  * A listener of a resolution change: what Pixi drew at, what it draws at now, and why.
@@ -9333,7 +9385,13 @@ type HostState = {
9333
9385
  * filter's input again after a cached group refreshed inside it (F10), went into Pixi's registry; `undefined` while
9334
9386
  * inert and when the module lacked the pieces.
9335
9387
  */
9336
- uninstallRenderGroup: (() => void) | undefined; /** The drawing resolution: device pixels, cap, override and the pending change. */
9388
+ uninstallRenderGroup: (() => void) | undefined;
9389
+ /**
9390
+ * Swaps Pixi's own WebGPU render target and pipeline systems back in. Set once per host state when the lazy canvas
9391
+ * pass (B3), which begins the canvas's pass at its first draw and keeps its stencil and depth only where something
9392
+ * reads them, went into Pixi's registry; `undefined` while inert and when the module lacked the pieces.
9393
+ */
9394
+ uninstallRenderPass: (() => void) | undefined; /** The drawing resolution: device pixels, cap, override and the pending change. */
9337
9395
  resolution: ResolutionState; /** Run after a frame applied a new resolution; emptied by `stopHost`. */
9338
9396
  onResolutionChange: ResolutionListener[]; /** The engine's own adapter and device of an agent build on WebGPU; `undefined` otherwise. */
9339
9397
  ownGpu: OwnGpu | undefined; /** Texture sources the engine keeps as pictures (F12, C14): `textures()` counts them apart. */
@@ -10528,7 +10586,7 @@ type PictureRequest = {
10528
10586
  reject: (error: Error) => void;
10529
10587
  };
10530
10588
  declare namespace types_d_exports$2 {
10531
- export { Api$1 as Api, AspectRange, BitmapFontData, CaptureOptions, Captured, Config$2 as Config, CountingClasses, CoverFrame, CreateTextureOptions$1 as CreateTextureOptions, DebugApi, DebugSwitches, DemandFrame, DemandModule, DemandReason, DemandState, Deps$2 as Deps, DisplayAdapter, DisplayEntry, DisplaysApi, DrawCounter, Events$2 as Events, FilterCache, FilterSlot, FilterSlotInputs, FiltersApi, FontsApi, FrameColumns, FrameReadResult, FrameReadout, FrameRecord, FrameRing, HitBox, HostApi, HostInternal, HostModule, HostState, HudPartValue, KeptInternal, KeptModule, KeptRange, KeptState, KeptStats, KernelSlice$2 as KernelSlice, LayerEntry, LegendEntry, LongFrameEntry, Modules, MonitorApi, MonitorConfig, MonitorCounts, MonitorDeps, MonitorInternal, MonitorModule, MonitorSections, MonitorState, NineBorders$1 as NineBorders, Orientation, OverlayEventDetail, OverlayLevelValue, OverlayMode, OverlayPhase, OverlayReport, OverlayValue, OverlayWhat, PassKind, PassRecord, PerfCause, PerfChange, PerfChangeEntry, PerfCollectorLine, PerfCounts, PerfDisplay, PerfEventLine, PerfEventName, PerfGapLine, PerfHeaderLine, PerfLogLine, PerfLongFrameLine, PerfMarkLine, PerfMeasured, PerfMonitorApi, PerfSampleLine, PerfSpikeLine, PerfStartupLine, PerfTelemetryLine, PerfThermalLine, PictureRect, PixiApplication, PixiBitmapFont, PixiBounds, PixiContainer, PixiFilter, PixiFilterManager, PixiGraphics, PixiMatrix, PixiModule, PixiNineSliceSprite, PixiRectangle, PixiRenderTexture, PixiSprite, PixiTexture, Point, PoolTrim, PoolTrimDetail, ProblemEventDetail, ProblemRule, Rect, RenderStats, RendererCtx, RendererKind, SafeArea, ShaderEventDetail, ShaderWhat, SliceFrame, State$2 as State, SyncApi, SyncCounts, SyncInternal, SyncModule, SyncState, TeardownScope, TextureProvider, TextureUsage, TexturesApi, Under, View, ViewKind, ViewportApi, ViewportInternal, ViewportModule, ViewportSize, ViewportState, WarmDetail };
10589
+ export { AdaptiveScale, Api$1 as Api, AspectRange, BitmapFontData, CaptureOptions, Captured, Config$2 as Config, CountingClasses, CoverFrame, CreateTextureOptions$1 as CreateTextureOptions, DebugApi, DebugSwitches, DemandFrame, DemandModule, DemandReason, DemandState, Deps$2 as Deps, DisplayAdapter, DisplayEntry, DisplaysApi, DrawCounter, Events$2 as Events, FilterCache, FilterSlot, FilterSlotInputs, FiltersApi, FontsApi, FrameColumns, FrameReadResult, FrameReadout, FrameRecord, FrameRing, HitBox, HostApi, HostInternal, HostModule, HostState, HudPartValue, KeptInternal, KeptModule, KeptRange, KeptState, KeptStats, KernelSlice$2 as KernelSlice, LayerEntry, LegendEntry, LongFrameEntry, Modules, MonitorApi, MonitorConfig, MonitorCounts, MonitorDeps, MonitorInternal, MonitorModule, MonitorSections, MonitorState, NineBorders$1 as NineBorders, Orientation, OverlayEventDetail, OverlayLevelValue, OverlayMode, OverlayPhase, OverlayReport, OverlayValue, OverlayWhat, PassKind, PassRecord, PerfCause, PerfChange, PerfChangeEntry, PerfCollectorLine, PerfCounts, PerfDisplay, PerfEventLine, PerfEventName, PerfGapLine, PerfHeaderLine, PerfLogLine, PerfLongFrameLine, PerfMarkLine, PerfMeasured, PerfMonitorApi, PerfSampleLine, PerfSpikeLine, PerfStartupLine, PerfTelemetryLine, PerfThermalLine, PictureRect, PixiApplication, PixiBitmapFont, PixiBounds, PixiContainer, PixiFilter, PixiFilterManager, PixiGraphics, PixiMatrix, PixiModule, PixiNineSliceSprite, PixiRectangle, PixiRenderTexture, PixiSprite, PixiTexture, Point, PoolTrim, PoolTrimDetail, ProblemEventDetail, ProblemRule, Rect, RenderStats, RendererCtx, RendererKind, SafeArea, ShaderEventDetail, ShaderWhat, SliceFrame, State$2 as State, SyncApi, SyncCounts, SyncInternal, SyncModule, SyncState, TeardownScope, TextureProvider, TextureUsage, TexturesApi, Under, View, ViewKind, ViewportApi, ViewportInternal, ViewportModule, ViewportSize, ViewportState, WarmDetail };
10532
10590
  }
10533
10591
  /**
10534
10592
  * The part of Pixi the engine uses: the classes `sync` builds views from (a `Rectangle` frames the
@@ -10540,7 +10598,9 @@ declare namespace types_d_exports$2 {
10540
10598
  * (the three WebGPU draw classes, the filter system, both texture systems and the batcher pipe whose `buildStart`
10541
10599
  * begins every instruction rebuild; production swaps the encoder alone, to count the passes), and the pieces of
10542
10600
  * batched distance-field text `host` installs: Pixi's `Batcher` with its geometry and buffers, the bitmap text pipe
10543
- * and the batcher pipe it subclasses, and the WGSL and GLSL shader pieces of the batch's SDF shader. The module object
10601
+ * and the batcher pipe it subclasses, and the WGSL and GLSL shader pieces of the batch's SDF shader, and the WebGPU
10602
+ * render target system with its adaptor, the pipeline system and the stencil system the lazy canvas pass of `host`
10603
+ * subclasses or registers again (`host/render-pass.ts`). The module object
10544
10604
  * never arrives through a static import: `config.loadPixi()` returns it, so a game without a screen carries no
10545
10605
  * Pixi in its bundle.
10546
10606
  *
@@ -10556,7 +10616,7 @@ declare namespace types_d_exports$2 {
10556
10616
  * pixi.defaultFilterVert.startsWith("in vec2 aPosition;"); // true
10557
10617
  * ```
10558
10618
  */
10559
- type PixiModule = Pick<typeof import("pixi.js"), "AlphaFilter" | "Application" | "Batcher" | "BatcherPipe" | "BitmapFont" | "BitmapText" | "BitmapTextPipe" | "BlurFilter" | "Bounds" | "Buffer" | "BufferUsage" | "Cache" | "ColorMatrixFilter" | "Container" | "DefaultBatcher" | "DisplacementFilter" | "ExtensionType" | "Filter" | "FilterSystem" | "Geometry" | "GlProgram" | "GlTextureSystem" | "GpuBatchAdaptor" | "GpuEncoderSystem" | "GpuGraphicsAdaptor" | "GpuProgram" | "GpuTextureSystem" | "Graphics" | "Matrix" | "NineSliceSprite" | "NoiseFilter" | "Particle" | "ParticleContainer" | "Rectangle" | "RenderGroupPipe" | "RenderTexture" | "Shader" | "Sprite" | "Texture" | "TexturePool" | "UniformGroup" | "bitmapFontTextParser" | "bitmapFontXMLStringParser" | "colorBit" | "colorBitGl" | "compileHighShaderGlProgram" | "compileHighShaderGpuProgram" | "defaultFilterVert" | "extensions" | "generateTextureBatchBit" | "generateTextureBatchBitGl" | "getBatchSamplersUniformGroup" | "mSDFBit" | "mSDFBitGl" | "roundPixelsBit" | "roundPixelsBitGl">;
10619
+ type PixiModule = Pick<typeof import("pixi.js"), "AlphaFilter" | "Application" | "Batcher" | "BatcherPipe" | "BitmapFont" | "BitmapText" | "BitmapTextPipe" | "BlurFilter" | "Bounds" | "Buffer" | "BufferUsage" | "Cache" | "ColorMatrixFilter" | "Container" | "DefaultBatcher" | "DisplacementFilter" | "ExtensionType" | "Filter" | "FilterSystem" | "Geometry" | "GlProgram" | "GlTextureSystem" | "GpuBatchAdaptor" | "GpuEncoderSystem" | "GpuGraphicsAdaptor" | "GpuProgram" | "GpuRenderTargetAdaptor" | "GpuRenderTargetSystem" | "GpuStencilSystem" | "GpuTextureSystem" | "Graphics" | "Matrix" | "NineSliceSprite" | "NoiseFilter" | "Particle" | "ParticleContainer" | "PipelineSystem" | "Rectangle" | "RenderGroupPipe" | "RenderTexture" | "Shader" | "Sprite" | "Texture" | "TexturePool" | "UniformGroup" | "bitmapFontTextParser" | "bitmapFontXMLStringParser" | "colorBit" | "colorBitGl" | "compileHighShaderGlProgram" | "compileHighShaderGpuProgram" | "defaultFilterVert" | "extensions" | "generateTextureBatchBit" | "generateTextureBatchBitGl" | "getBatchSamplersUniformGroup" | "mSDFBit" | "mSDFBitGl" | "roundPixelsBit" | "roundPixelsBitGl">;
10560
10620
  /**
10561
10621
  * One Pixi application: renderer, canvas and stage.
10562
10622
  */
@@ -10679,6 +10739,24 @@ type PoolTrim = {
10679
10739
  */
10680
10740
  aboveMb: number;
10681
10741
  };
10742
+ /**
10743
+ * The render scale the adaptive frame rate may lower on a GPU-bound screen (`time.adaptive` on): before the rate drops,
10744
+ * the canvas draws at 0.85, then 0.75 of its resolution, down to `floor`, and back up when there is room again.
10745
+ *
10746
+ * @example
10747
+ * ```ts
10748
+ * // The default: on a phone the memory screen draws at 1.5 instead of 2 before it drops to 60 fps.
10749
+ * const scale: AdaptiveScale = { floor: 0.75, devices: "phone" };
10750
+ * createApp({ pluginConfigs: { renderer: { mount: "#game", adaptiveScale: scale }, time: { maxFps: 120, adaptive: { floor: 60 } } } });
10751
+ * ```
10752
+ */
10753
+ type AdaptiveScale = {
10754
+ /** The lowest share of the resolution, a step of the scale: 1, 0.85, 0.75, 0.6 or 0.5. 1 allows none. */floor: number;
10755
+ /**
10756
+ * Where it applies: `"phone"`, a coarse pointer and a short side of at most 820 CSS px (read at start), or `"all"`.
10757
+ */
10758
+ devices: "phone" | "all";
10759
+ };
10682
10760
  /**
10683
10761
  * renderer plugin config.
10684
10762
  *
@@ -10697,6 +10775,8 @@ type PoolTrim = {
10697
10775
  * createApp({ pluginConfigs: { renderer: { mount: "#game", keptMb: 32 } } }); // a game with small art
10698
10776
  * // A short splash: two probe draws a frame create the pipelines sooner.
10699
10777
  * createApp({ pluginConfigs: { renderer: { mount: "#game", onDemand: true, warm: 2 } } });
10778
+ * // A game whose art must stay sharp: the adaptive frame rate drops the rate, never the resolution.
10779
+ * createApp({ pluginConfigs: { renderer: { mount: "#game", adaptiveScale: false } } });
10700
10780
  * ```
10701
10781
  */
10702
10782
  type Config$2 = {
@@ -10744,6 +10824,12 @@ type Config$2 = {
10744
10824
  * created in the first frame that draws with it, as before. A whole number from 0 to 16; default 1.
10745
10825
  */
10746
10826
  warm: number;
10827
+ /**
10828
+ * The render scale of the adaptive frame rate on a GPU-bound screen: `{ floor: 0.75, devices: "phone" }` by default,
10829
+ * `false` keeps the resolution. Needs `time.adaptive`. A player's `monitor.setResolution` wins over it. Every change
10830
+ * of the scale redraws the canvas and retakes the kept pictures once.
10831
+ */
10832
+ adaptiveScale: AdaptiveScale | false;
10747
10833
  };
10748
10834
  /**
10749
10835
  * The performance monitor of an agent build (`__MOKU_GAME_AGENT__`: dev and `--debug` builds): the spike budget, the
@@ -12203,4 +12289,4 @@ type BundleCompanion = {
12203
12289
  unload(bundle: string): void;
12204
12290
  };
12205
12291
  //#endregion
12206
- export { PassKind as $, FlowGraph as $n, Explained as $t, PixiSprite as A, TrackSegment as An, SaveUnreadableError as Ar, Orientation as At, FrameReadResult as B, TextStylesOf as Bn, State$7 as Br, OverlayValue as Bt, State$1 as C, MotionCause as Cn, Root as Cr, SHADER_WHATS as Ct, MonitorConfig as D, ProjectionSpec as Dn, PlayerStateProvider as Dr, DebugSwitches as Dt, Config$2 as E, ProjectionMotion as En, Patch as Er, WarmDetail as Et, types_d_exports$2 as F, EmitterIdOf as Fn, RngState as Fr, HudPart as Ft, MONITOR_SECTIONS as G, to as Gn, RateChange as Gr, SpriteOptions as Gt, FrameRecord as H, defineFlow as Hn, Api$7 as Hr, Shape as Ht, Captured as I, GameTypes as In, Api$6 as Ir, HudPartValue as It, OverlayWhat as J, FeaturePlugin as Jn, Time as Jr, TransformValue as Jt, MonitorSections as K, type as Kn, State$8 as Kr, SpriteValue as Kt, MonitorCounts as L, HudKeysOf as Ln, Config$7 as Lr, NineSlice$1 as Lt, PoolTrim as M, Api$3 as Mn, SnapshotOf as Mr, ViewportSize as Mt, State$2 as N, BundlesOf as Nn, StoreApi as Nr, FilterCache as Nt, PixiFilter as O, ReducedMotion as On, ProviderCall as Or, FilterSlot as Ot, Under as P, Config$4 as Pn, RngApi as Pr, Display as Pt, PROBLEM_RULES as Q, DefineNode as Qn, Require as Qr, Config$3 as Qt, RenderStats as R, Position as Rn, Events$6 as Rr, NineSliceValue as Rt, ScenesApi as S, Motion as Sn, Json as Sr, ProblemRule as St, Api$1 as T, NumericFields as Tn, types_d_exports$6 as Tr, ShaderWhat as Tt, FrameRing as U, exit as Un, Config$8 as Ur, ShapeValue as Ut, FrameReadout as V, types_d_exports$4 as Vn, types_d_exports$7 as Vr, Parent as Vt, LongFrameEntry as W, slot as Wn, FrameRate as Wr, Sprite as Wt, PERF_GAP_BUCKETS as X, AnyFlow as Xn, Config$9 as Xr, DEMAND_REASONS as Xt, PERF_CAUSES as Y, FeatureTree as Yn, types_d_exports$8 as Yr, sprite as Yt, PERF_LOG_VERSION as Z, Bookmark as Zn, Events$8 as Zr, Api$2 as Zt, DefineScene as _, SystemFor as _n, State$5 as _r, PerfStartupLine as _t, Config as a, ComponentHandle as an, TypeTag as ar, PerfCounts as at, SceneDefinition as b, DescriptionNode as bn, Config$6 as br, PoolTrimDetail as bt, LoadBundles as c, ComponentValue as cn, EffectOptions as cr, PerfEventName as ct, Manifest as d, FrameDiff as dn, NodeFx as dr, PerfLogLine as dt, State$3 as en, FlowState as er, PassRecord as et, State as f, Mut as fn, Answer as fr, PerfLongFrameLine as ft, AnySceneProjection as g, SystemDefinition as gn, FakeClock as gr, PerfSpikeLine as gt, types_d_exports as h, ResourceType as hn, Config$5 as hr, PerfSampleLine as ht, BundleSpec as i, AnyComponentValue as in, SceneIdOf as ir, PerfCollectorLine as it, PixiTexture as j, ViewHandle as jn, Snapshot as jr, Point as jt, PixiModule as k, TrackOptions as kn, SaveDoc as kr, FilterSlotInputs as kt, LoadReason as l, Entity as ln, GuideOptions as lr, PerfGapLine as lt, Usage as m, QueryTerm as mn, ClockSource as mr, PerfMeasured as mt, AssetsIo as n, AnyComponent as nn, NodeTable as nr, PerfChange as nt, DefineBundles as o, ComponentSchema as on, Descriptor as or, PerfDisplay as ot, Tier as p, Narrowed as pn, Api$4 as pr, PerfMarkLine as pt, OverlayEventDetail as q, FeatureDescription as qn, ThermalReading as qr, Transform as qt, BundleMap as r, AnyComponentType as rn, RouteStep as rr, PerfChangeEntry as rt, Events as s, ComponentType as sn, Effect as sr, PerfEventLine as st, Api as t, types_d_exports$3 as tn, JournalEntry as tr, PerfCause as tt, LoadResult as u, EntitySnapshot as un, Hint as ur, PerfHeaderLine as ut, Events$1 as v, TagType as vn, types_d_exports$5 as vr, PerfTelemetryLine as vt, types_d_exports$1 as w, MotionHandle as wn, State$6 as wr, ShaderEventDetail as wt, SceneSpec as x, Ease as xn, Events$5 as xr, ProblemEventDetail as xt, LayerMap as y, ChangeHook as yn, Api$5 as yr, PerfThermalLine as yt, FrameColumns as z, State$4 as zn, PauseReason as zr, Overlay as zt };
12292
+ export { PROBLEM_RULES as $, DefineNode as $n, Require as $r, Config$3 as $t, PixiModule as A, TrackOptions as An, SaveDoc as Ar, FilterSlotInputs as At, FrameColumns as B, State$4 as Bn, PauseReason as Br, Overlay as Bt, State$1 as C, Motion as Cn, Json as Cr, ProblemRule as Ct, Config$2 as D, ProjectionMotion as Dn, Patch as Dr, WarmDetail as Dt, Api$1 as E, NumericFields as En, types_d_exports$6 as Er, ShaderWhat as Et, Under as F, Config$4 as Fn, RngApi as Fr, Display as Ft, LongFrameEntry as G, slot as Gn, FrameRate as Gr, Sprite as Gt, FrameReadout as H, types_d_exports$4 as Hn, types_d_exports$7 as Hr, Parent as Ht, types_d_exports$2 as I, EmitterIdOf as In, RngState as Ir, HudPart as It, OverlayEventDetail as J, FeatureDescription as Jn, ThermalReading as Jr, Transform as Jt, MONITOR_SECTIONS as K, to as Kn, RateChange as Kr, SpriteOptions as Kt, Captured as L, GameTypes as Ln, Api$6 as Lr, HudPartValue as Lt, PixiTexture as M, ViewHandle as Mn, Snapshot as Mr, Point as Mt, PoolTrim as N, Api$3 as Nn, SnapshotOf as Nr, ViewportSize as Nt, MonitorConfig as O, ProjectionSpec as On, PlayerStateProvider as Or, DebugSwitches as Ot, State$2 as P, BundlesOf as Pn, StoreApi as Pr, FilterCache as Pt, PERF_LOG_VERSION as Q, Bookmark as Qn, Events$8 as Qr, Api$2 as Qt, MonitorCounts as R, HudKeysOf as Rn, Config$7 as Rr, NineSlice$1 as Rt, ScenesApi as S, Ease as Sn, Events$5 as Sr, ProblemEventDetail as St, AdaptiveScale as T, MotionHandle as Tn, State$6 as Tr, ShaderEventDetail as Tt, FrameRecord as U, defineFlow as Un, Api$7 as Ur, Shape as Ut, FrameReadResult as V, TextStylesOf as Vn, State$7 as Vr, OverlayValue as Vt, FrameRing as W, exit as Wn, Config$8 as Wr, ShapeValue as Wt, PERF_CAUSES as X, FeatureTree as Xn, types_d_exports$8 as Xr, sprite as Xt, OverlayWhat as Y, FeaturePlugin as Yn, Time as Yr, TransformValue as Yt, PERF_GAP_BUCKETS as Z, AnyFlow as Zn, Config$9 as Zr, DEMAND_REASONS as Zt, DefineScene as _, SystemDefinition as _n, FakeClock as _r, PerfSpikeLine as _t, Config as a, AnyComponentValue as an, SceneIdOf as ar, PerfCollectorLine as at, SceneDefinition as b, ChangeHook as bn, Api$5 as br, PerfThermalLine as bt, LoadBundles as c, ComponentType as cn, Effect as cr, PerfEventLine as ct, Manifest as d, EntitySnapshot as dn, Hint as dr, PerfHeaderLine as dt, Explained as en, FlowGraph as er, PassKind as et, State as f, FrameDiff as fn, NodeFx as fr, PerfLogLine as ft, AnySceneProjection as g, ResourceType as gn, Config$5 as gr, PerfSampleLine as gt, types_d_exports as h, QueryTerm as hn, ClockSource as hr, PerfMeasured as ht, BundleSpec as i, AnyComponentType as in, RouteStep as ir, PerfChangeEntry as it, PixiSprite as j, TrackSegment as jn, SaveUnreadableError as jr, Orientation as jt, PixiFilter as k, ReducedMotion as kn, ProviderCall as kr, FilterSlot as kt, LoadReason as l, ComponentValue as ln, EffectOptions as lr, PerfEventName as lt, Usage as m, Narrowed as mn, Api$4 as mr, PerfMarkLine as mt, AssetsIo as n, types_d_exports$3 as nn, JournalEntry as nr, PerfCause as nt, DefineBundles as o, ComponentHandle as on, TypeTag as or, PerfCounts as ot, Tier as p, Mut as pn, Answer as pr, PerfLongFrameLine as pt, MonitorSections as q, type as qn, State$8 as qr, SpriteValue as qt, BundleMap as r, AnyComponent as rn, NodeTable as rr, PerfChange as rt, Events as s, ComponentSchema as sn, Descriptor as sr, PerfDisplay as st, Api as t, State$3 as tn, FlowState as tr, PassRecord as tt, LoadResult as u, Entity as un, GuideOptions as ur, PerfGapLine as ut, Events$1 as v, SystemFor as vn, State$5 as vr, PerfStartupLine as vt, types_d_exports$1 as w, MotionCause as wn, Root as wr, SHADER_WHATS as wt, SceneSpec as x, DescriptionNode as xn, Config$6 as xr, PoolTrimDetail as xt, LayerMap as y, TagType as yn, types_d_exports$5 as yr, PerfTelemetryLine as yt, RenderStats as z, Position as zn, Events$6 as zr, NineSliceValue as zt };
@@ -1,4 +1,4 @@
1
- import { Cn as MotionCause, En as ProjectionMotion, Hr as Api, Jt as TransformValue, Mn as Api$1, Mt as ViewportSize, Qr as Require, Sn as Motion, Sr as Json, T as Api$3, Tn as NumericFields, Zt as Api$2, fr as Answer, in as AnyComponentValue, jn as ViewHandle, ln as Entity, nn as AnyComponent, or as Descriptor, pr as Api$5, rn as AnyComponentType, s as Events$1, sn as ComponentType, t as Api$4, ur as Hint, vn as TagType, wn as MotionHandle, yn as ChangeHook } from "./types-DnttyLeu.mjs";
1
+ import { $r as Require, Cn as Motion, Cr as Json, Dn as ProjectionMotion, E as Api$3, En as NumericFields, Mn as ViewHandle, Nn as Api$1, Nt as ViewportSize, Qt as Api$2, Tn as MotionHandle, Ur as Api, Yt as TransformValue, an as AnyComponentValue, bn as ChangeHook, cn as ComponentType, dr as Hint, in as AnyComponentType, mr as Api$5, pr as Answer, rn as AnyComponent, s as Events$1, sr as Descriptor, t as Api$4, un as Entity, wn as MotionCause, yn as TagType } from "./types-C4D9UVgb.mjs";
2
2
  import { Log } from "@moku-labs/common/browser";
3
3
  import { PluginCtx } from "@moku-labs/core";
4
4
 
@@ -1,5 +1,5 @@
1
- import { Sr as Json, jr as Snapshot } from "./types-DnttyLeu.mjs";
2
- import { t as HeadlessApp } from "./headless-DDkRwLnJ.mjs";
1
+ import { Cr as Json, Mr as Snapshot } from "./types-C4D9UVgb.mjs";
2
+ import { t as HeadlessApp } from "./headless-DobgwTKK.mjs";
3
3
  import { Log } from "@moku-labs/common/browser";
4
4
 
5
5
  //#region src/plugins/flow/doors/types.d.ts
@@ -1,7 +1,7 @@
1
- import { At as Orientation, Dr as PlayerStateProvider, E as Config$2, Jn as FeaturePlugin, Mr as SnapshotOf, Or as ProviderCall, Pn as Config$1, Sr as Json, Xn as AnyFlow, a as Config$3, ar as TypeTag, br as Config, d as Manifest, gr as FakeClock, k as PixiModule, kr as SaveDoc, mr as ClockSource, n as AssetsIo } from "./types-DnttyLeu.mjs";
2
- import { o as AudioContextLike, s as Config$4 } from "./types-C2LZJIxH.mjs";
3
- import { H as TextKey, I as I18nApi, V as StringTable } from "./types-CWSMo70I.mjs";
4
- import { ft as platformPlugin, i as screen, mt as PlatformProvider, t as createApp, wt as audioPlugin, xt as effectsPlugin } from "./index-DytzVJFz.mjs";
1
+ import { A as PixiModule, Ar as SaveDoc, Cr as Json, D as Config$2, Fn as Config$1, Nr as SnapshotOf, Or as PlayerStateProvider, Yn as FeaturePlugin, Zn as AnyFlow, _r as FakeClock, a as Config$3, d as Manifest, hr as ClockSource, jt as Orientation, kr as ProviderCall, n as AssetsIo, or as TypeTag, xr as Config } from "./types-C4D9UVgb.mjs";
2
+ import { o as AudioContextLike, s as Config$4 } from "./types-BkcgFOoB.mjs";
3
+ import { H as TextKey, I as I18nApi, V as StringTable } from "./types-CZGuMhV8.mjs";
4
+ import { ft as platformPlugin, i as screen, mt as PlatformProvider, t as createApp, wt as audioPlugin, xt as effectsPlugin } from "./index-CU4Oc2Qv.mjs";
5
5
  import { AnyPluginInstance } from "@moku-labs/core";
6
6
 
7
7
  //#region src/plugins/model/store/providers/memory.d.ts
@@ -1,9 +1,9 @@
1
- import { Ir as Api$3, T as Api, Zt as Api$1, yr as Api$2 } from "./types-DnttyLeu.mjs";
2
- import { P as AnimApi, r as UiApi } from "./types-C2LZJIxH.mjs";
3
- import { j as InputApi } from "./types-CWSMo70I.mjs";
4
- import { r as Repro } from "./headless-DDkRwLnJ.mjs";
5
- import { a as InputOf, r as ControlApp } from "./types-DFoxDq-g.mjs";
6
- import { t as commands } from "./commands-CAEwtEAy.mjs";
1
+ import { E as Api, Lr as Api$3, Qt as Api$1, br as Api$2 } from "./types-C4D9UVgb.mjs";
2
+ import { P as AnimApi, r as UiApi } from "./types-BkcgFOoB.mjs";
3
+ import { j as InputApi } from "./types-CZGuMhV8.mjs";
4
+ import { r as Repro } from "./headless-DobgwTKK.mjs";
5
+ import { a as InputOf, r as ControlApp } from "./types-Mj75CDO6.mjs";
6
+ import { t as commands } from "./commands-C8aWbThW.mjs";
7
7
 
8
8
  //#region src/visual/types.d.ts
9
9
  /** The base commands of the `/control` door, keyed by their short names. */
package/dist/visual.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as VisualApp, c as VisualRenderer, d as VisualStart, f as VisualStep, h as VisualTolerance, i as CheckpointResult, l as VisualReport, m as VisualTestResult, n as runVisualTests, o as VisualOptions, p as VisualTest, r as defineVisualTest, s as VisualPage, t as parseVisualArgv, u as VisualSetup } from "./visual-gTuXlmvH.mjs";
1
+ import { a as VisualApp, c as VisualRenderer, d as VisualStart, f as VisualStep, h as VisualTolerance, i as CheckpointResult, l as VisualReport, m as VisualTestResult, n as runVisualTests, o as VisualOptions, p as VisualTest, r as defineVisualTest, s as VisualPage, t as parseVisualArgv, u as VisualSetup } from "./visual-BV2A3kpr.mjs";
2
2
  export { type CheckpointResult, type VisualApp, type VisualOptions, type VisualPage, type VisualRenderer, type VisualReport, type VisualSetup, type VisualStart, type VisualStep, type VisualTest, type VisualTestResult, type VisualTolerance, defineVisualTest, parseVisualArgv, runVisualTests };
package/dist/visual.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as read, t as sources } from "./sources-OvHvyeJS.mjs";
2
- import { n as commands, t as run } from "./run-C07NXds7.mjs";
2
+ import { n as commands, t as run } from "./run-DlxDjgOO.mjs";
3
3
  import path from "node:path";
4
4
  import { createBrandConsole } from "@moku-labs/common/cli";
5
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moku-labs/game",
3
- "version": "0.15.6",
3
+ "version": "0.15.7",
4
4
  "description": "2D puzzle game engine on TypeScript and PixiJS, built on @moku-labs/core.",
5
5
  "type": "module",
6
6
  "sideEffects": [