cascading-reel 0.0.21 → 0.0.22

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/dist/index.es.js CHANGED
@@ -33,61 +33,61 @@ const q = [0.04, 0, -0.04], I = {
33
33
  pixelSnapY: "half"
34
34
  }
35
35
  }, Y = "normal";
36
- function V(e) {
37
- return I[e];
36
+ function V(s) {
37
+ return I[s];
38
38
  }
39
39
  I.normal.outroRowGapMs;
40
40
  I.normal.rowBaseSpacingRatio;
41
- const X = 5e3, G = 1800, k = 0.1, v = 720, D = 34, z = [255, 235, 110];
41
+ const X = 5e3, G = 1800, k = 0.1, L = 720, D = 34, z = [255, 235, 110];
42
42
  I.normal.columnStaggerMs;
43
43
  I.normal.fallMs;
44
44
  I.normal.outroOverlapMs;
45
45
  const $ = 200;
46
- function b(e, t, s) {
47
- return e < t ? t : e > s ? s : e;
46
+ function b(s, t, e) {
47
+ return s < t ? t : s > e ? e : s;
48
48
  }
49
- function K(e) {
50
- return Math.floor(Math.random() * e);
49
+ function K(s) {
50
+ return Math.floor(Math.random() * s);
51
51
  }
52
- function C(e, t) {
53
- return (e % t + t) % t;
52
+ function C(s, t) {
53
+ return (s % t + t) % t;
54
54
  }
55
- function L(e) {
56
- return b(Math.round(e), 0, 255);
55
+ function v(s) {
56
+ return b(Math.round(s), 0, 255);
57
57
  }
58
- function F(e) {
58
+ function F(s) {
59
59
  const t = [];
60
- for (let s = 0; s < 3; s += 1) {
60
+ for (let e = 0; e < 3; e += 1) {
61
61
  const i = [];
62
62
  for (let r = 0; r < 3; r += 1)
63
- i.push(K(e));
63
+ i.push(K(s));
64
64
  t.push(i);
65
65
  }
66
66
  return t;
67
67
  }
68
- function H(e) {
68
+ function H(s) {
69
69
  const t = /* @__PURE__ */ new Map();
70
70
  for (let n = 0; n < 3; n += 1)
71
71
  for (let o = 0; o < 3; o += 1) {
72
- const l = e[n][o];
73
- t.set(l, (t.get(l) ?? 0) + 1);
72
+ const h = s[n][o];
73
+ t.set(h, (t.get(h) ?? 0) + 1);
74
74
  }
75
- let s = e[0][0], i = -1;
75
+ let e = s[0][0], i = -1;
76
76
  for (const [n, o] of t.entries())
77
- o > i && (i = o, s = n);
77
+ o > i && (i = o, e = n);
78
78
  const r = [];
79
79
  for (let n = 0; n < 3; n += 1)
80
80
  for (let o = 0; o < 3; o += 1)
81
- e[n][o] === s && r.push({ col: n, row: o });
81
+ s[n][o] === e && r.push({ col: n, row: o });
82
82
  return r;
83
83
  }
84
84
  function m() {
85
85
  return Array.from({ length: 3 }, () => Array.from({ length: 3 }, () => 0));
86
86
  }
87
- function R(e, t) {
88
- for (let s = 0; s < 3; s += 1)
87
+ function R(s, t) {
88
+ for (let e = 0; e < 3; e += 1)
89
89
  for (let i = 0; i < 3; i += 1)
90
- e[s][i] = t;
90
+ s[e][i] = t;
91
91
  }
92
92
  class Q {
93
93
  rafId = null;
@@ -113,159 +113,159 @@ class Q {
113
113
  this.rafId !== null && (this.rafId = requestAnimationFrame(this.tick));
114
114
  };
115
115
  }
116
- function Z(e) {
117
- const t = b(e, 0, 1);
116
+ function j(s) {
117
+ const t = b(s, 0, 1);
118
118
  return t * t * t * (t * (t * 6 - 15) + 10);
119
119
  }
120
- function y(e, t) {
121
- if (e.endMs <= e.startMs)
122
- return { value: e.to, t: 1, done: !0 };
123
- const s = b((t - e.startMs) / (e.endMs - e.startMs), 0, 1), i = Z(s);
120
+ function y(s, t) {
121
+ if (s.endMs <= s.startMs)
122
+ return { value: s.to, t: 1, done: !0 };
123
+ const e = b((t - s.startMs) / (s.endMs - s.startMs), 0, 1), i = j(e);
124
124
  return {
125
- value: e.from + (e.to - e.from) * i,
126
- t: s,
127
- done: s >= 1
125
+ value: s.from + (s.to - s.from) * i,
126
+ t: e,
127
+ done: e >= 1
128
128
  };
129
129
  }
130
- function j(e, t, s, i) {
130
+ function Z(s, t, e, i) {
131
131
  const r = [0, 0, 0];
132
132
  let n = 0;
133
133
  for (let o = 2; o >= 0; o -= 1) {
134
- if (e[o] === 0) {
134
+ if (s[o] === 0) {
135
135
  r[o] = 0;
136
136
  continue;
137
137
  }
138
138
  r[o] = n;
139
- const l = Math.floor(t * i);
140
- n += l + s;
139
+ const h = Math.floor(t * i);
140
+ n += h + e;
141
141
  }
142
142
  return r;
143
143
  }
144
- function T(e) {
145
- const s = e.height - e.boardY + e.cellH + 2, i = [
146
- s,
147
- s,
148
- s
144
+ function x(s) {
145
+ const e = s.height - s.boardY + s.cellH + 2, i = [
146
+ e,
147
+ e,
148
+ e
149
149
  ];
150
150
  return {
151
- columnStaggerMs: e.motionProfile.columnStaggerMs,
152
- fallMs: e.motionProfile.fallMs,
153
- incomingAlphaRampMs: e.motionProfile.incomingAlphaRampMs,
154
- outgoingDistance: s,
155
- incomingFromOffsets: [-e.cellH, -e.cellH * 2, -e.cellH * 3],
156
- rowStartDelays: j(
151
+ columnStaggerMs: s.motionProfile.columnStaggerMs,
152
+ fallMs: s.motionProfile.fallMs,
153
+ incomingAlphaRampMs: s.motionProfile.incomingAlphaRampMs,
154
+ outgoingDistance: e,
155
+ incomingFromOffsets: [-s.cellH, -s.cellH * 2, -s.cellH * 3],
156
+ rowStartDelays: Z(
157
157
  i,
158
- e.motionProfile.fallMs,
159
- e.motionProfile.outroRowGapMs,
160
- e.motionProfile.rowBaseSpacingRatio
158
+ s.motionProfile.fallMs,
159
+ s.motionProfile.outroRowGapMs,
160
+ s.motionProfile.rowBaseSpacingRatio
161
161
  ),
162
162
  // Делаем небольшое перекрытие фаз: новые символы начинают входить
163
163
  // немного раньше окончания исходящих, чтобы движение воспринималось
164
164
  // как непрерывный поток.
165
165
  incomingStartShift: Math.max(
166
166
  0,
167
- e.motionProfile.fallMs - e.motionProfile.outroOverlapMs
167
+ s.motionProfile.fallMs - s.motionProfile.outroOverlapMs
168
168
  )
169
169
  };
170
170
  }
171
- function U(e) {
172
- let t = !0, s = !0;
173
- for (let i = 0; i < e.scriptedOutgoingOffsets.length; i += 1) {
174
- const r = e.elapsedMs - i * e.motionPlan.columnStaggerMs;
171
+ function U(s) {
172
+ let t = !0, e = !0;
173
+ for (let i = 0; i < s.scriptedOutgoingOffsets.length; i += 1) {
174
+ const r = s.elapsedMs - i * s.motionPlan.columnStaggerMs;
175
175
  for (let n = 0; n < 3; n += 1) {
176
- const o = r - e.motionPlan.rowStartDelays[n];
176
+ const o = r - s.motionPlan.rowStartDelays[n];
177
177
  if (o <= 0) {
178
- e.scriptedOutgoingOffsets[i][n] = 0, e.scriptedIncomingOffsets[i][n] = e.motionPlan.incomingFromOffsets[n], e.scriptedIncomingAlpha[i][n] = 0, e.scriptedIncomingVisibility[i][n] = "hidden", t = !1, s = !1;
178
+ s.scriptedOutgoingOffsets[i][n] = 0, s.scriptedIncomingOffsets[i][n] = s.motionPlan.incomingFromOffsets[n], s.scriptedIncomingAlpha[i][n] = 0, s.scriptedIncomingVisibility[i][n] = "hidden", t = !1, e = !1;
179
179
  continue;
180
180
  }
181
- const l = y(
181
+ const h = y(
182
182
  {
183
183
  startMs: 0,
184
- endMs: e.motionPlan.fallMs,
184
+ endMs: s.motionPlan.fallMs,
185
185
  from: 0,
186
- to: e.motionPlan.outgoingDistance
186
+ to: s.motionPlan.outgoingDistance
187
187
  },
188
188
  o
189
189
  );
190
- e.scriptedOutgoingOffsets[i][n] = l.value, e.scriptedIncomingVisibility[i][n] = l.done ? "entering" : "exiting", l.done || (t = !1);
191
- const h = o - e.motionPlan.incomingStartShift;
192
- if (h <= 0) {
193
- e.scriptedIncomingOffsets[i][n] = e.motionPlan.incomingFromOffsets[n], e.scriptedIncomingAlpha[i][n] = 0, e.scriptedIncomingVisibility[i][n] = "hidden", s = !1;
190
+ s.scriptedOutgoingOffsets[i][n] = h.value, s.scriptedIncomingVisibility[i][n] = h.done ? "entering" : "exiting", h.done || (t = !1);
191
+ const l = o - s.motionPlan.incomingStartShift;
192
+ if (l <= 0) {
193
+ s.scriptedIncomingOffsets[i][n] = s.motionPlan.incomingFromOffsets[n], s.scriptedIncomingAlpha[i][n] = 0, s.scriptedIncomingVisibility[i][n] = "hidden", e = !1;
194
194
  continue;
195
195
  }
196
196
  const c = y(
197
197
  {
198
198
  startMs: 0,
199
- endMs: e.motionPlan.fallMs,
200
- from: e.motionPlan.incomingFromOffsets[n],
199
+ endMs: s.motionPlan.fallMs,
200
+ from: s.motionPlan.incomingFromOffsets[n],
201
201
  to: 0
202
202
  },
203
- h
203
+ l
204
204
  );
205
- e.scriptedIncomingOffsets[i][n] = c.value, e.scriptedIncomingAlpha[i][n] = b(
206
- h / Math.max(1, e.motionPlan.incomingAlphaRampMs),
205
+ s.scriptedIncomingOffsets[i][n] = c.value, s.scriptedIncomingAlpha[i][n] = b(
206
+ l / Math.max(1, s.motionPlan.incomingAlphaRampMs),
207
207
  0,
208
208
  1
209
- ), e.scriptedIncomingVisibility[i][n] = c.done ? "active" : "entering", c.done || (s = !1);
209
+ ), s.scriptedIncomingVisibility[i][n] = c.done ? "active" : "entering", c.done || (e = !1);
210
210
  }
211
211
  }
212
- return { allOutgoingDone: t, allIncomingDone: s };
212
+ return { allOutgoingDone: t, allIncomingDone: e };
213
213
  }
214
- function J(e) {
215
- return e ? [
216
- L(e[0]),
217
- L(e[1]),
218
- L(e[2])
214
+ function J(s) {
215
+ return s ? [
216
+ v(s[0]),
217
+ v(s[1]),
218
+ v(s[2])
219
219
  ] : z;
220
220
  }
221
- function tt(e) {
222
- return e === "rainbow" ? "rainbow" : "solid";
221
+ function tt(s) {
222
+ return s === "rainbow" ? "rainbow" : "solid";
223
223
  }
224
- function x(e) {
225
- if (e.length !== 3)
224
+ function W(s) {
225
+ if (s.length !== 3)
226
226
  throw new Error("rows must contain 3 rows");
227
227
  for (let t = 0; t < 3; t += 1)
228
- if (!Array.isArray(e[t]) || e[t].length !== 3)
228
+ if (!Array.isArray(s[t]) || s[t].length !== 3)
229
229
  throw new Error(`rows[${t}] must contain 3 columns`);
230
230
  return [
231
- [e[0][0], e[1][0], e[2][0]],
232
- [e[0][1], e[1][1], e[2][1]],
233
- [e[0][2], e[1][2], e[2][2]]
231
+ [s[0][0], s[1][0], s[2][0]],
232
+ [s[0][1], s[1][1], s[2][1]],
233
+ [s[0][2], s[1][2], s[2][2]]
234
234
  ];
235
235
  }
236
- function W(e, t) {
237
- if (e.length !== 3)
236
+ function T(s, t) {
237
+ if (s.length !== 3)
238
238
  throw new Error("stopGrid must contain 3 columns");
239
- const s = [];
239
+ const e = [];
240
240
  for (let i = 0; i < 3; i += 1) {
241
- const r = e[i];
241
+ const r = s[i];
242
242
  if (!Array.isArray(r) || r.length !== 3)
243
243
  throw new Error(`stopGrid[${i}] must contain 3 rows`);
244
- s[i] = [
244
+ e[i] = [
245
245
  C(r[0], t),
246
246
  C(r[1], t),
247
247
  C(r[2], t)
248
248
  ];
249
249
  }
250
- return s;
250
+ return e;
251
251
  }
252
- function it(e, t) {
253
- return W(x(e), t);
252
+ function it(s, t) {
253
+ return T(W(s), t);
254
254
  }
255
- function et(e) {
255
+ function et(s) {
256
256
  return {
257
- stopGrid: e.stopGrid?.map((t) => [...t]),
258
- stopRows: e.stopRows?.map((t) => [...t]),
259
- finaleSequence: e.finaleSequence?.map((t) => t.map((s) => [...s])),
260
- finaleSequenceRows: e.finaleSequenceRows?.map((t) => t.map((s) => [...s])),
261
- highlightWin: e.highlightWin,
262
- callback: e.callback
257
+ stopGrid: s.stopGrid?.map((t) => [...t]),
258
+ stopRows: s.stopRows?.map((t) => [...t]),
259
+ finaleSequence: s.finaleSequence?.map((t) => t.map((e) => [...e])),
260
+ finaleSequenceRows: s.finaleSequenceRows?.map((t) => t.map((e) => [...e])),
261
+ highlightWin: s.highlightWin,
262
+ callback: s.callback
263
263
  };
264
264
  }
265
265
  class st {
266
266
  queue;
267
267
  constructor(t) {
268
- this.queue = (t ?? []).map((s) => et(s));
268
+ this.queue = (t ?? []).map((e) => et(e));
269
269
  }
270
270
  hasPending() {
271
271
  return this.queue.length > 0;
@@ -289,19 +289,19 @@ function nt() {
289
289
  winEffectsEnvelope: 1
290
290
  };
291
291
  }
292
- function rt(e, t) {
293
- e.hasStartedFirstSpin = !0, e.isSpinning = !0, e.phase = "outro", e.outroStartedAt = t.startedAt, e.activeSpinState = t.activeSpinState, e.shouldHighlightCurrentSpin = t.shouldHighlightCurrentSpin;
292
+ function rt(s, t) {
293
+ s.hasStartedFirstSpin = !0, s.isSpinning = !0, s.phase = "outro", s.outroStartedAt = t.startedAt, s.activeSpinState = t.activeSpinState, s.shouldHighlightCurrentSpin = t.shouldHighlightCurrentSpin;
294
294
  }
295
- function ot(e, t, s) {
296
- e.phase = "idle", e.idleStartedAt = s, e.isSpinning = !1, e.shouldHighlightCurrentSpin = !1, e.queueFinished = !t, e.activeSpinState = null;
295
+ function ot(s, t, e) {
296
+ s.phase = "idle", s.idleStartedAt = e, s.isSpinning = !1, s.shouldHighlightCurrentSpin = !1, s.queueFinished = !t, s.activeSpinState = null;
297
297
  }
298
- function N(e, t) {
299
- e.winFlashStartedAt = t, e.phase = "winFlash";
298
+ function N(s, t) {
299
+ s.winFlashStartedAt = t, s.phase = "winFlash";
300
300
  }
301
- function lt(e) {
302
- e.isSpinning = !1, e.queueFinished = !0;
301
+ function ht(s) {
302
+ s.isSpinning = !1, s.queueFinished = !0;
303
303
  }
304
- const ht = `
304
+ const lt = `
305
305
  attribute vec2 a_pos;
306
306
  uniform vec2 u_resolution;
307
307
  uniform vec4 u_destRect;
@@ -370,14 +370,14 @@ class ct {
370
370
  spriteSegmentHeight;
371
371
  constructor(t) {
372
372
  this.canvas = t.canvas, this.spriteImage = t.spriteImage, this.spriteElementsCount = Math.max(1, t.spriteElementsCount), this.spriteWidth = this.spriteImage.width, this.spriteHeight = this.spriteImage.height, this.spriteSegmentHeight = this.spriteHeight / this.spriteElementsCount;
373
- const s = this.canvas.getContext("webgl2", {
373
+ const e = this.canvas.getContext("webgl2", {
374
374
  alpha: !0,
375
375
  antialias: !1
376
376
  }) ?? this.canvas.getContext("webgl", { alpha: !0, antialias: !1 });
377
- if (!s)
377
+ if (!e)
378
378
  throw new Error("WebGL context is not available");
379
- this.gl = s;
380
- const i = this.createShader(this.gl.VERTEX_SHADER, ht), r = this.createShader(this.gl.FRAGMENT_SHADER, at);
379
+ this.gl = e;
380
+ const i = this.createShader(this.gl.VERTEX_SHADER, lt), r = this.createShader(this.gl.FRAGMENT_SHADER, at);
381
381
  this.program = this.createProgram(i, r), this.gl.deleteShader(i), this.gl.deleteShader(r);
382
382
  const n = this.gl.createBuffer();
383
383
  if (!n)
@@ -398,8 +398,8 @@ class ct {
398
398
  this.gl.UNSIGNED_BYTE,
399
399
  this.spriteImage
400
400
  ), this.gl.pixelStorei(this.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE), this.gl.useProgram(this.program);
401
- const l = this.gl.getAttribLocation(this.program, "a_pos");
402
- this.gl.enableVertexAttribArray(l), this.gl.vertexAttribPointer(l, 2, this.gl.FLOAT, !1, 8, 0), this.uniforms = {
401
+ const h = this.gl.getAttribLocation(this.program, "a_pos");
402
+ this.gl.enableVertexAttribArray(h), this.gl.vertexAttribPointer(h, 2, this.gl.FLOAT, !1, 8, 0), this.uniforms = {
403
403
  resolution: this.gl.getUniformLocation(this.program, "u_resolution"),
404
404
  destRect: this.gl.getUniformLocation(this.program, "u_destRect"),
405
405
  srcRect: this.gl.getUniformLocation(this.program, "u_srcRect"),
@@ -409,25 +409,25 @@ class ct {
409
409
  texture: this.gl.getUniformLocation(this.program, "u_texture")
410
410
  }, this.gl.uniform1i(this.uniforms.texture, 0), this.gl.clearColor(0, 0, 0, 0), this.gl.enable(this.gl.BLEND), this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
411
411
  }
412
- resize(t, s) {
413
- this.viewportW = Math.max(1, Math.floor(t)), this.viewportH = Math.max(1, Math.floor(s)), this.gl.viewport(0, 0, this.viewportW, this.viewportH);
412
+ resize(t, e) {
413
+ this.viewportW = Math.max(1, Math.floor(t)), this.viewportH = Math.max(1, Math.floor(e)), this.gl.viewport(0, 0, this.viewportW, this.viewportH);
414
414
  }
415
415
  beginFrame() {
416
416
  this.gl.useProgram(this.program), this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer), this.gl.activeTexture(this.gl.TEXTURE0), this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture), this.gl.uniform2f(this.uniforms.resolution, this.viewportW, this.viewportH), this.gl.uniform1f(this.uniforms.shapeMode, 0), this.gl.clear(this.gl.COLOR_BUFFER_BIT);
417
417
  }
418
- drawSprite(t, s, i, r, n, o = 1) {
419
- const h = C(t, this.spriteElementsCount) * this.spriteSegmentHeight, c = h + this.spriteSegmentHeight, a = 0.5, d = a / this.spriteWidth, g = 1 - a / this.spriteWidth, f = 1 - (c - a) / this.spriteHeight, S = 1 - (h + a) / this.spriteHeight;
420
- this.gl.uniform4f(this.uniforms.destRect, s, i, r, n), this.gl.uniform4f(this.uniforms.srcRect, d, f, g, S), this.gl.uniform4f(this.uniforms.color, 1, 1, 1, o), this.gl.uniform1f(this.uniforms.shapeMode, 0), this.gl.uniform1f(this.uniforms.useTexture, 1), this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
418
+ drawSprite(t, e, i, r, n, o = 1) {
419
+ const l = C(t, this.spriteElementsCount) * this.spriteSegmentHeight, c = l + this.spriteSegmentHeight, a = 0.5, d = a / this.spriteWidth, f = 1 - a / this.spriteWidth, g = 1 - (c - a) / this.spriteHeight, S = 1 - (l + a) / this.spriteHeight;
420
+ this.gl.uniform4f(this.uniforms.destRect, e, i, r, n), this.gl.uniform4f(this.uniforms.srcRect, d, g, f, S), this.gl.uniform4f(this.uniforms.color, 1, 1, 1, o), this.gl.uniform1f(this.uniforms.shapeMode, 0), this.gl.uniform1f(this.uniforms.useTexture, 1), this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
421
421
  }
422
- drawSolidRect(t, s, i, r, n) {
423
- this.gl.uniform4f(this.uniforms.destRect, t, s, i, r), this.gl.uniform4f(this.uniforms.srcRect, 0, 0, 1, 1), this.gl.uniform4f(this.uniforms.color, n[0], n[1], n[2], n[3]), this.gl.uniform1f(this.uniforms.shapeMode, 0), this.gl.uniform1f(this.uniforms.useTexture, 0), this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
422
+ drawSolidRect(t, e, i, r, n) {
423
+ this.gl.uniform4f(this.uniforms.destRect, t, e, i, r), this.gl.uniform4f(this.uniforms.srcRect, 0, 0, 1, 1), this.gl.uniform4f(this.uniforms.color, n[0], n[1], n[2], n[3]), this.gl.uniform1f(this.uniforms.shapeMode, 0), this.gl.uniform1f(this.uniforms.useTexture, 0), this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
424
424
  }
425
- drawSoftCircle(t, s, i, r) {
425
+ drawSoftCircle(t, e, i, r) {
426
426
  const n = i * 2;
427
427
  this.gl.uniform4f(
428
428
  this.uniforms.destRect,
429
429
  t - i,
430
- s - i,
430
+ e - i,
431
431
  n,
432
432
  n
433
433
  ), this.gl.uniform4f(this.uniforms.srcRect, 0, 0, 1, 1), this.gl.uniform4f(this.uniforms.color, r[0], r[1], r[2], r[3]), this.gl.uniform1f(this.uniforms.useTexture, 0), this.gl.uniform1f(this.uniforms.shapeMode, 1), this.gl.drawArrays(this.gl.TRIANGLES, 0, 6), this.gl.uniform1f(this.uniforms.shapeMode, 0);
@@ -441,21 +441,21 @@ class ct {
441
441
  dispose() {
442
442
  this.gl.deleteTexture(this.texture), this.gl.deleteBuffer(this.quadBuffer), this.gl.deleteProgram(this.program);
443
443
  }
444
- createShader(t, s) {
444
+ createShader(t, e) {
445
445
  const i = this.gl.createShader(t);
446
446
  if (!i)
447
447
  throw new Error("Failed to create WebGL shader");
448
- if (this.gl.shaderSource(i, s), this.gl.compileShader(i), !this.gl.getShaderParameter(i, this.gl.COMPILE_STATUS)) {
448
+ if (this.gl.shaderSource(i, e), this.gl.compileShader(i), !this.gl.getShaderParameter(i, this.gl.COMPILE_STATUS)) {
449
449
  const r = this.gl.getShaderInfoLog(i) ?? "unknown error";
450
450
  throw this.gl.deleteShader(i), new Error(`WebGL shader compile failed: ${r}`);
451
451
  }
452
452
  return i;
453
453
  }
454
- createProgram(t, s) {
454
+ createProgram(t, e) {
455
455
  const i = this.gl.createProgram();
456
456
  if (!i)
457
457
  throw new Error("Failed to create WebGL program");
458
- if (this.gl.attachShader(i, t), this.gl.attachShader(i, s), this.gl.linkProgram(i), !this.gl.getProgramParameter(i, this.gl.LINK_STATUS)) {
458
+ if (this.gl.attachShader(i, t), this.gl.attachShader(i, e), this.gl.linkProgram(i), !this.gl.getProgramParameter(i, this.gl.LINK_STATUS)) {
459
459
  const r = this.gl.getProgramInfoLog(i) ?? "unknown error";
460
460
  throw this.gl.deleteProgram(i), new Error(`WebGL program link failed: ${r}`);
461
461
  }
@@ -478,6 +478,7 @@ class u {
478
478
  particleColorMode;
479
479
  motionProfile;
480
480
  pixelSnapY;
481
+ debugPerf;
481
482
  spriteImage = null;
482
483
  webglRenderer = null;
483
484
  rafLoop = new Q();
@@ -513,6 +514,14 @@ class u {
513
514
  outroInterpolationAlpha = 1;
514
515
  isOutroPipelineWarmedUp = !1;
515
516
  isGpuPipelineWarmedUp = !1;
517
+ perfWindowStartedAt = 0;
518
+ perfFrameCount = 0;
519
+ perfDtSum = 0;
520
+ perfOver20MsCount = 0;
521
+ perfDtSamples = [];
522
+ perfLogLines = [];
523
+ static PERF_WINDOW_MS = 1500;
524
+ static PERF_LOG_LIMIT = 60;
516
525
  static PRE_SPIN_MS = 150;
517
526
  static WIN_EFFECTS_ENVELOPE_TAU_MS = 120;
518
527
  static MAX_FRAME_DELTA_MS = 250;
@@ -523,7 +532,7 @@ class u {
523
532
  this.canvas = t.canvas, this.container = t.container, this.button = t.button, this.spriteUrl = t.sprite, this.spriteElementsCount = Math.max(
524
533
  1,
525
534
  t.spriteElementsCount ?? 6
526
- ), this.highlightInitialWinningCells = t.highlightInitialWinningCells !== !1, this.spinQueueController = new st(t.queuedSpinStates), this.particleColorRgb = J(t.particleColorRgb), this.particleColorMode = tt(t.particleColorMode), this.motionProfile = V(t.motionProfile ?? Y), this.pixelSnapY = t.pixelSnapY ?? this.motionProfile.pixelSnapY, this.grid = t.initialSegments ? it(t.initialSegments, this.spriteElementsCount) : F(this.spriteElementsCount);
535
+ ), this.highlightInitialWinningCells = t.highlightInitialWinningCells !== !1, this.spinQueueController = new st(t.queuedSpinStates), this.particleColorRgb = J(t.particleColorRgb), this.particleColorMode = tt(t.particleColorMode), this.motionProfile = V(t.motionProfile ?? Y), this.pixelSnapY = t.pixelSnapY ?? this.motionProfile.pixelSnapY, this.debugPerf = t.debugPerf === !0, this.grid = t.initialSegments ? it(t.initialSegments, this.spriteElementsCount) : F(this.spriteElementsCount);
527
536
  }
528
537
  async init() {
529
538
  if (this.bindEvents(), this.resize(), await this.loadSpriteIfProvided(), !this.spriteImage)
@@ -537,7 +546,24 @@ class u {
537
546
  });
538
547
  }
539
548
  destroy() {
540
- this.unbindEvents(), this.rafLoop.stop(), this.simulationLastNow = 0, this.simulationAccumulatorMs = 0, lt(this.runtime), this.webglRenderer?.dispose(), this.webglRenderer = null, this.clearWinningCells();
549
+ this.unbindEvents(), this.rafLoop.stop(), this.simulationLastNow = 0, this.simulationAccumulatorMs = 0, ht(this.runtime), this.webglRenderer?.dispose(), this.webglRenderer = null, this.clearWinningCells();
550
+ }
551
+ getPerfLogs() {
552
+ return [...this.perfLogLines];
553
+ }
554
+ clearPerfLogs() {
555
+ this.perfLogLines.length = 0;
556
+ }
557
+ async copyPerfLogsToClipboard() {
558
+ if (this.perfLogLines.length === 0) return !1;
559
+ const t = this.perfLogLines.join(`
560
+ `), e = navigator.clipboard;
561
+ if (e && typeof e.writeText == "function")
562
+ return await e.writeText(t), !0;
563
+ const i = document.createElement("textarea");
564
+ i.value = t, i.setAttribute("readonly", ""), i.style.position = "fixed", i.style.left = "-9999px", document.body.appendChild(i), i.select();
565
+ const r = document.execCommand("copy");
566
+ return document.body.removeChild(i), r;
541
567
  }
542
568
  spin() {
543
569
  if (this.runtime.isSpinning || this.runtime.queueFinished) return;
@@ -545,8 +571,8 @@ class u {
545
571
  this.runtime.queueFinished = !0, this.button && (this.button.disabled = !0);
546
572
  return;
547
573
  }
548
- const t = this.spinQueueController.consume(), s = t?.highlightWin === !0;
549
- this.runtime.isSpinning = !0, this.runtime.phase = "preSpin", this.runtime.preSpinStartedAt = performance.now(), this.runtime.activeSpinState = t, this.runtime.shouldHighlightCurrentSpin = s, this.runtime.hasStartedFirstSpin = !0, this.simulationLastNow = 0, this.simulationAccumulatorMs = 0, this.button && (this.button.disabled = !0), this.startLoop();
574
+ const t = this.spinQueueController.consume(), e = t?.highlightWin === !0;
575
+ this.runtime.isSpinning = !0, this.runtime.phase = "preSpin", this.runtime.preSpinStartedAt = performance.now(), this.runtime.activeSpinState = t, this.runtime.shouldHighlightCurrentSpin = e, this.runtime.hasStartedFirstSpin = !0, this.simulationLastNow = 0, this.simulationAccumulatorMs = 0, this.button && (this.button.disabled = !0), this.startLoop();
550
576
  }
551
577
  bindEvents() {
552
578
  window.addEventListener("resize", this.resize), this.button?.addEventListener("click", this.onSpinClick);
@@ -562,7 +588,7 @@ class u {
562
588
  this.runtime.isSpinning || this.spin();
563
589
  };
564
590
  getNextGrid(t) {
565
- return t ? W(t, this.spriteElementsCount) : F(this.spriteElementsCount);
591
+ return t ? T(t, this.spriteElementsCount) : F(this.spriteElementsCount);
566
592
  }
567
593
  update(t) {
568
594
  if (this.runtime.isSpinning) {
@@ -574,9 +600,9 @@ class u {
574
600
  shouldHighlightCurrentSpin: this.runtime.shouldHighlightCurrentSpin,
575
601
  startedAt: t
576
602
  }), this.runtime.preSpinStartedAt = 0;
577
- const s = this.runtime.activeSpinState?.finaleSequenceRows ? this.runtime.activeSpinState.finaleSequenceRows.map((n) => x(n)) : this.runtime.activeSpinState?.finaleSequence ?? [];
578
- this.scriptedCascadeQueue = s.map((n) => n.map((o) => [...o])), this.clearWinningCells();
579
- const i = this.runtime.activeSpinState?.stopRows ? x(this.runtime.activeSpinState.stopRows) : this.runtime.activeSpinState?.stopGrid, r = this.getNextGrid(i);
603
+ const e = this.runtime.activeSpinState?.finaleSequenceRows ? this.runtime.activeSpinState.finaleSequenceRows.map((n) => W(n)) : this.runtime.activeSpinState?.finaleSequence ?? [];
604
+ this.scriptedCascadeQueue = e.map((n) => n.map((o) => [...o])), this.clearWinningCells();
605
+ const i = this.runtime.activeSpinState?.stopRows ? W(this.runtime.activeSpinState.stopRows) : this.runtime.activeSpinState?.stopGrid, r = this.getNextGrid(i);
580
606
  this.startOutroTransition(r, t);
581
607
  }
582
608
  if (this.runtime.phase !== "outro" && this.runtime.phase === "winFlash") {
@@ -590,13 +616,13 @@ class u {
590
616
  this.finishSpinWithUi();
591
617
  return;
592
618
  }
593
- this.outroMotionPlan || (this.outroMotionPlan = T({
619
+ this.outroMotionPlan || (this.outroMotionPlan = x({
594
620
  height: this.height,
595
621
  boardY: this.boardY,
596
622
  cellH: this.cellH,
597
623
  motionProfile: this.motionProfile
598
624
  })), this.scriptedOutroElapsedMs += t;
599
- const { allOutgoingDone: s, allIncomingDone: i } = U({
625
+ const { allOutgoingDone: e, allIncomingDone: i } = U({
600
626
  elapsedMs: this.scriptedOutroElapsedMs,
601
627
  scriptedOutgoingOffsets: this.scriptedOutgoingOffsets,
602
628
  scriptedIncomingOffsets: this.scriptedIncomingOffsets,
@@ -604,7 +630,7 @@ class u {
604
630
  scriptedIncomingVisibility: this.scriptedIncomingVisibility,
605
631
  motionPlan: this.outroMotionPlan
606
632
  });
607
- if (!(!s || !i) && (this.grid = this.scriptedPendingGrid, this.scriptedOutgoingGrid = null, this.scriptedPendingGrid = null, this.outroMotionPlan = null, this.clearWinningCells(), this.resetOutroBuffers(1, "active"), !this.tryStartScriptedCascade(this.scriptedOutroStartedAt + this.scriptedOutroElapsedMs))) {
633
+ if (!(!e || !i) && (this.grid = this.scriptedPendingGrid, this.scriptedOutgoingGrid = null, this.scriptedPendingGrid = null, this.outroMotionPlan = null, this.clearWinningCells(), this.resetOutroBuffers(1, "active"), !this.tryStartScriptedCascade(this.scriptedOutroStartedAt + this.scriptedOutroElapsedMs))) {
608
634
  if (!this.runtime.shouldHighlightCurrentSpin) {
609
635
  this.finishSpinWithUi();
610
636
  return;
@@ -614,20 +640,20 @@ class u {
614
640
  }
615
641
  tryStartScriptedCascade(t) {
616
642
  if (this.scriptedCascadeQueue.length === 0) return !1;
617
- const s = this.scriptedCascadeQueue.shift();
618
- return s ? (this.startOutroTransition(W(s, this.spriteElementsCount), t), !0) : !1;
643
+ const e = this.scriptedCascadeQueue.shift();
644
+ return e ? (this.startOutroTransition(T(e, this.spriteElementsCount), t), !0) : !1;
619
645
  }
620
- startOutroTransition(t, s) {
621
- this.scriptedOutgoingGrid = this.grid.map((i) => [...i]), this.scriptedPendingGrid = t.map((i) => [...i]), this.outroMotionPlan = T({
646
+ startOutroTransition(t, e) {
647
+ this.scriptedOutgoingGrid = this.grid.map((i) => [...i]), this.scriptedPendingGrid = t.map((i) => [...i]), this.outroMotionPlan = x({
622
648
  height: this.height,
623
649
  boardY: this.boardY,
624
650
  cellH: this.cellH,
625
651
  motionProfile: this.motionProfile
626
- }), this.resetOutroBuffers(0, "hidden"), this.clearWinningCells(), this.runtime.phase = "outro", this.scriptedOutroStartedAt = s, this.scriptedOutroElapsedMs = 0, this.outroInterpolationAlpha = 1;
652
+ }), this.resetOutroBuffers(0, "hidden"), this.clearWinningCells(), this.runtime.phase = "outro", this.scriptedOutroStartedAt = e, this.scriptedOutroElapsedMs = 0, this.outroInterpolationAlpha = 1;
627
653
  }
628
654
  /** @param skipCallback true при закрытии подсветки по клику (callback уже вызван по окончании прокрутки) */
629
655
  finishSpinWithUi(t = !1) {
630
- const s = this.runtime.activeSpinState, i = t ? void 0 : s?.callback, r = this.spinQueueController.hasPending();
656
+ const e = this.runtime.activeSpinState, i = t ? void 0 : e?.callback, r = this.spinQueueController.hasPending();
631
657
  ot(this.runtime, r, performance.now()), this.button && (this.button.disabled = this.runtime.queueFinished), i?.();
632
658
  }
633
659
  applyInitialHighlightIfNeeded() {
@@ -635,21 +661,21 @@ class u {
635
661
  }
636
662
  warmUpOutroPipeline() {
637
663
  if (this.isOutroPipelineWarmedUp) return;
638
- const t = T({
664
+ const t = x({
639
665
  height: this.height,
640
666
  boardY: this.boardY,
641
667
  cellH: this.cellH,
642
668
  motionProfile: this.motionProfile
643
- }), s = m(), i = m(), r = m(), n = u.createVisibilityGrid("hidden"), o = Math.max(...t.rowStartDelays), l = 2 * t.columnStaggerMs, h = [
669
+ }), e = m(), i = m(), r = m(), n = u.createVisibilityGrid("hidden"), o = Math.max(...t.rowStartDelays), h = 2 * t.columnStaggerMs, l = [
644
670
  0,
645
671
  this.motionProfile.fixedStepMs,
646
672
  t.incomingStartShift + this.motionProfile.fixedStepMs,
647
- t.fallMs + o + l + this.motionProfile.fixedStepMs
673
+ t.fallMs + o + h + this.motionProfile.fixedStepMs
648
674
  ];
649
- for (const c of h)
675
+ for (const c of l)
650
676
  U({
651
677
  elapsedMs: c,
652
- scriptedOutgoingOffsets: s,
678
+ scriptedOutgoingOffsets: e,
653
679
  scriptedIncomingOffsets: i,
654
680
  scriptedIncomingAlpha: r,
655
681
  scriptedIncomingVisibility: n,
@@ -661,22 +687,42 @@ class u {
661
687
  if (this.isGpuPipelineWarmedUp) return;
662
688
  const t = this.webglRenderer;
663
689
  if (!t) return;
664
- const s = Math.max(8, this.cellW * 0.2), i = Math.max(8, this.cellH * 0.2), r = this.boardX + 2, n = this.boardY + 2;
665
- t.beginFrame(), t.drawSprite(0, r, n, s, i, 1), t.drawSolidRect(r + s + 2, n, s, i, [1, 1, 1, 0.35]), t.beginAdditiveBlend(), t.drawSoftCircle(
666
- r + s * 0.5,
690
+ const e = Math.max(8, this.cellW * 0.2), i = Math.max(8, this.cellH * 0.2), r = this.boardX + 2, n = this.boardY + 2;
691
+ t.beginFrame(), t.drawSprite(0, r, n, e, i, 1), t.drawSolidRect(r + e + 2, n, e, i, [1, 1, 1, 0.35]), t.beginAdditiveBlend(), t.drawSoftCircle(
692
+ r + e * 0.5,
667
693
  n + i * 0.5,
668
- Math.max(2, s * 0.25),
694
+ Math.max(2, e * 0.25),
669
695
  [1, 0.9, 0.4, 0.4]
670
696
  ), t.endAdditiveBlend(), this.isGpuPipelineWarmedUp = !0;
671
697
  }
698
+ trackOutroPerf(t, e) {
699
+ if (this.debugPerf) {
700
+ if (this.runtime.phase !== "outro") {
701
+ this.resetPerfWindow();
702
+ return;
703
+ }
704
+ this.perfWindowStartedAt <= 0 && (this.perfWindowStartedAt = e), this.perfFrameCount += 1, this.perfDtSum += t, t > 20 && (this.perfOver20MsCount += 1), this.perfDtSamples.push(t), !(e - this.perfWindowStartedAt < u.PERF_WINDOW_MS) && (this.flushPerfWindow(), this.perfWindowStartedAt = e);
705
+ }
706
+ }
707
+ resetPerfWindow() {
708
+ this.perfWindowStartedAt = 0, this.perfFrameCount = 0, this.perfDtSum = 0, this.perfOver20MsCount = 0, this.perfDtSamples.length = 0;
709
+ }
710
+ flushPerfWindow() {
711
+ if (this.perfFrameCount === 0) return;
712
+ const t = this.perfDtSum / this.perfFrameCount, e = [...this.perfDtSamples].sort((l, c) => l - c), i = Math.max(0, Math.min(e.length - 1, Math.floor(e.length * 0.95))), r = e[i], n = e[e.length - 1], o = t > 0 ? 1e3 / t : 0, h = `[CascadingReel][outro perf] avg=${t.toFixed(2)}ms p95=${r.toFixed(2)}ms max=${n.toFixed(2)}ms fps=${o.toFixed(1)} slow>20ms=${this.perfOver20MsCount}/${this.perfFrameCount}`;
713
+ this.perfLogLines.push(h), this.perfLogLines.length > u.PERF_LOG_LIMIT && this.perfLogLines.splice(0, this.perfLogLines.length - u.PERF_LOG_LIMIT), console.log(h), this.perfFrameCount = 0, this.perfDtSum = 0, this.perfOver20MsCount = 0, this.perfDtSamples.length = 0;
714
+ }
672
715
  render(t) {
673
716
  if (!this.webglRenderer) return;
674
717
  this.initialHighlightRequestedAt > 0 && t - this.initialHighlightRequestedAt >= $ && (N(this.runtime, this.initialHighlightRequestedAt), this.runtime.winEffectsEnvelope = 1, this.initialHighlightRequestedAt = 0, this.button && (this.button.disabled = !1));
675
- const s = this.runtime.phase === "preSpin" ? 0 : this.runtime.phase === "winFlash" ? 1 : 0;
718
+ const e = this.runtime.phase === "preSpin" ? 0 : this.runtime.phase === "winFlash" ? 1 : 0;
676
719
  if (this.lastRafTime > 0) {
677
- const l = Math.min(t - this.lastRafTime, 50), h = 1 - Math.exp(-l / u.WIN_EFFECTS_ENVELOPE_TAU_MS);
678
- this.runtime.winEffectsEnvelope += (s - this.runtime.winEffectsEnvelope) * h;
679
- }
720
+ const h = Math.min(t - this.lastRafTime, 50);
721
+ this.trackOutroPerf(h, t);
722
+ const l = 1 - Math.exp(-h / u.WIN_EFFECTS_ENVELOPE_TAU_MS);
723
+ this.runtime.winEffectsEnvelope += (e - this.runtime.winEffectsEnvelope) * l;
724
+ } else
725
+ this.resetPerfWindow();
680
726
  this.lastRafTime = t, this.webglRenderer.beginFrame();
681
727
  const i = this.runtime.phase === "winFlash" || this.runtime.phase === "preSpin" || this.initialHighlightRequestedAt > 0 && this.winningCells.length > 0;
682
728
  this.runtime.phase === "outro" && this.scriptedOutgoingGrid && this.scriptedPendingGrid ? (this.drawGridInterpolated(
@@ -703,53 +749,53 @@ class u {
703
749
  winEffectsEnvelope: o
704
750
  });
705
751
  }
706
- isWinningCell = (t, s) => this.winningCellKeys.has(`${t}:${s}`);
752
+ isWinningCell = (t, e) => this.winningCellKeys.has(`${t}:${e}`);
707
753
  getRowCompactOffset(t) {
708
754
  return (q[t] ?? 0) * this.cellH;
709
755
  }
710
756
  applyPixelSnapY(t) {
711
757
  return this.pixelSnapY === "integer" ? Math.round(t) : this.pixelSnapY === "half" ? Math.round(t * 2) / 2 : t;
712
758
  }
713
- drawGrid(t, s, i) {
759
+ drawGrid(t, e, i) {
714
760
  this.drawGridWithSampler({
715
761
  grid: t,
716
762
  skipWinningCells: i,
717
- sampleOffsetY: (r, n) => s ? s[r][n] : 0,
763
+ sampleOffsetY: (r, n) => e ? e[r][n] : 0,
718
764
  sampleAlpha: () => 1,
719
765
  isVisible: () => !0
720
766
  });
721
767
  }
722
- drawGridInterpolated(t, s, i, r, n, o, l, h) {
768
+ drawGridInterpolated(t, e, i, r, n, o, h, l) {
723
769
  this.drawGridWithSampler({
724
770
  grid: t,
725
771
  skipWinningCells: n,
726
- sampleOffsetY: (c, a) => s[c][a] + (i[c][a] - s[c][a]) * r,
727
- sampleAlpha: (c, a) => o && l ? o[c][a] + (l[c][a] - o[c][a]) * r : 1,
728
- isVisible: (c, a) => !h || h[c][a] !== "hidden"
772
+ sampleOffsetY: (c, a) => e[c][a] + (i[c][a] - e[c][a]) * r,
773
+ sampleAlpha: (c, a) => o && h ? o[c][a] + (h[c][a] - o[c][a]) * r : 1,
774
+ isVisible: (c, a) => !l || l[c][a] !== "hidden"
729
775
  });
730
776
  }
731
777
  drawGridWithSampler(t) {
732
- const s = this.webglRenderer;
733
- if (s)
778
+ const e = this.webglRenderer;
779
+ if (e)
734
780
  for (let i = 0; i < 3; i += 1) {
735
781
  const r = this.boardX + i * this.cellW;
736
782
  for (let n = 0; n < 3; n += 1) {
737
783
  if (t.skipWinningCells && this.isWinningCell(i, n) || !t.isVisible(i, n)) continue;
738
- const o = t.sampleOffsetY(i, n), l = this.applyPixelSnapY(
784
+ const o = t.sampleOffsetY(i, n), h = this.applyPixelSnapY(
739
785
  this.boardY + n * this.cellH + o + this.getRowCompactOffset(n)
740
786
  );
741
- if (l > this.height || l + this.cellH < 0) continue;
742
- const h = t.sampleAlpha(i, n);
743
- h <= 0 || s.drawSprite(t.grid[i][n], r, l, this.cellW, this.cellH, h);
787
+ if (h > this.height || h + this.cellH < 0) continue;
788
+ const l = t.sampleAlpha(i, n);
789
+ l <= 0 || e.drawSprite(t.grid[i][n], r, h, this.cellW, this.cellH, l);
744
790
  }
745
791
  }
746
792
  }
747
793
  drawWinningEffects(t) {
748
- const s = this.webglRenderer;
749
- if (!s || this.winningCells.length === 0 || t.phase !== "winFlash" && t.phase !== "preSpin") return;
750
- const i = Math.max(0, Math.min(1, t.winEffectsEnvelope)), r = Math.max(0, t.now - t.winFlashStartedAt), n = r % G / G, o = 1 + Math.sin(n * Math.PI * 2) * k * i, l = Math.max(1, this.cellW * u.WIN_BORDER_INSET_RATIO), h = Math.max(1, this.cellW * 0.03), c = this.runtime.phase === "winFlash" && this.runtime.shouldHighlightCurrentSpin && this.runtime.hasStartedFirstSpin;
794
+ const e = this.webglRenderer;
795
+ if (!e || this.winningCells.length === 0 || t.phase !== "winFlash" && t.phase !== "preSpin") return;
796
+ const i = Math.max(0, Math.min(1, t.winEffectsEnvelope)), r = Math.max(0, t.now - t.winFlashStartedAt), n = r % G / G, o = 1 + Math.sin(n * Math.PI * 2) * k * i, h = Math.max(1, this.cellW * u.WIN_BORDER_INSET_RATIO), l = Math.max(1, this.cellW * 0.03), c = this.runtime.phase === "winFlash" && this.runtime.shouldHighlightCurrentSpin && this.runtime.hasStartedFirstSpin;
751
797
  for (const a of this.winningCells) {
752
- const d = this.boardX + a.col * this.cellW, g = this.boardY + a.row * this.cellH + this.getRowCompactOffset(a.row), f = this.grid[a.col][a.row], S = u.WIN_BORDER_ALPHA * i, p = this.particleColorMode === "rainbow" ? u.hslToRgb01(
798
+ const d = this.boardX + a.col * this.cellW, f = this.boardY + a.row * this.cellH + this.getRowCompactOffset(a.row), g = this.grid[a.col][a.row], S = u.WIN_BORDER_ALPHA * i, p = this.particleColorMode === "rainbow" ? u.hslToRgb01(
753
799
  (r * 0.2 + a.col * 36 + a.row * 22) % 360,
754
800
  0.96,
755
801
  0.64
@@ -757,90 +803,90 @@ class u {
757
803
  this.particleColorRgb[0] / 255,
758
804
  this.particleColorRgb[1] / 255,
759
805
  this.particleColorRgb[2] / 255
760
- ], E = this.cellW * o, A = this.cellH * o, w = (this.cellW - E) * 0.5, B = (this.cellH - A) * 0.5;
761
- s.drawSprite(f, d + w, g + B, E, A, 1);
762
- const M = d + l, _ = g + l, O = this.cellW - l * 2, P = this.cellH - l * 2;
763
- O <= h * 2 || P <= h * 2 || (s.drawSolidRect(M, _, O, h, [
806
+ ], A = this.cellW * o, w = this.cellH * o, M = (this.cellW - A) * 0.5, B = (this.cellH - w) * 0.5;
807
+ e.drawSprite(g, d + M, f + B, A, w, 1);
808
+ const O = d + h, E = f + h, _ = this.cellW - h * 2, P = this.cellH - h * 2;
809
+ _ <= l * 2 || P <= l * 2 || (e.drawSolidRect(O, E, _, l, [
764
810
  p[0],
765
811
  p[1],
766
812
  p[2],
767
813
  S
768
- ]), s.drawSolidRect(M, _ + P - h, O, h, [
814
+ ]), e.drawSolidRect(O, E + P - l, _, l, [
769
815
  p[0],
770
816
  p[1],
771
817
  p[2],
772
818
  S
773
- ]), s.drawSolidRect(M, _, h, P, [
819
+ ]), e.drawSolidRect(O, E, l, P, [
774
820
  p[0],
775
821
  p[1],
776
822
  p[2],
777
823
  S
778
- ]), s.drawSolidRect(M + O - h, _, h, P, [
824
+ ]), e.drawSolidRect(O + _ - l, E, l, P, [
779
825
  p[0],
780
826
  p[1],
781
827
  p[2],
782
828
  S
783
829
  ]), c && this.drawCellParticleBurst({
784
- renderer: s,
830
+ renderer: e,
785
831
  cell: a,
786
832
  centerX: d + this.cellW * 0.5,
787
- centerY: g + this.cellH * 0.5,
833
+ centerY: f + this.cellH * 0.5,
788
834
  elapsed: r,
789
835
  envelope: i
790
836
  }));
791
837
  }
792
838
  }
793
839
  drawCellParticleBurst(t) {
794
- const s = Math.min(this.cellW, this.cellH) * u.PARTICLE_MAX_DISTANCE, i = Math.min(this.cellW, this.cellH) * u.PARTICLE_BASE_RADIUS, r = u.getParticleSeeds(t.cell.col, t.cell.row), n = [
840
+ const e = Math.min(this.cellW, this.cellH) * u.PARTICLE_MAX_DISTANCE, i = Math.min(this.cellW, this.cellH) * u.PARTICLE_BASE_RADIUS, r = u.getParticleSeeds(t.cell.col, t.cell.row), n = [
795
841
  this.particleColorRgb[0] / 255,
796
842
  this.particleColorRgb[1] / 255,
797
843
  this.particleColorRgb[2] / 255
798
844
  ];
799
845
  t.renderer.beginAdditiveBlend();
800
846
  for (let o = 0; o < this.particlesPerCell; o += 1) {
801
- const l = r[o], h = l.phaseOffset * v, c = t.elapsed - h;
847
+ const h = r[o], l = h.phaseOffset * L, c = t.elapsed - l;
802
848
  if (c < 0) continue;
803
- const a = c % v / v, d = l.seedA * Math.PI * 2, g = s * a * (0.35 + l.seedB * 0.65), f = t.centerX + Math.cos(d) * g, S = t.centerY + Math.sin(d) * g, p = 0.7 + 0.9 * Math.max(0, Math.sin((t.elapsed * 0.012 + l.twinkleSeed * 2) * Math.PI * 2)), E = Math.max(1, i * (0.55 + l.seedC * 0.6) * (1 - a * 0.5)), A = Math.max(
849
+ const a = c % L / L, d = h.seedA * Math.PI * 2, f = e * a * (0.35 + h.seedB * 0.65), g = t.centerX + Math.cos(d) * f, S = t.centerY + Math.sin(d) * f, p = 0.7 + 0.9 * Math.max(0, Math.sin((t.elapsed * 0.012 + h.twinkleSeed * 2) * Math.PI * 2)), A = Math.max(1, i * (0.55 + h.seedC * 0.6) * (1 - a * 0.5)), w = Math.max(
804
850
  0,
805
851
  Math.min(1, (0.9 + p * 0.2) * u.PARTICLE_GLOBAL_ALPHA * t.envelope)
806
852
  );
807
- if (A <= 0) continue;
808
- const w = this.particleColorMode === "rainbow" ? u.getRainbowParticleColor(
853
+ if (w <= 0) continue;
854
+ const M = this.particleColorMode === "rainbow" ? u.getRainbowParticleColor(
809
855
  t.elapsed,
810
856
  t.cell.col,
811
857
  t.cell.row,
812
- l.seedA
858
+ h.seedA
813
859
  ) : n;
814
- t.renderer.drawSoftCircle(f, S, E, [w[0], w[1], w[2], A]);
860
+ t.renderer.drawSoftCircle(g, S, A, [M[0], M[1], M[2], w]);
815
861
  }
816
862
  t.renderer.endAdditiveBlend();
817
863
  }
818
- static hslToRgb01(t, s, i) {
819
- const r = (t % 360 + 360) % 360, n = Math.max(0, Math.min(1, s)), o = Math.max(0, Math.min(1, i)), l = (1 - Math.abs(2 * o - 1)) * n, h = r / 60, c = l * (1 - Math.abs(h % 2 - 1));
820
- let a = 0, d = 0, g = 0;
821
- h >= 0 && h < 1 ? (a = l, d = c) : h < 2 ? (a = c, d = l) : h < 3 ? (d = l, g = c) : h < 4 ? (d = c, g = l) : h < 5 ? (a = c, g = l) : (a = l, g = c);
822
- const f = o - l * 0.5;
823
- return [a + f, d + f, g + f];
864
+ static hslToRgb01(t, e, i) {
865
+ const r = (t % 360 + 360) % 360, n = Math.max(0, Math.min(1, e)), o = Math.max(0, Math.min(1, i)), h = (1 - Math.abs(2 * o - 1)) * n, l = r / 60, c = h * (1 - Math.abs(l % 2 - 1));
866
+ let a = 0, d = 0, f = 0;
867
+ l >= 0 && l < 1 ? (a = h, d = c) : l < 2 ? (a = c, d = h) : l < 3 ? (d = h, f = c) : l < 4 ? (d = c, f = h) : l < 5 ? (a = c, f = h) : (a = h, f = c);
868
+ const g = o - h * 0.5;
869
+ return [a + g, d + g, f + g];
824
870
  }
825
- static getRainbowParticleColor(t, s, i, r) {
826
- const n = (r * 360 + t * 0.24 + s * 38 + i * 22) % 360, o = 360 / u.RAINBOW_HUE_BUCKETS, l = Math.floor(n / o) * o;
827
- return u.hslToRgb01(l, 0.98, 0.64);
871
+ static getRainbowParticleColor(t, e, i, r) {
872
+ const n = (r * 360 + t * 0.24 + e * 38 + i * 22) % 360, o = 360 / u.RAINBOW_HUE_BUCKETS, h = Math.floor(n / o) * o;
873
+ return u.hslToRgb01(h, 0.98, 0.64);
828
874
  }
829
- static hash01(t, s, i, r) {
830
- const n = Math.sin(t * 127.1 + s * 311.7 + i * 74.7 + r * 19.3) * 43758.5453;
875
+ static hash01(t, e, i, r) {
876
+ const n = Math.sin(t * 127.1 + e * 311.7 + i * 74.7 + r * 19.3) * 43758.5453;
831
877
  return n - Math.floor(n);
832
878
  }
833
- static getParticleSeeds(t, s) {
834
- const i = `${t},${s}`, r = u.particleSeedsCache.get(i);
879
+ static getParticleSeeds(t, e) {
880
+ const i = `${t},${e}`, r = u.particleSeedsCache.get(i);
835
881
  if (r) return r;
836
882
  const n = [];
837
883
  for (let o = 0; o < D; o += 1)
838
884
  n.push({
839
- seedA: u.hash01(t, s, o, 1),
840
- seedB: u.hash01(t, s, o, 2),
841
- seedC: u.hash01(t, s, o, 3),
842
- phaseOffset: u.hash01(t, s, o, 4),
843
- twinkleSeed: u.hash01(t, s, o, 5)
885
+ seedA: u.hash01(t, e, o, 1),
886
+ seedB: u.hash01(t, e, o, 2),
887
+ seedC: u.hash01(t, e, o, 3),
888
+ phaseOffset: u.hash01(t, e, o, 4),
889
+ twinkleSeed: u.hash01(t, e, o, 5)
844
890
  });
845
891
  return u.particleSeedsCache.set(i, n), n;
846
892
  }
@@ -849,8 +895,8 @@ class u {
849
895
  }
850
896
  setWinningCells(t) {
851
897
  this.winningCells = t, this.winningCellKeys.clear();
852
- for (const s of t)
853
- this.winningCellKeys.add(`${s.col}:${s.row}`);
898
+ for (const e of t)
899
+ this.winningCellKeys.add(`${e.col}:${e.row}`);
854
900
  }
855
901
  resize = () => {
856
902
  const t = this.container.getBoundingClientRect(), i = typeof window.matchMedia == "function" && window.matchMedia("(pointer: coarse)").matches || navigator.maxTouchPoints > 0 ? 1.5 : 2, r = Math.max(1, Math.min(window.devicePixelRatio || 1, i)), n = Math.max(300, Math.floor(t.width * r));
@@ -873,7 +919,7 @@ class u {
873
919
  this.simulationLastNow = t, this.update(t);
874
920
  return;
875
921
  }
876
- const s = Math.max(
922
+ const e = Math.max(
877
923
  0,
878
924
  Math.min(t - this.simulationLastNow, u.MAX_FRAME_DELTA_MS)
879
925
  );
@@ -881,7 +927,7 @@ class u {
881
927
  this.outroInterpolationAlpha = 1;
882
928
  return;
883
929
  }
884
- this.snapshotOutroState(), this.simulationAccumulatorMs += s;
930
+ this.snapshotOutroState(), this.simulationAccumulatorMs += e;
885
931
  const i = this.motionProfile.fixedStepMs;
886
932
  let r = 0;
887
933
  for (; this.simulationAccumulatorMs >= i && r < this.motionProfile.maxCatchUpStepsPerFrame && this.runtime.phase === "outro"; )
@@ -895,26 +941,26 @@ class u {
895
941
  snapshotOutroState() {
896
942
  this.copyOffsets(this.scriptedOutgoingOffsetsPrev, this.scriptedOutgoingOffsets), this.copyOffsets(this.scriptedIncomingOffsetsPrev, this.scriptedIncomingOffsets), this.copyOffsets(this.scriptedIncomingAlphaPrev, this.scriptedIncomingAlpha), this.copyVisibility(this.scriptedIncomingVisibilityPrev, this.scriptedIncomingVisibility);
897
943
  }
898
- copyOffsets(t, s) {
944
+ copyOffsets(t, e) {
899
945
  for (let i = 0; i < 3; i += 1)
900
946
  for (let r = 0; r < 3; r += 1)
901
- t[i][r] = s[i][r];
947
+ t[i][r] = e[i][r];
902
948
  }
903
- copyVisibility(t, s) {
949
+ copyVisibility(t, e) {
904
950
  for (let i = 0; i < 3; i += 1)
905
951
  for (let r = 0; r < 3; r += 1)
906
- t[i][r] = s[i][r];
952
+ t[i][r] = e[i][r];
907
953
  }
908
- resetOutroBuffers(t, s) {
909
- R(this.scriptedOutgoingOffsets, 0), R(this.scriptedIncomingOffsets, 0), R(this.scriptedOutgoingOffsetsPrev, 0), R(this.scriptedIncomingOffsetsPrev, 0), R(this.scriptedIncomingAlpha, t), R(this.scriptedIncomingAlphaPrev, t), this.fillVisibilityGrid(this.scriptedIncomingVisibility, s), this.fillVisibilityGrid(this.scriptedIncomingVisibilityPrev, s);
954
+ resetOutroBuffers(t, e) {
955
+ R(this.scriptedOutgoingOffsets, 0), R(this.scriptedIncomingOffsets, 0), R(this.scriptedOutgoingOffsetsPrev, 0), R(this.scriptedIncomingOffsetsPrev, 0), R(this.scriptedIncomingAlpha, t), R(this.scriptedIncomingAlphaPrev, t), this.fillVisibilityGrid(this.scriptedIncomingVisibility, e), this.fillVisibilityGrid(this.scriptedIncomingVisibilityPrev, e);
910
956
  }
911
957
  static createVisibilityGrid(t) {
912
958
  return Array.from({ length: 3 }, () => Array.from({ length: 3 }, () => t));
913
959
  }
914
- fillVisibilityGrid(t, s) {
960
+ fillVisibilityGrid(t, e) {
915
961
  for (let i = 0; i < 3; i += 1)
916
962
  for (let r = 0; r < 3; r += 1)
917
- t[i][r] = s;
963
+ t[i][r] = e;
918
964
  }
919
965
  startLoop() {
920
966
  this.rafLoop.isRunning() || this.rafLoop.start((t) => (this.advanceSimulation(t), this.render(t), this.shouldKeepAnimating()));