@moku-labs/game 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -24
- package/dist/assets.d.mts +1 -1
- package/dist/{commands-BOxqlv7w.d.mts → commands-C0BljsM5.d.mts} +4 -4
- package/dist/control.d.mts +3 -3
- package/dist/{define-BMo0pHe_.d.mts → define-CjP_4H0G.d.mts} +1 -1
- package/dist/index.d.mts +189 -318
- package/dist/index.mjs +7015 -6404
- package/dist/inspect.d.mts +7 -7
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/{runtime-BstIkrhH.d.mts → runtime-Bn5TXNxP.d.mts} +1 -1
- package/dist/testing.d.mts +44 -21
- package/dist/testing.mjs +113 -43
- package/dist/{types-Cjf3ywai.d.mts → types-BZ1OLf24.d.mts} +20 -3
- package/dist/{types-DgwbzDLP.d.mts → types-C47fKNcn.d.mts} +7 -2
- package/dist/{types-KlE_GL1z.d.mts → types-CqkrEY06.d.mts} +296 -6
- package/dist/{types-BTycq8_Z.d.mts → types-CxZy7Pi4.d.mts} +31 -17
- package/dist/{types-D0uYTTC3.d.mts → types-DmhTHRVW.d.mts} +1 -1
- package/dist/{types-C0SLQsx0.d.mts → types-X9jXjka3.d.mts} +1 -1
- package/package.json +6 -1
package/dist/inspect.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as Position, Dt as Api, dt as FlowGraph, h as Api$1, l as RenderStats, pt as JournalEntry, t as Api$2, z as EntitySnapshot, zt as Snapshot } from "./types-
|
|
2
|
-
import { f as Usage, t as Api$3 } from "./types-
|
|
3
|
-
import { a as InputOf, c as Source, d as HeadlessApp, i as InputArguments, l as WatchApp, o as InputSchema, t as CheatEntry, u as WatchInput } from "./types-
|
|
4
|
-
import { c as UiNode } from "./types-
|
|
5
|
-
import {
|
|
6
|
-
import { n as defineSource } from "./define-
|
|
7
|
-
import { _ as EffectsApi, a as SoundEntry, t as AudioApi, v as EffectsStats } from "./types-
|
|
1
|
+
import { $ as Position, Dt as Api, dt as FlowGraph, h as Api$1, l as RenderStats, pt as JournalEntry, t as Api$2, z as EntitySnapshot, zt as Snapshot } from "./types-BZ1OLf24.mjs";
|
|
2
|
+
import { f as Usage, t as Api$3 } from "./types-C47fKNcn.mjs";
|
|
3
|
+
import { a as InputOf, c as Source, d as HeadlessApp, i as InputArguments, l as WatchApp, o as InputSchema, t as CheatEntry, u as WatchInput } from "./types-DmhTHRVW.mjs";
|
|
4
|
+
import { c as UiNode } from "./types-X9jXjka3.mjs";
|
|
5
|
+
import { A as UiApi } from "./types-CqkrEY06.mjs";
|
|
6
|
+
import { n as defineSource } from "./define-CjP_4H0G.mjs";
|
|
7
|
+
import { _ as EffectsApi, a as SoundEntry, t as AudioApi, v as EffectsStats } from "./types-CxZy7Pi4.mjs";
|
|
8
8
|
|
|
9
9
|
//#region src/plugins/flow/doors/read.d.ts
|
|
10
10
|
/**
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as jsxs, i as jsxDEV, n as JSX, r as jsx, t as Fragment } from "./runtime-
|
|
1
|
+
import { a as jsxs, i as jsxDEV, n as JSX, r as jsx, t as Fragment } from "./runtime-Bn5TXNxP.mjs";
|
|
2
2
|
export { Fragment, type JSX, jsx, jsxDEV, jsxs };
|
package/dist/jsx-runtime.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as jsxs, n as JSX, r as jsx, t as Fragment } from "./runtime-
|
|
1
|
+
import { a as jsxs, n as JSX, r as jsx, t as Fragment } from "./runtime-Bn5TXNxP.mjs";
|
|
2
2
|
export { Fragment, type JSX, jsx, jsxs };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as JsxChild, m as UiIntrinsicElements, t as DescriptionNode } from "./types-
|
|
1
|
+
import { a as JsxChild, m as UiIntrinsicElements, t as DescriptionNode } from "./types-X9jXjka3.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/plugins/ui/jsx/runtime.d.ts
|
|
4
4
|
/** What the compiler passes as props: the children plus whatever the tag declared. */
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { At as Json, Dt as Api$2, Ft as PlayerStateProvider, It as ProviderCall, Lt as SaveDoc, Ut as Api$3, Zt as FakeClock, h as Api$1, t as Api } from "./types-
|
|
2
|
-
import { _ as stepFrames, a as InputOf, d as HeadlessApp, f as HeadlessGame, g as runRepro, h as createHeadless, m as ReproResult, p as Repro, r as ControlApp } from "./types-
|
|
3
|
-
import { H as InputApi } from "./types-
|
|
4
|
-
import {
|
|
5
|
-
import { t as commands } from "./commands-
|
|
1
|
+
import { At as Json, Dt as Api$2, Ft as PlayerStateProvider, It as ProviderCall, Lt as SaveDoc, Ut as Api$3, Zt as FakeClock, h as Api$1, t as Api } from "./types-BZ1OLf24.mjs";
|
|
2
|
+
import { _ as stepFrames, a as InputOf, d as HeadlessApp, f as HeadlessGame, g as runRepro, h as createHeadless, m as ReproResult, p as Repro, r as ControlApp } from "./types-DmhTHRVW.mjs";
|
|
3
|
+
import { H as InputApi } from "./types-X9jXjka3.mjs";
|
|
4
|
+
import { A as UiApi, t as AnimApi } from "./types-CqkrEY06.mjs";
|
|
5
|
+
import { t as commands } from "./commands-C0BljsM5.mjs";
|
|
6
6
|
|
|
7
7
|
//#region src/plugins/clock/fake.d.ts
|
|
8
8
|
/**
|
|
@@ -116,8 +116,8 @@ type VisualStep = {
|
|
|
116
116
|
checkpoint: string;
|
|
117
117
|
} | { [K in StepCommand]: { [P in K]: InputOf<Catalogue[K]["input"]> } }[StepCommand];
|
|
118
118
|
/**
|
|
119
|
-
* A visual test as `defineVisualTest` answers it: its name, where it starts
|
|
120
|
-
* Frozen data; nothing runs at definition.
|
|
119
|
+
* A visual test as `defineVisualTest` answers it: its name, where it starts, its steps, and
|
|
120
|
+
* `webgl`, true when it also runs in the WebGL leg. Frozen data; nothing runs at definition.
|
|
121
121
|
*
|
|
122
122
|
* @example
|
|
123
123
|
* ```ts
|
|
@@ -126,6 +126,7 @@ type VisualStep = {
|
|
|
126
126
|
* steps: [{ tap: { key: "play" } }, { checkpoint: "board" }]
|
|
127
127
|
* });
|
|
128
128
|
* test.name; // "reward-popup"
|
|
129
|
+
* test.webgl; // false
|
|
129
130
|
* Object.isFrozen(test.steps); // true
|
|
130
131
|
* ```
|
|
131
132
|
*/
|
|
@@ -133,6 +134,7 @@ type VisualTest = {
|
|
|
133
134
|
readonly name: string;
|
|
134
135
|
readonly start: Readonly<VisualStart>;
|
|
135
136
|
readonly steps: readonly VisualStep[];
|
|
137
|
+
readonly webgl: boolean;
|
|
136
138
|
};
|
|
137
139
|
/**
|
|
138
140
|
* What the runner needs of an app: the control app, the plugins the base commands act on and
|
|
@@ -200,22 +202,36 @@ type VisualTolerance = {
|
|
|
200
202
|
ratio: number;
|
|
201
203
|
threshold: number;
|
|
202
204
|
};
|
|
205
|
+
/**
|
|
206
|
+
* The backend the browser leg draws with: `"webgpu"`, or `"webgl"` for the WebGL leg.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```ts
|
|
210
|
+
* const renderer: VisualRenderer = "webgl"; // what --webgl asks for
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
type VisualRenderer = "webgpu" | "webgl";
|
|
203
214
|
/**
|
|
204
215
|
* The options of a run. Each one left out comes from the command line (`argv`), then from its
|
|
205
216
|
* default: `dir` `"tests/visual"`, `update` false, `pixels` true with a `page` on a Mac,
|
|
206
|
-
* `settleFrames` 600, `tolerance` `{ ratio: 0.001, threshold: 24 }`,
|
|
207
|
-
* `process.argv.slice(2)`. An option given here wins over a flag.
|
|
217
|
+
* `renderer` `"webgpu"`, `settleFrames` 600, `tolerance` `{ ratio: 0.001, threshold: 24 }`,
|
|
218
|
+
* `argv` `process.argv.slice(2)`. An option given here wins over a flag. `renderer: "webgl"`
|
|
219
|
+
* runs only the tests with `webgl: true`, on the page with `?renderer=webgl`, and compares their
|
|
220
|
+
* pictures with `screen.webgl.webp`.
|
|
208
221
|
*
|
|
209
222
|
* @example
|
|
210
223
|
* ```ts
|
|
211
224
|
* // The same as `bun tests/visual/run.ts --only reward-popup --no-pixels`.
|
|
212
225
|
* const options: VisualOptions = { only: ["reward-popup"], pixels: false };
|
|
226
|
+
* // The same as `bun tests/visual/run.ts --webgl`.
|
|
227
|
+
* const webgl: VisualOptions = { renderer: "webgl" };
|
|
213
228
|
* ```
|
|
214
229
|
*/
|
|
215
230
|
type VisualOptions = {
|
|
216
231
|
dir?: string;
|
|
217
232
|
update?: boolean;
|
|
218
233
|
pixels?: boolean;
|
|
234
|
+
renderer?: VisualRenderer;
|
|
219
235
|
only?: readonly string[];
|
|
220
236
|
settleFrames?: number;
|
|
221
237
|
tolerance?: VisualTolerance;
|
|
@@ -288,6 +304,7 @@ type VisualFlags = {
|
|
|
288
304
|
dir?: string;
|
|
289
305
|
update?: boolean;
|
|
290
306
|
pixels?: boolean;
|
|
307
|
+
renderer?: VisualRenderer;
|
|
291
308
|
only?: readonly string[];
|
|
292
309
|
};
|
|
293
310
|
//#endregion
|
|
@@ -297,33 +314,34 @@ type VisualFlags = {
|
|
|
297
314
|
* `/control` command by its short name with that command's input, or `{ checkpoint: name }`,
|
|
298
315
|
* where the runner saves `state.json` and `describe.json` next to the test. `walk` runs fast: a
|
|
299
316
|
* popup its last node opens never mounts, so the step before a checkpoint that shows a node's
|
|
300
|
-
* result is `answer` or `tap`.
|
|
317
|
+
* result is `answer` or `tap`. With `webgl: true` the test also runs in the WebGL leg
|
|
318
|
+
* (`--webgl`), whose pictures go to `screen.webgl.webp`: set it on a screen with a custom filter.
|
|
319
|
+
* The answer is a frozen copy; nothing runs here.
|
|
301
320
|
*
|
|
302
321
|
* @param name - The test name, also its folder: lowercase letters, digits and dashes.
|
|
303
|
-
* @param test - Where it starts and its
|
|
322
|
+
* @param test - Where it starts, its steps and its WebGL leg.
|
|
304
323
|
* @param test.start - The player, and optionally the session, the rng and the checkpoint.
|
|
305
324
|
* @param test.steps - The commands and the checkpoints, in order.
|
|
325
|
+
* @param test.webgl - True to run the test in the WebGL leg too; false by default.
|
|
306
326
|
* @returns The test, frozen.
|
|
307
327
|
* @throws {Error} When the name or a checkpoint name is not a file name, a checkpoint name is
|
|
308
328
|
* used twice, or a step is not one step command.
|
|
309
329
|
* @example
|
|
310
330
|
* ```ts
|
|
311
|
-
* // tests/visual/
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
* steps: [{ tap: { key: "play" } }, { answer: { intent: "deliver", payload: { orderId: "o1" } } },
|
|
315
|
-
* { checkpoint: "open" }, { tap: { key: "claim" } }, { checkpoint: "claimed" }]
|
|
316
|
-
* });
|
|
331
|
+
* // tests/visual/home.visual.ts: Home with the glowing Play plank, in both legs.
|
|
332
|
+
* const home = defineVisualTest("home", { start: atHome, steps: [{ checkpoint: "rest" }], webgl: true });
|
|
333
|
+
* home.webgl; // true
|
|
317
334
|
* ```
|
|
318
335
|
*/
|
|
319
336
|
declare function defineVisualTest(name: string, test: {
|
|
320
337
|
start: VisualStart;
|
|
321
338
|
steps: readonly VisualStep[];
|
|
339
|
+
webgl?: boolean;
|
|
322
340
|
}): VisualTest;
|
|
323
341
|
//#endregion
|
|
324
342
|
//#region src/visual/run.d.ts
|
|
325
343
|
/**
|
|
326
|
-
* Reads the flags of the visual tests from a command line: `--update`, `--no-pixels`,
|
|
344
|
+
* Reads the flags of the visual tests from a command line: `--update`, `--no-pixels`, `--webgl`,
|
|
327
345
|
* `--only <name>` (repeatable) and `--dir <path>`. An argument it does not know is left to the
|
|
328
346
|
* script that got it, so a test runner's own arguments pass through.
|
|
329
347
|
*
|
|
@@ -335,12 +353,16 @@ declare function defineVisualTest(name: string, test: {
|
|
|
335
353
|
* // `bun tests/visual/run.ts --update --only reward-popup`
|
|
336
354
|
* parseVisualArgv(["--update", "--only", "reward-popup"]); // { update: true, only: ["reward-popup"] }
|
|
337
355
|
* parseVisualArgv(["--no-pixels", "--dir", "shots"]); // { pixels: false, dir: "shots" }
|
|
356
|
+
* parseVisualArgv(["--webgl"]); // { renderer: "webgl" }
|
|
338
357
|
* ```
|
|
339
358
|
*/
|
|
340
359
|
declare function parseVisualArgv(argv: readonly string[]): VisualFlags;
|
|
341
360
|
/**
|
|
342
361
|
* Runs visual tests: the headless leg over every selected test, then the browser leg over the
|
|
343
|
-
* same tests when `pixels` is on (by default only with a `page` on a Mac).
|
|
362
|
+
* same tests when `pixels` is on (by default only with a `page` on a Mac). With `renderer:
|
|
363
|
+
* "webgl"` (`--webgl`) only the tests with `webgl: true` run, the page opens with
|
|
364
|
+
* `?renderer=webgl` and its pictures go to `screen.webgl.webp`; `state.json` and `describe.json`
|
|
365
|
+
* are shared with the WebGPU leg and compared as always. A checkpoint saves
|
|
344
366
|
* `state.json` and `describe.json` in `<dir>/<test>/<checkpoint>/`, and the browser leg
|
|
345
367
|
* `screen.webp`, lossless: a missing file is written, `--update` rewrites every file of the tests
|
|
346
368
|
* run, a JSON file is compared exactly. The browser leg opens the dev page in Chrome with WebGPU
|
|
@@ -359,7 +381,8 @@ declare function parseVisualArgv(argv: readonly string[]): VisualFlags;
|
|
|
359
381
|
* @throws {Error} When a test is not well formed, two tests share a name, `only` names no test,
|
|
360
382
|
* a flag misses its value, or the browser leg fails as a whole: no `page`, no
|
|
361
383
|
* `playwright-core`, no Chrome, or a page that does not open, expose `game` and `doors`, start,
|
|
362
|
-
* draw with
|
|
384
|
+
* draw with the requested backend or stop loading. In the WebGL leg, also when `only` names a
|
|
385
|
+
* test without `webgl: true`.
|
|
363
386
|
* @example
|
|
364
387
|
* ```ts
|
|
365
388
|
* // tests/visual/run.ts of a game, `bun tests/visual/run.ts --update` on a Mac
|
|
@@ -372,4 +395,4 @@ declare function parseVisualArgv(argv: readonly string[]): VisualFlags;
|
|
|
372
395
|
*/
|
|
373
396
|
declare function runVisualTests(setup: VisualSetup, tests: readonly VisualTest[], options?: VisualOptions): Promise<VisualReport>;
|
|
374
397
|
//#endregion
|
|
375
|
-
export { type CheckpointResult, type HeadlessApp, type HeadlessGame, type Repro, type ReproResult, type VisualApp, type VisualOptions, type VisualPage, type VisualReport, type VisualSetup, type VisualStart, type VisualStep, type VisualTest, type VisualTestResult, type VisualTolerance, createHeadless, defineVisualTest, fakeClock, memory, parseVisualArgv, runRepro, runVisualTests, saveOf, stepFrames };
|
|
398
|
+
export { type CheckpointResult, type HeadlessApp, type HeadlessGame, type Repro, type ReproResult, type VisualApp, type VisualOptions, type VisualPage, type VisualRenderer, type VisualReport, type VisualSetup, type VisualStart, type VisualStep, type VisualTest, type VisualTestResult, type VisualTolerance, createHeadless, defineVisualTest, fakeClock, memory, parseVisualArgv, runRepro, runVisualTests, saveOf, stepFrames };
|
package/dist/testing.mjs
CHANGED
|
@@ -199,8 +199,8 @@ function runStep(app, name, input) {
|
|
|
199
199
|
//#endregion
|
|
200
200
|
//#region src/visual/define.ts
|
|
201
201
|
/**
|
|
202
|
-
* @file visual — `defineVisualTest`: a name, where the test starts
|
|
203
|
-
* frozen. Nothing runs at definition.
|
|
202
|
+
* @file visual — `defineVisualTest`: a name, where the test starts, its steps and whether it runs
|
|
203
|
+
* in the WebGL leg, checked and frozen. Nothing runs at definition.
|
|
204
204
|
*/
|
|
205
205
|
/** A file name: lowercase letters and digits, words joined by single dashes. */
|
|
206
206
|
const fileName = /^[\da-z]+(?:-[\da-z]+)*$/u;
|
|
@@ -262,31 +262,33 @@ function checkVisualTest(name, steps) {
|
|
|
262
262
|
* `/control` command by its short name with that command's input, or `{ checkpoint: name }`,
|
|
263
263
|
* where the runner saves `state.json` and `describe.json` next to the test. `walk` runs fast: a
|
|
264
264
|
* popup its last node opens never mounts, so the step before a checkpoint that shows a node's
|
|
265
|
-
* result is `answer` or `tap`.
|
|
265
|
+
* result is `answer` or `tap`. With `webgl: true` the test also runs in the WebGL leg
|
|
266
|
+
* (`--webgl`), whose pictures go to `screen.webgl.webp`: set it on a screen with a custom filter.
|
|
267
|
+
* The answer is a frozen copy; nothing runs here.
|
|
266
268
|
*
|
|
267
269
|
* @param name - The test name, also its folder: lowercase letters, digits and dashes.
|
|
268
|
-
* @param test - Where it starts and its
|
|
270
|
+
* @param test - Where it starts, its steps and its WebGL leg.
|
|
269
271
|
* @param test.start - The player, and optionally the session, the rng and the checkpoint.
|
|
270
272
|
* @param test.steps - The commands and the checkpoints, in order.
|
|
273
|
+
* @param test.webgl - True to run the test in the WebGL leg too; false by default.
|
|
271
274
|
* @returns The test, frozen.
|
|
272
275
|
* @throws {Error} When the name or a checkpoint name is not a file name, a checkpoint name is
|
|
273
276
|
* used twice, or a step is not one step command.
|
|
274
277
|
* @example
|
|
275
278
|
* ```ts
|
|
276
|
-
* // tests/visual/
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* steps: [{ tap: { key: "play" } }, { answer: { intent: "deliver", payload: { orderId: "o1" } } },
|
|
280
|
-
* { checkpoint: "open" }, { tap: { key: "claim" } }, { checkpoint: "claimed" }]
|
|
281
|
-
* });
|
|
279
|
+
* // tests/visual/home.visual.ts: Home with the glowing Play plank, in both legs.
|
|
280
|
+
* const home = defineVisualTest("home", { start: atHome, steps: [{ checkpoint: "rest" }], webgl: true });
|
|
281
|
+
* home.webgl; // true
|
|
282
282
|
* ```
|
|
283
283
|
*/
|
|
284
284
|
function defineVisualTest(name, test) {
|
|
285
285
|
checkVisualTest(name, test.steps);
|
|
286
|
+
const webgl = test.webgl ?? false;
|
|
286
287
|
return freezeDeep(structuredClone({
|
|
287
288
|
name,
|
|
288
289
|
start: test.start,
|
|
289
|
-
steps: test.steps
|
|
290
|
+
steps: test.steps,
|
|
291
|
+
webgl
|
|
290
292
|
}));
|
|
291
293
|
}
|
|
292
294
|
//#endregion
|
|
@@ -1489,13 +1491,54 @@ const READY_MS = 15e3;
|
|
|
1489
1491
|
* multiple.
|
|
1490
1492
|
*/
|
|
1491
1493
|
const START_MS = 5e3;
|
|
1492
|
-
/** The
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1494
|
+
/** The name of each backend in a message. */
|
|
1495
|
+
const BACKEND = {
|
|
1496
|
+
webgpu: "WebGPU",
|
|
1497
|
+
webgl: "WebGL"
|
|
1498
|
+
};
|
|
1499
|
+
/** What to do about a page that draws with another backend than the leg asked for. */
|
|
1500
|
+
const OTHER_BACKEND_FIX = {
|
|
1501
|
+
webgpu: "The WebGPU baselines need a Chrome with WebGPU on a Mac: use one, or run with --no-pixels.",
|
|
1502
|
+
webgl: "The WebGL baselines need a page that passes renderer=webgl from its query to the renderer: serve one, or run without --webgl."
|
|
1497
1503
|
};
|
|
1498
1504
|
/**
|
|
1505
|
+
* Names the URL a leg opens: the dev page as it is for WebGPU, with `renderer=webgl` in its query
|
|
1506
|
+
* for WebGL.
|
|
1507
|
+
*
|
|
1508
|
+
* @param url - The URL of the dev page.
|
|
1509
|
+
* @param renderer - The backend of the leg.
|
|
1510
|
+
* @returns The URL to open.
|
|
1511
|
+
* @example
|
|
1512
|
+
* ```ts
|
|
1513
|
+
* rendererUrl("http://localhost:3000/", "webgl"); // "http://localhost:3000/?renderer=webgl"
|
|
1514
|
+
* ```
|
|
1515
|
+
*/
|
|
1516
|
+
function rendererUrl(url, renderer) {
|
|
1517
|
+
if (renderer === "webgpu") return url;
|
|
1518
|
+
const withRenderer = new URL(url);
|
|
1519
|
+
withRenderer.searchParams.set("renderer", renderer);
|
|
1520
|
+
return withRenderer.href;
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* Names the pictures of a checkpoint for a backend: `screen.webp` and its actual and diff for
|
|
1524
|
+
* WebGPU, the same names with `.webgl` before the end for WebGL.
|
|
1525
|
+
*
|
|
1526
|
+
* @param renderer - The backend of the leg.
|
|
1527
|
+
* @returns The file names of the baseline, the actual and the diff.
|
|
1528
|
+
* @example
|
|
1529
|
+
* ```ts
|
|
1530
|
+
* screenFiles("webgl"); // { baseline: "screen.webgl.webp", actual: "screen.webgl.actual.webp", diff: "screen.webgl.diff.webp" }
|
|
1531
|
+
* ```
|
|
1532
|
+
*/
|
|
1533
|
+
function screenFiles(renderer) {
|
|
1534
|
+
const stem = renderer === "webgpu" ? "screen" : `screen.${renderer}`;
|
|
1535
|
+
return {
|
|
1536
|
+
baseline: `${stem}.webp`,
|
|
1537
|
+
actual: `${stem}.actual.webp`,
|
|
1538
|
+
diff: `${stem}.diff.webp`
|
|
1539
|
+
};
|
|
1540
|
+
}
|
|
1541
|
+
/**
|
|
1499
1542
|
* Reads the first line of a Playwright error, without the name of the call that failed.
|
|
1500
1543
|
*
|
|
1501
1544
|
* @param error - What Playwright threw.
|
|
@@ -1687,15 +1730,16 @@ async function startPage(page, url, run) {
|
|
|
1687
1730
|
}
|
|
1688
1731
|
/**
|
|
1689
1732
|
* Opens the dev page for one test: the page script first, then the URL, then the wait for
|
|
1690
|
-
* `game` and `doors`, for the graph at its first gate, the check that it draws with
|
|
1691
|
-
* the wait until no request ran for half a second, so no load is left for the
|
|
1733
|
+
* `game` and `doors`, for the graph at its first gate, the check that it draws with the backend
|
|
1734
|
+
* of the leg, and the wait until no request ran for half a second, so no load is left for the
|
|
1735
|
+
* stepped frames.
|
|
1692
1736
|
*
|
|
1693
1737
|
* @param context - The browser context.
|
|
1694
|
-
* @param url - The URL of the
|
|
1695
|
-
* @param run - The run options, for `settleFrames`.
|
|
1738
|
+
* @param url - The URL of the page the leg opens.
|
|
1739
|
+
* @param run - The run options, for `settleFrames` and `renderer`.
|
|
1696
1740
|
* @returns The open page.
|
|
1697
1741
|
* @throws {Error} When the page does not open, never exposes `game` and `doors`, does not start,
|
|
1698
|
-
*
|
|
1742
|
+
* draws with another backend or never stops loading. The page is closed then.
|
|
1699
1743
|
*/
|
|
1700
1744
|
async function openPage(context, url, run) {
|
|
1701
1745
|
const page = await context.newPage();
|
|
@@ -1708,7 +1752,7 @@ async function openPage(context, url, run) {
|
|
|
1708
1752
|
throw new Error(`[game] The page at ${url} exposes no game and doors.\n Serve the dev page (bun ./web/serve.ts) and set globalThis.game and globalThis.doors in it.`);
|
|
1709
1753
|
});
|
|
1710
1754
|
const kind = await startPage(page, url, run);
|
|
1711
|
-
if (kind !==
|
|
1755
|
+
if (kind !== run.renderer) throw new Error(`[game] The page at ${url} draws with ${kind}, not ${BACKEND[run.renderer]}.\n ${OTHER_BACKEND_FIX[run.renderer]}`);
|
|
1712
1756
|
await page.waitForLoadState("networkidle", { timeout: READY_MS }).catch(() => {
|
|
1713
1757
|
throw new Error(`[game] The page at ${url} did not stop loading in ${READY_MS / 1e3} s.\n Let it finish its requests: the leg pauses the game once nothing loads.`);
|
|
1714
1758
|
});
|
|
@@ -1719,9 +1763,9 @@ async function openPage(context, url, run) {
|
|
|
1719
1763
|
}
|
|
1720
1764
|
}
|
|
1721
1765
|
/**
|
|
1722
|
-
* Checks the picture of a checkpoint against `screen.webp
|
|
1723
|
-
* writes it; a difference writes `screen.actual.webp`,
|
|
1724
|
-
* match.
|
|
1766
|
+
* Checks the picture of a checkpoint against `screen.webp` (`screen.webgl.webp` in the WebGL
|
|
1767
|
+
* leg): a missing baseline, or `--update`, writes it; a difference writes `screen.actual.webp`,
|
|
1768
|
+
* and `screen.diff.webp` when the sizes match, named the same way.
|
|
1725
1769
|
*
|
|
1726
1770
|
* @param play - The test being played.
|
|
1727
1771
|
* @param file - Names a file of the checkpoint.
|
|
@@ -1731,9 +1775,10 @@ async function openPage(context, url, run) {
|
|
|
1731
1775
|
*/
|
|
1732
1776
|
async function checkScreen(play, file, where, screen) {
|
|
1733
1777
|
const { run } = play;
|
|
1734
|
-
const
|
|
1778
|
+
const names = screenFiles(run.renderer);
|
|
1779
|
+
const baseline = run.update ? void 0 : await readScreen(file(names.baseline));
|
|
1735
1780
|
if (baseline === void 0) {
|
|
1736
|
-
await writeScreen(file(
|
|
1781
|
+
await writeScreen(file(names.baseline), screen);
|
|
1737
1782
|
return { outcome: "written" };
|
|
1738
1783
|
}
|
|
1739
1784
|
const compared = await callPage(play.page, pageCompare, {
|
|
@@ -1745,14 +1790,14 @@ async function checkScreen(play, file, where, screen) {
|
|
|
1745
1790
|
});
|
|
1746
1791
|
const found = pixelOutcome(compared, run.tolerance);
|
|
1747
1792
|
if (found.outcome === "different") {
|
|
1748
|
-
await writeScreen(file(
|
|
1749
|
-
if (compared.diff !== void 0) await writeScreen(file(
|
|
1793
|
+
await writeScreen(file(names.actual), screen);
|
|
1794
|
+
if (compared.diff !== void 0) await writeScreen(file(names.diff), compared.diff);
|
|
1750
1795
|
}
|
|
1751
1796
|
return found;
|
|
1752
1797
|
}
|
|
1753
1798
|
/**
|
|
1754
1799
|
* Plays a checkpoint in the page and checks what it found: the state against `state.json` the
|
|
1755
|
-
* headless leg wrote, the picture against
|
|
1800
|
+
* headless leg wrote, the picture against the baseline of the leg's backend.
|
|
1756
1801
|
*
|
|
1757
1802
|
* @param play - The test being played.
|
|
1758
1803
|
* @param name - The checkpoint name.
|
|
@@ -1767,7 +1812,7 @@ async function checkpoint(play, name, where) {
|
|
|
1767
1812
|
where,
|
|
1768
1813
|
settleFrames: run.settleFrames
|
|
1769
1814
|
});
|
|
1770
|
-
if (shot.screen === void 0) throw new Error(`[game] Visual test "${test.name}", ${where}: the page gave no picture.\n Serve a dev build with
|
|
1815
|
+
if (shot.screen === void 0) throw new Error(`[game] Visual test "${test.name}", ${where}: the page gave no picture.\n Serve a dev build with ${BACKEND[run.renderer]}: renderer.capture() answers only there.`);
|
|
1771
1816
|
const file = (kind) => baselineFile(run.dir, test.name, name, kind);
|
|
1772
1817
|
return {
|
|
1773
1818
|
state: await compareBaseline(file("state.json"), stableJson(shot.state)),
|
|
@@ -1826,7 +1871,7 @@ async function playSteps(play, found) {
|
|
|
1826
1871
|
* @param play - The test and the run options; the page is opened here.
|
|
1827
1872
|
* @param play.test - The test.
|
|
1828
1873
|
* @param play.run - The run options.
|
|
1829
|
-
* @param url - The URL of the
|
|
1874
|
+
* @param url - The URL of the page the leg opens.
|
|
1830
1875
|
* @param headless - The result of the test in the headless leg.
|
|
1831
1876
|
* @returns The result of the test with its pixel fields.
|
|
1832
1877
|
* @throws {Error} When the page fails to open: that fails the leg.
|
|
@@ -1860,8 +1905,9 @@ async function browserTest(context, play, url, headless) {
|
|
|
1860
1905
|
}
|
|
1861
1906
|
/**
|
|
1862
1907
|
* Runs the browser leg over the tests the headless leg played, one page per test, and answers
|
|
1863
|
-
* their results with the pixel fields.
|
|
1864
|
-
* browser closes at the end, also after an
|
|
1908
|
+
* their results with the pixel fields. The page opens with `?renderer=webgl` in the WebGL leg. A
|
|
1909
|
+
* test the headless leg failed is left as it is. The browser closes at the end, also after an
|
|
1910
|
+
* error.
|
|
1865
1911
|
*
|
|
1866
1912
|
* @param setup - The setup: its `page`, and its app for the size of the page.
|
|
1867
1913
|
* @param tests - The selected tests.
|
|
@@ -1870,13 +1916,15 @@ async function browserTest(context, play, url, headless) {
|
|
|
1870
1916
|
* @param load - Loads `chromium`; `playwright-core` by default.
|
|
1871
1917
|
* @returns One result per test, in order.
|
|
1872
1918
|
* @throws {Error} When the setup has no page, `playwright-core` or Chrome is missing, or the page
|
|
1873
|
-
* does not open, expose `game` and `doors`, start, draw with
|
|
1919
|
+
* does not open, expose `game` and `doors`, start, draw with the backend of the leg or stop
|
|
1920
|
+
* loading.
|
|
1874
1921
|
*/
|
|
1875
1922
|
async function runBrowserLeg(setup, tests, run, headless, load = loadChromium) {
|
|
1876
1923
|
const page = setup.page;
|
|
1877
1924
|
if (page === void 0) throw new Error("[game] The pixel leg needs the dev page.\n Pass page: { url } in the setup, or run with --no-pixels.");
|
|
1878
1925
|
const chromium = await load();
|
|
1879
1926
|
const options = pageSize(setup, page);
|
|
1927
|
+
const url = rendererUrl(page.url, run.renderer);
|
|
1880
1928
|
const browser = await launchChrome(chromium, page.browser);
|
|
1881
1929
|
try {
|
|
1882
1930
|
const context = await browser.newContext(options);
|
|
@@ -1889,7 +1937,7 @@ async function runBrowserLeg(setup, tests, run, headless, load = loadChromium) {
|
|
|
1889
1937
|
results.push(before.error === void 0 ? await browserTest(context, {
|
|
1890
1938
|
test,
|
|
1891
1939
|
run
|
|
1892
|
-
},
|
|
1940
|
+
}, url, before) : before);
|
|
1893
1941
|
}
|
|
1894
1942
|
return results;
|
|
1895
1943
|
} finally {
|
|
@@ -1900,8 +1948,8 @@ async function runBrowserLeg(setup, tests, run, headless, load = loadChromium) {
|
|
|
1900
1948
|
//#region src/visual/run.ts
|
|
1901
1949
|
/**
|
|
1902
1950
|
* @file visual — `runVisualTests`, the runner a game's script calls, and `parseVisualArgv`, its
|
|
1903
|
-
* command line. It resolves the options, selects the tests
|
|
1904
|
-
* `pixels` on, the browser leg, prints one line per checkpoint through the branded console of
|
|
1951
|
+
* command line. It resolves the options, selects the tests (in the WebGL leg, the ones with
|
|
1952
|
+
* `webgl: true`), runs the headless leg and then, with `pixels` on, the browser leg, prints one line per checkpoint through the branded console of
|
|
1905
1953
|
* `@moku-labs/common/cli` and answers one report. The game's script sets the exit code.
|
|
1906
1954
|
*/
|
|
1907
1955
|
/** The folder of the visual tests, relative to where the script runs. */
|
|
@@ -1929,7 +1977,7 @@ function valueAfter(argv, index, placeholder) {
|
|
|
1929
1977
|
throw new Error(`[game] The flag ${flag} needs a value.\n Write it as ${flag} ${placeholder}.`);
|
|
1930
1978
|
}
|
|
1931
1979
|
/**
|
|
1932
|
-
* Reads the flags of the visual tests from a command line: `--update`, `--no-pixels`,
|
|
1980
|
+
* Reads the flags of the visual tests from a command line: `--update`, `--no-pixels`, `--webgl`,
|
|
1933
1981
|
* `--only <name>` (repeatable) and `--dir <path>`. An argument it does not know is left to the
|
|
1934
1982
|
* script that got it, so a test runner's own arguments pass through.
|
|
1935
1983
|
*
|
|
@@ -1941,6 +1989,7 @@ function valueAfter(argv, index, placeholder) {
|
|
|
1941
1989
|
* // `bun tests/visual/run.ts --update --only reward-popup`
|
|
1942
1990
|
* parseVisualArgv(["--update", "--only", "reward-popup"]); // { update: true, only: ["reward-popup"] }
|
|
1943
1991
|
* parseVisualArgv(["--no-pixels", "--dir", "shots"]); // { pixels: false, dir: "shots" }
|
|
1992
|
+
* parseVisualArgv(["--webgl"]); // { renderer: "webgl" }
|
|
1944
1993
|
* ```
|
|
1945
1994
|
*/
|
|
1946
1995
|
function parseVisualArgv(argv) {
|
|
@@ -1949,6 +1998,7 @@ function parseVisualArgv(argv) {
|
|
|
1949
1998
|
for (const [index, argument] of argv.entries()) {
|
|
1950
1999
|
if (argument === "--update") flags.update = true;
|
|
1951
2000
|
if (argument === "--no-pixels") flags.pixels = false;
|
|
2001
|
+
if (argument === "--webgl") flags.renderer = "webgl";
|
|
1952
2002
|
if (argument === "--only") only.push(valueAfter(argv, index, "<name>"));
|
|
1953
2003
|
if (argument === "--dir") flags.dir = valueAfter(argv, index, "<path>");
|
|
1954
2004
|
}
|
|
@@ -1959,7 +2009,7 @@ function parseVisualArgv(argv) {
|
|
|
1959
2009
|
}
|
|
1960
2010
|
/**
|
|
1961
2011
|
* Fills in the options of a run: an explicit option wins over a flag of `argv`, a flag over the
|
|
1962
|
-
* default. `pixels` is on by default only with a `page` on a Mac
|
|
2012
|
+
* default. `pixels` is on by default only with a `page` on a Mac; `renderer` is `"webgpu"`.
|
|
1963
2013
|
*
|
|
1964
2014
|
* @param setup - The setup, for its `page`.
|
|
1965
2015
|
* @param options - The options the script passed.
|
|
@@ -1973,6 +2023,7 @@ function resolveVisualOptions(setup, options = {}) {
|
|
|
1973
2023
|
dir: options.dir ?? flags.dir ?? DEFAULT_DIR,
|
|
1974
2024
|
update: options.update ?? flags.update ?? false,
|
|
1975
2025
|
pixels: options.pixels ?? flags.pixels ?? (setup.page !== void 0 && process.platform === "darwin"),
|
|
2026
|
+
renderer: options.renderer ?? flags.renderer ?? "webgpu",
|
|
1976
2027
|
settleFrames: options.settleFrames ?? DEFAULT_SETTLE_FRAMES,
|
|
1977
2028
|
tolerance: options.tolerance ?? { ...DEFAULT_TOLERANCE }
|
|
1978
2029
|
};
|
|
@@ -1982,6 +2033,21 @@ function resolveVisualOptions(setup, options = {}) {
|
|
|
1982
2033
|
};
|
|
1983
2034
|
}
|
|
1984
2035
|
/**
|
|
2036
|
+
* Keeps the tests the WebGL leg plays: the ones with `webgl: true`. The WebGPU leg plays every
|
|
2037
|
+
* test.
|
|
2038
|
+
*
|
|
2039
|
+
* @param tests - The tests `only` selected.
|
|
2040
|
+
* @param run - The run options, for `renderer` and `only`.
|
|
2041
|
+
* @returns The tests of the leg.
|
|
2042
|
+
* @throws {Error} When `only` names a test without `webgl: true` in the WebGL leg.
|
|
2043
|
+
*/
|
|
2044
|
+
function legTests(tests, run) {
|
|
2045
|
+
if (run.renderer === "webgpu") return [...tests];
|
|
2046
|
+
const withoutLeg = run.only === void 0 ? void 0 : tests.find((test) => !test.webgl);
|
|
2047
|
+
if (withoutLeg !== void 0) throw new Error(`[game] The visual test "${withoutLeg.name}" has no WebGL leg.\n Pass webgl: true to its defineVisualTest, or run without --webgl.`);
|
|
2048
|
+
return tests.filter((test) => test.webgl);
|
|
2049
|
+
}
|
|
2050
|
+
/**
|
|
1985
2051
|
* Picks the tests a run plays: all of them, or the ones `only` names, in the order given.
|
|
1986
2052
|
*
|
|
1987
2053
|
* @param tests - Every test of the script.
|
|
@@ -2097,7 +2163,10 @@ async function withPixelLeg(ui, setup, tests, run, headless) {
|
|
|
2097
2163
|
}
|
|
2098
2164
|
/**
|
|
2099
2165
|
* Runs visual tests: the headless leg over every selected test, then the browser leg over the
|
|
2100
|
-
* same tests when `pixels` is on (by default only with a `page` on a Mac).
|
|
2166
|
+
* same tests when `pixels` is on (by default only with a `page` on a Mac). With `renderer:
|
|
2167
|
+
* "webgl"` (`--webgl`) only the tests with `webgl: true` run, the page opens with
|
|
2168
|
+
* `?renderer=webgl` and its pictures go to `screen.webgl.webp`; `state.json` and `describe.json`
|
|
2169
|
+
* are shared with the WebGPU leg and compared as always. A checkpoint saves
|
|
2101
2170
|
* `state.json` and `describe.json` in `<dir>/<test>/<checkpoint>/`, and the browser leg
|
|
2102
2171
|
* `screen.webp`, lossless: a missing file is written, `--update` rewrites every file of the tests
|
|
2103
2172
|
* run, a JSON file is compared exactly. The browser leg opens the dev page in Chrome with WebGPU
|
|
@@ -2116,7 +2185,8 @@ async function withPixelLeg(ui, setup, tests, run, headless) {
|
|
|
2116
2185
|
* @throws {Error} When a test is not well formed, two tests share a name, `only` names no test,
|
|
2117
2186
|
* a flag misses its value, or the browser leg fails as a whole: no `page`, no
|
|
2118
2187
|
* `playwright-core`, no Chrome, or a page that does not open, expose `game` and `doors`, start,
|
|
2119
|
-
* draw with
|
|
2188
|
+
* draw with the requested backend or stop loading. In the WebGL leg, also when `only` names a
|
|
2189
|
+
* test without `webgl: true`.
|
|
2120
2190
|
* @example
|
|
2121
2191
|
* ```ts
|
|
2122
2192
|
* // tests/visual/run.ts of a game, `bun tests/visual/run.ts --update` on a Mac
|
|
@@ -2129,7 +2199,7 @@ async function withPixelLeg(ui, setup, tests, run, headless) {
|
|
|
2129
2199
|
*/
|
|
2130
2200
|
async function runVisualTests(setup, tests, options = {}) {
|
|
2131
2201
|
const run = resolveVisualOptions(setup, options);
|
|
2132
|
-
const selected = selectTests(tests, run.only);
|
|
2202
|
+
const selected = legTests(selectTests(tests, run.only), run);
|
|
2133
2203
|
const ui = createBrandConsole();
|
|
2134
2204
|
const headless = await runHeadlessLeg(setup, selected, run);
|
|
2135
2205
|
const results = run.pixels ? await withPixelLeg(ui, setup, selected, run, headless) : headless;
|
|
@@ -1527,7 +1527,7 @@ type FxApi = {
|
|
|
1527
1527
|
* @example
|
|
1528
1528
|
* ```ts
|
|
1529
1529
|
* // The screen wants a haptic tick outside any node. Nothing waits for it.
|
|
1530
|
-
* app.flow.fx.dispatch({ kind: "haptic", payload: {
|
|
1530
|
+
* app.flow.fx.dispatch({ kind: "haptic", payload: { kind: "light" } });
|
|
1531
1531
|
* ```
|
|
1532
1532
|
*/
|
|
1533
1533
|
dispatch(descriptor: Descriptor | Hint): void;
|
|
@@ -4755,6 +4755,21 @@ type HostApi = {
|
|
|
4755
4755
|
* ```
|
|
4756
4756
|
*/
|
|
4757
4757
|
device(): GPUDevice | undefined;
|
|
4758
|
+
/**
|
|
4759
|
+
* The WebGL2 context of the live WebGL application, read at call time like `device()`. Pixi
|
|
4760
|
+
* restores a lost context itself, so a caller asks again instead of keeping it.
|
|
4761
|
+
*
|
|
4762
|
+
* @returns The context, or `undefined` while inert, before `ready()`, while the context is lost,
|
|
4763
|
+
* on the unsupported screen and on WebGPU.
|
|
4764
|
+
* @example
|
|
4765
|
+
* ```ts
|
|
4766
|
+
* // effects compiles a custom filter's GLSL once in a dev build, on the WebGL fallback only
|
|
4767
|
+
* const gl = ctx.require(rendererPlugin).host.gl();
|
|
4768
|
+
* if (gl === undefined) return; // WebGPU, inert or a lost context: nothing to compile on
|
|
4769
|
+
* const shader = gl.createShader(gl.FRAGMENT_SHADER); // then shaderSource and compileShader
|
|
4770
|
+
* ```
|
|
4771
|
+
*/
|
|
4772
|
+
gl(): WebGL2RenderingContext | undefined;
|
|
4758
4773
|
};
|
|
4759
4774
|
/**
|
|
4760
4775
|
* The textures the GPU holds: how many sources, and their estimated bytes.
|
|
@@ -5776,7 +5791,8 @@ declare namespace types_d_exports {
|
|
|
5776
5791
|
* The part of Pixi the engine uses: the classes `sync` builds views from (a `Rectangle` frames the
|
|
5777
5792
|
* crop of a `"cover"` sprite), the bitmap-font pieces `fonts.install` needs, the `BitmapText` a
|
|
5778
5793
|
* plugin above builds through `host.pixi()`, the filter and particle classes `effects` builds
|
|
5779
|
-
* through it
|
|
5794
|
+
* through it (a custom filter carries a `GpuProgram` and a `GlProgram` over `defaultFilterVert`),
|
|
5795
|
+
* and the extension registry with the three WebGPU draw classes the dev draw-call
|
|
5780
5796
|
* counter swaps and the bitmap text pipe `host` swaps for one whose SDF shader applies the alpha
|
|
5781
5797
|
* once (with the WGSL and GLSL shader pieces it compiles that shader from). The module object
|
|
5782
5798
|
* never arrives through a static import: `config.loadPixi()` returns it, so a game without a screen carries no
|
|
@@ -5788,9 +5804,10 @@ declare namespace types_d_exports {
|
|
|
5788
5804
|
* pixi.Texture.WHITE.width; // 1
|
|
5789
5805
|
* pixi.GpuBatchAdaptor.extension.name; // "batch"
|
|
5790
5806
|
* pixi.BitmapTextPipe.extension.name; // "bitmapText"
|
|
5807
|
+
* pixi.defaultFilterVert.startsWith("in vec2 aPosition;"); // true
|
|
5791
5808
|
* ```
|
|
5792
5809
|
*/
|
|
5793
|
-
type PixiModule = Pick<typeof import("pixi.js"), "AlphaFilter" | "Application" | "BitmapFont" | "BitmapText" | "BitmapTextPipe" | "BlurFilter" | "Cache" | "ColorMatrixFilter" | "Container" | "DisplacementFilter" | "Filter" | "GpuBatchAdaptor" | "GpuEncoderSystem" | "GpuGraphicsAdaptor" | "GpuProgram" | "Graphics" | "Matrix" | "NineSliceSprite" | "NoiseFilter" | "Particle" | "ParticleContainer" | "Rectangle" | "Shader" | "Sprite" | "Texture" | "UniformGroup" | "bitmapFontTextParser" | "bitmapFontXMLStringParser" | "colorBit" | "colorBitGl" | "compileHighShaderGlProgram" | "compileHighShaderGpuProgram" | "extensions" | "generateTextureBatchBit" | "generateTextureBatchBitGl" | "getBatchSamplersUniformGroup" | "localUniformMSDFBit" | "localUniformMSDFBitGl" | "mSDFBit" | "mSDFBitGl" | "roundPixelsBit" | "roundPixelsBitGl">;
|
|
5810
|
+
type PixiModule = Pick<typeof import("pixi.js"), "AlphaFilter" | "Application" | "BitmapFont" | "BitmapText" | "BitmapTextPipe" | "BlurFilter" | "Cache" | "ColorMatrixFilter" | "Container" | "DisplacementFilter" | "Filter" | "GlProgram" | "GpuBatchAdaptor" | "GpuEncoderSystem" | "GpuGraphicsAdaptor" | "GpuProgram" | "Graphics" | "Matrix" | "NineSliceSprite" | "NoiseFilter" | "Particle" | "ParticleContainer" | "Rectangle" | "Shader" | "Sprite" | "Texture" | "UniformGroup" | "bitmapFontTextParser" | "bitmapFontXMLStringParser" | "colorBit" | "colorBitGl" | "compileHighShaderGlProgram" | "compileHighShaderGpuProgram" | "defaultFilterVert" | "extensions" | "generateTextureBatchBit" | "generateTextureBatchBitGl" | "getBatchSamplersUniformGroup" | "localUniformMSDFBit" | "localUniformMSDFBitGl" | "mSDFBit" | "mSDFBitGl" | "roundPixelsBit" | "roundPixelsBitGl">;
|
|
5794
5811
|
/**
|
|
5795
5812
|
* One Pixi application: renderer, canvas and stage.
|
|
5796
5813
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { St as Api$3, f as SliceFrame, mt as NodeInfo, nn as Require, o as PixiTexture, q as Api$1, t as Api$2, vt as Descriptor } from "./types-
|
|
1
|
+
import { St as Api$3, f as SliceFrame, mt as NodeInfo, nn as Require, o as PixiTexture, q as Api$1, t as Api$2, vt as Descriptor } from "./types-BZ1OLf24.mjs";
|
|
2
2
|
import { Log } from "@moku-labs/common/browser";
|
|
3
3
|
import { PluginCtx } from "@moku-labs/core";
|
|
4
4
|
|
|
@@ -59,11 +59,15 @@ type CreateTextureOptions = {
|
|
|
59
59
|
/**
|
|
60
60
|
* The part of a fetch response the plugin reads: the manifest is `json`, a texture is a `blob`,
|
|
61
61
|
* a font file is `text` and an audio file stays the raw `arrayBuffer`. The global `Response`
|
|
62
|
-
* fits it.
|
|
62
|
+
* fits it. `headers` gives the `content-type`: on `tauri://` a missing file comes back `200` with
|
|
63
|
+
* `index.html`, so `text/html` for a path that is not `.html` counts as missing.
|
|
63
64
|
*/
|
|
64
65
|
type FetchResponse = {
|
|
65
66
|
ok: boolean;
|
|
66
67
|
status: number;
|
|
68
|
+
headers: {
|
|
69
|
+
get(name: string): string | null;
|
|
70
|
+
};
|
|
67
71
|
json(): Promise<unknown>;
|
|
68
72
|
blob(): Promise<Blob>;
|
|
69
73
|
text(): Promise<string>;
|
|
@@ -80,6 +84,7 @@ type FetchResponse = {
|
|
|
80
84
|
* fetch: async () => ({
|
|
81
85
|
* ok: true,
|
|
82
86
|
* status: 200,
|
|
87
|
+
* headers: { get: () => null },
|
|
83
88
|
* json: async () => ({}),
|
|
84
89
|
* blob: async () => blob,
|
|
85
90
|
* text: async () => 'info face="body"',
|