@moku-labs/game 0.14.11 → 0.14.13
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 +13 -12
- package/dist/app/page.d.mts +8 -3
- package/dist/app/page.mjs +57 -12
- package/dist/app/system.d.mts +5 -3
- package/dist/app/system.mjs +2 -0
- package/dist/app.d.mts +15 -7
- package/dist/app.mjs +131 -27
- package/dist/{assets-BrKSg1O6.mjs → assets-CEMfBogh.mjs} +471 -120
- package/dist/assets.d.mts +30 -13
- package/dist/assets.mjs +1 -1
- package/dist/cli.d.mts +105 -8
- package/dist/cli.mjs +1036 -128
- package/dist/{commands-d5Zlh9hf.d.mts → commands-DAETmK86.d.mts} +43 -7
- package/dist/{config-CdARrrhU.mjs → config-B87aFTW-.mjs} +25 -4
- package/dist/control.d.mts +130 -17
- package/dist/control.mjs +4 -4
- package/dist/{define-BN15lAWb.d.mts → define-BASd9ZUh.d.mts} +32 -4
- package/dist/dev-DbHgx-R-.mjs +89 -0
- package/dist/{fake-MpzwZhIZ.mjs → fake-6mazmHK3.mjs} +20 -2
- package/dist/features-DowEilZm.mjs +266 -0
- package/dist/{headless-CrhefcLu.d.mts → headless-cFveciuY.d.mts} +1 -1
- package/dist/hot.d.mts +4 -2
- package/dist/hot.mjs +7 -4
- package/dist/{index-0GIP3tgm.d.mts → index-DedbED3T.d.mts} +317 -69
- package/dist/index.d.mts +5 -6
- package/dist/index.mjs +3 -3
- package/dist/inspect.d.mts +12 -7
- package/dist/inspect.mjs +2 -2
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/lint.d.mts +8 -3
- package/dist/lint.mjs +432 -20
- package/dist/project.d.mts +15 -1
- package/dist/project.mjs +1 -1
- package/dist/{run-Bf2hKyjZ.mjs → run-BbipFRc6.mjs} +250 -51
- package/dist/{runtime-aLkoeoGj.d.mts → runtime-DoSlRx8X.d.mts} +1 -1
- package/dist/{session-DgukhR_7.mjs → session-CeKgO2hy.mjs} +30 -2
- package/dist/{sources-Duzj6lhV.mjs → sources-Cdvb0rOS.mjs} +33 -6
- package/dist/{src-Do697seR.mjs → src-BEbJ_sSx.mjs} +29154 -11121
- package/dist/testing.d.mts +119 -14
- package/dist/testing.mjs +97 -7
- package/dist/{types-BZa187kz.d.mts → types-7GXcXxxv.d.mts} +196 -242
- package/dist/{types-BT9S_Lo2.d.mts → types-BGcda5Le.d.mts} +4464 -735
- package/dist/{types-yiHtzg1Y.d.mts → types-C73hbmxi.d.mts} +129 -17
- package/dist/{types-Bc9AvZVO.d.mts → types-DngFQJro.d.mts} +43 -5
- package/dist/{types-kNiV7iFj.d.mts → types-GHE4J5Uf.d.mts} +1027 -192
- package/dist/{visual-dMW8iqAE.mjs → visual-2m4wJL_z.mjs} +111 -7
- package/dist/visual-_XhoGeIC.d.mts +345 -0
- package/dist/visual.d.mts +1 -332
- package/dist/visual.mjs +130 -20
- package/dist/{watch-CWI_on4T.mjs → watch-BEdrp80i.mjs} +149 -30
- package/llms.txt +103 -51
- package/package.json +8 -6
- package/dist/dev-Cc50Dk7H.mjs +0 -47
- package/dist/memory-DR1ibF_s.d.mts +0 -50
- package/dist/types-DMoi447V.d.mts +0 -656
|
@@ -1,9 +1,91 @@
|
|
|
1
|
-
import { A as Api$
|
|
2
|
-
import {
|
|
1
|
+
import { A as PixiSprite, Ar as Api$1, Br as Require, Er as Events$5, Jn as Descriptor, Kt as AnyComponentValue, O as PixiFilter, T as Api$4, Wt as AnyComponent, Yt as ComponentType, Zt as Entity, _n as TrackOptions, _t as FilterSlotInputs, bn as Api$2, fn as MotionHandle, gn as ReducedMotion, gt as FilterSlot, j as PixiTexture, k as PixiModule, ln as Ease, lr as Events$3, pn as NumericFields, qn as TypeTag, qt as ComponentHandle, s as Events$1, sr as Api$6, t as Api$5, ur as Json, v as Events$4, vn as TrackSegment, xt as FilterCache, yt as Point, zr as Events$2, zt as Api$3 } from "./types-BGcda5Le.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-7GXcXxxv.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";
|
|
6
6
|
|
|
7
|
+
//#region src/plugins/debug/types.d.ts
|
|
8
|
+
declare namespace types_d_exports$4 {
|
|
9
|
+
export { Api, OverlayApi, OverlayMode };
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* @file debug plugin — type definitions: the overlay call.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* The two visible modes of the editor's overlay: the small pill or the full card.
|
|
16
|
+
*/
|
|
17
|
+
type OverlayMode = "pill" | "card";
|
|
18
|
+
/**
|
|
19
|
+
* The editor's overlay, from the game: open it, close it, toggle it, ask whether it shows. Every call is a no-op that
|
|
20
|
+
* answers `false` on a page without the agent (a release build, a test): no import of the editor, no guard needed.
|
|
21
|
+
*/
|
|
22
|
+
type OverlayApi = {
|
|
23
|
+
/**
|
|
24
|
+
* Shows the overlay: the card, or the pill with `{ mode: "pill" }`.
|
|
25
|
+
*
|
|
26
|
+
* @param options - How the overlay shows.
|
|
27
|
+
* @param options.mode - `"card"` (the default) or `"pill"`.
|
|
28
|
+
* @returns True when an overlay took the call; false on a page without the agent.
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* // A game's own "?" button of its settings sheet opens the overlay of a debug build.
|
|
32
|
+
* app.debug.overlay.open(); // true on `moku-game build --debug`; false on the store build
|
|
33
|
+
* app.debug.overlay.open({ mode: "pill" }); // true: the small pill
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
open(options?: {
|
|
37
|
+
mode?: OverlayMode;
|
|
38
|
+
}): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Hides the overlay.
|
|
41
|
+
*
|
|
42
|
+
* @returns True when an overlay took the call; false without the agent.
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* app.debug.overlay.close(); // true; app.debug.overlay.isOpen() is false after it
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
close(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Switches between hidden and the last visible mode.
|
|
51
|
+
*
|
|
52
|
+
* @returns True when an overlay took the call; false without the agent.
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // A game binds a three-finger tap of its own to the overlay.
|
|
56
|
+
* app.debug.overlay.toggle(); // true: shown (the card, or the pill if the pill was the last mode)
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
toggle(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Tells whether the overlay shows, as the pill or the card.
|
|
62
|
+
*
|
|
63
|
+
* @returns True while it shows; false when hidden and without the agent.
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* app.debug.overlay.open({ mode: "pill" });
|
|
67
|
+
* app.debug.overlay.isOpen(); // true
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
isOpen(): boolean;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The `debug` plugin's API: the overlay call.
|
|
74
|
+
*/
|
|
75
|
+
type Api = {
|
|
76
|
+
/**
|
|
77
|
+
* The editor's overlay. Usable anywhere the app is; a no-op without the agent. The ui tag `DebugTrigger` is one
|
|
78
|
+
* helper on top of it.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* // ui's DebugTrigger, after five taps:
|
|
83
|
+
* ctx.require(debugPlugin).overlay.open(); // true on a debug build
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
overlay: OverlayApi;
|
|
87
|
+
};
|
|
88
|
+
//#endregion
|
|
7
89
|
//#region src/plugins/anim/tween/types.d.ts
|
|
8
90
|
/**
|
|
9
91
|
* One running track: the numeric fields of one component of one entity moving from the values
|
|
@@ -16,7 +98,8 @@ import { Node, Yoga } from "yoga-layout/load";
|
|
|
16
98
|
* id: 1, entity: 1_048_576, component: Transform, to: { x: 200 },
|
|
17
99
|
* keys: { x: "1048576:Transform:x" }, ms: 350, ease: "out", delayMs: 0, elapsed: 0,
|
|
18
100
|
* from: undefined, muted: () => new Set(), additive: false, driven: false, bornFrame: 4,
|
|
19
|
-
* ended: false, segments: undefined, repeatsLeft: 0, held: false, masked: new Set()
|
|
101
|
+
* ended: false, segments: undefined, repeatsLeft: 0, held: false, masked: new Set(), keep: false,
|
|
102
|
+
* reveals: "place"
|
|
20
103
|
* };
|
|
21
104
|
* ```
|
|
22
105
|
*/
|
|
@@ -60,7 +143,14 @@ type Track = {
|
|
|
60
143
|
* When such a field is given back, the track adds to the value it finds there and not to the
|
|
61
144
|
* base it kept. Empty for a track that owns its fields.
|
|
62
145
|
*/
|
|
63
|
-
masked: Set<string>;
|
|
146
|
+
masked: Set<string>; /** Started with `reduced: "keep"`: reduced motion neither shortens nor holds it. */
|
|
147
|
+
readonly keep: boolean;
|
|
148
|
+
/**
|
|
149
|
+
* What the track writes that could show its view again, handed to `renderer.sync.loopsHeld` by an endless track
|
|
150
|
+
* (spec 26 R1.7.4): `"alpha"`, `"place"` (where the view is or how large), `"both"`, or `undefined` for a write
|
|
151
|
+
* that cannot (a tint, a fill colour). Computed once when the track is made.
|
|
152
|
+
*/
|
|
153
|
+
readonly reveals: "alpha" | "place" | "both" | undefined;
|
|
64
154
|
};
|
|
65
155
|
/**
|
|
66
156
|
* A motion handle that can also be advanced by hand: what the timeline cursor needs, so a track
|
|
@@ -178,6 +268,8 @@ declare function mark(name: string): Step;
|
|
|
178
268
|
* @param options.additive - `true` adds an offset instead of owning the fields.
|
|
179
269
|
* @param options.space - `"root"` reads the `Transform` fields as a root pose; `"local"` when
|
|
180
270
|
* omitted.
|
|
271
|
+
* @param options.reduced - `"keep"` plays the track at its length under reduced motion, a fade
|
|
272
|
+
* for one; `"cut"` (the default) lands it at once.
|
|
181
273
|
* @returns The tween step.
|
|
182
274
|
* @example
|
|
183
275
|
* ```ts
|
|
@@ -202,6 +294,7 @@ declare function tween<Value extends object>(target: Target, component: Componen
|
|
|
202
294
|
delayMs?: number;
|
|
203
295
|
additive?: boolean;
|
|
204
296
|
space?: "local" | "root";
|
|
297
|
+
reduced?: ReducedMotion;
|
|
205
298
|
}): Step;
|
|
206
299
|
/**
|
|
207
300
|
* Writes a component patch at once. Any field may be written, not only the numeric ones. The
|
|
@@ -392,7 +485,8 @@ type SfxDescriptor = {
|
|
|
392
485
|
readonly key: string;
|
|
393
486
|
readonly bus: string;
|
|
394
487
|
};
|
|
395
|
-
readonly cosmetic: true;
|
|
488
|
+
readonly cosmetic: true; /** Never set: `await fx(sfx(...))` resolves nothing. */
|
|
489
|
+
readonly $result?: () => void;
|
|
396
490
|
};
|
|
397
491
|
/**
|
|
398
492
|
* One haptic tick a device can play: the impact, selection and notification families of Tauri.
|
|
@@ -420,7 +514,8 @@ type HapticDescriptor = {
|
|
|
420
514
|
readonly payload: {
|
|
421
515
|
readonly kind: HapticKind;
|
|
422
516
|
};
|
|
423
|
-
readonly cosmetic: true;
|
|
517
|
+
readonly cosmetic: true; /** Never set: `await fx(haptic(...))` resolves nothing. */
|
|
518
|
+
readonly $result?: () => void;
|
|
424
519
|
};
|
|
425
520
|
/**
|
|
426
521
|
* The two descriptors `anim` owns. As a step, the descriptor is dispatched through
|
|
@@ -451,7 +546,8 @@ type PlayDescriptor = {
|
|
|
451
546
|
readonly animation: string;
|
|
452
547
|
readonly slots: Json;
|
|
453
548
|
};
|
|
454
|
-
readonly cosmetic: true;
|
|
549
|
+
readonly cosmetic: true; /** Never set: `await fx(play(...))` resolves nothing. */
|
|
550
|
+
readonly $result?: () => void;
|
|
455
551
|
};
|
|
456
552
|
/**
|
|
457
553
|
* One step of a choreography: plain frozen data with no callback inside, so a step tree can be
|
|
@@ -484,7 +580,8 @@ type Step = {
|
|
|
484
580
|
readonly ease: Ease;
|
|
485
581
|
readonly delayMs: number;
|
|
486
582
|
readonly additive: boolean; /** `"root"`: the `Transform` fields are a root pose, turned local when the track starts. */
|
|
487
|
-
readonly space: "local" | "root";
|
|
583
|
+
readonly space: "local" | "root"; /** `"keep"`: reduced motion plays the track as written; `"cut"` lands it at once. */
|
|
584
|
+
readonly reduced: ReducedMotion;
|
|
488
585
|
} | {
|
|
489
586
|
readonly kind: "set";
|
|
490
587
|
readonly target: Target;
|
|
@@ -625,20 +722,22 @@ type TimelineRuntime = {
|
|
|
625
722
|
};
|
|
626
723
|
/**
|
|
627
724
|
* One running timeline: its cursor, the marks it reached, the entities it counts on, the entities
|
|
628
|
-
* it spawned and despawns at its end, and the
|
|
725
|
+
* its key targets named at its start, the entities it spawned and despawns at its end, and the
|
|
726
|
+
* resolver of its `done` promise.
|
|
629
727
|
*/
|
|
630
728
|
type RunningTimeline = {
|
|
631
729
|
readonly id: number;
|
|
632
730
|
readonly animation: string;
|
|
633
731
|
readonly cursor: Cursor;
|
|
634
732
|
readonly marks: string[];
|
|
635
|
-
readonly entities: readonly Entity[]; /** The entities its `
|
|
733
|
+
readonly entities: readonly Entity[]; /** The entities its `{ projection, key }` targets named when it started, by target key. */
|
|
734
|
+
readonly targets: ReadonlyMap<string, Entity>; /** The entities its `spawn` steps made, by spawn id. Despawned when the timeline ends. */
|
|
636
735
|
readonly spawned: Map<string, Entity>;
|
|
637
736
|
readonly resolve: () => void;
|
|
638
737
|
ended: boolean;
|
|
639
738
|
};
|
|
640
739
|
declare namespace types_d_exports$3 {
|
|
641
|
-
export { AnimApi, AnimCtx, AnimPlayerValue, AnimationDefinition, AnimationSpec, AnyAnimationDefinition, BuildTools, Config$3 as Config, Cursor, Deps$3 as Deps, ErasedFields, Events
|
|
740
|
+
export { AnimApi, AnimCtx, AnimPlayerValue, AnimationDefinition, AnimationSpec, AnyAnimationDefinition, BuildTools, Config$3 as Config, Cursor, Deps$3 as Deps, ErasedFields, Events, ExternalPlayer, FrameLoop, FramesValue, FxStep, HapticDescriptor, HapticKind, KernelSlice$3 as KernelSlice, MarkListener, MotionKeyframe, PlayDescriptor, PlayHandle, Pose, RunningTimeline, SfxDescriptor, SlotRecord, SlotTags, SlotValue, SlotValues, State$3 as State, Step, StepMotion, Target, TimelineRuntime, Track };
|
|
642
741
|
}
|
|
643
742
|
/**
|
|
644
743
|
* What a step and a slot are pointed at: the projection key of a live view or of an element a
|
|
@@ -806,7 +905,7 @@ type MarkListener = (animation: string, mark: string) => void;
|
|
|
806
905
|
* }); // a reached mark("done") step logs { mark: "done" }
|
|
807
906
|
* ```
|
|
808
907
|
*/
|
|
809
|
-
type Events
|
|
908
|
+
type Events = {
|
|
810
909
|
/** A `mark` step was reached, or jumped by `finish()`. */"anim:mark": {
|
|
811
910
|
animation: string;
|
|
812
911
|
mark: string;
|
|
@@ -931,6 +1030,12 @@ type State$3 = {
|
|
|
931
1030
|
*/
|
|
932
1031
|
frameMutes: Map<Entity, () => void>; /** Removers of the `onAdded` and `onRemoved` hooks on `Frames`. */
|
|
933
1032
|
offFrames: Array<() => void>;
|
|
1033
|
+
/**
|
|
1034
|
+
* The renderer's `sync.loopsHeld`, bound in `onStart`: an endless loop of an entity it answers true for writes
|
|
1035
|
+
* nothing while its clock runs on (spec 22 O9), told what the loop reveals (spec 26 R1.7). `undefined` before the
|
|
1036
|
+
* start and after the stop: nothing is held.
|
|
1037
|
+
*/
|
|
1038
|
+
loopsHeld: ((entity: Entity, reveals?: "alpha" | "place" | "both") => boolean) | undefined;
|
|
934
1039
|
};
|
|
935
1040
|
/**
|
|
936
1041
|
* anim plugin API, `app.anim`: play a choreography, end everything, count what runs and listen
|
|
@@ -1112,9 +1217,9 @@ type AnimPlayerValue = {
|
|
|
1112
1217
|
* `tween` in `space: "root"` local with the pure `localPoseOf` of the same module.
|
|
1113
1218
|
*/
|
|
1114
1219
|
type Deps$3 = {
|
|
1115
|
-
time: Api;
|
|
1116
|
-
flow: Api$
|
|
1117
|
-
world: Api$
|
|
1220
|
+
time: Api$1;
|
|
1221
|
+
flow: Api$2;
|
|
1222
|
+
world: Api$3;
|
|
1118
1223
|
};
|
|
1119
1224
|
/**
|
|
1120
1225
|
* What the kernel context offers before the deps are attached.
|
|
@@ -1123,7 +1228,7 @@ type Deps$3 = {
|
|
|
1123
1228
|
* row 8), so the own events reach the context the kernel hands the factories and `emit` is the
|
|
1124
1229
|
* kernel's own, anim-typed one. No member of the context is cast.
|
|
1125
1230
|
*/
|
|
1126
|
-
type KernelSlice$3 = PluginCtx<Config$3, State$3, Events
|
|
1231
|
+
type KernelSlice$3 = PluginCtx<Config$3, State$3, Events> & {
|
|
1127
1232
|
readonly global: object;
|
|
1128
1233
|
readonly log: Log.LogApi;
|
|
1129
1234
|
readonly require: Require;
|
|
@@ -1134,297 +1239,1010 @@ type KernelSlice$3 = PluginCtx<Config$3, State$3, Events$1> & {
|
|
|
1134
1239
|
type AnimCtx = KernelSlice$3 & {
|
|
1135
1240
|
readonly deps: Deps$3;
|
|
1136
1241
|
};
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
}
|
|
1242
|
+
//#endregion
|
|
1243
|
+
//#region src/plugins/effects/filters/types.d.ts
|
|
1140
1244
|
/**
|
|
1141
|
-
*
|
|
1245
|
+
* One uniform of a custom filter, as declared: a number is an `f32` (`float` in GLSL), `{ color }`
|
|
1246
|
+
* a `0xrrggbb` hex sent as a `vec3<f32>` (`vec3`), a tuple of 2 to 4 numbers a `vecN<f32>`
|
|
1247
|
+
* (`vecN`).
|
|
1142
1248
|
*
|
|
1143
1249
|
* @example
|
|
1144
1250
|
* ```ts
|
|
1145
|
-
* const
|
|
1251
|
+
* const uniforms: Record<string, UniformDeclaration> = { amount: 0.5, color: { color: 0xffd700 }, offset: [2, 2] };
|
|
1146
1252
|
* ```
|
|
1147
1253
|
*/
|
|
1148
|
-
type
|
|
1254
|
+
type UniformDeclaration = number | {
|
|
1255
|
+
readonly color: number;
|
|
1256
|
+
} | readonly [number, number] | readonly [number, number, number] | readonly [number, number, number, number];
|
|
1149
1257
|
/**
|
|
1150
|
-
*
|
|
1151
|
-
*
|
|
1258
|
+
* The component field a uniform declaration becomes: a number for a number and for a colour, a
|
|
1259
|
+
* list of numbers for a tuple.
|
|
1152
1260
|
*
|
|
1153
1261
|
* @example
|
|
1154
1262
|
* ```ts
|
|
1155
|
-
*
|
|
1263
|
+
* type Amount = UniformValue<0.5>; // number
|
|
1156
1264
|
* ```
|
|
1157
1265
|
*/
|
|
1158
|
-
type
|
|
1159
|
-
|
|
1160
|
-
}
|
|
1266
|
+
type UniformValue<Declaration> = Declaration extends number ? number : Declaration extends {
|
|
1267
|
+
readonly color: number;
|
|
1268
|
+
} ? number : readonly number[];
|
|
1161
1269
|
/**
|
|
1162
|
-
* The
|
|
1163
|
-
*
|
|
1270
|
+
* The value of a filter component made by `defineFilter`: one field per uniform, then `enabled`
|
|
1271
|
+
* and `order`.
|
|
1164
1272
|
*
|
|
1165
1273
|
* @example
|
|
1166
1274
|
* ```ts
|
|
1167
|
-
*
|
|
1275
|
+
* type TintValue = FilterValueOf<{ amount: number; color: { color: number } }>;
|
|
1276
|
+
* // { amount: number; color: number; enabled: boolean; order: number }
|
|
1168
1277
|
* ```
|
|
1169
1278
|
*/
|
|
1170
|
-
type
|
|
1279
|
+
type FilterValueOf<Uniforms extends Record<string, UniformDeclaration>> = { -readonly [Name in keyof Uniforms]: UniformValue<Uniforms[Name]> } & {
|
|
1280
|
+
enabled: boolean;
|
|
1281
|
+
order: number;
|
|
1282
|
+
};
|
|
1171
1283
|
/**
|
|
1172
|
-
*
|
|
1173
|
-
*
|
|
1284
|
+
* A rectangle in the filtered entity's own units — the space its box, its hit box and its children's positions are in
|
|
1285
|
+
* (reference units for a view at the root without scale): x, y, width, height.
|
|
1174
1286
|
*
|
|
1175
1287
|
* @example
|
|
1176
1288
|
* ```ts
|
|
1177
|
-
*
|
|
1289
|
+
* // A lens disc of reach 88 around (195, 189): the 176 × 176 box it can draw in.
|
|
1290
|
+
* const area: FilterArea = [107, 101, 176, 176];
|
|
1178
1291
|
* ```
|
|
1179
1292
|
*/
|
|
1180
|
-
type
|
|
1293
|
+
type FilterArea = readonly [x: number, y: number, width: number, height: number];
|
|
1181
1294
|
/**
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1295
|
+
* What `defineFilter` takes besides the id. Both bodies are required, so the filter draws on
|
|
1296
|
+
* WebGPU and on the WebGL fallback: `wgsl` is the WGSL fragment body only, the engine prepends the
|
|
1297
|
+
* vertex stage, the input bindings and the `FilterUniforms` struct; `glsl` is its GLSL ES 3.0 twin
|
|
1298
|
+
* over the same uniform names, the engine prepends the version, the inputs, `finalColor` and one
|
|
1299
|
+
* `uniform` per declared uniform.
|
|
1184
1300
|
*
|
|
1185
1301
|
* @example
|
|
1186
1302
|
* ```ts
|
|
1187
|
-
*
|
|
1303
|
+
* // A Memory Missing's frost: the body reads a blurred copy of the scene through sampleBlur(uv).
|
|
1304
|
+
* const Frost = defineFilter("Frost", {
|
|
1305
|
+
* wgsl: FROST_WGSL,
|
|
1306
|
+
* glsl: FROST_GLSL,
|
|
1307
|
+
* uniforms: { view: [0, 0, 1], rectA: [0, 0, 0, 0], strength: 16, vivid: 1.2 },
|
|
1308
|
+
* inputs: { blur: { stages: [FrostBox4, FrostHalf, FrostGauss], chain: frostChain } },
|
|
1309
|
+
* fallback: FrostVeil
|
|
1310
|
+
* });
|
|
1311
|
+
* Frost.filter.fallback?.id; // "FrostVeil"
|
|
1188
1312
|
* ```
|
|
1189
1313
|
*/
|
|
1190
|
-
type
|
|
1314
|
+
type FilterSpec<Uniforms extends Record<string, UniformDeclaration>> = {
|
|
1315
|
+
/** The WGSL fragment body: `fn mainFragment` and its helpers, without the engine's header. */readonly wgsl: string;
|
|
1316
|
+
/**
|
|
1317
|
+
* The GLSL ES 3.0 fragment body: `void main()`, which sets `finalColor`, and its helpers, without
|
|
1318
|
+
* the engine's header. It reads each uniform under its bare name: `amount`, not `fu.amount`.
|
|
1319
|
+
*/
|
|
1320
|
+
readonly glsl: string; /** The uniforms in struct order. Default `{}`. */
|
|
1321
|
+
readonly uniforms?: Uniforms; /** Render passes one apply of the filter costs, an integer of at least 1. Default `1`. */
|
|
1322
|
+
readonly passes?: number; /** Pixels around the view's bounds, or the name of a number uniform whose live value they are. Default `0`. */
|
|
1323
|
+
readonly padding?: number | string;
|
|
1324
|
+
/**
|
|
1325
|
+
* Second textures the body reads, by name: `blur` declares `sampleBlur(uv)` in the WGSL and the GLSL, with the
|
|
1326
|
+
* texture, its sampler and two uniforms the engine fills. Leave `passes` out: the engine counts them. Default none.
|
|
1327
|
+
*/
|
|
1328
|
+
readonly inputs?: Readonly<Record<string, FilterInput<FilterValueOf<Uniforms>>>>;
|
|
1329
|
+
/**
|
|
1330
|
+
* What draws instead when the filter is broken (its shader or a stage does not compile on the device, its apply
|
|
1331
|
+
* throws, its chain fails): another filter over a subset of its uniforms, with the same value. Default none: a broken
|
|
1332
|
+
* filter leaves its view unfiltered.
|
|
1333
|
+
*/
|
|
1334
|
+
readonly fallback?: FilterStage;
|
|
1335
|
+
/**
|
|
1336
|
+
* What the renderer may do with a view this filter draws on, while nothing it depends on changes: `"local"` (the
|
|
1337
|
+
* default) keeps it as a picture, also while the view moves; `"placed"` keeps it with its canvas origin, for a body
|
|
1338
|
+
* that reads where it is drawn through `canvasPixel(uv)` (a body that calls the helper is placed by itself); set
|
|
1339
|
+
* `false` for a body whose look depends on where the view is drawn in a way the engine cannot see (a time read from
|
|
1340
|
+
* a texture, a hash of the screen position): the view is then drawn live in every frame. A body that reads
|
|
1341
|
+
* `uGlobalFrame`, `@builtin(position)`, `gl_FragCoord`, `uOutputTexture` or the origin of `uOutputFrame` and
|
|
1342
|
+
* declares nothing is drawn live as well, and a dev build warns once: declare `cache: false`.
|
|
1343
|
+
*/
|
|
1344
|
+
readonly cache?: "local" | "placed" | false;
|
|
1345
|
+
/**
|
|
1346
|
+
* The rectangle outside of which this filter draws nothing, in the filtered entity's own units, from the component's
|
|
1347
|
+
* value; `undefined` for "the view's bounds" (the default). Outside it Pixi draws nothing of the view at all — neither
|
|
1348
|
+
* the filter nor the view's own content — so declare it only for a filter whose output is transparent there. A view
|
|
1349
|
+
* with several enabled filters gets the union; a view with an enabled filter that declares no area gets none. Called
|
|
1350
|
+
* only when the value changed.
|
|
1351
|
+
*/
|
|
1352
|
+
readonly area?: (value: Readonly<FilterValueOf<Uniforms>>) => FilterArea | undefined;
|
|
1353
|
+
};
|
|
1354
|
+
/**
|
|
1355
|
+
* How one uniform travels to the GPU: its name, its WGSL type and the form it was declared in.
|
|
1356
|
+
*
|
|
1357
|
+
* @example
|
|
1358
|
+
* ```ts
|
|
1359
|
+
* const spec: UniformSpec = { name: "color", type: "vec3<f32>", form: "color", size: 3 };
|
|
1360
|
+
* ```
|
|
1361
|
+
*/
|
|
1362
|
+
type UniformSpec = {
|
|
1191
1363
|
readonly name: string;
|
|
1192
|
-
readonly
|
|
1193
|
-
readonly
|
|
1364
|
+
readonly type: "f32" | "vec2<f32>" | "vec3<f32>" | "vec4<f32>";
|
|
1365
|
+
readonly form: "number" | "color" | "vector";
|
|
1366
|
+
readonly size: number;
|
|
1194
1367
|
};
|
|
1195
1368
|
/**
|
|
1196
|
-
* The
|
|
1197
|
-
*
|
|
1369
|
+
* The filter a component made by `defineFilter` carries: the assembled WGSL in `source`, the
|
|
1370
|
+
* assembled GLSL in `glsl`, the uniforms in struct order, the passes one apply costs, the
|
|
1371
|
+
* padding, the second textures the body reads and the filter drawn in its place when it is broken.
|
|
1198
1372
|
*
|
|
1199
1373
|
* @example
|
|
1200
1374
|
* ```ts
|
|
1201
|
-
*
|
|
1375
|
+
* Tint.filter.source.includes("fn mainFragment"); // true: the WGSL, drawn on WebGPU
|
|
1376
|
+
* Tint.filter.glsl.startsWith("#version 300 es"); // true: the GLSL, drawn on WebGL
|
|
1377
|
+
* Tint.filter.uniforms.map(uniform => uniform.name); // ["amount", "color"]
|
|
1378
|
+
* Tint.filter.inputs.length; // 0: it reads no second texture
|
|
1379
|
+
* Tint.filter.cache; // "local": a still view under it is drawn from a picture
|
|
1202
1380
|
* ```
|
|
1203
1381
|
*/
|
|
1204
|
-
type
|
|
1382
|
+
type FilterDefinition = {
|
|
1383
|
+
readonly id: string; /** The assembled WGSL: the engine's header, the uniform struct, the input bindings, the body. */
|
|
1384
|
+
readonly source: string; /** The assembled GLSL ES 3.0: the engine's header, one `uniform` per uniform, the inputs, the body. */
|
|
1385
|
+
readonly glsl: string;
|
|
1386
|
+
readonly uniforms: readonly UniformSpec[];
|
|
1387
|
+
readonly passes: number;
|
|
1388
|
+
readonly padding: number | string; /** The second textures the body reads, in declaration order; empty for a filter with none. */
|
|
1389
|
+
readonly inputs: readonly FilterInputDefinition[]; /** What draws in its place when it is broken: another definition over a subset of its uniforms. */
|
|
1390
|
+
readonly fallback: FilterDefinition | undefined; /** What the kept-picture cache may do with it: the worst of its declaration, its body and its stages' bodies. */
|
|
1391
|
+
readonly cache: FilterCache;
|
|
1392
|
+
/**
|
|
1393
|
+
* The engine's `keptOrigin` uniform (`vec2<f32>`) of a body that calls `canvasPixel(uv)`, kept out of `uniforms`;
|
|
1394
|
+
* `undefined` for any other body.
|
|
1395
|
+
*/
|
|
1396
|
+
readonly origin: UniformSpec | undefined; /** The rectangle outside of which the filter draws nothing, from the value; present only when the spec gave one. */
|
|
1397
|
+
readonly area?: (value: Readonly<FilterFields>) => FilterArea | undefined;
|
|
1398
|
+
};
|
|
1399
|
+
/**
|
|
1400
|
+
* A filter a chain may draw: any component `defineFilter` made. Listed in an input's `stages` and named by its steps.
|
|
1401
|
+
* A built-in Pixi-core kind (`Blur`, `ColorMatrix`, …) has no `filter` and cannot be a stage.
|
|
1402
|
+
*
|
|
1403
|
+
* @example
|
|
1404
|
+
* ```ts
|
|
1405
|
+
* const FrostGauss = defineFilter("FrostGauss", { wgsl: gaussWgsl, glsl: gaussGlsl, uniforms: { dir: [0, 0], sigma: 0 } });
|
|
1406
|
+
* const stages: readonly FilterStage[] = [FrostBox4, FrostHalf, FrostGauss];
|
|
1407
|
+
* stages.map(stage => stage.filter.id); // ["FrostBox4", "FrostHalf", "FrostGauss"]
|
|
1408
|
+
* ```
|
|
1409
|
+
*/
|
|
1410
|
+
type FilterStage = {
|
|
1411
|
+
readonly componentName: string;
|
|
1412
|
+
readonly defaults: object;
|
|
1413
|
+
readonly filter: FilterDefinition;
|
|
1414
|
+
};
|
|
1415
|
+
/**
|
|
1416
|
+
* One step of a chain: the stage that draws, the share of the input's resolution it draws at, and the stage uniforms
|
|
1417
|
+
* of this step. A uniform the step leaves out takes the stage's default. A colour is a `0xrrggbb` number.
|
|
1418
|
+
*
|
|
1419
|
+
* @example
|
|
1420
|
+
* ```ts
|
|
1421
|
+
* // A Gaussian along x at an eighth of the resolution of the view's input.
|
|
1422
|
+
* const step: FilterStep = { stage: FrostGauss, scale: 1 / 8, uniforms: { dir: [1, 0], sigma: 4.66 } };
|
|
1423
|
+
* ```
|
|
1424
|
+
*/
|
|
1425
|
+
type FilterStep = {
|
|
1426
|
+
readonly stage: FilterStage; /** Above 0 and at most 1: the target of this step has `scale` × the resolution of the view's input. */
|
|
1427
|
+
readonly scale: number;
|
|
1428
|
+
readonly uniforms?: Readonly<Record<string, number | readonly number[]>>;
|
|
1429
|
+
};
|
|
1430
|
+
/**
|
|
1431
|
+
* What a chain is told besides the value: the real pixels per CSS pixel of the texture the view is drawn into (the
|
|
1432
|
+
* canvas resolution for a view at the top, less under a filter of lower resolution).
|
|
1433
|
+
*
|
|
1434
|
+
* @example
|
|
1435
|
+
* ```ts
|
|
1436
|
+
* // The owner's phone at maxResolution 3: 16 units of blur are 37 real pixels, an eighth is enough.
|
|
1437
|
+
* frostChain({ ...Frost().value, strength: 16, view: [0, 0, 384 / 390] }, { resolution: 2.8125 }).map(step => step.scale);
|
|
1438
|
+
* // [0.25, 0.125, 0.125, 0.125]
|
|
1439
|
+
* ```
|
|
1440
|
+
*/
|
|
1441
|
+
type FilterChainContext = {
|
|
1442
|
+
readonly resolution: number;
|
|
1443
|
+
};
|
|
1444
|
+
/**
|
|
1445
|
+
* A second texture the body of a filter reads, named by its key in `inputs`: `blur` gives the body
|
|
1446
|
+
* `sampleBlur(uv)`. `chain` returns the steps that draw it from the view's own input, each from the one before;
|
|
1447
|
+
* the body reads the last one. `stages` lists every filter the chain may name: they are checked on the device and
|
|
1448
|
+
* warmed up before the first draw, and a step naming another one is refused. The chain runs again only when a uniform
|
|
1449
|
+
* of the value or the resolution changed, never per frame; it may return `[]`, and the body then reads the view's own
|
|
1450
|
+
* input.
|
|
1451
|
+
*
|
|
1452
|
+
* @example
|
|
1453
|
+
* ```ts
|
|
1454
|
+
* const input: FilterInput<{ strength: number; enabled: boolean; order: number }> = {
|
|
1455
|
+
* stages: [FrostHalf, FrostGauss],
|
|
1456
|
+
* chain: (value, { resolution }) => [
|
|
1457
|
+
* { stage: FrostHalf, scale: 1 / 2 },
|
|
1458
|
+
* { stage: FrostGauss, scale: 1 / 2, uniforms: { dir: [1, 0], sigma: (value.strength * resolution) / 2 } },
|
|
1459
|
+
* { stage: FrostGauss, scale: 1 / 2, uniforms: { dir: [0, 1], sigma: (value.strength * resolution) / 2 } }
|
|
1460
|
+
* ]
|
|
1461
|
+
* };
|
|
1462
|
+
* ```
|
|
1463
|
+
*/
|
|
1464
|
+
type FilterInput<Value> = {
|
|
1465
|
+
readonly stages: readonly FilterStage[];
|
|
1466
|
+
/**
|
|
1467
|
+
* The steps of the second texture for this value and resolution. Pure: no state, no randomness; the context object
|
|
1468
|
+
* is the engine's and valid during the call only.
|
|
1469
|
+
*
|
|
1470
|
+
* @param value - The stored value of the filter component.
|
|
1471
|
+
* @param context - The resolution of the texture the view is drawn into.
|
|
1472
|
+
* @returns The steps in draw order, at most 16.
|
|
1473
|
+
* @example
|
|
1474
|
+
* ```ts
|
|
1475
|
+
* // A quarter is enough at one real pixel per CSS pixel: the box, then the Gaussian along x and along y.
|
|
1476
|
+
* Frost.filter.inputs[0]?.chain({ ...Frost().value, strength: 16, view: [0, 0, 1] }, { resolution: 1 }).length; // 3
|
|
1477
|
+
* ```
|
|
1478
|
+
*/
|
|
1479
|
+
chain(value: Readonly<Value>, context: FilterChainContext): readonly FilterStep[];
|
|
1480
|
+
};
|
|
1481
|
+
/**
|
|
1482
|
+
* An input as `defineFilter` stored it: the names the engine declared for it in both shader languages, its two
|
|
1483
|
+
* uniforms, its stages and its chain.
|
|
1484
|
+
*
|
|
1485
|
+
* @example
|
|
1486
|
+
* ```ts
|
|
1487
|
+
* const [blur] = Frost.filter.inputs;
|
|
1488
|
+
* [blur?.texture, blur?.sampler, blur?.scale.name, blur?.clamp.name, blur?.sample];
|
|
1489
|
+
* // ["blurTexture", "blurSampler", "blurScale", "blurClamp", "sampleBlur"]
|
|
1490
|
+
* ```
|
|
1491
|
+
*/
|
|
1492
|
+
type FilterInputDefinition = {
|
|
1205
1493
|
readonly name: string;
|
|
1206
|
-
readonly
|
|
1207
|
-
readonly
|
|
1494
|
+
readonly texture: string;
|
|
1495
|
+
readonly sampler: string;
|
|
1496
|
+
readonly scale: UniformSpec;
|
|
1497
|
+
readonly clamp: UniformSpec;
|
|
1498
|
+
readonly sample: string;
|
|
1499
|
+
readonly stages: readonly FilterStage[];
|
|
1500
|
+
readonly chain: FilterInput<FilterFields>["chain"];
|
|
1208
1501
|
};
|
|
1209
1502
|
/**
|
|
1210
|
-
*
|
|
1211
|
-
*
|
|
1503
|
+
* A filter component type: the `component()` of its id, with the filter definition attached. Its
|
|
1504
|
+
* numeric fields are tweenable like any component.
|
|
1505
|
+
*
|
|
1506
|
+
* @example
|
|
1507
|
+
* ```ts
|
|
1508
|
+
* const Tint: FilterComponent<{ amount: number; enabled: boolean; order: number }> =
|
|
1509
|
+
* defineFilter("fx.tint", { wgsl: tintWgsl, glsl: tintGlsl, uniforms: { amount: 0 } });
|
|
1510
|
+
* Tint.componentName; // "fx.tint"
|
|
1511
|
+
* ```
|
|
1512
|
+
*/
|
|
1513
|
+
type FilterComponent<Value extends object> = ComponentType<Value> & {
|
|
1514
|
+
readonly filter: FilterDefinition;
|
|
1515
|
+
};
|
|
1516
|
+
/**
|
|
1517
|
+
* One field of a stored filter value: a number, a switch, an asset key or a vector.
|
|
1518
|
+
*
|
|
1519
|
+
* @example
|
|
1520
|
+
* ```ts
|
|
1521
|
+
* const field: FilterField = 0.5;
|
|
1522
|
+
* ```
|
|
1212
1523
|
*/
|
|
1213
|
-
type
|
|
1214
|
-
readonly lift?: infer Lift;
|
|
1215
|
-
} ? string extends Exclude<Lift, undefined> ? Spec : Exclude<Lift, undefined> extends Layer ? Spec : SceneProjection<Layer> : Spec;
|
|
1524
|
+
type FilterField = number | boolean | string | readonly number[];
|
|
1216
1525
|
/**
|
|
1217
|
-
*
|
|
1218
|
-
*
|
|
1526
|
+
* The stored value of any filter component, with the kind erased: the filter sync reads every
|
|
1527
|
+
* kind through it.
|
|
1219
1528
|
*/
|
|
1220
|
-
type
|
|
1221
|
-
readonly
|
|
1222
|
-
|
|
1529
|
+
type FilterFields = {
|
|
1530
|
+
readonly enabled: boolean;
|
|
1531
|
+
readonly order: number;
|
|
1532
|
+
readonly [field: string]: FilterField;
|
|
1533
|
+
};
|
|
1223
1534
|
/**
|
|
1224
|
-
*
|
|
1225
|
-
* error sits on the projection that is wrong and not on the whole list.
|
|
1535
|
+
* `Glow`: a soft halo of `color` around the opaque pixels of the view.
|
|
1226
1536
|
*
|
|
1227
1537
|
* @example
|
|
1228
1538
|
* ```ts
|
|
1229
|
-
*
|
|
1539
|
+
* const value: GlowValue = { strength: 2, distance: 10, color: 0xffffff, alpha: 1, enabled: true, order: 0 };
|
|
1230
1540
|
* ```
|
|
1231
1541
|
*/
|
|
1232
|
-
type
|
|
1542
|
+
type GlowValue = {
|
|
1543
|
+
strength: number;
|
|
1544
|
+
distance: number;
|
|
1545
|
+
color: number;
|
|
1546
|
+
alpha: number;
|
|
1547
|
+
enabled: boolean;
|
|
1548
|
+
order: number;
|
|
1549
|
+
};
|
|
1550
|
+
/**
|
|
1551
|
+
* `Outline`: a ring of `thickness` pixels in `color` around the opaque pixels of the view.
|
|
1552
|
+
*
|
|
1553
|
+
* @example
|
|
1554
|
+
* ```ts
|
|
1555
|
+
* const value: OutlineValue = { thickness: 2, color: 0x000000, alpha: 1, enabled: true, order: 0 };
|
|
1556
|
+
* ```
|
|
1557
|
+
*/
|
|
1558
|
+
type OutlineValue = {
|
|
1559
|
+
thickness: number;
|
|
1560
|
+
color: number;
|
|
1561
|
+
alpha: number;
|
|
1562
|
+
enabled: boolean;
|
|
1563
|
+
order: number;
|
|
1564
|
+
};
|
|
1565
|
+
/**
|
|
1566
|
+
* `Blur`: Pixi's blur. `quality: 0` means `config.blur.quality`; `resolution: 0` means
|
|
1567
|
+
* `config.blur.phoneResolution` on a phone, otherwise 1.
|
|
1568
|
+
*
|
|
1569
|
+
* @example
|
|
1570
|
+
* ```ts
|
|
1571
|
+
* const value: BlurValue = { strength: 8, quality: 0, resolution: 0, repeatEdgePixels: true, enabled: true, order: 0 };
|
|
1572
|
+
* ```
|
|
1573
|
+
*/
|
|
1574
|
+
type BlurValue = {
|
|
1575
|
+
strength: number;
|
|
1576
|
+
quality: number;
|
|
1577
|
+
resolution: number;
|
|
1578
|
+
repeatEdgePixels: boolean;
|
|
1579
|
+
enabled: boolean;
|
|
1580
|
+
order: number;
|
|
1581
|
+
};
|
|
1582
|
+
/**
|
|
1583
|
+
* `ColorMatrix`: brightness, saturation, contrast, hue and grayscale composed in that order.
|
|
1584
|
+
* Every default is the identity.
|
|
1585
|
+
*
|
|
1586
|
+
* @example
|
|
1587
|
+
* ```ts
|
|
1588
|
+
* const value: ColorMatrixValue = { brightness: 1, saturation: 0, contrast: 0, hue: 0, grayscale: 1, enabled: true, order: 0 };
|
|
1589
|
+
* ```
|
|
1590
|
+
*/
|
|
1591
|
+
type ColorMatrixValue = {
|
|
1592
|
+
brightness: number;
|
|
1593
|
+
saturation: number;
|
|
1594
|
+
contrast: number;
|
|
1595
|
+
hue: number;
|
|
1596
|
+
grayscale: number;
|
|
1597
|
+
enabled: boolean;
|
|
1598
|
+
order: number;
|
|
1599
|
+
};
|
|
1600
|
+
/**
|
|
1601
|
+
* `Noise`: Pixi's noise with its seed always given, so two runs draw the same grain.
|
|
1602
|
+
*
|
|
1603
|
+
* @example
|
|
1604
|
+
* ```ts
|
|
1605
|
+
* const value: NoiseValue = { amount: 0.5, seed: 7, enabled: true, order: 0 };
|
|
1606
|
+
* ```
|
|
1607
|
+
*/
|
|
1608
|
+
type NoiseValue = {
|
|
1609
|
+
amount: number;
|
|
1610
|
+
seed: number;
|
|
1611
|
+
enabled: boolean;
|
|
1612
|
+
order: number;
|
|
1613
|
+
};
|
|
1614
|
+
/**
|
|
1615
|
+
* `Displacement`: Pixi's displacement over the texture of an asset key.
|
|
1616
|
+
*
|
|
1617
|
+
* @example
|
|
1618
|
+
* ```ts
|
|
1619
|
+
* const value: DisplacementValue = { map: "fx.ripple", scaleX: 20, scaleY: 20, enabled: true, order: 0 };
|
|
1620
|
+
* ```
|
|
1621
|
+
*/
|
|
1622
|
+
type DisplacementValue = {
|
|
1623
|
+
map: string;
|
|
1624
|
+
scaleX: number;
|
|
1625
|
+
scaleY: number;
|
|
1626
|
+
enabled: boolean;
|
|
1627
|
+
order: number;
|
|
1628
|
+
};
|
|
1233
1629
|
/**
|
|
1234
|
-
*
|
|
1235
|
-
* the appended `ui`; `NoInfer` keeps `projections` out of that inference, so a wrong name is
|
|
1236
|
-
* reported on the projection and never widens the layer union. `music` is an asset key of the
|
|
1237
|
-
* game, narrowed to its audio keys once the scanner splits them.
|
|
1630
|
+
* `Alpha`: Pixi's alpha over the whole subtree, as one layer.
|
|
1238
1631
|
*
|
|
1239
1632
|
* @example
|
|
1240
1633
|
* ```ts
|
|
1241
|
-
* const
|
|
1242
|
-
*
|
|
1243
|
-
|
|
1244
|
-
|
|
1634
|
+
* const value: AlphaValue = { alpha: 0.5, enabled: true, order: 0 };
|
|
1635
|
+
* ```
|
|
1636
|
+
*/
|
|
1637
|
+
type AlphaValue = {
|
|
1638
|
+
alpha: number;
|
|
1639
|
+
enabled: boolean;
|
|
1640
|
+
order: number;
|
|
1641
|
+
};
|
|
1642
|
+
/**
|
|
1643
|
+
* The five built-in kinds drawn by a Pixi core filter.
|
|
1644
|
+
*
|
|
1645
|
+
* @example
|
|
1646
|
+
* ```ts
|
|
1647
|
+
* const kind: CoreKind = "blur";
|
|
1648
|
+
* ```
|
|
1649
|
+
*/
|
|
1650
|
+
type CoreKind = "blur" | "colorMatrix" | "noise" | "displacement" | "alpha";
|
|
1651
|
+
/**
|
|
1652
|
+
* Where a filter kind comes from: our or a game's shaders (`"wgsl"`, with the GLSL twin beside
|
|
1653
|
+
* it), or a Pixi core filter.
|
|
1654
|
+
*/
|
|
1655
|
+
type KindSource = {
|
|
1656
|
+
readonly source: "wgsl";
|
|
1657
|
+
readonly definition: FilterDefinition;
|
|
1658
|
+
} | {
|
|
1659
|
+
readonly source: "core";
|
|
1660
|
+
readonly core: CoreKind;
|
|
1661
|
+
};
|
|
1662
|
+
/**
|
|
1663
|
+
* A filter kind before it is registered: its id, its component and its source.
|
|
1664
|
+
*/
|
|
1665
|
+
type KindEntry = KindSource & {
|
|
1666
|
+
readonly id: string;
|
|
1667
|
+
readonly component: ComponentHandle<FilterFields>;
|
|
1668
|
+
};
|
|
1669
|
+
/**
|
|
1670
|
+
* One registered filter kind. `index` is the registration order: the built-ins first, then the
|
|
1671
|
+
* filters of every feature in feature order.
|
|
1672
|
+
*/
|
|
1673
|
+
type FilterKind = KindEntry & {
|
|
1674
|
+
readonly index: number;
|
|
1675
|
+
};
|
|
1676
|
+
/**
|
|
1677
|
+
* The values of the uniform group of one of our filter instances: a number per `f32`, a vector
|
|
1678
|
+
* per colour and tuple. Written where they differ from the stored value.
|
|
1679
|
+
*/
|
|
1680
|
+
type UniformValues = Record<string, number | Float32Array>;
|
|
1681
|
+
/**
|
|
1682
|
+
* The uniform group of one of our filter instances, as the instance writes it.
|
|
1683
|
+
*/
|
|
1684
|
+
type FilterUniforms = {
|
|
1685
|
+
readonly uniforms: UniformValues;
|
|
1686
|
+
};
|
|
1687
|
+
/**
|
|
1688
|
+
* The Pixi object of one kind on one view, with the passes one apply of it costs now: what the
|
|
1689
|
+
* builders of `instance.ts` make before the instance gets its sort keys. A Pixi-core kind keeps
|
|
1690
|
+
* the fields its setters were last given, `applied`, so an equal value calls no setter.
|
|
1691
|
+
*/
|
|
1692
|
+
type FilterBody = {
|
|
1693
|
+
readonly kind: "wgsl";
|
|
1694
|
+
readonly filter: PixiFilter;
|
|
1695
|
+
readonly group: FilterUniforms | undefined;
|
|
1696
|
+
readonly definition: FilterDefinition;
|
|
1697
|
+
passes: number; /** The chains and their places; `undefined` for a definition without inputs. Set once, by `createFilter`. */
|
|
1698
|
+
inputs: InputsState | undefined; /** The dev mark drawn after the fallback by a stand-in (E5.4); `undefined` otherwise. */
|
|
1699
|
+
readonly mark: OursBody | undefined; /** The definition's last area answer, filled in place; `some: false` for `undefined` (B4). */
|
|
1700
|
+
readonly area: AreaBox; /** The value changed since the area was last asked: the next sync asks the definition again. */
|
|
1701
|
+
areaStale: boolean;
|
|
1702
|
+
} | {
|
|
1703
|
+
readonly kind: "blur";
|
|
1704
|
+
readonly filter: InstanceType<PixiModule["BlurFilter"]>; /** The fields the setters were last given; compared before a write. */
|
|
1705
|
+
readonly applied: Record<string, FilterField>;
|
|
1706
|
+
passes: number;
|
|
1707
|
+
} | {
|
|
1708
|
+
readonly kind: "colorMatrix";
|
|
1709
|
+
readonly filter: InstanceType<PixiModule["ColorMatrixFilter"]>; /** The fields the setters were last given; compared before a write. */
|
|
1710
|
+
readonly applied: Record<string, FilterField>;
|
|
1711
|
+
passes: number;
|
|
1712
|
+
} | {
|
|
1713
|
+
readonly kind: "noise";
|
|
1714
|
+
readonly filter: InstanceType<PixiModule["NoiseFilter"]>; /** The fields the setters were last given; compared before a write. */
|
|
1715
|
+
readonly applied: Record<string, FilterField>;
|
|
1716
|
+
passes: number;
|
|
1717
|
+
} | {
|
|
1718
|
+
readonly kind: "displacement";
|
|
1719
|
+
readonly filter: InstanceType<PixiModule["DisplacementFilter"]>;
|
|
1720
|
+
readonly sprite: PixiSprite; /** The fields the setters were last given; compared before a write. */
|
|
1721
|
+
readonly applied: Record<string, FilterField>; /** The asset key the map sprite shows now. */
|
|
1722
|
+
map: string;
|
|
1723
|
+
passes: number;
|
|
1724
|
+
} | {
|
|
1725
|
+
readonly kind: "alpha";
|
|
1726
|
+
readonly filter: InstanceType<PixiModule["AlphaFilter"]>; /** The fields the setters were last given; compared before a write. */
|
|
1727
|
+
readonly applied: Record<string, FilterField>;
|
|
1728
|
+
passes: number;
|
|
1729
|
+
};
|
|
1730
|
+
/**
|
|
1731
|
+
* A probe of the warm-up (spec 27 F4): the Pixi filter handed to `renderer.sync.filters.warm`, and its teardown.
|
|
1732
|
+
*/
|
|
1733
|
+
type WarmProbe = {
|
|
1734
|
+
readonly filter: PixiFilter;
|
|
1735
|
+
destroy(): void;
|
|
1736
|
+
};
|
|
1737
|
+
/**
|
|
1738
|
+
* A filter area as the filter sync keeps it, written in place: the four numbers, and whether there is one.
|
|
1739
|
+
*/
|
|
1740
|
+
type AreaBox = {
|
|
1741
|
+
x: number;
|
|
1742
|
+
y: number;
|
|
1743
|
+
width: number;
|
|
1744
|
+
height: number;
|
|
1745
|
+
some: boolean;
|
|
1746
|
+
};
|
|
1747
|
+
/**
|
|
1748
|
+
* The instance of one kind on one view: its Pixi object, and what it sorts by on the view, the
|
|
1749
|
+
* `order` of its component (written every frame) and the `index` of its kind. The instance is
|
|
1750
|
+
* the object the builder made, never a copy: a closure made while building (the apply guard)
|
|
1751
|
+
* reads and writes the same fields the filter sync does.
|
|
1752
|
+
*/
|
|
1753
|
+
type FilterInstance = FilterBody & {
|
|
1754
|
+
order: number;
|
|
1755
|
+
readonly index: number; /** True once the instance broke (its apply threw, its chain failed): it stays broken until it is retired. */
|
|
1756
|
+
broken: boolean; /** The value the filter sync handed over last: the chain and a stand-in are built from it. */
|
|
1757
|
+
value: Readonly<FilterFields>; /** The kind this instance draws for; a stand-in carries the id of the kind it stands in for. */
|
|
1758
|
+
readonly kindId: string; /** True for an instance that draws in place of a broken kind or instance (E5). */
|
|
1759
|
+
readonly standIn: boolean; /** A stand-in built while this broken instance was drawing; the next sync puts it in its place. */
|
|
1760
|
+
replacement: FilterInstance | undefined;
|
|
1761
|
+
};
|
|
1762
|
+
/**
|
|
1763
|
+
* One of our bodies: a `Filter` over the assembled programs, the kind of every place of a chain and of a mark.
|
|
1764
|
+
*/
|
|
1765
|
+
type OursBody = Extract<FilterBody, {
|
|
1766
|
+
kind: "wgsl";
|
|
1767
|
+
}>;
|
|
1768
|
+
/** One place of a chain: the Pixi filter that draws the stage there, and the share of the resolution it draws at. */
|
|
1769
|
+
type Place = {
|
|
1770
|
+
readonly definition: FilterDefinition;
|
|
1771
|
+
readonly body: OursBody;
|
|
1772
|
+
scale: number;
|
|
1773
|
+
};
|
|
1774
|
+
/**
|
|
1775
|
+
* The chains of one instance of a filter with inputs: what draws each second texture, and the seam spec 23 keeps
|
|
1776
|
+
* pictures through.
|
|
1777
|
+
*/
|
|
1778
|
+
type InputsState = {
|
|
1779
|
+
/** A uniform of the value changed since the last evaluation (set by `writeFilter`). */stale: boolean; /** The resolution of the last evaluation. */
|
|
1780
|
+
resolution: number; /** Changes whenever what the stages draw changes; 1 after the first evaluation. */
|
|
1781
|
+
version: number; /** The object `chain` receives, reused: its `resolution` is written before each call. */
|
|
1782
|
+
readonly context: {
|
|
1783
|
+
resolution: number;
|
|
1784
|
+
}; /** Per input, its places in draw order (each with the scale of its step). */
|
|
1785
|
+
readonly places: Place[][]; /** Bodies of places that left the chain, destroyed by the next sync. */
|
|
1786
|
+
readonly retired: OursBody[]; /** Pooled textures taken by the running apply; emptied in its `finally`. One array, reused. */
|
|
1787
|
+
readonly taken: PixiTexture[]; /** The options object handed to `TexturePool.getOptimalTexture`, reused. */
|
|
1788
|
+
readonly request: {
|
|
1789
|
+
width: number;
|
|
1790
|
+
height: number;
|
|
1791
|
+
resolution: number;
|
|
1792
|
+
}; /** Results lent by spec 23: while set, the apply draws the main body only, over them. */
|
|
1793
|
+
held: readonly PixiTexture[] | undefined; /** The slot seam, a frozen object replaced when a place is built or dropped. */
|
|
1794
|
+
slot: FilterSlotInputs;
|
|
1795
|
+
};
|
|
1796
|
+
/**
|
|
1797
|
+
* Where the shader check of every definition a kind can draw stands, in every build: one run per start of the
|
|
1798
|
+
* plugin.
|
|
1799
|
+
*/
|
|
1800
|
+
type CheckState = {
|
|
1801
|
+
/** Bumped by `stopEffects`: an answer of an earlier run is ignored. */run: number; /** The checks were started on the running backend. */
|
|
1802
|
+
started: boolean; /** Where each definition stands. */
|
|
1803
|
+
status: WeakMap<FilterDefinition, "pending" | "ok" | "broken">; /** Definitions still pending. */
|
|
1804
|
+
waiting: number; /** Definitions started, for the `effects:checks` line. */
|
|
1805
|
+
checked: number; /** Definitions that failed, for the `effects:checks` line. */
|
|
1806
|
+
failed: number; /** GLSL compiles in flight under `KHR_parallel_shader_compile`. */
|
|
1807
|
+
gl: Array<{
|
|
1808
|
+
definition: FilterDefinition;
|
|
1809
|
+
shader: WebGLShader;
|
|
1810
|
+
}>; /** `performance.now()` when the checks started, for the `effects:checks` line. */
|
|
1811
|
+
startedAt: number; /** Resolves when `started` and `waiting === 0`. */
|
|
1812
|
+
settled: Promise<void>; /** Resolves `settled`. */
|
|
1813
|
+
resolve: () => void;
|
|
1814
|
+
};
|
|
1815
|
+
/**
|
|
1816
|
+
* What the filter sync keeps for one entity: the kinds it carries, one instance per kind, the
|
|
1817
|
+
* instances waiting to be destroyed after the next assignment, the slots last handed to
|
|
1818
|
+
* `renderer.sync.filters.set`, the core kinds whose component changed this frame, the
|
|
1819
|
+
* instances of this frame in their sorted order (one array, reused every frame), and the one
|
|
1820
|
+
* `renderer.invalidate` call a visible filter write of the frame makes.
|
|
1821
|
+
*/
|
|
1822
|
+
type FilteredView = {
|
|
1823
|
+
readonly kinds: Set<string>;
|
|
1824
|
+
readonly instances: Map<string, FilterInstance>;
|
|
1825
|
+
readonly retired: FilterInstance[];
|
|
1826
|
+
assigned: readonly FilterSlot[];
|
|
1827
|
+
readonly changed: Set<string>;
|
|
1828
|
+
readonly placed: FilterInstance[]; /** True once `renderer.invalidate` was called for this view in the current frame. */
|
|
1829
|
+
signalled: boolean; /** Calls `renderer.invalidate(entity)` once per frame for this view, before the write; made once with the record. */
|
|
1830
|
+
readonly signal: () => void; /** The area last handed to `renderer.sync.filters.area`, written in place (B4). */
|
|
1831
|
+
readonly areaSent: AreaBox; /** The `enabled` switches of the placed instances when the area was last judged, one bit each in placed order. */
|
|
1832
|
+
areaMask: number;
|
|
1833
|
+
};
|
|
1834
|
+
//#endregion
|
|
1835
|
+
//#region src/plugins/effects/particles/types.d.ts
|
|
1836
|
+
/**
|
|
1837
|
+
* An inclusive `[min, max]` range; every particle draws its own value from it.
|
|
1838
|
+
*
|
|
1839
|
+
* @example
|
|
1840
|
+
* ```ts
|
|
1841
|
+
* const lifeMs: Range = [500, 900];
|
|
1842
|
+
* ```
|
|
1843
|
+
*/
|
|
1844
|
+
type Range = readonly [min: number, max: number];
|
|
1845
|
+
/**
|
|
1846
|
+
* A value over the life of a particle, linear from its birth (`from`) to its death (`to`).
|
|
1847
|
+
*
|
|
1848
|
+
* @example
|
|
1849
|
+
* ```ts
|
|
1850
|
+
* const shrink: Curve = { from: 1, to: 0.2 };
|
|
1851
|
+
* ```
|
|
1852
|
+
*/
|
|
1853
|
+
type Curve = {
|
|
1854
|
+
readonly from: number;
|
|
1855
|
+
readonly to: number;
|
|
1856
|
+
};
|
|
1857
|
+
/**
|
|
1858
|
+
* Where a particle is born, around the origin of its emitter, in reference units. `circle` is
|
|
1859
|
+
* uniform over the disc, `ring` uniform between `radius − width / 2` and `radius + width / 2`,
|
|
1860
|
+
* `rect` uniform over the centred box.
|
|
1861
|
+
*
|
|
1862
|
+
* @example
|
|
1863
|
+
* ```ts
|
|
1864
|
+
* const burstRing: Shape = { kind: "ring", radius: 48, width: 16 };
|
|
1865
|
+
* ```
|
|
1866
|
+
*/
|
|
1867
|
+
type Shape = {
|
|
1868
|
+
readonly kind: "point";
|
|
1869
|
+
} | {
|
|
1870
|
+
readonly kind: "circle";
|
|
1871
|
+
readonly radius: number;
|
|
1872
|
+
} | {
|
|
1873
|
+
readonly kind: "rect";
|
|
1874
|
+
readonly w: number;
|
|
1875
|
+
readonly h: number;
|
|
1876
|
+
} | {
|
|
1877
|
+
readonly kind: "ring";
|
|
1878
|
+
readonly radius: number;
|
|
1879
|
+
readonly width: number;
|
|
1880
|
+
};
|
|
1881
|
+
/**
|
|
1882
|
+
* A particle effect as data, what `defineEmitter` takes. Every field is optional except
|
|
1883
|
+
* `textures` and exactly one of `burst` and `rate`. Speeds are reference units per second, angles
|
|
1884
|
+
* degrees with 0 to the right and 90 down, spins radians per second.
|
|
1885
|
+
*
|
|
1886
|
+
* @example
|
|
1887
|
+
* ```ts
|
|
1888
|
+
* const stars: EmitterConfig = {
|
|
1889
|
+
* textures: ["fx.star", "fx.sparkle"], burst: 40, lifeMs: [500, 900], speed: [300, 700],
|
|
1890
|
+
* gravity: 900, drag: 0.2, shape: { kind: "circle", radius: 24 }, alpha: { from: 1, to: 0 }
|
|
1245
1891
|
* };
|
|
1246
1892
|
* ```
|
|
1247
1893
|
*/
|
|
1248
|
-
type
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1894
|
+
type EmitterConfig = {
|
|
1895
|
+
/** 1 to 16 asset keys of one atlas page; a particle picks one at random. */readonly textures: readonly string[]; /** Particles emitted once, when the component appears or its `effect` changes. */
|
|
1896
|
+
readonly burst?: number; /** Particles per second while `active` is true and the entity lives. */
|
|
1897
|
+
readonly rate?: number; /** Life of a particle in milliseconds. Default `[600, 1000]`. */
|
|
1898
|
+
readonly lifeMs?: Range; /** Start speed in reference units per second. Default `[0, 0]`. */
|
|
1899
|
+
readonly speed?: Range; /** Start direction in degrees, 0 right, 90 down. Default `[0, 360]`. */
|
|
1900
|
+
readonly angle?: Range; /** Downward acceleration in reference units per second². Default `0`. */
|
|
1901
|
+
readonly gravity?: number; /** Velocity lost per second, 0..1: `v *= (1 − drag) ^ seconds`. Default `0`. */
|
|
1902
|
+
readonly drag?: number; /** Spin in radians per second. Default `[0, 0]`. */
|
|
1903
|
+
readonly spin?: Range; /** Where particles are born around the origin. Default `{ kind: "point" }`. */
|
|
1904
|
+
readonly shape?: Shape; /** Scale over life. Default `{ from: 1, to: 1 }`. */
|
|
1905
|
+
readonly scale?: Curve; /** Alpha over life, 0..1. Default `{ from: 1, to: 1 }`. */
|
|
1906
|
+
readonly alpha?: Curve; /** Tint over life, `0xrrggbb`, linear per channel. Default white to white. */
|
|
1907
|
+
readonly tint?: Curve; /** `"world"`: particles outlive the entity. `"local"`: they move and die with it. Default `"world"`. */
|
|
1908
|
+
readonly space?: "world" | "local"; /** Milliseconds simulated before the first frame, for streams, 0..5000. Default `0`. */
|
|
1909
|
+
readonly prewarmMs?: number; /** Hard ceiling of live particles of one instance, 1..5000. Default `256`. */
|
|
1910
|
+
readonly maxParticles?: number; /** Blend mode of the particle container. Default `"normal"`. */
|
|
1911
|
+
readonly blend?: "normal" | "add";
|
|
1253
1912
|
};
|
|
1254
1913
|
/**
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1914
|
+
* An `EmitterConfig` with every default filled in. `burst` and `rate` stay as given: exactly one
|
|
1915
|
+
* of them is present.
|
|
1257
1916
|
*
|
|
1258
1917
|
* @example
|
|
1259
1918
|
* ```ts
|
|
1260
|
-
*
|
|
1919
|
+
* defineEmitter("fx.steam", { textures: ["fx.puff"], rate: 12 }).config.lifeMs; // [600, 1000]
|
|
1261
1920
|
* ```
|
|
1262
1921
|
*/
|
|
1263
|
-
type
|
|
1922
|
+
type ResolvedEmitterConfig = Required<Omit<EmitterConfig, "burst" | "rate">> & Pick<EmitterConfig, "burst" | "rate">;
|
|
1264
1923
|
/**
|
|
1265
|
-
* A
|
|
1924
|
+
* A particle effect as `defineEmitter` returns it: frozen, registered through the `emitters` key
|
|
1925
|
+
* of a feature and started by an `Emitter` component that names its id.
|
|
1266
1926
|
*
|
|
1267
1927
|
* @example
|
|
1268
1928
|
* ```ts
|
|
1269
|
-
*
|
|
1270
|
-
* //
|
|
1271
|
-
* // layers: [{ name: "items", sort: "y" }, { name: "ui", sort: "none" }], projections: [] }
|
|
1929
|
+
* const steam: EmitterDefinition = defineEmitter("fx.steam", { textures: ["fx.puff"], rate: 12 });
|
|
1930
|
+
* steam.config.rate; // 12
|
|
1272
1931
|
* ```
|
|
1273
1932
|
*/
|
|
1274
|
-
type
|
|
1933
|
+
type EmitterDefinition = {
|
|
1275
1934
|
readonly id: string;
|
|
1276
|
-
readonly
|
|
1277
|
-
readonly music: string | undefined; /** Draw order, bottom first. */
|
|
1278
|
-
readonly layers: readonly LayerSpec[]; /** Names of the projections the scene mounts. */
|
|
1279
|
-
readonly projections: readonly string[];
|
|
1935
|
+
readonly config: ResolvedEmitterConfig;
|
|
1280
1936
|
};
|
|
1281
1937
|
/**
|
|
1282
|
-
* The
|
|
1283
|
-
*
|
|
1938
|
+
* The value of the `Emitter` component: which effect runs on the entity and whether a stream
|
|
1939
|
+
* emits. `""` draws nothing.
|
|
1284
1940
|
*
|
|
1285
1941
|
* @example
|
|
1286
1942
|
* ```ts
|
|
1287
|
-
* const
|
|
1943
|
+
* const value: EmitterValue = { effect: "fx.steam", active: true };
|
|
1288
1944
|
* ```
|
|
1289
1945
|
*/
|
|
1290
|
-
type
|
|
1291
|
-
|
|
1292
|
-
|
|
1946
|
+
type EmitterValue = {
|
|
1947
|
+
effect: string;
|
|
1948
|
+
active: boolean;
|
|
1949
|
+
};
|
|
1950
|
+
/**
|
|
1951
|
+
* The cosmetic random source of one instance: xorshift32 over its own seed, never `Math.random`
|
|
1952
|
+
* and never the model's rng.
|
|
1953
|
+
*/
|
|
1954
|
+
type Rng = {
|
|
1955
|
+
/** The next number in `[0, 1)`. */next(): number; /** An integer in `[0, count)`. */
|
|
1956
|
+
int(count: number): number; /** A number in `[min, max]`. */
|
|
1957
|
+
between(min: number, max: number): number;
|
|
1958
|
+
};
|
|
1959
|
+
/**
|
|
1960
|
+
* A Pixi particle container: what one emitter instance draws in.
|
|
1961
|
+
*/
|
|
1962
|
+
type PixiParticleContainer = InstanceType<PixiModule["ParticleContainer"]>;
|
|
1963
|
+
/**
|
|
1964
|
+
* One particle of a container, as the container keeps it.
|
|
1965
|
+
*/
|
|
1966
|
+
type PixiParticle = PixiParticleContainer["particleChildren"][number];
|
|
1967
|
+
/**
|
|
1968
|
+
* What one effect id bakes to on first use: the 64-entry curve tables, the reach rectangle's half
|
|
1969
|
+
* side and the resolved textures. Dropped when a bundle with one of its textures leaves.
|
|
1970
|
+
*/
|
|
1971
|
+
type BakedEmitter = {
|
|
1972
|
+
readonly id: string;
|
|
1973
|
+
readonly config: ResolvedEmitterConfig; /** Scale per 1/64 of the life. */
|
|
1974
|
+
readonly scaleTable: Float32Array; /** Alpha per 1/64 of the life, 0..1. */
|
|
1975
|
+
readonly alphaTable: Float32Array; /** Tint per 1/64 of the life, packed as Pixi's `0xbbggrr`. */
|
|
1976
|
+
readonly tintTable: Uint32Array; /** Half side of the box no particle leaves, in reference units. */
|
|
1977
|
+
readonly reach: number;
|
|
1978
|
+
readonly textures: readonly PixiTexture[]; /** The texture source of the first texture: every texture of the effect samples it. */
|
|
1979
|
+
readonly source: PixiTexture["source"] | undefined; /** The largest side of the textures, in pixels. */
|
|
1980
|
+
readonly maxSide: number;
|
|
1981
|
+
};
|
|
1982
|
+
/**
|
|
1983
|
+
* The per-particle numbers a Pixi particle has no field for, one entry per live particle, in the
|
|
1984
|
+
* order of `particleChildren`.
|
|
1985
|
+
*/
|
|
1986
|
+
type BornFields = {
|
|
1987
|
+
readonly age: Float32Array;
|
|
1988
|
+
readonly life: Float32Array;
|
|
1989
|
+
readonly vx: Float32Array;
|
|
1990
|
+
readonly vy: Float32Array;
|
|
1991
|
+
readonly spin: Float32Array;
|
|
1992
|
+
readonly variant: Float32Array;
|
|
1993
|
+
};
|
|
1994
|
+
/**
|
|
1995
|
+
* One running effect: its container, the plugin-owned entity that carries it, the particle pool
|
|
1996
|
+
* and the numbers the step needs.
|
|
1997
|
+
*/
|
|
1998
|
+
type EmitterInstance = {
|
|
1999
|
+
readonly id: string;
|
|
2000
|
+
readonly baked: BakedEmitter; /** The entity whose `Emitter` started it. */
|
|
2001
|
+
readonly host: Entity; /** The plugin-owned entity whose `Display` is the container. */
|
|
2002
|
+
readonly entity: Entity;
|
|
2003
|
+
readonly container: PixiParticleContainer; /** Retired particles, reused before a new one is made. */
|
|
2004
|
+
readonly pool: PixiParticle[];
|
|
2005
|
+
readonly born: BornFields; /** Fraction of a particle owed to the next frame of a stream. */
|
|
2006
|
+
carry: number;
|
|
2007
|
+
readonly rng: Rng; /** The point the container was placed at, in root space (world space only). */
|
|
2008
|
+
readonly origin: Readonly<Point>;
|
|
2009
|
+
readonly space: "world" | "local"; /** Pixi's particle class, from the module the renderer loaded. */
|
|
2010
|
+
readonly particleClass: PixiModule["Particle"];
|
|
1293
2011
|
};
|
|
2012
|
+
declare namespace types_d_exports$2 {
|
|
2013
|
+
export { AlphaValue, AssetsReplaced$1 as AssetsReplaced, BlurValue, BundleUnloaded$1 as BundleUnloaded, ColorMatrixValue, Config$2 as Config, CoreKind, Curve, Deps$2 as Deps, DisplacementValue, EffectsApi, EffectsCtx, EffectsDiagnostics, EffectsStats, EmitterConfig, EmitterDefinition, EmitterValue, FilterArea, FilterCache, FilterChainContext, FilterComponent, FilterDefinition, FilterInput, FilterInputDefinition, FilterSpec, FilterStage, FilterStep, FilterValueOf, GlowValue, HotSwap, KernelSlice$2 as KernelSlice, NoiseValue, OutlineValue, Range, ResolvedEmitterConfig, Shape, State$2 as State, UniformDeclaration, UniformSpec, UniformValue };
|
|
2014
|
+
}
|
|
1294
2015
|
/**
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
2016
|
+
* effects plugin config. `maxParticles` here is the global warning line; the `maxParticles` of an
|
|
2017
|
+
* emitter config caps one instance.
|
|
1297
2018
|
*
|
|
1298
2019
|
* @example
|
|
1299
2020
|
* ```ts
|
|
1300
|
-
*
|
|
2021
|
+
* createApp({
|
|
2022
|
+
* plugins: [...screen, effectsPlugin],
|
|
2023
|
+
* pluginConfigs: { effects: { maxPasses: 16, phone: false } }
|
|
2024
|
+
* });
|
|
1301
2025
|
* ```
|
|
1302
2026
|
*/
|
|
1303
|
-
type Config$2 =
|
|
2027
|
+
type Config$2 = {
|
|
2028
|
+
/** Live particles over all instances above which one dev warning fires per crossing. */maxParticles: number; /** Render passes per frame above which one dev warning fires per crossing. */
|
|
2029
|
+
maxPasses: number; /** Whether this device is a phone. `"auto"`: a coarse pointer and a short side of at most 820 CSS px, read once in `onStart`. */
|
|
2030
|
+
phone: boolean | "auto";
|
|
2031
|
+
/**
|
|
2032
|
+
* What a `Blur` with `quality: 0` and `resolution: 0` resolves to. Shallow merge: a game that
|
|
2033
|
+
* sets `blur` gives both fields.
|
|
2034
|
+
*/
|
|
2035
|
+
blur: {
|
|
2036
|
+
quality: number;
|
|
2037
|
+
phoneResolution: number;
|
|
2038
|
+
};
|
|
2039
|
+
};
|
|
1304
2040
|
/**
|
|
1305
|
-
*
|
|
2041
|
+
* effects plugin state: the particle half, the filter half, and what both share.
|
|
1306
2042
|
*/
|
|
1307
2043
|
type State$2 = {
|
|
1308
|
-
/**
|
|
1309
|
-
|
|
2044
|
+
/** Resolved in `onStart`. */phone: boolean; /** The `emitters` of every feature, read in `onStart`. */
|
|
2045
|
+
emitters: Map<string, EmitterDefinition>; /** Per effect id, built on first use. */
|
|
2046
|
+
baked: Map<string, BakedEmitter>; /** Host entity to its running instance. */
|
|
2047
|
+
instances: Map<Entity, EmitterInstance>; /** World-space instances whose host left, stepped until empty. */
|
|
2048
|
+
orphans: Set<EmitterInstance>; /** Ordinal of the next instance: the cosmetic seed. */
|
|
2049
|
+
seedCounter: number; /** Live particles after the last step. */
|
|
2050
|
+
particles: number; /** Filter kinds whose shader or one of whose stages failed the check on the running backend, in every build. */
|
|
2051
|
+
broken: Set<string>; /** Filter kinds whose main definition and every stage answered ok: a kind's status is a set lookup once settled. */
|
|
2052
|
+
ready: Set<string>; /** The filter kinds, built-ins first, then the filters of every feature. */
|
|
2053
|
+
kinds: Map<string, FilterKind>; /** The shader check of every definition a kind can draw, in every build. */
|
|
2054
|
+
checks: CheckState; /** Entity to the filters the sync keeps for it. */
|
|
2055
|
+
views: Map<Entity, FilteredView>; /** Keys of the one-shot warnings: `"emitter:fx.x"`, `"texture:board.cell"`, `"atlas:fx.x"`. */
|
|
2056
|
+
warned: Set<string>; /** Whether each budget warning is in force, so a crossing warns once. */
|
|
2057
|
+
over: {
|
|
2058
|
+
particles: boolean;
|
|
2059
|
+
passes: boolean;
|
|
2060
|
+
fullScreen: boolean;
|
|
2061
|
+
}; /** The teardown closure, the two systems and the world hooks. */
|
|
2062
|
+
removers: Array<() => void>;
|
|
2063
|
+
/**
|
|
2064
|
+
* The switches of a debug build: the kind ids in registration order (frozen, filled in `onStart`), the kinds
|
|
2065
|
+
* turned off, and those as a frozen list in the order of `kinds`.
|
|
2066
|
+
*/
|
|
2067
|
+
diagnostics: {
|
|
2068
|
+
kinds: readonly string[];
|
|
2069
|
+
off: Set<string>;
|
|
2070
|
+
offList: readonly string[];
|
|
2071
|
+
};
|
|
1310
2072
|
/**
|
|
1311
|
-
* The
|
|
1312
|
-
*
|
|
1313
|
-
* with `expect`. A rest node clears it; a transit node clears it only when it took it; an over
|
|
1314
|
-
* node takes it and clears it, whatever is mounted, except an over transit node of a fast walk,
|
|
1315
|
-
* which leaves it alone.
|
|
2073
|
+
* The warm-up hand-over (spec 27 F4): started at the first frame with a ready host, the Pixi-core kinds noted then,
|
|
2074
|
+
* and the probes handed to `renderer.sync.filters.warm`, kept until the app stops.
|
|
1316
2075
|
*/
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
2076
|
+
warm: {
|
|
2077
|
+
started: boolean;
|
|
2078
|
+
core: string[];
|
|
2079
|
+
probes: WarmProbe[];
|
|
2080
|
+
};
|
|
1320
2081
|
};
|
|
1321
2082
|
/**
|
|
1322
|
-
*
|
|
2083
|
+
* What `app.effects.stats()` answers: live particles, running emitter instances, filter instances
|
|
2084
|
+
* on views, and the render passes of the frame as the renderer counts them.
|
|
1323
2085
|
*
|
|
1324
2086
|
* @example
|
|
1325
2087
|
* ```ts
|
|
1326
|
-
*
|
|
1327
|
-
* createPlugin("music", {
|
|
1328
|
-
* depends: [scenesPlugin],
|
|
1329
|
-
* hooks: ctx => ({ "scenes:changed": ({ music }) => ctx.log.info("scene music", { music }) })
|
|
1330
|
-
* }); // entering the board logs { music: "board.theme" }
|
|
2088
|
+
* const stats: EffectsStats = { particles: 120, emitters: 3, filters: 25, renderPasses: 49 };
|
|
1331
2089
|
* ```
|
|
1332
2090
|
*/
|
|
1333
|
-
type
|
|
1334
|
-
/**
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
};
|
|
2091
|
+
type EffectsStats = {
|
|
2092
|
+
/** Live particles over every instance and orphan after the last step. */particles: number; /** Running instances plus the orphans still flying. */
|
|
2093
|
+
emitters: number; /** Filter instances over every view; the stages of a filter's inputs are counted in `renderPasses`, not here. */
|
|
2094
|
+
filters: number; /** `renderer.sync.renderPasses()`, read at call time. */
|
|
2095
|
+
renderPasses: number;
|
|
1339
2096
|
};
|
|
1340
2097
|
/**
|
|
1341
|
-
*
|
|
1342
|
-
*
|
|
2098
|
+
* effects plugin API, `app.effects`. Everything a game does with effects is data on entities;
|
|
2099
|
+
* the API only counts.
|
|
1343
2100
|
*
|
|
1344
2101
|
* @example
|
|
1345
2102
|
* ```ts
|
|
1346
|
-
* // A
|
|
1347
|
-
*
|
|
1348
|
-
* app.
|
|
2103
|
+
* // A test waits for a merge burst to land before it compares the board.
|
|
2104
|
+
* while (app.effects.stats().particles > 0) app.time.step(16);
|
|
2105
|
+
* app.effects.stats().particles; // 0
|
|
1349
2106
|
* ```
|
|
1350
2107
|
*/
|
|
1351
|
-
type
|
|
2108
|
+
type EffectsApi = {
|
|
1352
2109
|
/**
|
|
1353
|
-
*
|
|
2110
|
+
* Counts what runs now. `renderPasses` is the renderer's own number, read at call time; the
|
|
2111
|
+
* others are the plugin's. Headless every number is 0.
|
|
1354
2112
|
*
|
|
1355
|
-
* @returns
|
|
2113
|
+
* @returns A fresh object: live particles, emitter instances with orphans, filter instances
|
|
2114
|
+
* and render passes.
|
|
1356
2115
|
* @example
|
|
1357
2116
|
* ```ts
|
|
1358
|
-
* //
|
|
1359
|
-
* app.
|
|
2117
|
+
* // After the board rests: one steam stream, 24 enabled glows on 24 views, one disabled blur.
|
|
2118
|
+
* app.effects.stats();
|
|
2119
|
+
* // { particles: 18, emitters: 1, filters: 25, renderPasses: 49 }: 1 + 24 × (1 + 1), the disabled blur costs 0
|
|
1360
2120
|
* ```
|
|
1361
2121
|
*/
|
|
1362
|
-
|
|
1363
|
-
/**
|
|
1364
|
-
*
|
|
1365
|
-
*
|
|
1366
|
-
*
|
|
1367
|
-
* with the scene under it, also when the popup is a transit node that waits for its answer:
|
|
1368
|
-
* the scene of such a popup is mounted before `flow.restore` resolves.
|
|
1369
|
-
* An over node takes the expected scene too, whatever is mounted, so a popup bookmark restored
|
|
1370
|
-
* on a page that shows another scene switches to the scene of the bookmark. With nothing
|
|
1371
|
-
* expected an over node never switches. An over transit node of a fast walk mounts nothing and
|
|
1372
|
-
* keeps the record.
|
|
2122
|
+
stats(): EffectsStats;
|
|
2123
|
+
/**
|
|
2124
|
+
* Switches of a debug build: filter kinds turned off by hand, to measure what a kind costs on the device. Acts on
|
|
2125
|
+
* a page with the agent flag (a debug build, the dev page); elsewhere `disable` and `enable` change nothing. An off
|
|
2126
|
+
* kind keeps its instances: `stats().filters` still counts them, `renderPasses` drops.
|
|
1373
2127
|
*
|
|
1374
|
-
* @param id - Id of a scene a feature declared.
|
|
1375
|
-
* @throws {Error} For an id no feature declared, also before `onStart` filled the registry.
|
|
1376
2128
|
* @example
|
|
1377
2129
|
* ```ts
|
|
1378
|
-
* // A
|
|
1379
|
-
* //
|
|
1380
|
-
* app.
|
|
1381
|
-
* await app.flow.restore(bookmark); // resolves when the popup's gate is open
|
|
1382
|
-
* app.scenes.current(); // "home"
|
|
2130
|
+
* // A game's overlay toggle "Glow": the frame without any glow, then with it again.
|
|
2131
|
+
* app.effects.diagnostics.disable("effects.glow"); // true
|
|
2132
|
+
* app.effects.diagnostics.enable("effects.glow"); // true
|
|
1383
2133
|
* ```
|
|
1384
2134
|
*/
|
|
1385
|
-
|
|
2135
|
+
diagnostics: EffectsDiagnostics;
|
|
2136
|
+
};
|
|
2137
|
+
/**
|
|
2138
|
+
* Switches of a debug build: filter kinds turned off by hand, to measure what a kind costs on the device. Acts on
|
|
2139
|
+
* a page with the agent flag (a debug build, the dev page); elsewhere `disable` and `enable` change nothing.
|
|
2140
|
+
*
|
|
2141
|
+
* @example
|
|
2142
|
+
* ```ts
|
|
2143
|
+
* // A game's overlay toggle "Glow" (H4.4): the frame without any glow, then with it again.
|
|
2144
|
+
* app.effects.diagnostics.disable("effects.glow"); // true
|
|
2145
|
+
* app.effects.diagnostics.enable("effects.glow"); // true
|
|
2146
|
+
* ```
|
|
2147
|
+
*/
|
|
2148
|
+
type EffectsDiagnostics = {
|
|
2149
|
+
/**
|
|
2150
|
+
* The filter kinds this app knows, in registration order: the seven built-ins, then the `filters` of every
|
|
2151
|
+
* feature. The same frozen array on every call; empty before start. Every build.
|
|
2152
|
+
*
|
|
2153
|
+
* @returns The kind ids.
|
|
2154
|
+
* @example
|
|
2155
|
+
* ```ts
|
|
2156
|
+
* // A game with the frost filter of its casefile feature, after start.
|
|
2157
|
+
* app.effects.diagnostics.kinds();
|
|
2158
|
+
* // ["effects.glow", "effects.outline", "effects.blur", "effects.colorMatrix", "effects.noise",
|
|
2159
|
+
* // "effects.displacement", "effects.alpha", "casefile.frost"]
|
|
2160
|
+
* ```
|
|
2161
|
+
*/
|
|
2162
|
+
kinds(): readonly string[];
|
|
2163
|
+
/**
|
|
2164
|
+
* Turns a filter kind off: from the next frame no view draws it (no apply, no render pass), while its instances
|
|
2165
|
+
* stay and are still written, so `enable` shows the current look at once. Agent pages only.
|
|
2166
|
+
*
|
|
2167
|
+
* @param kind - A kind id of `kinds()`.
|
|
2168
|
+
* @returns True when the kind is known and now off; false for an unknown kind, and on a page without the agent
|
|
2169
|
+
* flag, where nothing changes.
|
|
2170
|
+
* @example
|
|
2171
|
+
* ```ts
|
|
2172
|
+
* // The owner measures the board without the glow of its four cards (one glow pass each).
|
|
2173
|
+
* app.effects.diagnostics.disable("effects.glow"); // true
|
|
2174
|
+
* app.time.step(16);
|
|
2175
|
+
* app.effects.stats().renderPasses; // 9, down from 13
|
|
2176
|
+
* app.effects.diagnostics.disable("fx.nope"); // false, and one warning effects:diagnostics-unknown
|
|
2177
|
+
* ```
|
|
2178
|
+
*/
|
|
2179
|
+
disable(kind: string): boolean;
|
|
2180
|
+
/**
|
|
2181
|
+
* Turns a filter kind on again: from the next frame its views draw it with their current values.
|
|
2182
|
+
*
|
|
2183
|
+
* @param kind - A kind id of `kinds()`.
|
|
2184
|
+
* @returns True when the kind is known and now on; false for an unknown kind and without the agent flag.
|
|
2185
|
+
* @example
|
|
2186
|
+
* ```ts
|
|
2187
|
+
* app.effects.diagnostics.enable("effects.glow"); // true
|
|
2188
|
+
* app.time.step(16);
|
|
2189
|
+
* app.effects.stats().renderPasses; // 13
|
|
2190
|
+
* ```
|
|
2191
|
+
*/
|
|
2192
|
+
enable(kind: string): boolean;
|
|
2193
|
+
/**
|
|
2194
|
+
* The kinds turned off now, in registration order. The same frozen array until the next change; empty without
|
|
2195
|
+
* the agent flag.
|
|
2196
|
+
*
|
|
2197
|
+
* @returns The kind ids.
|
|
2198
|
+
* @example
|
|
2199
|
+
* ```ts
|
|
2200
|
+
* app.effects.diagnostics.disable("casefile.frost");
|
|
2201
|
+
* app.effects.diagnostics.disable("effects.glow");
|
|
2202
|
+
* app.effects.diagnostics.disabled(); // ["effects.glow", "casefile.frost"]
|
|
2203
|
+
* ```
|
|
2204
|
+
*/
|
|
2205
|
+
disabled(): readonly string[];
|
|
1386
2206
|
};
|
|
1387
2207
|
/**
|
|
1388
2208
|
* Resolved dependency APIs.
|
|
1389
2209
|
*/
|
|
1390
2210
|
type Deps$2 = {
|
|
1391
|
-
flow: Api$
|
|
1392
|
-
world: Api$
|
|
1393
|
-
|
|
1394
|
-
|
|
2211
|
+
flow: Api$2;
|
|
2212
|
+
world: Api$3;
|
|
2213
|
+
renderer: Api$4;
|
|
2214
|
+
assets: Api$5;
|
|
2215
|
+
anim: AnimApi;
|
|
1395
2216
|
};
|
|
1396
2217
|
/**
|
|
1397
|
-
* What the kernel context offers before the deps are attached.
|
|
1398
|
-
*
|
|
1399
|
-
* `index.ts` writes `events` with an annotated `register` (core spec `14-EVENT-REGISTRATION.md`
|
|
1400
|
-
* row 8), so the own event reaches the context the kernel hands the factories and `emit` is the
|
|
1401
|
-
* kernel's own, scenes-typed one. No member of the context is cast.
|
|
2218
|
+
* What the kernel context offers before the deps are attached. `effects` owns no event, so
|
|
2219
|
+
* `emit` is the kernel's and never called here.
|
|
1402
2220
|
*/
|
|
1403
|
-
type KernelSlice$2 = PluginCtx<Config$2, State$2
|
|
2221
|
+
type KernelSlice$2 = PluginCtx<Config$2, State$2> & {
|
|
1404
2222
|
readonly global: object;
|
|
1405
2223
|
readonly log: Log.LogApi;
|
|
1406
2224
|
readonly require: Require;
|
|
1407
2225
|
};
|
|
1408
2226
|
/**
|
|
1409
|
-
* Domain context shared by the
|
|
2227
|
+
* Domain context shared by both modules: the kernel slice plus the resolved deps.
|
|
1410
2228
|
*/
|
|
1411
|
-
type
|
|
2229
|
+
type EffectsCtx = KernelSlice$2 & {
|
|
1412
2230
|
readonly deps: Deps$2;
|
|
1413
2231
|
};
|
|
1414
2232
|
/**
|
|
1415
|
-
*
|
|
1416
|
-
*
|
|
1417
|
-
* @example
|
|
1418
|
-
* ```ts
|
|
1419
|
-
* const run: RunContext = { mode: "live", signal: new AbortController().signal };
|
|
1420
|
-
* ```
|
|
2233
|
+
* Payload of the `assets:bundle-unloaded` hook: `keys` names every texture that is gone.
|
|
1421
2234
|
*/
|
|
1422
|
-
type
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
2235
|
+
type BundleUnloaded$1 = Events$1["assets:bundle-unloaded"];
|
|
2236
|
+
/**
|
|
2237
|
+
* Payload of the `assets:replaced` hook: `keys` names every asset a dev hot swap gave new bytes.
|
|
2238
|
+
*/
|
|
2239
|
+
type AssetsReplaced$1 = Events$1["assets:replaced"];
|
|
2240
|
+
/**
|
|
2241
|
+
* Payload of the global `ui:hot-swap` hook: the saved file and its new exports.
|
|
2242
|
+
*/
|
|
2243
|
+
type HotSwap = Events$2["ui:hot-swap"];
|
|
1426
2244
|
declare namespace types_d_exports$1 {
|
|
1427
|
-
export { AssetsReplaced, AudioApi, AudioContextLike, AudioCtx, AudioSessionLike, AudioSessionType, BundleUnloaded, Bus, BusState, Config$1 as Config, Deps$1 as Deps, KernelSlice$1 as KernelSlice, LifecycleChanged, ModelCommitted, MusicDescriptor, MusicMode, MusicOptions, MusicRequest, MusicSwitch, MusicTrack, RetiringTrack, SceneChanged, SfxRequest, SoundEntry, State$1 as State, StreamTrack, Volumes };
|
|
2245
|
+
export { AssetsReplaced, AudioApi, AudioContextLike, AudioCtx, AudioSessionLike, AudioSessionType, BundleUnloaded, Bus, BusState, Config$1 as Config, Deps$1 as Deps, KernelSlice$1 as KernelSlice, LifecycleChanged, ModelCommitted, MusicDescriptor, MusicMode, MusicOptions, MusicRequest, MusicSwitch, MusicTrack, RetiringTrack, SceneChanged, SfxRequest, SoundEntry, State$1 as State, StreamTrack, Volumes, VolumesFor };
|
|
1428
2246
|
}
|
|
1429
2247
|
/**
|
|
1430
2248
|
* The three volume buses. `master` carries the whole game, `music` the scene track, `sfx` every
|
|
@@ -1464,14 +2282,14 @@ type MusicOptions = {
|
|
|
1464
2282
|
};
|
|
1465
2283
|
/**
|
|
1466
2284
|
* `music` bound to the audio asset keys of one game. `defineGame` returns it through `audioFor`;
|
|
1467
|
-
* the loose export accepts any string.
|
|
2285
|
+
* the loose export accepts any string. The descriptor resolves nothing.
|
|
1468
2286
|
*
|
|
1469
2287
|
* @example
|
|
1470
2288
|
* ```ts
|
|
1471
2289
|
* const gameMusic: MusicDescriptor<"board.theme"> = music;
|
|
1472
2290
|
* ```
|
|
1473
2291
|
*/
|
|
1474
|
-
type MusicDescriptor<Asset extends string> = (key: Asset | null, options?: MusicOptions) => Descriptor
|
|
2292
|
+
type MusicDescriptor<Asset extends string> = (key: Asset | null, options?: MusicOptions) => Descriptor<void>;
|
|
1475
2293
|
/**
|
|
1476
2294
|
* Reads the player's volume choice out of the committed player state. Every bus it names is
|
|
1477
2295
|
* applied; the ones it leaves out keep the value they had.
|
|
@@ -1482,6 +2300,17 @@ type MusicDescriptor<Asset extends string> = (key: Asset | null, options?: Music
|
|
|
1482
2300
|
* ```
|
|
1483
2301
|
*/
|
|
1484
2302
|
type Volumes = (player: Json) => Partial<Record<Bus, number>>;
|
|
2303
|
+
/**
|
|
2304
|
+
* `Volumes`, written against the player type of one game: `defineGame` hands it as `volumes`, so
|
|
2305
|
+
* the callback reads the game's player with no cast. The same function at run time.
|
|
2306
|
+
*
|
|
2307
|
+
* @example
|
|
2308
|
+
* ```ts
|
|
2309
|
+
* // index.ts of a game: `volumes` comes from the kit, so `player` is the game's Player.
|
|
2310
|
+
* pluginConfigs: { audio: { volumes: volumes(player => ({ music: player.settings.music })) } }
|
|
2311
|
+
* ```
|
|
2312
|
+
*/
|
|
2313
|
+
type VolumesFor<Player> = (read: (player: Player) => Partial<Record<Bus, number>>) => Volumes;
|
|
1485
2314
|
/**
|
|
1486
2315
|
* How a music track is played. `"decode"`: one AudioBuffer per track, gapless, about 58 MB per
|
|
1487
2316
|
* 150 s at 48 kHz. `"stream"`: an `<audio>` element on a `blob:` URL of the bytes `assets` holds,
|
|
@@ -1554,10 +2383,11 @@ type RetiringTrack = {
|
|
|
1554
2383
|
*
|
|
1555
2384
|
* @example
|
|
1556
2385
|
* ```ts
|
|
2386
|
+
* // `volumes` comes from the game's `defineGame` kit, so `player` is the game's Player.
|
|
1557
2387
|
* createApp({
|
|
1558
2388
|
* plugins: [...screen, audioPlugin],
|
|
1559
2389
|
* pluginConfigs: {
|
|
1560
|
-
* audio: { musicFadeMs: 400, music: "stream", session: "playback", volumes: player => player.settings.audio }
|
|
2390
|
+
* audio: { musicFadeMs: 400, music: "stream", session: "playback", volumes: volumes(player => player.settings.audio) }
|
|
1561
2391
|
* }
|
|
1562
2392
|
* });
|
|
1563
2393
|
* ```
|
|
@@ -1754,6 +2584,9 @@ type AudioApi = {
|
|
|
1754
2584
|
* and a music switch to the track that already plays are not in it. Empty while
|
|
1755
2585
|
* `config.journal` is 0, the default, and after the app stopped.
|
|
1756
2586
|
*
|
|
2587
|
+
* No copy and no live view: the list and its entries are never written. Every new sound replaces the plugin's list
|
|
2588
|
+
* with a new frozen one, so a list read earlier keeps what it held, and a caller cannot change the journal through it.
|
|
2589
|
+
*
|
|
1757
2590
|
* @returns The journal, frozen; a later sound replaces the list and leaves this one as it was.
|
|
1758
2591
|
* @example
|
|
1759
2592
|
* ```ts
|
|
@@ -1770,10 +2603,10 @@ type AudioApi = {
|
|
|
1770
2603
|
* Resolved dependency APIs.
|
|
1771
2604
|
*/
|
|
1772
2605
|
type Deps$1 = {
|
|
1773
|
-
flow: Api$
|
|
1774
|
-
assets: Api$
|
|
1775
|
-
model: Api$
|
|
1776
|
-
time: Api;
|
|
2606
|
+
flow: Api$2;
|
|
2607
|
+
assets: Api$5;
|
|
2608
|
+
model: Api$6;
|
|
2609
|
+
time: Api$1;
|
|
1777
2610
|
};
|
|
1778
2611
|
/**
|
|
1779
2612
|
* What the kernel context offers before the deps are attached.
|
|
@@ -1794,23 +2627,23 @@ type AudioCtx = KernelSlice$1 & {
|
|
|
1794
2627
|
/**
|
|
1795
2628
|
* Payload of the `model:committed` hook: the source of every volume a game sets.
|
|
1796
2629
|
*/
|
|
1797
|
-
type ModelCommitted = Events$
|
|
2630
|
+
type ModelCommitted = Events$3["model:committed"];
|
|
1798
2631
|
/**
|
|
1799
2632
|
* Payload of the `scenes:changed` hook: `music` is the track the next scene declared.
|
|
1800
2633
|
*/
|
|
1801
|
-
type SceneChanged = Events["scenes:changed"];
|
|
2634
|
+
type SceneChanged = Events$4["scenes:changed"];
|
|
1802
2635
|
/**
|
|
1803
2636
|
* Payload of the `lifecycle:changed` hook: the pause that holds every bus at zero.
|
|
1804
2637
|
*/
|
|
1805
|
-
type LifecycleChanged = Events$
|
|
2638
|
+
type LifecycleChanged = Events$5["lifecycle:changed"];
|
|
1806
2639
|
/**
|
|
1807
2640
|
* Payload of the `assets:bundle-unloaded` hook: `keys` names every decoded sound that is gone.
|
|
1808
2641
|
*/
|
|
1809
|
-
type BundleUnloaded = Events$
|
|
2642
|
+
type BundleUnloaded = Events$1["assets:bundle-unloaded"];
|
|
1810
2643
|
/**
|
|
1811
2644
|
* Payload of the `assets:replaced` hook: `keys` names every asset a dev hot swap gave new bytes.
|
|
1812
2645
|
*/
|
|
1813
|
-
type AssetsReplaced = Events$
|
|
2646
|
+
type AssetsReplaced = Events$1["assets:replaced"];
|
|
1814
2647
|
/**
|
|
1815
2648
|
* What one play of a sound asks for: the key and the bus the sound goes to.
|
|
1816
2649
|
*/
|
|
@@ -1840,7 +2673,8 @@ type LayoutState = {
|
|
|
1840
2673
|
scrollStart: {
|
|
1841
2674
|
pointerY: number;
|
|
1842
2675
|
offset: number;
|
|
1843
|
-
};
|
|
2676
|
+
}; /** One line of the `body` style as the icons were last measured with it; none before that. */
|
|
2677
|
+
iconLine: number | undefined;
|
|
1844
2678
|
order: number;
|
|
1845
2679
|
cleanups: Array<() => void>;
|
|
1846
2680
|
};
|
|
@@ -1949,10 +2783,11 @@ type State = {
|
|
|
1949
2783
|
*/
|
|
1950
2784
|
type Deps = {
|
|
1951
2785
|
anim: AnimApi;
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
2786
|
+
debug: Api;
|
|
2787
|
+
time: Api$1;
|
|
2788
|
+
flow: Api$2;
|
|
2789
|
+
world: Api$3;
|
|
2790
|
+
renderer: Api$4;
|
|
1956
2791
|
input: InputApi;
|
|
1957
2792
|
i18n: I18nApi;
|
|
1958
2793
|
text: TextApi;
|
|
@@ -1962,7 +2797,7 @@ type Deps = {
|
|
|
1962
2797
|
*
|
|
1963
2798
|
* `ui` owns no event of its own; `emit` sends the global `ui:hot-swap` of the dev hot swap.
|
|
1964
2799
|
*/
|
|
1965
|
-
type KernelSlice = PluginCtx<Config, State, Events$
|
|
2800
|
+
type KernelSlice = PluginCtx<Config, State, Events$2> & {
|
|
1966
2801
|
readonly global: object;
|
|
1967
2802
|
readonly log: Log.LogApi;
|
|
1968
2803
|
readonly require: Require;
|
|
@@ -2061,4 +2896,4 @@ type UiApi = {
|
|
|
2061
2896
|
fill(key: string, value: string): boolean;
|
|
2062
2897
|
};
|
|
2063
2898
|
//#endregion
|
|
2064
|
-
export {
|
|
2899
|
+
export { sequence as $, GlowValue as A, Target as B, BlurValue as C, FilterComponent as D, FilterArea as E, AnimPlayerValue as F, HAPTIC_KINDS as G, HapticKind as H, Config$3 as I, frames as J, defineAnimation as K, FramesValue as L, OutlineValue as M, UniformDeclaration as N, FilterSpec as O, AnimApi as P, play as Q, MotionKeyframe as R, AlphaValue as S, DisplacementValue as T, SfxDescriptor as U, types_d_exports$3 as V, Step as W, mark as X, haptic as Y, parallel as Z, State$2 as _, AudioApi as a, tween as at, EmitterDefinition as b, MusicDescriptor as c, OverlayApi as ct, State$1 as d, set as et, VolumesFor as f, EffectsStats as g, EffectsApi as h, types_d_exports as i, stagger as it, NoiseValue as j, FilterValueOf as k, MusicOptions as l, types_d_exports$4 as lt, Config$2 as m, State as n, spawn as nt, AudioContextLike as o, use as ot, types_d_exports$1 as p, external as q, UiApi as r, spawned as rt, Config$1 as s, wait as st, Config as t, sfx as tt, SoundEntry as u, types_d_exports$2 as v, ColorMatrixValue as w, EmitterValue as x, EmitterConfig as y, State$3 as z };
|