@moku-labs/game 0.15.1 → 0.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
- import { Jn as AnyFlow, Kn as FeaturePlugin, br as Json, cr as Hint, er as NodeTable, fr as ClockSource, ir as Descriptor, lr as NodeFx, mr as FakeClock } from "./types-E2ykwIUO.mjs";
2
- import { t as createApp } from "./index-CCiTo1_3.mjs";
3
- import { b as saveOf, v as WithGameState, y as memory } from "./types-CpdkyhaC.mjs";
4
- import { a as createHeadless, i as ReproResult, n as HeadlessGame, o as runRepro, r as Repro, s as stepFrames, t as HeadlessApp } from "./headless-B0mH9qYg.mjs";
1
+ import { Jn as FeaturePlugin, Sr as Json, Xn as AnyFlow, dr as NodeFx, gr as FakeClock, mr as ClockSource, nr as NodeTable, or as Descriptor, ur as Hint } from "./types-DlC3Ytbj.mjs";
2
+ import { t as createApp } from "./index-ByvWj9OX.mjs";
3
+ import { b as saveOf, v as WithGameState, y as memory } from "./types-BApuIqwq.mjs";
4
+ import { a as createHeadless, i as ReproResult, n as HeadlessGame, o as runRepro, r as Repro, s as stepFrames, t as HeadlessApp } from "./headless-D0U5AXiK.mjs";
5
5
  import { AnyPluginInstance } from "@moku-labs/core";
6
6
 
7
7
  //#region src/plugins/clock/fake.d.ts
package/dist/testing.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { nn as refuseStart, on as type, p as flattenFeatures, rn as exit, t as createApp } from "./src-CwVzErzN.mjs";
1
+ import { an as exit, cn as type, in as refuseStart, m as flattenFeatures, t as createApp } from "./src-xChMXzwH.mjs";
2
2
  import { n as saveOf, t as memory } from "./memory-CWlqhS7l.mjs";
3
3
  import { t as fakeClock } from "./fake-6mazmHK3.mjs";
4
4
  import { i as stepFrames, r as runRepro, t as createHeadless } from "./headless-BA6ffzqD.mjs";
@@ -1,5 +1,5 @@
1
- import { br as Json, kr as Snapshot } from "./types-E2ykwIUO.mjs";
2
- import { t as HeadlessApp } from "./headless-B0mH9qYg.mjs";
1
+ import { Sr as Json, jr as Snapshot } from "./types-DlC3Ytbj.mjs";
2
+ import { t as HeadlessApp } from "./headless-D0U5AXiK.mjs";
3
3
  import { Log } from "@moku-labs/common/browser";
4
4
 
5
5
  //#region src/plugins/flow/doors/types.d.ts
@@ -1,7 +1,7 @@
1
- import { Ar as SnapshotOf, Dr as SaveDoc, E as Config$2, Er as ProviderCall, Jn as AnyFlow, Kn as FeaturePlugin, Mn as Config$1, Ot as Orientation, Tr as PlayerStateProvider, a as Config$3, br as Json, d as Manifest, fr as ClockSource, k as PixiModule, mr as FakeClock, n as AssetsIo, rr as TypeTag, vr as Config } from "./types-E2ykwIUO.mjs";
2
- import { o as AudioContextLike, s as Config$4 } from "./types-Bw-qLjFZ.mjs";
3
- import { H as TextKey, I as I18nApi, V as StringTable } from "./types-G3ZAAsbd.mjs";
4
- import { Ct as audioPlugin, bt as effectsPlugin, dt as platformPlugin, i as screen, pt as PlatformProvider, t as createApp } from "./index-CCiTo1_3.mjs";
1
+ import { At as Orientation, Dr as PlayerStateProvider, E as Config$2, Jn as FeaturePlugin, Mr as SnapshotOf, Or as ProviderCall, Pn as Config$1, Sr as Json, Xn as AnyFlow, a as Config$3, ar as TypeTag, br as Config, d as Manifest, gr as FakeClock, k as PixiModule, kr as SaveDoc, mr as ClockSource, n as AssetsIo } from "./types-DlC3Ytbj.mjs";
2
+ import { o as AudioContextLike, s as Config$4 } from "./types-CsMLBPf-.mjs";
3
+ import { H as TextKey, I as I18nApi, V as StringTable } from "./types-yLdzHyTl.mjs";
4
+ import { ft as platformPlugin, i as screen, mt as PlatformProvider, t as createApp, wt as audioPlugin, xt as effectsPlugin } from "./index-ByvWj9OX.mjs";
5
5
  import { AnyPluginInstance } from "@moku-labs/core";
6
6
 
7
7
  //#region src/plugins/model/store/providers/memory.d.ts
@@ -1,5 +1,5 @@
1
- import { A as PixiSprite, An as Api$2, Br as Api$1, Cn as NumericFields, Dn as TrackOptions, Dt as FilterSlotInputs, En as ReducedMotion, Et as FilterSlot, Ir as Events$5, O as PixiFilter, On as TrackSegment, Sn as MotionHandle, T as Api$4, Xr as Require, Yr as Events$2, Yt as Api$3, _r as Api$6, an as ComponentType, br as Json, en as AnyComponent, ir as Descriptor, j as PixiTexture, jt as FilterCache, k as PixiModule, kt as Point, nn as AnyComponentValue, rn as ComponentHandle, rr as TypeTag, s as Events$1, sn as Entity, t as Api$5, v as Events$4, yn as Ease, yr as Events$3 } from "./types-E2ykwIUO.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-G3ZAAsbd.mjs";
1
+ import { A as PixiSprite, An as TrackSegment, Hr as Api$1, Mn as Api$2, Nt as FilterCache, O as PixiFilter, On as ReducedMotion, Ot as FilterSlot, Qr as Require, Rr as Events$5, Sr as Json, T as Api$4, Tn as NumericFields, Zr as Events$2, Zt as Api$3, an as ComponentHandle, ar as TypeTag, in as AnyComponentValue, j as PixiTexture, jt as Point, k as PixiModule, kn as TrackOptions, kt as FilterSlotInputs, ln as Entity, nn as AnyComponent, or as Descriptor, s as Events$1, sn as ComponentType, t as Api$5, v as Events$4, wn as MotionHandle, xn as Ease, xr as Events$3, yr as Api$6 } from "./types-DlC3Ytbj.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-yLdzHyTl.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";
@@ -91,22 +91,15 @@ type Api = {
91
91
  * One running track: the numeric fields of one component of one entity moving from the values
92
92
  * read at the end of the delay to the exact target, straight or through keyframe segments. A
93
93
  * track with repeats walks again from its first segment each time a run ends.
94
- *
95
- * @example
96
- * ```ts
97
- * const track: Track = {
98
- * id: 1, entity: 1_048_576, component: Transform, to: { x: 200 },
99
- * keys: { x: "1048576:Transform:x" }, ms: 350, ease: "out", delayMs: 0, elapsed: 0,
100
- * from: undefined, muted: () => new Set(), additive: false, driven: false, bornFrame: 4,
101
- * ended: false, segments: undefined, repeatsLeft: 0, held: false, masked: new Set(), keep: false,
102
- * reveals: "place"
103
- * };
104
- * ```
105
94
  */
106
95
  type Track = {
107
96
  readonly id: number;
108
97
  readonly entity: Entity;
109
- readonly component: AnyComponent; /** The target fields. Retarget deletes the fields a newer absolute track took over. */
98
+ readonly component: AnyComponent;
99
+ /**
100
+ * The target fields. Retarget deletes the fields a newer absolute track took over. A frame reads
101
+ * the slots (`names`, `targets`, `live`) instead.
102
+ */
110
103
  to: Record<string, number>;
111
104
  /**
112
105
  * The key of the owner, bases and offsets tables per field, built once when the track starts.
@@ -116,8 +109,30 @@ type Track = {
116
109
  readonly ms: number;
117
110
  readonly ease: Ease;
118
111
  readonly delayMs: number;
119
- elapsed: number; /** Read when the delay ends, never earlier. */
120
- from: Record<string, number> | undefined;
112
+ /**
113
+ * `[0]`: the milliseconds the track has run, its delay included; `[1]`: the normalised time of
114
+ * the write that runs. Cells and not fields, so a frame writes them in place: a double stored in
115
+ * an object field is a new heap number.
116
+ */
117
+ readonly clock: Float64Array; /** True once the start values are read, when the delay ends, never earlier. */
118
+ begun: boolean; /** The target fields in slot order: every field `to` held when the track started. */
119
+ readonly names: readonly string[]; /** The key of each slot: the strings of `keys`, by slot. */
120
+ readonly slotKeys: readonly string[]; /** The target of each slot. */
121
+ readonly targets: Float64Array; /** The start value of each slot, read when the delay ends. */
122
+ readonly starts: Float64Array; /** `1` while the track drives the slot, `0` once a newer absolute track took its field. */
123
+ readonly live: Uint8Array; /** `1` for a slot the frame that runs moved: a write of only some fields reads it. */
124
+ readonly moved: Uint8Array;
125
+ /**
126
+ * Per slot, the numbers of the write that runs: first what the slot contributes, then what the
127
+ * field reads, the base plus every offset. Kept here so no number crosses a call boxed.
128
+ */
129
+ readonly values: Float64Array;
130
+ /**
131
+ * Per slot, the value this track last left in the field or found there, `NaN` while unknown: at
132
+ * the start and while another writer holds the field. A frame whose value moved off it writes
133
+ * without reading the field back.
134
+ */
135
+ readonly seen: Float64Array;
121
136
  readonly muted: () => ReadonlySet<string>;
122
137
  readonly additive: boolean; /** True for a track a timeline step advances by hand; the frame step leaves it alone. */
123
138
  readonly driven: boolean; /** The frame step the track was born in. That step does not advance it a second time. */
@@ -151,16 +166,24 @@ type Track = {
151
166
  * that cannot (a tint, a fill colour). Computed once when the track is made.
152
167
  */
153
168
  readonly reveals: "alpha" | "place" | "both" | undefined;
169
+ /**
170
+ * The patch the track writes when a frame moves every field, one per track with every field of
171
+ * `to` in it: a frame fills it in place instead of building one. Rebuilt when the track loses a
172
+ * field.
173
+ */
174
+ patch: Record<string, unknown>;
175
+ /**
176
+ * The patch of a frame that moves only some fields (another writer holds one, or one stands
177
+ * still): exactly the fields `partialMoved` flags, filled in place by the next frame that moves
178
+ * the same ones and built again when they change, so a field the track lost, which never moves
179
+ * again, is never in it. `undefined` until the first such frame.
180
+ */
181
+ partial: Record<string, unknown> | undefined; /** The `moved` flags `partial` was built for, by slot. */
182
+ readonly partialMoved: Uint8Array;
154
183
  };
155
184
  /**
156
185
  * A motion handle that can also be advanced by hand: what the timeline cursor needs, so a track
157
186
  * born inside a frame step still consumes the remainder of that step's delta.
158
- *
159
- * @example
160
- * ```ts
161
- * const motion: StepMotion = { ...inert, advance: () => 0 };
162
- * motion.advance(16); // 0: nothing is left over
163
- * ```
164
187
  */
165
188
  type StepMotion = MotionHandle & {
166
189
  /**
@@ -624,8 +647,12 @@ type ExternalPlayer = {
624
647
  type Cursor = {
625
648
  readonly step: Step;
626
649
  readonly children: readonly Cursor[]; /** Position in a `sequence`, and the last written key of a `frames` step. */
627
- index: number; /** Consumed milliseconds of a `wait` or a `frames` step. */
628
- elapsed: number;
650
+ index: number;
651
+ /**
652
+ * `[0]`: the consumed milliseconds of a `wait` or a `frames` step. A cell and not a field, so a
653
+ * frame writes it in place: a double stored in an object field is a new heap number.
654
+ */
655
+ readonly clock: Float64Array;
629
656
  motion: StepMotion | undefined;
630
657
  started: boolean;
631
658
  ended: boolean; /** The entity a running `frames` step holds against its `Frames` loop, until the step ends. */
@@ -720,6 +747,18 @@ type TimelineRuntime = {
720
747
  */
721
748
  releaseFrames(entity: Entity): void;
722
749
  };
750
+ /**
751
+ * What the cursor functions carry down the tree: the runtime, the animation id marks are
752
+ * reported under, the list of marks reached so far, the entities the timeline spawned, by id, and
753
+ * the entities its key targets named when it started.
754
+ */
755
+ type CursorCtx = {
756
+ /** The runtime of the frame step that walks the tree now. */rt: TimelineRuntime; /** Swapped for the nested id while a `use` step walks its tree, and set back after. */
757
+ animation: string;
758
+ readonly marks: string[];
759
+ readonly spawned: Map<string, Entity>; /** The entities the key targets named when the timeline started, by target object. */
760
+ readonly targets: ReadonlyMap<Target, Entity>;
761
+ };
723
762
  /**
724
763
  * One running timeline: its cursor, the marks it reached, the entities it counts on, the entities
725
764
  * its key targets named at its start, the entities it spawned and despawns at its end, and the
@@ -730,11 +769,12 @@ type RunningTimeline = {
730
769
  readonly animation: string;
731
770
  readonly cursor: Cursor;
732
771
  readonly marks: string[];
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. */
772
+ readonly entities: readonly Entity[]; /** The entities its `{ projection, key }` targets named when it started, by target object. */
773
+ readonly targets: ReadonlyMap<Target, Entity>; /** The entities its `spawn` steps made, by spawn id. Despawned when the timeline ends. */
735
774
  readonly spawned: Map<string, Entity>;
736
775
  readonly resolve: () => void;
737
- ended: boolean;
776
+ ended: boolean; /** The one cursor context of the timeline, made at its start and reused by every frame. */
777
+ readonly cctx: CursorCtx;
738
778
  };
739
779
  declare namespace types_d_exports$3 {
740
780
  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 };
@@ -1002,17 +1042,35 @@ type Config$3 = {
1002
1042
  * offsets accumulator, the running timelines and the animation registry.
1003
1043
  */
1004
1044
  type State$3 = {
1005
- /** The one track table. Insertion order is advance order. */tracks: Map<number, Track>; /** Ids of tracks and timelines. */
1045
+ /** The one track table. Insertion order is advance order. */tracks: Map<number, Track>;
1046
+ /**
1047
+ * The tracks of the table in start order, as a dense list the frame step walks by index. An ended
1048
+ * track stays in it until the next frame step drops it.
1049
+ */
1050
+ trackList: Track[]; /** Ids of tracks and timelines. */
1006
1051
  nextId: number; /** `"<entity>:<component>:<field>"` to the id of the absolute track that drives the field. */
1007
- owner: Map<string, number>; /** Per field key, the delta each additive track contributes. */
1008
- offsets: Map<string, Map<number, number>>; /** Per field key, the value the offsets are added to. Dropped when no track drives the field. */
1009
- bases: Map<string, number>;
1052
+ owner: Map<string, number>;
1053
+ /**
1054
+ * Per field key, the delta each additive track contributes, in a one-number cell per track that
1055
+ * a frame writes in place.
1056
+ */
1057
+ offsets: Map<string, Map<number, Float64Array>>;
1058
+ /**
1059
+ * Per field key, the value the offsets are added to, in a one-number cell a frame writes in
1060
+ * place. Dropped when no track drives the field.
1061
+ */
1062
+ bases: Map<string, Float64Array>;
1010
1063
  /**
1011
1064
  * Per entity, its running additive tracks. `offsetsOf` of the driver reads it, so the cost of
1012
1065
  * one answer is the loops of that entity and not every track of the game.
1013
1066
  */
1014
1067
  additive: Map<Entity, Set<Track>>; /** The running timelines, by id. */
1015
- timelines: Map<number, RunningTimeline>; /** The `animations` of every feature, read in `onStart`. */
1068
+ timelines: Map<number, RunningTimeline>;
1069
+ /**
1070
+ * The timelines in start order, as a dense list the frame step walks by index. An ended timeline
1071
+ * stays in it until the next frame step drops it.
1072
+ */
1073
+ timelineList: RunningTimeline[]; /** The `animations` of every feature, read in `onStart`. */
1016
1074
  registry: Map<string, AnyAnimationDefinition>; /** `onMark` subscribers, in subscription order. */
1017
1075
  markListeners: Set<MarkListener>; /** Counter of the frame steps. A track born in the running step is not advanced by it. */
1018
1076
  frame: number; /** True while the track count is over `maxTracks`, so the warning is one per crossing. */
@@ -1702,29 +1760,34 @@ type FilterBody = {
1702
1760
  } | {
1703
1761
  readonly kind: "blur";
1704
1762
  readonly filter: InstanceType<PixiModule["BlurFilter"]>; /** The fields the setters were last given; compared before a write. */
1705
- readonly applied: Record<string, FilterField>;
1763
+ readonly applied: Record<string, FilterField>; /** The keys of `applied`, listed once: a compare walks them by index, with no `Object.keys` per frame. */
1764
+ readonly fields: readonly string[];
1706
1765
  passes: number;
1707
1766
  } | {
1708
1767
  readonly kind: "colorMatrix";
1709
1768
  readonly filter: InstanceType<PixiModule["ColorMatrixFilter"]>; /** The fields the setters were last given; compared before a write. */
1710
- readonly applied: Record<string, FilterField>;
1769
+ readonly applied: Record<string, FilterField>; /** The keys of `applied`, listed once: a compare walks them by index, with no `Object.keys` per frame. */
1770
+ readonly fields: readonly string[];
1711
1771
  passes: number;
1712
1772
  } | {
1713
1773
  readonly kind: "noise";
1714
1774
  readonly filter: InstanceType<PixiModule["NoiseFilter"]>; /** The fields the setters were last given; compared before a write. */
1715
- readonly applied: Record<string, FilterField>;
1775
+ readonly applied: Record<string, FilterField>; /** The keys of `applied`, listed once: a compare walks them by index, with no `Object.keys` per frame. */
1776
+ readonly fields: readonly string[];
1716
1777
  passes: number;
1717
1778
  } | {
1718
1779
  readonly kind: "displacement";
1719
1780
  readonly filter: InstanceType<PixiModule["DisplacementFilter"]>;
1720
1781
  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. */
1782
+ readonly applied: Record<string, FilterField>; /** The keys of `applied`, listed once: a compare walks them by index, with no `Object.keys` per frame. */
1783
+ readonly fields: readonly string[]; /** The asset key the map sprite shows now. */
1722
1784
  map: string;
1723
1785
  passes: number;
1724
1786
  } | {
1725
1787
  readonly kind: "alpha";
1726
1788
  readonly filter: InstanceType<PixiModule["AlphaFilter"]>; /** The fields the setters were last given; compared before a write. */
1727
- readonly applied: Record<string, FilterField>;
1789
+ readonly applied: Record<string, FilterField>; /** The keys of `applied`, listed once: a compare walks them by index, with no `Object.keys` per frame. */
1790
+ readonly fields: readonly string[];
1728
1791
  passes: number;
1729
1792
  };
1730
1793
  /**
@@ -1758,6 +1821,11 @@ type FilterInstance = FilterBody & {
1758
1821
  readonly kindId: string; /** True for an instance that draws in place of a broken kind or instance (E5). */
1759
1822
  readonly standIn: boolean; /** A stand-in built while this broken instance was drawing; the next sync puts it in its place. */
1760
1823
  replacement: FilterInstance | undefined;
1824
+ /**
1825
+ * The entity of the view it draws on, set when the filter sync takes it in; 0 for a warm-up probe. A break inside a
1826
+ * render tells the renderer about this view (`renderer.invalidate`) before it switches the filter off.
1827
+ */
1828
+ entity: Entity;
1761
1829
  };
1762
1830
  /**
1763
1831
  * One of our bodies: a `Filter` over the assembled programs, the kind of every place of a chain and of a mark.
@@ -1815,21 +1883,48 @@ type CheckState = {
1815
1883
  /**
1816
1884
  * What the filter sync keeps for one entity: the kinds it carries, one instance per kind, the
1817
1885
  * 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.
1886
+ * `renderer.sync.filters.set`, the run in which each core kind's component last changed, the
1887
+ * instances of this frame in their sorted order (one array, reused every frame), the one
1888
+ * `renderer.invalidate` call a visible filter write of the frame makes, and whether the next run
1889
+ * syncs it.
1821
1890
  */
1822
1891
  type FilteredView = {
1892
+ /** The entity the record is kept for. */readonly entity: Entity;
1823
1893
  readonly kinds: Set<string>;
1824
1894
  readonly instances: Map<string, FilterInstance>;
1825
1895
  readonly retired: FilterInstance[];
1826
1896
  assigned: readonly FilterSlot[];
1827
- readonly changed: Set<string>;
1897
+ /**
1898
+ * Per kind `index`, the run of the filter sync in which its component was last seen changed; read only for a
1899
+ * Pixi-core kind, which is written only in such a run. A number per kind, so marking allocates nothing.
1900
+ */
1901
+ readonly marks: number[];
1828
1902
  readonly placed: FilterInstance[]; /** True once `renderer.invalidate` was called for this view in the current frame. */
1829
1903
  signalled: boolean; /** Calls `renderer.invalidate(entity)` once per frame for this view, before the write; made once with the record. */
1830
1904
  readonly signal: () => void; /** The area last handed to `renderer.sync.filters.area`, written in place (B4). */
1831
1905
  readonly areaSent: AreaBox; /** The `enabled` switches of the placed instances when the area was last judged, one bit each in placed order. */
1832
1906
  areaMask: number;
1907
+ /**
1908
+ * The next run of the filter sync brings the view up to date: a filter component of it changed, came or left, its
1909
+ * map was retired, a kind of it still waits for its instance, or a chain left places to destroy.
1910
+ */
1911
+ dirty: boolean; /** Forgotten: out of `State.views`; the next run drops it from `State.viewList`. */
1912
+ gone: boolean;
1913
+ };
1914
+ /**
1915
+ * Where the filter sync stands between two runs. It syncs only the views marked dirty, and judges the full-screen
1916
+ * budget only when something it depends on moved.
1917
+ */
1918
+ type FilterSyncState = {
1919
+ /** The current run, counted from 1: a core kind's change mark holds the run it was made in. */round: number;
1920
+ /**
1921
+ * Every view syncs at the next run: a debug switch turned a kind off or on, or a filter broke or ran its chains at a
1922
+ * new resolution inside a render, where the view it belongs to is not known.
1923
+ */
1924
+ all: boolean; /** A view was marked dirty or forgotten since the last walk: the next run walks the dense list, otherwise it skips it. */
1925
+ pending: boolean; /** The viewport width the full-screen budget was last judged at; -1 before the first judgement. */
1926
+ width: number; /** The viewport height the full-screen budget was last judged at; -1 before the first judgement. */
1927
+ height: number;
1833
1928
  };
1834
1929
  //#endregion
1835
1930
  //#region src/plugins/effects/particles/types.d.ts
@@ -1973,7 +2068,12 @@ type BakedEmitter = {
1973
2068
  readonly config: ResolvedEmitterConfig; /** Scale per 1/64 of the life. */
1974
2069
  readonly scaleTable: Float32Array; /** Alpha per 1/64 of the life, 0..1. */
1975
2070
  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. */
2071
+ readonly tintTable: Uint32Array;
2072
+ /**
2073
+ * The colour a particle is drawn with per 1/64 of the life, packed as Pixi's `0xaabbggrr`: the tint under the alpha
2074
+ * byte. Read straight from the table every frame: a number above the small integers handed back by a call is boxed.
2075
+ */
2076
+ readonly colorTable: Uint32Array; /** Half side of the box no particle leaves, in reference units. */
1977
2077
  readonly reach: number;
1978
2078
  readonly textures: readonly PixiTexture[]; /** The texture source of the first texture: every texture of the effect samples it. */
1979
2079
  readonly source: PixiTexture["source"] | undefined; /** The largest side of the textures, in pixels. */
@@ -2052,7 +2152,14 @@ type State$2 = {
2052
2152
  ready: Set<string>; /** The filter kinds, built-ins first, then the filters of every feature. */
2053
2153
  kinds: Map<string, FilterKind>; /** The shader check of every definition a kind can draw, in every build. */
2054
2154
  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"`. */
2155
+ views: Map<Entity, FilteredView>;
2156
+ /**
2157
+ * The records of `views` in the order they were first seen: the dense list the filter sync walks by index. A
2158
+ * forgotten record stays, `gone`, until the next run drops it.
2159
+ */
2160
+ viewList: FilteredView[]; /** The filter kinds in registration order, one per `index`: the change sets the filter sync reads, by index. */
2161
+ kindList: FilterKind[]; /** Where the filter sync stands between two runs. */
2162
+ filterSync: FilterSyncState; /** Keys of the one-shot warnings: `"emitter:fx.x"`, `"texture:board.cell"`, `"atlas:fx.x"`. */
2056
2163
  warned: Set<string>; /** Whether each budget warning is in force, so a crossing warns once. */
2057
2164
  over: {
2058
2165
  particles: boolean;