pixi-reels 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +167 -0
  3. package/dist/SpineSymbol-B40TevSr.cjs +2 -0
  4. package/dist/SpineSymbol-B40TevSr.cjs.map +1 -0
  5. package/dist/SpineSymbol-D2jhCzFW.js +82 -0
  6. package/dist/SpineSymbol-D2jhCzFW.js.map +1 -0
  7. package/dist/config/SpeedPresets.d.ts +49 -0
  8. package/dist/config/SpeedPresets.d.ts.map +1 -0
  9. package/dist/config/defaults.d.ts +12 -0
  10. package/dist/config/defaults.d.ts.map +1 -0
  11. package/dist/config/types.d.ts +93 -0
  12. package/dist/config/types.d.ts.map +1 -0
  13. package/dist/core/Reel.d.ts +106 -0
  14. package/dist/core/Reel.d.ts.map +1 -0
  15. package/dist/core/ReelMotion.d.ts +43 -0
  16. package/dist/core/ReelMotion.d.ts.map +1 -0
  17. package/dist/core/ReelSet.d.ts +101 -0
  18. package/dist/core/ReelSet.d.ts.map +1 -0
  19. package/dist/core/ReelSetBuilder.d.ts +102 -0
  20. package/dist/core/ReelSetBuilder.d.ts.map +1 -0
  21. package/dist/core/ReelViewport.d.ts +43 -0
  22. package/dist/core/ReelViewport.d.ts.map +1 -0
  23. package/dist/core/StopSequencer.d.ts +26 -0
  24. package/dist/core/StopSequencer.d.ts.map +1 -0
  25. package/dist/debug/debug.d.ts +65 -0
  26. package/dist/debug/debug.d.ts.map +1 -0
  27. package/dist/events/EventEmitter.d.ts +25 -0
  28. package/dist/events/EventEmitter.d.ts.map +1 -0
  29. package/dist/events/ReelEvents.d.ts +40 -0
  30. package/dist/events/ReelEvents.d.ts.map +1 -0
  31. package/dist/frame/FrameBuilder.d.ts +50 -0
  32. package/dist/frame/FrameBuilder.d.ts.map +1 -0
  33. package/dist/frame/OffsetCalculator.d.ts +19 -0
  34. package/dist/frame/OffsetCalculator.d.ts.map +1 -0
  35. package/dist/frame/RandomSymbolProvider.d.ts +27 -0
  36. package/dist/frame/RandomSymbolProvider.d.ts.map +1 -0
  37. package/dist/index.cjs +5 -0
  38. package/dist/index.cjs.map +1 -0
  39. package/dist/index.d.ts +51 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +1454 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/pool/ObjectPool.d.ts +36 -0
  44. package/dist/pool/ObjectPool.d.ts.map +1 -0
  45. package/dist/speed/SpeedManager.d.ts +38 -0
  46. package/dist/speed/SpeedManager.d.ts.map +1 -0
  47. package/dist/spin/SpinController.d.ts +71 -0
  48. package/dist/spin/SpinController.d.ts.map +1 -0
  49. package/dist/spin/modes/CascadeMode.d.ts +16 -0
  50. package/dist/spin/modes/CascadeMode.d.ts.map +1 -0
  51. package/dist/spin/modes/ImmediateMode.d.ts +10 -0
  52. package/dist/spin/modes/ImmediateMode.d.ts.map +1 -0
  53. package/dist/spin/modes/SpinningMode.d.ts +18 -0
  54. package/dist/spin/modes/SpinningMode.d.ts.map +1 -0
  55. package/dist/spin/modes/StandardMode.d.ts +10 -0
  56. package/dist/spin/modes/StandardMode.d.ts.map +1 -0
  57. package/dist/spin/phases/AnticipationPhase.d.ts +24 -0
  58. package/dist/spin/phases/AnticipationPhase.d.ts.map +1 -0
  59. package/dist/spin/phases/PhaseFactory.d.ts +21 -0
  60. package/dist/spin/phases/PhaseFactory.d.ts.map +1 -0
  61. package/dist/spin/phases/ReelPhase.d.ts +39 -0
  62. package/dist/spin/phases/ReelPhase.d.ts.map +1 -0
  63. package/dist/spin/phases/SpinPhase.d.ts +25 -0
  64. package/dist/spin/phases/SpinPhase.d.ts.map +1 -0
  65. package/dist/spin/phases/StartPhase.d.ts +26 -0
  66. package/dist/spin/phases/StartPhase.d.ts.map +1 -0
  67. package/dist/spin/phases/StopPhase.d.ts +37 -0
  68. package/dist/spin/phases/StopPhase.d.ts.map +1 -0
  69. package/dist/spine/SpineReelSymbol.d.ts +111 -0
  70. package/dist/spine/SpineReelSymbol.d.ts.map +1 -0
  71. package/dist/spine/index.d.ts +5 -0
  72. package/dist/spine/index.d.ts.map +1 -0
  73. package/dist/spine.cjs +2 -0
  74. package/dist/spine.cjs.map +1 -0
  75. package/dist/spine.js +123 -0
  76. package/dist/spine.js.map +1 -0
  77. package/dist/spotlight/SymbolSpotlight.d.ts +70 -0
  78. package/dist/spotlight/SymbolSpotlight.d.ts.map +1 -0
  79. package/dist/symbols/AnimatedSpriteSymbol.d.ts +30 -0
  80. package/dist/symbols/AnimatedSpriteSymbol.d.ts.map +1 -0
  81. package/dist/symbols/ReelSymbol.d.ts +84 -0
  82. package/dist/symbols/ReelSymbol.d.ts.map +1 -0
  83. package/dist/symbols/SpineSymbol.d.ts +34 -0
  84. package/dist/symbols/SpineSymbol.d.ts.map +1 -0
  85. package/dist/symbols/SpriteSymbol.d.ts +29 -0
  86. package/dist/symbols/SpriteSymbol.d.ts.map +1 -0
  87. package/dist/symbols/SymbolFactory.d.ts +20 -0
  88. package/dist/symbols/SymbolFactory.d.ts.map +1 -0
  89. package/dist/symbols/SymbolRegistry.d.ts +25 -0
  90. package/dist/symbols/SymbolRegistry.d.ts.map +1 -0
  91. package/dist/testing/FakeTicker.d.ts +45 -0
  92. package/dist/testing/FakeTicker.d.ts.map +1 -0
  93. package/dist/testing/HeadlessSymbol.d.ts +28 -0
  94. package/dist/testing/HeadlessSymbol.d.ts.map +1 -0
  95. package/dist/testing/index.d.ts +5 -0
  96. package/dist/testing/index.d.ts.map +1 -0
  97. package/dist/testing/testHarness.d.ts +70 -0
  98. package/dist/testing/testHarness.d.ts.map +1 -0
  99. package/dist/utils/Disposable.d.ts +10 -0
  100. package/dist/utils/Disposable.d.ts.map +1 -0
  101. package/dist/utils/TickerRef.d.ts +30 -0
  102. package/dist/utils/TickerRef.d.ts.map +1 -0
  103. package/package.json +86 -0
package/dist/index.js ADDED
@@ -0,0 +1,1454 @@
1
+ import { n as e, t } from "./SpineSymbol-D2jhCzFW.js";
2
+ import { AnimatedSprite as n, Container as r, Graphics as i, Sprite as a } from "pixi.js";
3
+ import { gsap as o } from "gsap";
4
+ //#region src/events/EventEmitter.ts
5
+ var s = class {
6
+ _listeners = /* @__PURE__ */ new Map();
7
+ on(e, t, n) {
8
+ return this._add(e, t, n, !1);
9
+ }
10
+ once(e, t, n) {
11
+ return this._add(e, t, n, !0);
12
+ }
13
+ off(e, t, n) {
14
+ let r = this._listeners.get(e);
15
+ if (!r) return this;
16
+ if (!t) return this._listeners.delete(e), this;
17
+ let i = r.filter((e) => e.fn !== t || n !== void 0 && e.context !== n);
18
+ return i.length === 0 ? this._listeners.delete(e) : this._listeners.set(e, i), this;
19
+ }
20
+ emit(e, ...t) {
21
+ let n = this._listeners.get(e);
22
+ if (!n || n.length === 0) return !1;
23
+ let r = n.slice();
24
+ for (let n of r) n.once && this.off(e, n.fn, n.context), n.fn.apply(n.context, t);
25
+ return !0;
26
+ }
27
+ removeAllListeners(e) {
28
+ return e === void 0 ? this._listeners.clear() : this._listeners.delete(e), this;
29
+ }
30
+ listenerCount(e) {
31
+ return this._listeners.get(e)?.length ?? 0;
32
+ }
33
+ _add(e, t, n, r) {
34
+ let i = this._listeners.get(e);
35
+ return i || (i = [], this._listeners.set(e, i)), i.push({
36
+ fn: t,
37
+ context: n,
38
+ once: r
39
+ }), this;
40
+ }
41
+ }, c = class {
42
+ _symbolHeight;
43
+ _symbolGapY;
44
+ _slotHeight;
45
+ _minY;
46
+ _maxY;
47
+ constructor(e, t, n, r, i, a) {
48
+ this._symbols = e, this._bufferAbove = r, this._onSymbolWrapped = a, this._symbolHeight = t, this._symbolGapY = n, this._slotHeight = t + n, this._maxY = (i + 1) * this._slotHeight, this._minY = -(this._bufferAbove + 1) * this._slotHeight;
49
+ }
50
+ displace(e) {
51
+ if (e !== 0) {
52
+ for (let t of this._symbols) t.view.y += e;
53
+ e > 0 ? this._wrapBottomToTop() : this._wrapTopToBottom();
54
+ }
55
+ }
56
+ snapToGrid() {
57
+ for (let e = 0; e < this._symbols.length; e++) {
58
+ let t = (e - this._bufferAbove) * this._slotHeight;
59
+ this._symbols[e].view.y = t;
60
+ }
61
+ }
62
+ setToTopPosition() {
63
+ for (let e = 0; e < this._symbols.length; e++) this._symbols[e].view.y = this._minY - (this._symbols.length - e) * this._slotHeight;
64
+ }
65
+ getRowY(e) {
66
+ return (e - this._bufferAbove) * this._slotHeight;
67
+ }
68
+ get slotHeight() {
69
+ return this._slotHeight;
70
+ }
71
+ _wrapBottomToTop() {
72
+ let e = this._symbols.length - 1, t = this._symbols[e];
73
+ if (t.view.y < this._maxY) return;
74
+ let n = this._symbols[0];
75
+ t.view.y = n.view.y - this._slotHeight, this._symbols.pop(), this._symbols.unshift(t), this._onSymbolWrapped(t, 0, "up");
76
+ }
77
+ _wrapTopToBottom() {
78
+ let e = this._symbols[0];
79
+ if (e.view.y >= this._minY) return;
80
+ let t = this._symbols[this._symbols.length - 1];
81
+ e.view.y = t.view.y + this._slotHeight, this._symbols.shift(), this._symbols.push(e), this._onSymbolWrapped(e, this._symbols.length - 1, "down");
82
+ }
83
+ }, l = class {
84
+ _frame = [];
85
+ _remaining = 0;
86
+ setFrame(e) {
87
+ this._frame = [...e], this._remaining = this._frame.length;
88
+ }
89
+ next() {
90
+ return this._remaining > 0 ? (this._remaining--, this._frame[this._remaining]) : this._frame[0] ?? "";
91
+ }
92
+ get hasRemaining() {
93
+ return this._remaining > 0;
94
+ }
95
+ get remaining() {
96
+ return this._remaining;
97
+ }
98
+ reset() {
99
+ this._frame = [], this._remaining = 0;
100
+ }
101
+ }, u = class {
102
+ name = "standard";
103
+ computeDeltaY(e, t, n) {
104
+ let r = e * t * n / 1e3;
105
+ return Math.min(r, e / 2);
106
+ }
107
+ }, d = class {
108
+ container;
109
+ events;
110
+ reelIndex;
111
+ symbols;
112
+ speed = 0;
113
+ spinningMode = new u();
114
+ motion;
115
+ stopSequencer;
116
+ _symbolFactory;
117
+ _randomProvider;
118
+ _viewport;
119
+ _symbolsData;
120
+ _visibleRows;
121
+ _bufferAbove;
122
+ _symbolWidth;
123
+ _symbolHeight;
124
+ _isDestroyed = !1;
125
+ _isStopping = !1;
126
+ constructor(e, t, n, i) {
127
+ this.reelIndex = e.reelIndex, this._symbolFactory = t, this._randomProvider = n, this._viewport = i, this._symbolsData = e.symbolsData, this._visibleRows = e.visibleRows, this._bufferAbove = e.bufferAbove, this._symbolWidth = e.symbolWidth, this._symbolHeight = e.symbolHeight, this.events = new s(), this.stopSequencer = new l(), this.container = new r(), this.container.sortableChildren = !0, this.container.x = e.reelIndex * (e.symbolWidth + e.symbolGapX), this.symbols = e.initialSymbols.map((n, r) => {
128
+ let i = t.acquire(n);
129
+ return i.resize(e.symbolWidth, e.symbolHeight), i;
130
+ }), this.motion = new c(this.symbols, e.symbolHeight, e.symbolGapY, e.bufferAbove, e.visibleRows, (e, t, n) => this._onSymbolWrapped(e, t, n)), this._setupSymbolPositions(e);
131
+ }
132
+ get isDestroyed() {
133
+ return this._isDestroyed;
134
+ }
135
+ get isStopping() {
136
+ return this._isStopping;
137
+ }
138
+ set isStopping(e) {
139
+ this._isStopping = e;
140
+ }
141
+ get bufferAbove() {
142
+ return this._bufferAbove;
143
+ }
144
+ get bufferBelow() {
145
+ return this.symbols.length - this._bufferAbove - this._visibleRows;
146
+ }
147
+ get visibleRows() {
148
+ return this._visibleRows;
149
+ }
150
+ update(e) {
151
+ if (this.speed === 0) return;
152
+ let t = this.spinningMode.computeDeltaY(this.motion.slotHeight, this.speed, e);
153
+ t !== 0 && this.motion.displace(t);
154
+ }
155
+ setStopFrame(e) {
156
+ this.stopSequencer.setFrame(e);
157
+ }
158
+ getVisibleSymbols() {
159
+ let e = [];
160
+ for (let t = this._bufferAbove; t < this._bufferAbove + this._visibleRows; t++) e.push(this.symbols[t].symbolId);
161
+ return e;
162
+ }
163
+ getSymbolAt(e) {
164
+ return this.symbols[this._bufferAbove + e];
165
+ }
166
+ notifySpinStart() {
167
+ for (let e = this._bufferAbove; e < this._bufferAbove + this._visibleRows; e++) this.symbols[e].onReelSpinStart();
168
+ }
169
+ notifySpinEnd() {
170
+ for (let e = this._bufferAbove; e < this._bufferAbove + this._visibleRows; e++) this.symbols[e].onReelSpinEnd();
171
+ }
172
+ notifyLanded() {
173
+ for (let e = this._bufferAbove; e < this._bufferAbove + this._visibleRows; e++) this.symbols[e].onReelLanded();
174
+ }
175
+ snapToGrid() {
176
+ this.motion.snapToGrid(), this.refreshZIndex();
177
+ }
178
+ placeSymbols(e) {
179
+ let t = this.symbols.length;
180
+ for (let n = 0; n < t; n++) {
181
+ let t = n < this._bufferAbove ? this._randomProvider.next(!0) : n < this._bufferAbove + e.length ? e[n - this._bufferAbove] : this._randomProvider.next(!0);
182
+ this._replaceSymbol(n, t);
183
+ }
184
+ this.motion.snapToGrid(), this.refreshZIndex();
185
+ }
186
+ refreshZIndex() {
187
+ for (let e = 0; e < this.symbols.length; e++) {
188
+ let t = this.symbols[e], n = this._symbolsData[t.symbolId]?.zIndex ?? 0;
189
+ t.view.zIndex = n * 100 + e;
190
+ }
191
+ }
192
+ destroy() {
193
+ if (!this._isDestroyed) {
194
+ for (let e of this.symbols) this._symbolFactory.release(e);
195
+ this.symbols = [], this.events.removeAllListeners(), this.container.destroy({ children: !0 }), this._isDestroyed = !0, this.events.emit("destroyed");
196
+ }
197
+ }
198
+ _setupSymbolPositions(e) {
199
+ for (let t = 0; t < this.symbols.length; t++) {
200
+ let n = this.symbols[t], r = (t - e.bufferAbove) * (e.symbolHeight + e.symbolGapY);
201
+ n.view.y = r, n.view.x = 0, this.container.addChild(n.view);
202
+ }
203
+ this._viewport.maskedContainer.addChild(this.container);
204
+ }
205
+ _onSymbolWrapped(e, t, n) {
206
+ let r;
207
+ r = this._isStopping && this.stopSequencer.hasRemaining ? this.stopSequencer.next() : this._randomProvider.next(), this._replaceSymbol(this.symbols.indexOf(e), r), this.refreshZIndex();
208
+ }
209
+ _replaceSymbol(e, t) {
210
+ let n = this.symbols[e];
211
+ if (n.symbolId === t) {
212
+ n.view.alpha = 1, n.view.scale.set(1, 1), n.view.zIndex = 0;
213
+ return;
214
+ }
215
+ let r = n.view.parent, i = n.view.y;
216
+ this._symbolFactory.release(n);
217
+ let a = this._symbolFactory.acquire(t);
218
+ a.resize(this._symbolWidth, this._symbolHeight), a.view.y = i, a.view.x = 0, a.view.alpha = 1, a.view.scale.set(1, 1), a.view.zIndex = 0, r && r.addChild(a.view), this.symbols[e] = a, this.events.emit("symbol:created", t, e);
219
+ }
220
+ }, f = class extends r {
221
+ maskedContainer;
222
+ unmaskedContainer;
223
+ spotlightContainer;
224
+ dimOverlay;
225
+ _mask;
226
+ _isDestroyed = !1;
227
+ constructor(e, t, n = {
228
+ x: 0,
229
+ y: 0
230
+ }) {
231
+ super(), this.x = n.x, this.y = n.y, this._mask = new i(), this._mask.rect(0, 0, e, t).fill({ color: 16777215 }), this.maskedContainer = new r(), this.maskedContainer.sortableChildren = !0, this.maskedContainer.addChild(this._mask), this.maskedContainer.mask = this._mask, this.addChild(this.maskedContainer), this.unmaskedContainer = new r(), this.unmaskedContainer.sortableChildren = !0, this.addChild(this.unmaskedContainer), this.dimOverlay = new i(), this.dimOverlay.rect(0, 0, e, t).fill({
232
+ color: 0,
233
+ alpha: .5
234
+ }), this.dimOverlay.visible = !1, this.addChild(this.dimOverlay), this.spotlightContainer = new r(), this.spotlightContainer.sortableChildren = !0, this.addChild(this.spotlightContainer);
235
+ }
236
+ get isDestroyed() {
237
+ return this._isDestroyed;
238
+ }
239
+ showDim(e = .5) {
240
+ this.dimOverlay.alpha = e, this.dimOverlay.visible = !0;
241
+ }
242
+ hideDim() {
243
+ this.dimOverlay.visible = !1;
244
+ }
245
+ updateMaskSize(e, t) {
246
+ this._mask.clear(), this._mask.rect(0, 0, e, t).fill({ color: 16777215 });
247
+ }
248
+ destroy() {
249
+ this._isDestroyed || (this._isDestroyed = !0, super.destroy({ children: !0 }));
250
+ }
251
+ }, p = class {
252
+ _reel;
253
+ _speed;
254
+ _resolve = null;
255
+ _isActive = !1;
256
+ constructor(e, t) {
257
+ this._reel = e, this._speed = t;
258
+ }
259
+ get reel() {
260
+ return this._reel;
261
+ }
262
+ get isActive() {
263
+ return this._isActive;
264
+ }
265
+ async run(e) {
266
+ return this._isActive = !0, this._reel.events.emit("phase:enter", this.name), new Promise((t) => {
267
+ this._resolve = () => {
268
+ this._isActive = !1, this._reel.events.emit("phase:exit", this.name), t();
269
+ }, this.onEnter(e);
270
+ });
271
+ }
272
+ skip() {
273
+ !this.skippable || !this._isActive || (this.onSkip(), this._complete());
274
+ }
275
+ forceComplete() {
276
+ this._isActive && (this.onSkip(), this._complete());
277
+ }
278
+ _complete() {
279
+ if (this._resolve) {
280
+ let e = this._resolve;
281
+ this._resolve = null, e();
282
+ }
283
+ }
284
+ }, m = class extends p {
285
+ name = "start";
286
+ skippable = !0;
287
+ _tween = null;
288
+ _delayedCall = null;
289
+ onEnter(e) {
290
+ let t = this._reel;
291
+ this._speed;
292
+ let n = e.delay ?? 0;
293
+ t.spinningMode = e.spinningMode, t.speed = 0, n > 0 ? this._delayedCall = o.delayedCall(n / 1e3, () => this._launch()) : this._launch();
294
+ }
295
+ _launch() {
296
+ this._delayedCall = null;
297
+ let e = this._reel, t = this._speed, n = (t.accelerationDuration ?? 300) / 1e3, r = t.accelerationEase ?? "power2.in";
298
+ this._tween = o.timeline(), t.bounceDistance > 0 && this._tween.to(e, {
299
+ speed: -2,
300
+ duration: .05,
301
+ ease: "power1.out"
302
+ }), this._tween.to(e, {
303
+ speed: t.spinSpeed,
304
+ duration: n,
305
+ ease: r,
306
+ onComplete: () => {
307
+ e.notifySpinStart(), this._complete();
308
+ }
309
+ });
310
+ }
311
+ update(e) {}
312
+ onSkip() {
313
+ this._kill(), this._reel.speed = this._speed.spinSpeed;
314
+ }
315
+ _kill() {
316
+ this._delayedCall &&= (this._delayedCall.kill(), null), this._tween &&= (this._tween.kill(), null);
317
+ }
318
+ }, h = class extends p {
319
+ name = "spin";
320
+ skippable = !1;
321
+ _elapsed = 0;
322
+ _minTime = 0;
323
+ _readyToStop = !1;
324
+ onEnter(e) {
325
+ this._elapsed = 0, this._minTime = e.minimumSpinTime ?? this._speed.minimumSpinTime ?? 500, this._readyToStop = !1;
326
+ }
327
+ update(e) {
328
+ this._elapsed += e, this._readyToStop && this._elapsed >= this._minTime && this._complete();
329
+ }
330
+ resolve() {
331
+ this._readyToStop = !0, this._elapsed >= this._minTime && this._complete();
332
+ }
333
+ onSkip() {}
334
+ }, g = class extends p {
335
+ name = "stop";
336
+ skippable = !0;
337
+ _config = null;
338
+ _delayTween = null;
339
+ _bounceTween = null;
340
+ _stage = "delay";
341
+ _baseY = 0;
342
+ onEnter(e) {
343
+ this._config = e, this._stage = "delay", this._baseY = this._reel.container.y;
344
+ let t = (e.delay ?? 0) / 1e3;
345
+ t > 0 ? this._delayTween = o.delayedCall(t, () => this._beginSpinOut()) : this._beginSpinOut();
346
+ }
347
+ _beginSpinOut() {
348
+ if (!this._config) return;
349
+ let e = this._reel, t = this._speed;
350
+ e.setStopFrame(this._config.targetFrame), e.isStopping = !0, e.speed = t.spinSpeed, this._stage = "spinning";
351
+ }
352
+ update(e) {
353
+ this._stage === "spinning" && (this._reel.stopSequencer.hasRemaining || this._landAndBounce());
354
+ }
355
+ _landAndBounce() {
356
+ let e = this._reel, t = this._speed;
357
+ e.speed = 0, e.isStopping = !1, e.snapToGrid(), e.notifySpinEnd(), e.notifyLanded();
358
+ let n = t.bounceDistance;
359
+ if (n <= 0) {
360
+ this._stage = "done", this._complete();
361
+ return;
362
+ }
363
+ let r = (t.bounceDuration ?? 600) / 2e3;
364
+ this._stage = "bouncing", this._bounceTween = o.timeline(), this._bounceTween.to(e.container, {
365
+ y: this._baseY + n,
366
+ duration: r,
367
+ ease: "power1.out"
368
+ }), this._bounceTween.to(e.container, {
369
+ y: this._baseY,
370
+ duration: r,
371
+ ease: "power1.out",
372
+ onComplete: () => {
373
+ this._stage = "done", this._complete();
374
+ }
375
+ });
376
+ }
377
+ onSkip() {
378
+ this._killTweens();
379
+ let e = this._reel;
380
+ if (e.speed = 0, e.isStopping = !1, this._stage !== "done" && this._config) {
381
+ let t = e.bufferAbove, n = e.visibleRows;
382
+ e.placeSymbols(this._config.targetFrame.slice(t, t + n));
383
+ }
384
+ e.snapToGrid(), e.container.y = this._baseY, e.notifySpinEnd(), e.notifyLanded(), this._stage = "done";
385
+ }
386
+ _killTweens() {
387
+ this._delayTween &&= (this._delayTween.kill(), null), this._bounceTween &&= (this._bounceTween.kill(), null);
388
+ }
389
+ }, _ = class extends p {
390
+ name = "anticipation";
391
+ skippable = !0;
392
+ _tween = null;
393
+ onEnter(e) {
394
+ let t = this._reel, n = this._speed, r = (e.duration ?? n.anticipationDelay) / 1e3, i = n.spinSpeed * (e.speedMultiplier ?? .3);
395
+ if (r <= 0) {
396
+ this._complete();
397
+ return;
398
+ }
399
+ this._tween = o.timeline(), this._tween.to(t, {
400
+ speed: i,
401
+ duration: r * .35,
402
+ ease: "power2.out"
403
+ }), this._tween.to({}, {
404
+ duration: r * .65,
405
+ onComplete: () => this._complete()
406
+ });
407
+ }
408
+ update(e) {}
409
+ onSkip() {
410
+ this._kill(), this._reel.speed = this._speed.spinSpeed;
411
+ }
412
+ _kill() {
413
+ this._tween &&= (this._tween.kill(), null);
414
+ }
415
+ }, v = class {
416
+ _registry = /* @__PURE__ */ new Map();
417
+ constructor() {
418
+ this._registry.set("start", m), this._registry.set("spin", h), this._registry.set("stop", g), this._registry.set("anticipation", _);
419
+ }
420
+ register(e, t) {
421
+ this._registry.set(e, t);
422
+ }
423
+ create(e, t, n) {
424
+ let r = this._registry.get(e);
425
+ if (!r) throw Error(`Phase '${e}' not registered. Available: ${[...this._registry.keys()].join(", ")}`);
426
+ return new r(t, n);
427
+ }
428
+ has(e) {
429
+ return this._registry.has(e);
430
+ }
431
+ }, y = class {
432
+ _callbacks = [];
433
+ _isDestroyed = !1;
434
+ constructor(e) {
435
+ this._ticker = e;
436
+ }
437
+ get isDestroyed() {
438
+ return this._isDestroyed;
439
+ }
440
+ add(e) {
441
+ this._isDestroyed || (this._callbacks.push(e), this._ticker.add(e));
442
+ }
443
+ remove(e) {
444
+ let t = this._callbacks.indexOf(e);
445
+ t !== -1 && (this._callbacks.splice(t, 1), this._ticker.remove(e));
446
+ }
447
+ destroy() {
448
+ if (!this._isDestroyed) {
449
+ for (let e of this._callbacks) this._ticker.remove(e);
450
+ this._callbacks.length = 0, this._isDestroyed = !0;
451
+ }
452
+ }
453
+ }, b = class {
454
+ _reels;
455
+ _speedManager;
456
+ _frameBuilder;
457
+ _phaseFactory;
458
+ _events;
459
+ _tickerRef;
460
+ _spinningMode;
461
+ _isSpinning = !1;
462
+ _spinStartTime = 0;
463
+ _resultSymbols = null;
464
+ _anticipationReels = [];
465
+ _stopDelayOverride = null;
466
+ _activePhases = /* @__PURE__ */ new Map();
467
+ _landedReels = /* @__PURE__ */ new Set();
468
+ _wasSkipped = !1;
469
+ _isDestroyed = !1;
470
+ _currentSpinResolve = null;
471
+ _spinGeneration = 0;
472
+ constructor(e, t, n, r, i, a, o) {
473
+ this._reels = e, this._speedManager = t, this._frameBuilder = n, this._phaseFactory = r, this._events = i, this._tickerRef = new y(a), this._spinningMode = o ?? new u(), this._tickerRef.add((e) => this._onTick(e));
474
+ }
475
+ get isSpinning() {
476
+ return this._isSpinning;
477
+ }
478
+ get isDestroyed() {
479
+ return this._isDestroyed;
480
+ }
481
+ async spin() {
482
+ if (this._isSpinning) throw Error("Cannot start a new spin while one is in progress.");
483
+ this._isSpinning = !0, this._wasSkipped = !1, this._spinStartTime = performance.now(), this._resultSymbols = null, this._anticipationReels = [], this._stopDelayOverride = null, this._landedReels.clear(), this._activePhases.clear(), this._spinGeneration++;
484
+ let e = this._spinGeneration, t = this._speedManager.active;
485
+ this._events.emit("spin:start");
486
+ let n = new Promise((e) => {
487
+ this._currentSpinResolve = e;
488
+ });
489
+ for (let n = 0; n < this._reels.length; n++) this._startReel(n, t, e);
490
+ return n;
491
+ }
492
+ setResult(e) {
493
+ this._isSpinning && (this._resultSymbols = e, this._tryBeginStopSequence());
494
+ }
495
+ setAnticipation(e) {
496
+ this._anticipationReels = e;
497
+ }
498
+ setStopDelays(e) {
499
+ this._stopDelayOverride = [...e];
500
+ }
501
+ skip() {
502
+ if (this._isSpinning) {
503
+ this._wasSkipped = !0, this._events.emit("skip:requested");
504
+ for (let [, e] of this._activePhases) e.forceComplete();
505
+ if (this._activePhases.clear(), this._spinGeneration++, this._resultSymbols) for (let e = 0; e < this._reels.length; e++) {
506
+ if (this._landedReels.has(e)) continue;
507
+ let t = this._reels[e];
508
+ t.speed = 0, t.isStopping = !1, t.placeSymbols(this._resultSymbols[e]), this._markLanded(e);
509
+ }
510
+ else for (let e = 0; e < this._reels.length; e++) {
511
+ if (this._landedReels.has(e)) continue;
512
+ let t = this._reels[e];
513
+ t.speed = 0, t.isStopping = !1, t.snapToGrid(), this._markLanded(e);
514
+ }
515
+ this._events.emit("skip:completed");
516
+ }
517
+ }
518
+ destroy() {
519
+ this._isDestroyed ||= (this._tickerRef.destroy(), this._activePhases.clear(), !0);
520
+ }
521
+ async _startReel(e, t, n) {
522
+ if (n !== this._spinGeneration) return;
523
+ let r = this._reels[e], i = this._phaseFactory.create("start", r, t);
524
+ if (this._activePhases.set(e, i), await i.run({
525
+ spinningMode: this._spinningMode,
526
+ delay: e * t.spinDelay
527
+ }), n !== this._spinGeneration) return;
528
+ let a = this._phaseFactory.create("spin", r, t);
529
+ this._activePhases.set(e, a);
530
+ let o = a.run({}), s = !0;
531
+ for (let e = 0; e < this._reels.length; e++) {
532
+ let t = this._activePhases.get(e);
533
+ if (!t || t.name !== "spin") {
534
+ s = !1;
535
+ break;
536
+ }
537
+ }
538
+ if (s && (this._events.emit("spin:allStarted"), this._tryBeginStopSequence()), await o, n !== this._spinGeneration) return;
539
+ let c = this._stopDelayFor(e, t), l = this._frameFor(e);
540
+ if (this._anticipationReels.includes(e) && t.anticipationDelay > 0) {
541
+ this._events.emit("spin:stopping", e);
542
+ let i = this._phaseFactory.create("anticipation", r, t);
543
+ if (this._activePhases.set(e, i), await i.run({}), n !== this._spinGeneration) return;
544
+ } else this._events.emit("spin:stopping", e);
545
+ let u = this._phaseFactory.create("stop", r, t);
546
+ this._activePhases.set(e, u), await u.run({
547
+ targetFrame: l,
548
+ delay: c
549
+ }), n === this._spinGeneration && this._markLanded(e);
550
+ }
551
+ _stopDelayFor(e, t) {
552
+ return this._stopDelayOverride ? this._stopDelayOverride[e] ?? 0 : e * t.stopDelay;
553
+ }
554
+ _cachedFrames = null;
555
+ _frameFor(e) {
556
+ return this._cachedFrames ? this._cachedFrames[e] : [];
557
+ }
558
+ _tryBeginStopSequence() {
559
+ if (!this._resultSymbols) return;
560
+ for (let e = 0; e < this._reels.length; e++) {
561
+ let t = this._activePhases.get(e);
562
+ if (!t || t.name !== "spin") return;
563
+ }
564
+ let e = [];
565
+ for (let t = 0; t < this._reels.length; t++) {
566
+ let n = this._reels[t];
567
+ e.push(this._frameBuilder.build(t, n.visibleRows, n.bufferAbove, n.bufferBelow, this._resultSymbols[t]));
568
+ }
569
+ this._cachedFrames = e;
570
+ for (let e = 0; e < this._reels.length; e++) {
571
+ let t = this._activePhases.get(e);
572
+ t?.resolve && t.resolve();
573
+ }
574
+ }
575
+ _markLanded(e) {
576
+ if (this._landedReels.has(e)) return;
577
+ this._landedReels.add(e);
578
+ let t = this._reels[e], n = t.getVisibleSymbols();
579
+ t.events.emit("landed", n), this._events.emit("spin:reelLanded", e, n), this._landedReels.size === this._reels.length && this._finishSpin();
580
+ }
581
+ _finishSpin() {
582
+ let e = {
583
+ symbols: this._reels.map((e) => e.getVisibleSymbols()),
584
+ wasSkipped: this._wasSkipped,
585
+ duration: performance.now() - this._spinStartTime
586
+ };
587
+ this._isSpinning = !1, this._activePhases.clear(), this._cachedFrames = null, this._events.emit("spin:allLanded", e), this._events.emit("spin:complete", e), this._currentSpinResolve &&= (this._currentSpinResolve(e), null);
588
+ }
589
+ _onTick(e) {
590
+ if (!this._isSpinning) return;
591
+ let t = e.deltaMS;
592
+ for (let e of this._reels) e.update(t);
593
+ for (let e of this._activePhases.values()) e.isActive && e.update(t);
594
+ }
595
+ }, x = class {
596
+ _profiles = /* @__PURE__ */ new Map();
597
+ _activeName;
598
+ _active;
599
+ constructor(e, t) {
600
+ for (let [t, n] of e) this._profiles.set(t, n);
601
+ let n = this._profiles.get(t);
602
+ if (!n) throw Error(`Speed profile '${t}' not found. Available: ${[...this._profiles.keys()].join(", ")}`);
603
+ this._activeName = t, this._active = n;
604
+ }
605
+ get active() {
606
+ return this._active;
607
+ }
608
+ get activeName() {
609
+ return this._activeName;
610
+ }
611
+ set(e) {
612
+ let t = this._profiles.get(e);
613
+ if (!t) throw Error(`Speed profile '${e}' not found. Available: ${[...this._profiles.keys()].join(", ")}`);
614
+ let n = this._active;
615
+ return this._activeName = e, this._active = t, {
616
+ previous: n,
617
+ current: t
618
+ };
619
+ }
620
+ addProfile(e, t) {
621
+ this._profiles.set(e, t);
622
+ }
623
+ getProfile(e) {
624
+ return this._profiles.get(e);
625
+ }
626
+ get profileNames() {
627
+ return [...this._profiles.keys()];
628
+ }
629
+ }, S = class {
630
+ _reels;
631
+ _viewport;
632
+ _promoted = [];
633
+ _isActive = !1;
634
+ _isDestroyed = !1;
635
+ _cycleAbort = null;
636
+ constructor(e, t) {
637
+ this._reels = e, this._viewport = t;
638
+ }
639
+ get isActive() {
640
+ return this._isActive;
641
+ }
642
+ get isDestroyed() {
643
+ return this._isDestroyed;
644
+ }
645
+ async show(e, t = {}) {
646
+ this.hide();
647
+ let { dimAmount: n = .5, playWinAnimation: r = !0, promoteAboveMask: i = !0 } = t;
648
+ this._isActive = !0, this._viewport.showDim(n);
649
+ let a = [];
650
+ for (let t of e) {
651
+ let e = this._reels[t.reelIndex];
652
+ if (!e) continue;
653
+ let n = e.getSymbolAt(t.rowIndex);
654
+ if (!n) continue;
655
+ let o = n.view.parent;
656
+ if (this._promoted.push({
657
+ symbol: n,
658
+ originalParent: o,
659
+ position: t
660
+ }), i) {
661
+ let e = n.view.getGlobalPosition();
662
+ this._viewport.spotlightContainer.addChild(n.view);
663
+ let t = this._viewport.spotlightContainer.toLocal(e);
664
+ n.view.x = t.x, n.view.y = t.y;
665
+ }
666
+ r && a.push(n.playWin());
667
+ }
668
+ a.length > 0 && await Promise.all(a);
669
+ }
670
+ hide() {
671
+ this._cycleAbort &&= (this._cycleAbort.abort(), null);
672
+ for (let { symbol: e, originalParent: t } of this._promoted) {
673
+ if (t && e.view.parent !== t) {
674
+ let n = e.view.getGlobalPosition();
675
+ t.addChild(e.view);
676
+ let r = t.toLocal(n);
677
+ e.view.x = r.x, e.view.y = r.y;
678
+ }
679
+ e.stopAnimation();
680
+ }
681
+ this._promoted = [], this._viewport.hideDim(), this._isActive = !1;
682
+ }
683
+ async cycle(e, t = {}) {
684
+ let { displayDuration: n = 2e3, gapDuration: r = 300, cycles: i = 1 } = t;
685
+ if (e.length === 0) return;
686
+ this._cycleAbort = new AbortController();
687
+ let a = this._cycleAbort.signal, o = 0;
688
+ for (; i === -1 || o < i;) {
689
+ for (let i of e) {
690
+ if (a.aborted || (await this.show(i.positions, t), await this._wait(n, a), a.aborted)) return;
691
+ this.hide(), await this._wait(r, a);
692
+ }
693
+ o++;
694
+ }
695
+ }
696
+ destroy() {
697
+ this._isDestroyed ||= (this.hide(), !0);
698
+ }
699
+ _wait(e, t) {
700
+ return new Promise((n) => {
701
+ if (t.aborted) {
702
+ n();
703
+ return;
704
+ }
705
+ let r = setTimeout(n, e);
706
+ t.addEventListener("abort", () => {
707
+ clearTimeout(r), n();
708
+ }, { once: !0 });
709
+ });
710
+ }
711
+ }, C = class extends r {
712
+ _events = new s();
713
+ _reels;
714
+ _viewport;
715
+ _spinController;
716
+ _speedManager;
717
+ _spotlight;
718
+ _symbolFactory;
719
+ _isDestroyed = !1;
720
+ constructor(e) {
721
+ super(), this._reels = e.reels, this._viewport = e.viewport, this._symbolFactory = e.symbolFactory, this._speedManager = new x(e.config.speeds, e.config.initialSpeed), this._spinController = new b(e.reels, this._speedManager, e.frameBuilder, e.phaseFactory, this._events, e.config.ticker, e.spinningMode), this._spotlight = new S(e.reels, e.viewport), this.addChild(this._viewport);
722
+ }
723
+ get events() {
724
+ return this._events;
725
+ }
726
+ async spin() {
727
+ return this._spinController.spin();
728
+ }
729
+ setResult(e) {
730
+ this._spinController.setResult(e);
731
+ }
732
+ setAnticipation(e) {
733
+ this._spinController.setAnticipation(e);
734
+ }
735
+ setStopDelays(e) {
736
+ this._spinController.setStopDelays(e);
737
+ }
738
+ skip() {
739
+ this._spinController.skip();
740
+ }
741
+ get isSpinning() {
742
+ return this._spinController.isSpinning;
743
+ }
744
+ get speed() {
745
+ return this._speedManager;
746
+ }
747
+ setSpeed(e) {
748
+ let { previous: t, current: n } = this._speedManager.set(e);
749
+ this._events.emit("speed:changed", n, t);
750
+ }
751
+ get spotlight() {
752
+ return this._spotlight;
753
+ }
754
+ get reels() {
755
+ return this._reels;
756
+ }
757
+ getReel(e) {
758
+ return this._reels[e];
759
+ }
760
+ get viewport() {
761
+ return this._viewport;
762
+ }
763
+ get isDestroyed() {
764
+ return this._isDestroyed;
765
+ }
766
+ destroy() {
767
+ if (!this._isDestroyed) {
768
+ this._isDestroyed = !0, this._spotlight.destroy(), this._spinController.destroy();
769
+ for (let e of this._reels) e.destroy();
770
+ this._symbolFactory.destroy(), this._viewport.destroy(), this._events.emit("destroyed"), this._events.removeAllListeners(), super.destroy({ children: !0 });
771
+ }
772
+ }
773
+ }, w = {
774
+ bufferSymbols: 1,
775
+ symbolGap: {
776
+ x: 0,
777
+ y: 0
778
+ },
779
+ initialSpeed: "normal",
780
+ maxPoolPerKey: 20,
781
+ zIndexStep: 100
782
+ }, T = {
783
+ NORMAL: {
784
+ name: "normal",
785
+ spinDelay: 100,
786
+ spinSpeed: 30,
787
+ stopDelay: 140,
788
+ anticipationDelay: 450,
789
+ bounceDistance: 56,
790
+ bounceDuration: 600,
791
+ accelerationEase: "power2.in",
792
+ decelerationEase: "power2.out",
793
+ accelerationDuration: 300,
794
+ minimumSpinTime: 500
795
+ },
796
+ TURBO: {
797
+ name: "turbo",
798
+ spinDelay: 30,
799
+ spinSpeed: 50,
800
+ stopDelay: 0,
801
+ anticipationDelay: 250,
802
+ bounceDistance: 42,
803
+ bounceDuration: 200,
804
+ accelerationEase: "power2.in",
805
+ decelerationEase: "power2.out",
806
+ accelerationDuration: 200,
807
+ minimumSpinTime: 300
808
+ },
809
+ SUPER_TURBO: {
810
+ name: "superTurbo",
811
+ spinDelay: 0,
812
+ spinSpeed: 80,
813
+ stopDelay: 0,
814
+ anticipationDelay: 0,
815
+ bounceDistance: 14,
816
+ bounceDuration: 120,
817
+ accelerationEase: "power1.in",
818
+ decelerationEase: "power1.out",
819
+ accelerationDuration: 50,
820
+ minimumSpinTime: 100
821
+ }
822
+ }, E = class {
823
+ _entries = /* @__PURE__ */ new Map();
824
+ register(e, t, n) {
825
+ if (this._entries.has(e)) throw Error(`Symbol '${e}' is already registered.`);
826
+ this._entries.set(e, {
827
+ SymbolClass: t,
828
+ options: n
829
+ });
830
+ }
831
+ create(e) {
832
+ let t = this._entries.get(e);
833
+ if (!t) throw Error(`Symbol '${e}' is not registered. Available: ${[...this._entries.keys()].join(", ")}`);
834
+ let n = new t.SymbolClass(t.options);
835
+ return n.activate(e), n;
836
+ }
837
+ has(e) {
838
+ return this._entries.has(e);
839
+ }
840
+ get symbolIds() {
841
+ return [...this._entries.keys()];
842
+ }
843
+ get size() {
844
+ return this._entries.size;
845
+ }
846
+ }, D = class {
847
+ _pools = /* @__PURE__ */ new Map();
848
+ _isDestroyed = !1;
849
+ constructor(e, t, n, r = 20) {
850
+ this._factory = e, this._reset = t, this._dispose = n, this._maxPerKey = r;
851
+ }
852
+ get isDestroyed() {
853
+ return this._isDestroyed;
854
+ }
855
+ acquire(e) {
856
+ let t = this._pools.get(e);
857
+ if (t && t.length > 0) {
858
+ let e = t.pop();
859
+ return this._reset?.(e), e;
860
+ }
861
+ return this._factory(e);
862
+ }
863
+ release(e, t) {
864
+ let n = this._pools.get(e);
865
+ if (n || (n = [], this._pools.set(e, n)), n.length >= this._maxPerKey) {
866
+ this._dispose?.(t);
867
+ return;
868
+ }
869
+ n.push(t);
870
+ }
871
+ size(e) {
872
+ return this._pools.get(e)?.length ?? 0;
873
+ }
874
+ get totalSize() {
875
+ let e = 0;
876
+ for (let t of this._pools.values()) e += t.length;
877
+ return e;
878
+ }
879
+ clear() {
880
+ if (this._dispose) for (let e of this._pools.values()) for (let t of e) this._dispose(t);
881
+ this._pools.clear();
882
+ }
883
+ destroy() {
884
+ this._isDestroyed ||= (this.clear(), !0);
885
+ }
886
+ }, O = class {
887
+ _pool;
888
+ constructor(e, t = 20) {
889
+ this._registry = e, this._pool = new D((e) => this._registry.create(e), (e) => e.reset(), (e) => e.destroy(), t);
890
+ }
891
+ acquire(e) {
892
+ let t = this._pool.acquire(e);
893
+ return t.symbolId !== e && t.activate(e), t;
894
+ }
895
+ release(e) {
896
+ let t = e.symbolId;
897
+ e.deactivate(), this._pool.release(t, e);
898
+ }
899
+ destroy() {
900
+ this._pool.destroy();
901
+ }
902
+ }, k = class {
903
+ _symbols;
904
+ _weights;
905
+ _cumulativeWeights = [];
906
+ _totalWeight = 0;
907
+ _excludeSpinning = /* @__PURE__ */ new Set();
908
+ _excludeBuffer = /* @__PURE__ */ new Set();
909
+ constructor(e) {
910
+ this._symbols = Object.keys(e), this._weights = this._symbols.map((t) => e[t].weight), this._rebuildWeights();
911
+ }
912
+ next(e = !1) {
913
+ let t = e ? new Set([...this._excludeSpinning, ...this._excludeBuffer]) : this._excludeSpinning;
914
+ if (t.size === 0) return this._pickWeighted();
915
+ let n = 0, r = [];
916
+ for (let e = 0; e < this._symbols.length; e++) t.has(this._symbols[e]) || (n += this._weights[e], r.push({
917
+ id: this._symbols[e],
918
+ cumWeight: n
919
+ }));
920
+ if (n === 0 || r.length === 0) {
921
+ for (let e of this._symbols) if (!t.has(e)) return e;
922
+ return this._symbols[0];
923
+ }
924
+ let i = Math.random() * n, a = 0, o = r.length - 1;
925
+ for (; a < o;) {
926
+ let e = a + o >> 1;
927
+ r[e].cumWeight <= i ? a = e + 1 : o = e;
928
+ }
929
+ return r[a].id;
930
+ }
931
+ setExcludeSpinning(e) {
932
+ this._excludeSpinning = new Set(e);
933
+ }
934
+ setExcludeBuffer(e) {
935
+ this._excludeBuffer = new Set(e);
936
+ }
937
+ updateWeights(e) {
938
+ this._symbols = Object.keys(e), this._weights = this._symbols.map((t) => e[t].weight), this._rebuildWeights();
939
+ }
940
+ _rebuildWeights() {
941
+ this._cumulativeWeights = [], this._totalWeight = 0;
942
+ for (let e of this._weights) this._totalWeight += e, this._cumulativeWeights.push(this._totalWeight);
943
+ }
944
+ _pickWeighted() {
945
+ let e = Math.random() * this._totalWeight, t = 0, n = this._cumulativeWeights.length - 1;
946
+ for (; t < n;) {
947
+ let r = t + n >> 1;
948
+ this._cumulativeWeights[r] <= e ? t = r + 1 : n = r;
949
+ }
950
+ return this._symbols[t];
951
+ }
952
+ }, A = class {
953
+ _middlewares = [];
954
+ _sorted = !1;
955
+ constructor(e) {
956
+ this._randomProvider = e, this.use(new j(e)), this.use(new M());
957
+ }
958
+ use(e) {
959
+ return this._middlewares.push(e), this._sorted = !1, this;
960
+ }
961
+ remove(e) {
962
+ return this._middlewares = this._middlewares.filter((t) => t.name !== e), this;
963
+ }
964
+ build(e, t, n, r, i, a = !1) {
965
+ this._sorted ||= (this._middlewares.sort((e, t) => e.priority - t.priority), !0);
966
+ let o = n + t + r, s = {
967
+ reelIndex: e,
968
+ visibleRows: t,
969
+ bufferAbove: n,
970
+ bufferBelow: r,
971
+ symbols: Array(o).fill(""),
972
+ targetSymbols: i,
973
+ isSpinning: a,
974
+ metadata: {}
975
+ }, c = 0, l = () => {
976
+ c < this._middlewares.length && this._middlewares[c++].process(s, l);
977
+ };
978
+ return l(), s.symbols;
979
+ }
980
+ buildAll(e, t, n, r, i, a = !1) {
981
+ return Array.from({ length: e }, (e, o) => this.build(o, t, n, r, i?.[o], a));
982
+ }
983
+ get randomProvider() {
984
+ return this._randomProvider;
985
+ }
986
+ }, j = class {
987
+ name = "random-fill";
988
+ priority = 0;
989
+ constructor(e) {
990
+ this._provider = e;
991
+ }
992
+ process(e, t) {
993
+ for (let t = 0; t < e.symbols.length; t++) if (!e.symbols[t]) {
994
+ let n = t < e.bufferAbove || t >= e.bufferAbove + e.visibleRows;
995
+ e.symbols[t] = this._provider.next(n);
996
+ }
997
+ t();
998
+ }
999
+ }, M = class {
1000
+ name = "target-placement";
1001
+ priority = 10;
1002
+ process(e, t) {
1003
+ if (e.targetSymbols) for (let t = 0; t < e.targetSymbols.length; t++) {
1004
+ let n = e.bufferAbove + t;
1005
+ n < e.symbols.length && (e.symbols[n] = e.targetSymbols[t]);
1006
+ }
1007
+ t();
1008
+ }
1009
+ }, N = class {
1010
+ _offsets = [];
1011
+ constructor(e, t, n, r) {
1012
+ this._reelCount = e, this._totalRows = t, this._symbolWidth = n, this._config = r, this._compute();
1013
+ }
1014
+ getOffset(e, t) {
1015
+ return this._offsets[e]?.[t] ?? 0;
1016
+ }
1017
+ get offsets() {
1018
+ return this._offsets;
1019
+ }
1020
+ _compute() {
1021
+ if (this._config.mode === "none") {
1022
+ this._offsets = Array.from({ length: this._reelCount }, () => Array(this._totalRows).fill(0));
1023
+ return;
1024
+ }
1025
+ let e = this._config, t = (this._reelCount - 1) / 2;
1026
+ this._offsets = [];
1027
+ for (let n = 0; n < this._reelCount; n++) {
1028
+ let r = this._reelCount > 1 ? (n - t) / (this._reelCount / 2) : 0, i = [];
1029
+ for (let t = 0; t < this._totalRows; t++) {
1030
+ let n = this._totalRows > 1 ? t / (this._totalRows - 1) : .5, a = r * e.widthDifference * e.topWidthFactor, o = a + (r * e.widthDifference * e.bottomWidthFactor - a) * n;
1031
+ i.push(o);
1032
+ }
1033
+ this._offsets.push(i);
1034
+ }
1035
+ }
1036
+ }, P = class {
1037
+ _reelCount;
1038
+ _visibleRows;
1039
+ _symbolWidth;
1040
+ _symbolHeight;
1041
+ _symbolGap = { ...w.symbolGap };
1042
+ _bufferSymbols = w.bufferSymbols;
1043
+ _symbolRegistry = new E();
1044
+ _weights = {};
1045
+ _speeds = /* @__PURE__ */ new Map();
1046
+ _initialSpeed = w.initialSpeed;
1047
+ _offset = { mode: "none" };
1048
+ _ticker;
1049
+ _spinningMode = new u();
1050
+ _phaseFactory = new v();
1051
+ _middlewares = [];
1052
+ _initialFrame;
1053
+ _symbolDataOverrides = {};
1054
+ reels(e) {
1055
+ return this._reelCount = e, this;
1056
+ }
1057
+ visibleSymbols(e) {
1058
+ return this._visibleRows = e, this;
1059
+ }
1060
+ symbolSize(e, t) {
1061
+ return this._symbolWidth = e, this._symbolHeight = t, this;
1062
+ }
1063
+ symbolGap(e, t) {
1064
+ return this._symbolGap = {
1065
+ x: e,
1066
+ y: t
1067
+ }, this;
1068
+ }
1069
+ bufferSymbols(e) {
1070
+ return this._bufferSymbols = e, this;
1071
+ }
1072
+ symbols(e) {
1073
+ return e(this._symbolRegistry), this;
1074
+ }
1075
+ weights(e) {
1076
+ return this._weights = e, this;
1077
+ }
1078
+ symbolData(e) {
1079
+ return this._symbolDataOverrides = {
1080
+ ...this._symbolDataOverrides,
1081
+ ...e
1082
+ }, this;
1083
+ }
1084
+ speed(e, t) {
1085
+ return this._speeds.set(e, t), this;
1086
+ }
1087
+ initialSpeed(e) {
1088
+ return this._initialSpeed = e, this;
1089
+ }
1090
+ offsetConfig(e) {
1091
+ return this._offset = e, this;
1092
+ }
1093
+ ticker(e) {
1094
+ return this._ticker = e, this;
1095
+ }
1096
+ spinningMode(e) {
1097
+ return this._spinningMode = e, this;
1098
+ }
1099
+ frameMiddleware(e) {
1100
+ return this._middlewares.push(e), this;
1101
+ }
1102
+ phases(e) {
1103
+ return e(this._phaseFactory), this;
1104
+ }
1105
+ initialFrame(e) {
1106
+ return this._initialFrame = e, this;
1107
+ }
1108
+ build() {
1109
+ this._validate();
1110
+ let e = this._reelCount, t = this._visibleRows, n = this._symbolWidth, r = this._symbolHeight, i = this._bufferSymbols, a = this._bufferSymbols, o = this._ticker;
1111
+ this._speeds.size === 0 && this._speeds.set("normal", T.NORMAL);
1112
+ let s = {}, c = this._symbolRegistry.symbolIds;
1113
+ for (let e of c) {
1114
+ let t = this._symbolDataOverrides[e] ?? {};
1115
+ s[e] = {
1116
+ weight: t.weight ?? this._weights[e] ?? 10,
1117
+ zIndex: t.zIndex ?? 1,
1118
+ unmask: t.unmask
1119
+ };
1120
+ }
1121
+ let l = {
1122
+ grid: {
1123
+ reelCount: e,
1124
+ visibleRows: t,
1125
+ symbolWidth: n,
1126
+ symbolHeight: r,
1127
+ symbolGap: { ...this._symbolGap },
1128
+ bufferSymbols: this._bufferSymbols
1129
+ },
1130
+ symbols: s,
1131
+ speeds: this._speeds,
1132
+ initialSpeed: this._initialSpeed,
1133
+ offset: this._offset,
1134
+ ticker: o
1135
+ }, u = new O(this._symbolRegistry), p = new k(s), m = new A(p);
1136
+ for (let e of this._middlewares) m.use(e);
1137
+ let h = new f(e * (n + this._symbolGap.x) - this._symbolGap.x, t * (r + this._symbolGap.y) - this._symbolGap.y);
1138
+ new N(e, i + t + a, n, this._offset);
1139
+ let g = this._initialFrame ? m.buildAll(e, t, i, a, this._initialFrame) : m.buildAll(e, t, i, a), _ = [];
1140
+ for (let o = 0; o < e; o++) {
1141
+ let e = new d({
1142
+ reelIndex: o,
1143
+ visibleRows: t,
1144
+ bufferAbove: i,
1145
+ bufferBelow: a,
1146
+ symbolWidth: n,
1147
+ symbolHeight: r,
1148
+ symbolGapX: this._symbolGap.x,
1149
+ symbolGapY: this._symbolGap.y,
1150
+ symbolsData: s,
1151
+ initialSymbols: g[o]
1152
+ }, u, p, h);
1153
+ _.push(e);
1154
+ }
1155
+ return new C({
1156
+ config: l,
1157
+ reels: _,
1158
+ viewport: h,
1159
+ symbolFactory: u,
1160
+ frameBuilder: m,
1161
+ phaseFactory: this._phaseFactory,
1162
+ spinningMode: this._spinningMode
1163
+ });
1164
+ }
1165
+ _validate() {
1166
+ let e = [];
1167
+ if ((this._reelCount === void 0 || this._reelCount <= 0) && e.push("reels() must be called with a positive number."), (this._visibleRows === void 0 || this._visibleRows <= 0) && e.push("visibleSymbols() must be called with a positive number."), (this._symbolWidth === void 0 || this._symbolHeight === void 0) && e.push("symbolSize() must be called with width and height."), this._symbolRegistry.size === 0 && e.push("symbols() must register at least one symbol."), this._ticker || e.push("ticker() must be called with a PixiJS Ticker."), this._speeds.size > 0 && !this._speeds.has(this._initialSpeed) && e.push(`initialSpeed '${this._initialSpeed}' does not match any registered speed profile. Available: ${[...this._speeds.keys()].join(", ")}`), e.length > 0) throw Error(`ReelSetBuilder validation failed:\n - ${e.join("\n - ")}`);
1168
+ }
1169
+ }, F = class extends e {
1170
+ _sprite;
1171
+ _textures;
1172
+ _winTween = null;
1173
+ constructor(e) {
1174
+ super(), this._textures = e.textures;
1175
+ let t = e.anchor ?? {
1176
+ x: 0,
1177
+ y: 0
1178
+ };
1179
+ this._sprite = new a(), this._sprite.anchor.set(t.x, t.y), this.view.addChild(this._sprite);
1180
+ }
1181
+ onActivate(e) {
1182
+ let t = this._textures[e];
1183
+ t && (this._sprite.texture = t);
1184
+ }
1185
+ onDeactivate() {
1186
+ this._killWinTween(), this._sprite.scale.set(1, 1);
1187
+ }
1188
+ async playWin() {
1189
+ return this._killWinTween(), new Promise((e) => {
1190
+ this._winTween = o.to(this._sprite.scale, {
1191
+ x: 1.15,
1192
+ y: 1.15,
1193
+ duration: .15,
1194
+ yoyo: !0,
1195
+ repeat: 1,
1196
+ ease: "power2.inOut",
1197
+ onComplete: e
1198
+ });
1199
+ });
1200
+ }
1201
+ stopAnimation() {
1202
+ this._killWinTween(), this._sprite.scale.set(1, 1);
1203
+ }
1204
+ resize(e, t) {
1205
+ this._sprite.width = e, this._sprite.height = t;
1206
+ }
1207
+ onDestroy() {
1208
+ this._killWinTween();
1209
+ }
1210
+ _killWinTween() {
1211
+ this._winTween &&= (this._winTween.kill(), null);
1212
+ }
1213
+ }, I = class extends e {
1214
+ _animSprite;
1215
+ _frames;
1216
+ _animationSpeed;
1217
+ _winResolve = null;
1218
+ constructor(e) {
1219
+ super(), this._frames = e.frames, this._animationSpeed = e.animationSpeed ?? 1;
1220
+ let t = e.anchor ?? {
1221
+ x: 0,
1222
+ y: 0
1223
+ }, r = Object.values(this._frames)[0] ?? [];
1224
+ this._animSprite = new n(r.length > 0 ? r : []), this._animSprite.anchor.set(t.x, t.y), this._animSprite.animationSpeed = this._animationSpeed, this._animSprite.loop = !1, this.view.addChild(this._animSprite);
1225
+ }
1226
+ onActivate(e) {
1227
+ let t = this._frames[e];
1228
+ t && t.length > 0 && (this._animSprite.textures = t, this._animSprite.gotoAndStop(0));
1229
+ }
1230
+ onDeactivate() {
1231
+ this._animSprite.stop(), this._winResolve = null;
1232
+ }
1233
+ async playWin() {
1234
+ return new Promise((e) => {
1235
+ this._winResolve = e, this._animSprite.loop = !1, this._animSprite.onComplete = () => {
1236
+ this._winResolve = null, this._animSprite.onComplete = void 0, e();
1237
+ }, this._animSprite.gotoAndPlay(0);
1238
+ });
1239
+ }
1240
+ stopAnimation() {
1241
+ this._animSprite.stop(), this._animSprite.gotoAndStop(0), this._winResolve &&= (this._winResolve(), null);
1242
+ }
1243
+ resize(e, t) {
1244
+ this._animSprite.width = e, this._animSprite.height = t;
1245
+ }
1246
+ }, L = class {
1247
+ name = "cascade";
1248
+ _gravity;
1249
+ constructor(e = 1.5) {
1250
+ this._gravity = e;
1251
+ }
1252
+ computeDeltaY(e, t, n) {
1253
+ let r = e * t * this._gravity * n / 1e3;
1254
+ return Math.min(r, e);
1255
+ }
1256
+ }, R = class {
1257
+ name = "immediate";
1258
+ computeDeltaY(e, t, n) {
1259
+ return 0;
1260
+ }
1261
+ };
1262
+ //#endregion
1263
+ //#region src/debug/debug.ts
1264
+ function z(e) {
1265
+ let t = e.reels, n = t.map((e, t) => ({
1266
+ index: t,
1267
+ speed: e.speed,
1268
+ isStopping: e.isStopping,
1269
+ allSymbols: e.symbols.map((e, t) => ({
1270
+ row: t,
1271
+ symbolId: e.symbolId,
1272
+ y: Math.round(e.view.y)
1273
+ })),
1274
+ visibleSymbols: e.getVisibleSymbols()
1275
+ })), r = [];
1276
+ for (let e of n) r.push(e.visibleSymbols);
1277
+ return {
1278
+ timestamp: Date.now(),
1279
+ isSpinning: e.isSpinning,
1280
+ currentSpeed: e.speed.activeName,
1281
+ availableSpeeds: e.speed.profileNames,
1282
+ spotlightActive: e.spotlight.isActive,
1283
+ reelCount: t.length,
1284
+ visibleRows: t[0]?.getVisibleSymbols().length ?? 0,
1285
+ reels: n,
1286
+ grid: r
1287
+ };
1288
+ }
1289
+ function B(e) {
1290
+ let { grid: t, visibleRows: n } = z(e);
1291
+ if (t.length === 0) return "(empty grid)";
1292
+ let r = (e) => e.slice(0, 8).padEnd(8), i = (e, n, r) => e + t.map(() => "─".repeat(8)).join(n) + r, a = [];
1293
+ a.push(i("┌", "┬", "┐"));
1294
+ for (let e = 0; e < n; e++) {
1295
+ let n = t.map((t) => r(t[e] ?? "?"));
1296
+ a.push("│" + n.join("│") + "│");
1297
+ }
1298
+ return a.push(i("└", "┴", "┘")), a.join("\n");
1299
+ }
1300
+ function V(e) {
1301
+ typeof window > "u" || (window.__PIXI_REELS_DEBUG = {
1302
+ reelSet: e,
1303
+ snapshot: () => z(e),
1304
+ grid: () => B(e),
1305
+ log: () => {
1306
+ let t = z(e);
1307
+ return console.log(`[pixi-reels debug] spinning=${t.isSpinning} speed=${t.currentSpeed}`), console.log(B(e)), t;
1308
+ },
1309
+ trace: () => {
1310
+ for (let t of [
1311
+ "spin:start",
1312
+ "spin:allStarted",
1313
+ "spin:stopping",
1314
+ "spin:reelLanded",
1315
+ "spin:allLanded",
1316
+ "spin:complete",
1317
+ "skip:requested",
1318
+ "skip:completed",
1319
+ "speed:changed",
1320
+ "spotlight:start",
1321
+ "spotlight:end",
1322
+ "destroyed"
1323
+ ]) e.events.on(t, (...e) => {
1324
+ console.log(`[pixi-reels] ${t}`, ...e);
1325
+ });
1326
+ console.log("[pixi-reels debug] tracing enabled for all events");
1327
+ }
1328
+ }, console.log("[pixi-reels] Debug mode enabled. Use __PIXI_REELS_DEBUG.log() to inspect state."));
1329
+ }
1330
+ //#endregion
1331
+ //#region src/testing/FakeTicker.ts
1332
+ var H = class {
1333
+ deltaMS = 16;
1334
+ deltaTime = 1;
1335
+ elapsedMS = 0;
1336
+ lastTime = 0;
1337
+ speed = 1;
1338
+ started = !1;
1339
+ FPS = 60;
1340
+ minFPS = 10;
1341
+ maxFPS = 0;
1342
+ _callbacks = [];
1343
+ add(e) {
1344
+ return this._callbacks.push(e), this;
1345
+ }
1346
+ addOnce(e) {
1347
+ let t = (n) => {
1348
+ this.remove(t), e(n);
1349
+ };
1350
+ return this.add(t);
1351
+ }
1352
+ remove(e) {
1353
+ let t = this._callbacks.indexOf(e);
1354
+ return t !== -1 && this._callbacks.splice(t, 1), this;
1355
+ }
1356
+ start() {
1357
+ return this.started = !0, this;
1358
+ }
1359
+ stop() {
1360
+ return this.started = !1, this;
1361
+ }
1362
+ destroy() {
1363
+ this._callbacks.length = 0, this.started = !1;
1364
+ }
1365
+ tick(e = 16) {
1366
+ this.deltaMS = e, this.deltaTime = e / (1e3 / 60), this.elapsedMS += e, this.lastTime += e;
1367
+ let t = this._callbacks.slice();
1368
+ for (let e of t) e(this);
1369
+ }
1370
+ tickFor(e, t = 16) {
1371
+ let n = e;
1372
+ for (; n > 0;) {
1373
+ let e = Math.min(t, n);
1374
+ this.tick(e), n -= e;
1375
+ }
1376
+ }
1377
+ get listenerCount() {
1378
+ return this._callbacks.length;
1379
+ }
1380
+ }, U = class extends e {
1381
+ _width = 0;
1382
+ _height = 0;
1383
+ onActivate(e) {}
1384
+ onDeactivate() {}
1385
+ async playWin() {}
1386
+ stopAnimation() {}
1387
+ resize(e, t) {
1388
+ this._width = e, this._height = t;
1389
+ }
1390
+ get width() {
1391
+ return this._width;
1392
+ }
1393
+ get height() {
1394
+ return this._height;
1395
+ }
1396
+ };
1397
+ //#endregion
1398
+ //#region src/testing/testHarness.ts
1399
+ function W(e = {}) {
1400
+ let t = e.reels ?? 5, n = e.visibleRows ?? 3, r = e.symbolIds ?? [
1401
+ "a",
1402
+ "b",
1403
+ "c"
1404
+ ], i = e.weights ?? {}, a = e.symbolSize ?? {
1405
+ width: 100,
1406
+ height: 100
1407
+ }, o = new H(), s = new P().reels(t).visibleSymbols(n).symbolSize(a.width, a.height).ticker(o).symbols((e) => {
1408
+ for (let t of r) e.register(t, U, {});
1409
+ });
1410
+ Object.keys(i).length > 0 && s.weights(i);
1411
+ let c = s.build();
1412
+ return {
1413
+ reelSet: c,
1414
+ ticker: o,
1415
+ advance(e, t = 16) {
1416
+ o.tickFor(e, t);
1417
+ },
1418
+ async spinAndLand(e) {
1419
+ return G(c, e);
1420
+ },
1421
+ destroy() {
1422
+ c.destroy(), o.destroy();
1423
+ }
1424
+ };
1425
+ }
1426
+ async function G(e, t) {
1427
+ let n = e.spin();
1428
+ return e.setResult(t), e.skip(), n;
1429
+ }
1430
+ function K(e, t) {
1431
+ let n = [];
1432
+ for (let r of t) e.events.on(r, (...e) => {
1433
+ n.push({
1434
+ event: r,
1435
+ args: e
1436
+ });
1437
+ });
1438
+ return n;
1439
+ }
1440
+ function q(e, t) {
1441
+ let n = z(e).grid, r = [];
1442
+ if (n.length !== t.length) throw Error(`Grid reel count mismatch: expected ${t.length} got ${n.length}\n${B(e)}`);
1443
+ for (let e = 0; e < t.length; e++) for (let i = 0; i < t[e].length; i++) t[e][i] !== n[e][i] && r.push(` reel ${e} row ${i}: expected "${t[e][i]}" got "${n[e][i]}"`);
1444
+ if (r.length > 0) throw Error(`Grid mismatch:\n${r.join("\n")}\n\nCurrent grid:\n${B(e)}`);
1445
+ }
1446
+ function J(e, t) {
1447
+ let n = 0;
1448
+ for (let r of z(e).grid) for (let e of r) e === t && n++;
1449
+ return n;
1450
+ }
1451
+ //#endregion
1452
+ export { I as AnimatedSpriteSymbol, _ as AnticipationPhase, L as CascadeMode, w as DEFAULTS, s as EventEmitter, H as FakeTicker, A as FrameBuilder, U as HeadlessSymbol, R as ImmediateMode, D as ObjectPool, N as OffsetCalculator, v as PhaseFactory, k as RandomSymbolProvider, d as Reel, c as ReelMotion, p as ReelPhase, C as ReelSet, P as ReelSetBuilder, e as ReelSymbol, f as ReelViewport, x as SpeedManager, T as SpeedPresets, b as SpinController, h as SpinPhase, t as SpineSymbol, F as SpriteSymbol, u as StandardMode, m as StartPhase, g as StopPhase, l as StopSequencer, O as SymbolFactory, E as SymbolRegistry, S as SymbolSpotlight, y as TickerRef, K as captureEvents, J as countSymbol, W as createTestReelSet, B as debugGrid, z as debugSnapshot, V as enableDebug, q as expectGrid, G as spinAndLand };
1453
+
1454
+ //# sourceMappingURL=index.js.map