@number10/phaserjsx 4.1.0 → 4.3.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 (67) hide show
  1. package/README.md +14 -1
  2. package/dist/clip/index.cjs +7 -695
  3. package/dist/clip/index.js +1 -687
  4. package/dist/clip/stencil-clip-depth.d.ts +10 -0
  5. package/dist/clip/stencil-clip-depth.d.ts.map +1 -0
  6. package/dist/clip/stencil-clip-fbo-bridge.d.ts +7 -0
  7. package/dist/clip/stencil-clip-fbo-bridge.d.ts.map +1 -0
  8. package/dist/clip/stencil-clip-renderer.d.ts +7 -0
  9. package/dist/clip/stencil-clip-renderer.d.ts.map +1 -0
  10. package/dist/clip/stencil-clip-state.d.ts +28 -0
  11. package/dist/clip/stencil-clip-state.d.ts.map +1 -0
  12. package/dist/clip/stencil-clip-types.d.ts +67 -0
  13. package/dist/clip/stencil-clip-types.d.ts.map +1 -0
  14. package/dist/clip/stencil-clip.d.ts +3 -84
  15. package/dist/clip/stencil-clip.d.ts.map +1 -1
  16. package/dist/clip-CHmjztBQ.cjs +705 -0
  17. package/dist/clip-CHmjztBQ.cjs.map +1 -0
  18. package/dist/clip-CPufWCSD.js +668 -0
  19. package/dist/clip-CPufWCSD.js.map +1 -0
  20. package/dist/components/appliers/applyParticles.d.ts.map +1 -1
  21. package/dist/components/custom/Badge.d.ts +73 -0
  22. package/dist/components/custom/Badge.d.ts.map +1 -0
  23. package/dist/components/custom/Checkbox.d.ts +41 -0
  24. package/dist/components/custom/Checkbox.d.ts.map +1 -0
  25. package/dist/components/custom/DebugPanel.d.ts +30 -0
  26. package/dist/components/custom/DebugPanel.d.ts.map +1 -0
  27. package/dist/components/custom/Particles.d.ts +14 -3
  28. package/dist/components/custom/Particles.d.ts.map +1 -1
  29. package/dist/components/custom/Popover.d.ts +89 -0
  30. package/dist/components/custom/Popover.d.ts.map +1 -0
  31. package/dist/components/custom/ProgressBar.d.ts +52 -0
  32. package/dist/components/custom/ProgressBar.d.ts.map +1 -0
  33. package/dist/components/custom/Toggle.d.ts.map +1 -1
  34. package/dist/components/custom/index.cjs +15 -1
  35. package/dist/components/custom/index.d.ts +5 -0
  36. package/dist/components/custom/index.d.ts.map +1 -1
  37. package/dist/components/custom/index.js +2 -2
  38. package/dist/components/index.d.ts +5 -1
  39. package/dist/components/index.d.ts.map +1 -1
  40. package/dist/components/primitives/graphics.d.ts +2 -2
  41. package/dist/components/primitives/particles.d.ts +14 -4
  42. package/dist/components/primitives/particles.d.ts.map +1 -1
  43. package/dist/components/primitives/tilesprite.d.ts +15 -19
  44. package/dist/components/primitives/tilesprite.d.ts.map +1 -1
  45. package/dist/{custom-Dp3yAJdU.cjs → custom-37gL0VZG.cjs} +1578 -264
  46. package/dist/custom-37gL0VZG.cjs.map +1 -0
  47. package/dist/{custom-C_w8D39m.js → custom-DMZASXll.js} +1455 -231
  48. package/dist/custom-DMZASXll.js.map +1 -0
  49. package/dist/gestures/gesture-manager.d.ts +1 -1
  50. package/dist/index.cjs +49 -111
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.js +29 -105
  53. package/dist/index.js.map +1 -1
  54. package/dist/particles/emit-zone.d.ts +34 -12
  55. package/dist/particles/emit-zone.d.ts.map +1 -1
  56. package/dist/particles/index.d.ts +1 -1
  57. package/dist/particles/index.d.ts.map +1 -1
  58. package/dist/particles/use-particles.d.ts +6 -2
  59. package/dist/particles/use-particles.d.ts.map +1 -1
  60. package/dist/theme-custom.d.ts +68 -0
  61. package/dist/theme-custom.d.ts.map +1 -1
  62. package/dist/theme-defaults.d.ts.map +1 -1
  63. package/package.json +3 -2
  64. package/dist/clip/index.cjs.map +0 -1
  65. package/dist/clip/index.js.map +0 -1
  66. package/dist/custom-C_w8D39m.js.map +0 -1
  67. package/dist/custom-Dp3yAJdU.cjs.map +0 -1
@@ -0,0 +1,668 @@
1
+ import * as Phaser from "phaser";
2
+ //#region src/clip/stencil-clip-depth.ts
3
+ /**
4
+ * Shared depth counter per GL context.
5
+ * Incremented before each clip's INCR pass, decremented after the DECR pass.
6
+ */
7
+ var _depthByGl = /* @__PURE__ */ new WeakMap();
8
+ var _prerenderHooked = /* @__PURE__ */ new WeakSet();
9
+ function getDepth(gl) {
10
+ let d = _depthByGl.get(gl);
11
+ if (!d) {
12
+ d = { value: 0 };
13
+ _depthByGl.set(gl, d);
14
+ }
15
+ return d;
16
+ }
17
+ /**
18
+ * Registers a per-frame prerender listener that resets stencil clip state.
19
+ * Registered at most once per Phaser.Game instance.
20
+ */
21
+ function ensurePrerenderReset(gl, game, resetFboState) {
22
+ if (_prerenderHooked.has(game)) return;
23
+ _prerenderHooked.add(game);
24
+ game.events.on("prerender", () => {
25
+ const d = _depthByGl.get(gl);
26
+ if (d) d.value = 0;
27
+ resetFboState(gl);
28
+ });
29
+ }
30
+ //#endregion
31
+ //#region src/clip/stencil-clip-fbo-bridge.ts
32
+ var _fboPatchByGl = /* @__PURE__ */ new WeakMap();
33
+ function resetFboPatchState(gl) {
34
+ const fbo = _fboPatchByGl.get(gl);
35
+ if (fbo) {
36
+ fbo.current = null;
37
+ fbo.saved = null;
38
+ }
39
+ }
40
+ /**
41
+ * Patches gl.bindFramebuffer once per GL context so that the stencil test is
42
+ * disabled while Phaser renders PostFX / RenderTextures into off-screen FBOs.
43
+ */
44
+ function ensureFboPatch(gl) {
45
+ if (_fboPatchByGl.has(gl)) return;
46
+ const state = {
47
+ current: null,
48
+ saved: null
49
+ };
50
+ _fboPatchByGl.set(gl, state);
51
+ const origBind = gl.bindFramebuffer.bind(gl);
52
+ gl.bindFramebuffer = (target, fb) => {
53
+ const wasMain = state.current === null;
54
+ const willBeMain = fb === null;
55
+ const enteringOffscreen = wasMain && !willBeMain;
56
+ const leavingOffscreen = !wasMain && willBeMain;
57
+ if (enteringOffscreen && gl.getParameter(gl.STENCIL_TEST)) {
58
+ state.saved = {
59
+ func: gl.getParameter(gl.STENCIL_FUNC),
60
+ ref: gl.getParameter(gl.STENCIL_REF),
61
+ valueMask: gl.getParameter(gl.STENCIL_VALUE_MASK),
62
+ fail: gl.getParameter(gl.STENCIL_FAIL),
63
+ zfail: gl.getParameter(gl.STENCIL_PASS_DEPTH_FAIL),
64
+ zpass: gl.getParameter(gl.STENCIL_PASS_DEPTH_PASS),
65
+ writeMask: gl.getParameter(gl.STENCIL_WRITEMASK)
66
+ };
67
+ gl.disable(gl.STENCIL_TEST);
68
+ }
69
+ origBind(target, fb);
70
+ state.current = fb;
71
+ if (leavingOffscreen && state.saved) {
72
+ gl.enable(gl.STENCIL_TEST);
73
+ gl.stencilFunc(state.saved.func, state.saved.ref, state.saved.valueMask);
74
+ gl.stencilOp(state.saved.fail, state.saved.zfail, state.saved.zpass);
75
+ gl.stencilMask(state.saved.writeMask);
76
+ state.saved = null;
77
+ }
78
+ };
79
+ }
80
+ //#endregion
81
+ //#region src/clip/stencil-clip-renderer.ts
82
+ function savePhaserGLState(renderer) {
83
+ const glWrapper = renderer.glWrapper;
84
+ return {
85
+ activeTexture: glWrapper.state?.bindings?.activeTexture,
86
+ arrayBuffer: glWrapper.state?.bindings?.arrayBuffer ?? null,
87
+ program: glWrapper.state?.bindings?.program ?? null,
88
+ vao: glWrapper.state?.vao ?? null
89
+ };
90
+ }
91
+ function restorePhaserGLState(renderer, saved, fallbackActiveTexture) {
92
+ const glWrapper = renderer.glWrapper;
93
+ if (glWrapper.update) {
94
+ glWrapper.update({
95
+ bindings: {
96
+ activeTexture: saved.activeTexture ?? fallbackActiveTexture,
97
+ arrayBuffer: saved.arrayBuffer,
98
+ program: saved.program
99
+ },
100
+ vao: saved.vao
101
+ }, true);
102
+ return;
103
+ }
104
+ glWrapper.updateBindingsActiveTexture?.({ bindings: { activeTexture: saved.activeTexture ?? fallbackActiveTexture } }, true);
105
+ }
106
+ var ROUND_RECT_VERT_SRC = `
107
+ attribute vec2 a_ndc;
108
+ attribute vec2 a_loc;
109
+ varying vec2 v_loc;
110
+ void main(){gl_Position=vec4(a_ndc,0.,1.);v_loc=a_loc;}
111
+ `;
112
+ var ROUND_RECT_FRAG_SRC = `
113
+ precision mediump float;
114
+ varying vec2 v_loc;
115
+ uniform vec2 u_halfSize;
116
+ uniform vec4 u_radii;
117
+ float sdRoundedBox(vec2 p,vec2 b,vec4 r){
118
+ r.xy=p.x>0.?r.yz:r.xw;
119
+ r.x =p.y>0.?r.y :r.x;
120
+ vec2 q=abs(p)-b+r.x;
121
+ return length(max(q,0.))+min(max(q.x,q.y),0.)-r.x;
122
+ }
123
+ void main(){
124
+ if(sdRoundedBox(v_loc,u_halfSize,u_radii)>0.)discard;
125
+ gl_FragColor=vec4(0.);
126
+ }
127
+ `;
128
+ var BITMAP_VERT_SRC = `
129
+ attribute vec2 a_ndc;
130
+ attribute vec2 a_uv;
131
+ varying vec2 v_uv;
132
+ void main(){gl_Position=vec4(a_ndc,0.,1.);v_uv=a_uv;}
133
+ `;
134
+ var BITMAP_FRAG_SRC = `
135
+ precision mediump float;
136
+ varying vec2 v_uv;
137
+ uniform sampler2D u_texture;
138
+ uniform float u_alphaThreshold;
139
+ uniform float u_invertAlpha;
140
+ void main(){
141
+ float a=texture2D(u_texture,v_uv).a;
142
+ bool keep=u_invertAlpha>0.5 ? a<u_alphaThreshold : a>=u_alphaThreshold;
143
+ if(!keep)discard;
144
+ gl_FragColor=vec4(0.);
145
+ }
146
+ `;
147
+ var _roundRectProgByGl = /* @__PURE__ */ new WeakMap();
148
+ var _bitmapProgByGl = /* @__PURE__ */ new WeakMap();
149
+ function createProgram(gl, vertSrc, fragSrc) {
150
+ const vs = gl.createShader(gl.VERTEX_SHADER);
151
+ gl.shaderSource(vs, vertSrc);
152
+ gl.compileShader(vs);
153
+ const fs = gl.createShader(gl.FRAGMENT_SHADER);
154
+ gl.shaderSource(fs, fragSrc);
155
+ gl.compileShader(fs);
156
+ const prog = gl.createProgram();
157
+ gl.attachShader(prog, vs);
158
+ gl.attachShader(prog, fs);
159
+ gl.linkProgram(prog);
160
+ return prog;
161
+ }
162
+ function getRoundRectProg(gl) {
163
+ let prog = _roundRectProgByGl.get(gl);
164
+ if (prog) return prog;
165
+ prog = createProgram(gl, ROUND_RECT_VERT_SRC, ROUND_RECT_FRAG_SRC);
166
+ _roundRectProgByGl.set(gl, prog);
167
+ return prog;
168
+ }
169
+ function getBitmapProg(gl) {
170
+ let prog = _bitmapProgByGl.get(gl);
171
+ if (prog) return prog;
172
+ prog = createProgram(gl, BITMAP_VERT_SRC, BITMAP_FRAG_SRC);
173
+ _bitmapProgByGl.set(gl, prog);
174
+ return prog;
175
+ }
176
+ var _roundRectLocsByProg = /* @__PURE__ */ new WeakMap();
177
+ var _bitmapLocsByProg = /* @__PURE__ */ new WeakMap();
178
+ function getRoundRectShaderLocs(gl, prog) {
179
+ let l = _roundRectLocsByProg.get(prog);
180
+ if (!l) {
181
+ l = {
182
+ ndc: gl.getAttribLocation(prog, "a_ndc"),
183
+ loc: gl.getAttribLocation(prog, "a_loc"),
184
+ halfSize: gl.getUniformLocation(prog, "u_halfSize"),
185
+ radii: gl.getUniformLocation(prog, "u_radii")
186
+ };
187
+ _roundRectLocsByProg.set(prog, l);
188
+ }
189
+ return l;
190
+ }
191
+ function getBitmapShaderLocs(gl, prog) {
192
+ let l = _bitmapLocsByProg.get(prog);
193
+ if (!l) {
194
+ l = {
195
+ ndc: gl.getAttribLocation(prog, "a_ndc"),
196
+ uv: gl.getAttribLocation(prog, "a_uv"),
197
+ texture: gl.getUniformLocation(prog, "u_texture"),
198
+ alphaThreshold: gl.getUniformLocation(prog, "u_alphaThreshold"),
199
+ invertAlpha: gl.getUniformLocation(prog, "u_invertAlpha")
200
+ };
201
+ _bitmapLocsByProg.set(prog, l);
202
+ }
203
+ return l;
204
+ }
205
+ var STRIDE = 16;
206
+ function drawRoundRectMaskShape(gl, scene, matrix, cameraMatrix, offsetX, offsetY, w, h, logW, logH, radii, vertBuf, verts) {
207
+ const { a, b, c, d, tx, ty } = matrix;
208
+ const hw = w / 2;
209
+ const hh = h / 2;
210
+ const cx = offsetX + hw;
211
+ const cy = offsetY + hh;
212
+ const corners = [
213
+ [cx - hw, cy - hh],
214
+ [cx + hw, cy - hh],
215
+ [cx + hw, cy + hh],
216
+ [cx - hw, cy + hh]
217
+ ];
218
+ for (let i = 0; i < 4; i++) {
219
+ const corner = corners[i];
220
+ const lx = corner[0];
221
+ const ly = corner[1];
222
+ const wx = a * lx + c * ly + tx;
223
+ const wy = b * lx + d * ly + ty;
224
+ const sx = cameraMatrix ? cameraMatrix.getX(wx, wy) : wx;
225
+ const sy = cameraMatrix ? cameraMatrix.getY(wx, wy) : wy;
226
+ verts[i * 4 + 0] = sx / logW * 2 - 1;
227
+ verts[i * 4 + 1] = 1 - sy / logH * 2;
228
+ verts[i * 4 + 2] = lx - cx;
229
+ verts[i * 4 + 3] = ly - cy;
230
+ }
231
+ const prevProg = gl.getParameter(gl.CURRENT_PROGRAM);
232
+ const prevBuf = gl.getParameter(gl.ARRAY_BUFFER_BINDING);
233
+ const prevVAO = gl.getParameter(34229);
234
+ const prevActiveTextureUnit = gl.getParameter(gl.ACTIVE_TEXTURE) - gl.TEXTURE0;
235
+ const renderer = scene.renderer;
236
+ const savedPhaserState = savePhaserGLState(renderer);
237
+ gl.bindVertexArray(null);
238
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
239
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, verts);
240
+ const prog = getRoundRectProg(gl);
241
+ gl.useProgram(prog);
242
+ const locs = getRoundRectShaderLocs(gl, prog);
243
+ gl.enableVertexAttribArray(locs.ndc);
244
+ gl.vertexAttribPointer(locs.ndc, 2, gl.FLOAT, false, STRIDE, 0);
245
+ gl.enableVertexAttribArray(locs.loc);
246
+ gl.vertexAttribPointer(locs.loc, 2, gl.FLOAT, false, STRIDE, 8);
247
+ gl.uniform2f(locs.halfSize, hw, hh);
248
+ gl.uniform4f(locs.radii, radii[0], radii[1], radii[2], radii[3]);
249
+ gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
250
+ gl.disableVertexAttribArray(locs.ndc);
251
+ gl.disableVertexAttribArray(locs.loc);
252
+ gl.bindBuffer(gl.ARRAY_BUFFER, prevBuf);
253
+ gl.useProgram(prevProg);
254
+ gl.bindVertexArray(prevVAO);
255
+ restorePhaserGLState(renderer, savedPhaserState, prevActiveTextureUnit);
256
+ }
257
+ function isTextureFrame(value) {
258
+ return typeof value === "object" && value !== null && "glTexture" in value && "u0" in value;
259
+ }
260
+ function resolveBitmapFrame(scene, source) {
261
+ const frame = isTextureFrame(source.texture) ? source.texture : typeof source.texture === "string" ? scene.textures.getFrame(source.texture, source.frame) : source.texture.get(source.frame);
262
+ if (!frame?.glTexture?.webGLTexture) return null;
263
+ return {
264
+ glTexture: frame.glTexture,
265
+ width: source.width ?? frame.cutWidth ?? frame.realWidth,
266
+ height: source.height ?? frame.cutHeight ?? frame.realHeight,
267
+ u0: frame.u0,
268
+ v0: frame.v0,
269
+ u1: frame.u1,
270
+ v1: frame.v1
271
+ };
272
+ }
273
+ function drawBitmapMaskShape(gl, scene, matrix, cameraMatrix, source, frameInfo, logW, logH, vertBuf, verts) {
274
+ const { a, b, c, d, tx, ty } = matrix;
275
+ const x0 = source.offsetX;
276
+ const y0 = source.offsetY;
277
+ const x1 = x0 + frameInfo.width;
278
+ const y1 = y0 + frameInfo.height;
279
+ const corners = [
280
+ [
281
+ x0,
282
+ y0,
283
+ frameInfo.u0,
284
+ frameInfo.v0
285
+ ],
286
+ [
287
+ x1,
288
+ y0,
289
+ frameInfo.u1,
290
+ frameInfo.v0
291
+ ],
292
+ [
293
+ x1,
294
+ y1,
295
+ frameInfo.u1,
296
+ frameInfo.v1
297
+ ],
298
+ [
299
+ x0,
300
+ y1,
301
+ frameInfo.u0,
302
+ frameInfo.v1
303
+ ]
304
+ ];
305
+ for (let i = 0; i < 4; i++) {
306
+ const corner = corners[i];
307
+ const lx = corner[0];
308
+ const ly = corner[1];
309
+ const wx = a * lx + c * ly + tx;
310
+ const wy = b * lx + d * ly + ty;
311
+ const sx = cameraMatrix ? cameraMatrix.getX(wx, wy) : wx;
312
+ const sy = cameraMatrix ? cameraMatrix.getY(wx, wy) : wy;
313
+ verts[i * 4 + 0] = sx / logW * 2 - 1;
314
+ verts[i * 4 + 1] = 1 - sy / logH * 2;
315
+ verts[i * 4 + 2] = corner[2];
316
+ verts[i * 4 + 3] = corner[3];
317
+ }
318
+ const prevProg = gl.getParameter(gl.CURRENT_PROGRAM);
319
+ const prevBuf = gl.getParameter(gl.ARRAY_BUFFER_BINDING);
320
+ const prevVAO = gl.getParameter(34229);
321
+ const prevActiveTextureUnit = gl.getParameter(gl.ACTIVE_TEXTURE) - gl.TEXTURE0;
322
+ const renderer = scene.renderer;
323
+ const savedPhaserState = savePhaserGLState(renderer);
324
+ gl.bindVertexArray(null);
325
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
326
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, verts);
327
+ const prog = getBitmapProg(gl);
328
+ gl.useProgram(prog);
329
+ const locs = getBitmapShaderLocs(gl, prog);
330
+ gl.enableVertexAttribArray(locs.ndc);
331
+ gl.vertexAttribPointer(locs.ndc, 2, gl.FLOAT, false, STRIDE, 0);
332
+ gl.enableVertexAttribArray(locs.uv);
333
+ gl.vertexAttribPointer(locs.uv, 2, gl.FLOAT, false, STRIDE, 8);
334
+ const textureUnits = renderer.glTextureUnits;
335
+ const prevTexture = textureUnits.units[0] ?? null;
336
+ textureUnits.bind(frameInfo.glTexture, 0);
337
+ gl.uniform1i(locs.texture, 0);
338
+ gl.uniform1f(locs.alphaThreshold, source.alphaThreshold);
339
+ gl.uniform1f(locs.invertAlpha, source.invertAlpha ? 1 : 0);
340
+ gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
341
+ gl.disableVertexAttribArray(locs.ndc);
342
+ gl.disableVertexAttribArray(locs.uv);
343
+ textureUnits.bind(prevTexture, 0);
344
+ renderer.glWrapper.updateBindingsActiveTexture({ bindings: { activeTexture: prevActiveTextureUnit } });
345
+ gl.bindBuffer(gl.ARRAY_BUFFER, prevBuf);
346
+ gl.useProgram(prevProg);
347
+ gl.bindVertexArray(prevVAO);
348
+ restorePhaserGLState(renderer, savedPhaserState, prevActiveTextureUnit);
349
+ }
350
+ function drawMaskShape(gl, scene, matrix, cameraMatrix, source, logW, logH, vertBuf, verts) {
351
+ if (source.kind === "bitmap") {
352
+ const frameInfo = resolveBitmapFrame(scene, source);
353
+ if (!frameInfo) return;
354
+ drawBitmapMaskShape(gl, scene, matrix, cameraMatrix, source, frameInfo, logW, logH, vertBuf, verts);
355
+ return;
356
+ }
357
+ drawRoundRectMaskShape(gl, scene, matrix, cameraMatrix, source.offsetX, source.offsetY, source.width, source.height, logW, logH, source.radii, vertBuf, verts);
358
+ }
359
+ //#endregion
360
+ //#region src/clip/stencil-clip-state.ts
361
+ function resolveRadii(r) {
362
+ if (!r) return [
363
+ 0,
364
+ 0,
365
+ 0,
366
+ 0
367
+ ];
368
+ if (typeof r === "number") return [
369
+ r,
370
+ r,
371
+ r,
372
+ r
373
+ ];
374
+ return [
375
+ r.tl ?? 0,
376
+ r.tr ?? 0,
377
+ r.br ?? 0,
378
+ r.bl ?? 0
379
+ ];
380
+ }
381
+ /** Returns true when a source/update selects the bitmap mask renderer. */
382
+ function isBitmapStencilClipSource(source) {
383
+ return source.kind === "bitmap";
384
+ }
385
+ function toRoundRectState(source) {
386
+ return {
387
+ kind: "roundRect",
388
+ width: source.width,
389
+ height: source.height,
390
+ offsetX: source.offsetX ?? 0,
391
+ offsetY: source.offsetY ?? 0,
392
+ radii: source.kind === "rect" ? [
393
+ 0,
394
+ 0,
395
+ 0,
396
+ 0
397
+ ] : resolveRadii(source.cornerRadius)
398
+ };
399
+ }
400
+ function toBitmapState(source) {
401
+ return {
402
+ kind: "bitmap",
403
+ texture: source.texture,
404
+ frame: source.frame,
405
+ width: source.width,
406
+ height: source.height,
407
+ offsetX: source.offsetX ?? 0,
408
+ offsetY: source.offsetY ?? 0,
409
+ alphaThreshold: source.alphaThreshold ?? .5,
410
+ invertAlpha: source.invertAlpha ?? false
411
+ };
412
+ }
413
+ function toMaskState(source) {
414
+ return isBitmapStencilClipSource(source) ? toBitmapState(source) : toRoundRectState(source);
415
+ }
416
+ function mergeMaskState(current, update) {
417
+ if (isBitmapStencilClipSource(update)) {
418
+ if (current.kind !== "bitmap" || update.texture !== void 0) return toBitmapState(update);
419
+ return {
420
+ kind: "bitmap",
421
+ texture: current.texture,
422
+ frame: update.frame !== void 0 ? update.frame : current.frame,
423
+ width: update.width !== void 0 ? update.width : current.width,
424
+ height: update.height !== void 0 ? update.height : current.height,
425
+ offsetX: update.offsetX !== void 0 ? update.offsetX : current.offsetX,
426
+ offsetY: update.offsetY !== void 0 ? update.offsetY : current.offsetY,
427
+ alphaThreshold: update.alphaThreshold !== void 0 ? update.alphaThreshold : current.alphaThreshold,
428
+ invertAlpha: update.invertAlpha !== void 0 ? update.invertAlpha : current.invertAlpha
429
+ };
430
+ }
431
+ if (current.kind === "bitmap" && update.kind === void 0) {
432
+ const bitmapUpdate = update;
433
+ return {
434
+ kind: "bitmap",
435
+ texture: current.texture,
436
+ frame: bitmapUpdate.frame !== void 0 ? bitmapUpdate.frame : current.frame,
437
+ width: bitmapUpdate.width !== void 0 ? bitmapUpdate.width : current.width,
438
+ height: bitmapUpdate.height !== void 0 ? bitmapUpdate.height : current.height,
439
+ offsetX: bitmapUpdate.offsetX !== void 0 ? bitmapUpdate.offsetX : current.offsetX,
440
+ offsetY: bitmapUpdate.offsetY !== void 0 ? bitmapUpdate.offsetY : current.offsetY,
441
+ alphaThreshold: bitmapUpdate.alphaThreshold !== void 0 ? bitmapUpdate.alphaThreshold : current.alphaThreshold,
442
+ invertAlpha: bitmapUpdate.invertAlpha !== void 0 ? bitmapUpdate.invertAlpha : current.invertAlpha
443
+ };
444
+ }
445
+ if (current.kind === "bitmap") return toRoundRectState(update);
446
+ const roundUpdate = update;
447
+ return {
448
+ kind: "roundRect",
449
+ width: roundUpdate.width !== void 0 ? roundUpdate.width : current.width,
450
+ height: roundUpdate.height !== void 0 ? roundUpdate.height : current.height,
451
+ offsetX: roundUpdate.offsetX !== void 0 ? roundUpdate.offsetX : current.offsetX,
452
+ offsetY: roundUpdate.offsetY !== void 0 ? roundUpdate.offsetY : current.offsetY,
453
+ radii: roundUpdate.kind === "rect" ? [
454
+ 0,
455
+ 0,
456
+ 0,
457
+ 0
458
+ ] : "cornerRadius" in roundUpdate ? resolveRadii(roundUpdate.cornerRadius) : current.radii
459
+ };
460
+ }
461
+ //#endregion
462
+ //#region src/clip/stencil-clip.ts
463
+ /**
464
+ * WebGL stencil-buffer clip for Phaser 4 Containers.
465
+ *
466
+ * Supports arbitrary nesting via the INCR/DECR model: each clip level
467
+ * increments the stencil on enter and decrements on exit, so child clips are
468
+ * automatically intersected with their parent clips at the hardware level.
469
+ *
470
+ * Shape variants:
471
+ * - Plain rectangle (cornerRadius omitted or 0)
472
+ * - Rounded rectangle (uniform radius or per-corner object)
473
+ *
474
+ * A single SDF-based shader handles both variants. For plain rectangles
475
+ * u_radii is vec4(0) and the `discard` branch never fires — no overhead
476
+ * compared to a rectangle-only shader.
477
+ *
478
+ * Transforms (translate, scale, rotation) are fully supported: the quad
479
+ * corners are transformed through `container.getWorldTransformMatrix()` at
480
+ * render time, so no per-layout world-position tracking is needed.
481
+ */
482
+ var STENCIL_HANDLE = Symbol("stencilClipHandle");
483
+ /** Returns the active stencil clip handle attached to a container, if any. */
484
+ function getStencilClipHandle(container) {
485
+ return container[STENCIL_HANDLE];
486
+ }
487
+ /** Removes any active stencil clip from a container. */
488
+ function clearStencilClip(container) {
489
+ getStencilClipHandle(container)?.destroy();
490
+ }
491
+ /**
492
+ * Applies a WebGL stencil-buffer clip to a Phaser 4 Container.
493
+ *
494
+ * The clip rectangle is expressed in the container's **local coordinate
495
+ * space**. `offsetX`/`offsetY` mark the top-left corner (default 0/0), so
496
+ * a container whose visual area starts at its local origin can be clipped with
497
+ * `applyStencilClip(container, { width, height })`.
498
+ *
499
+ * **Nesting** is handled transparently: each clip level occupies one stencil
500
+ * value (0 = no clip, 1 = depth 0, 2 = depth 1, …). Child clips are always
501
+ * the intersection of their own shape and all ancestor shapes.
502
+ *
503
+ * **Transforms** (translate, scale, rotation) are re-evaluated from
504
+ * `container.getWorldTransformMatrix()` on every frame, so animated or
505
+ * scroll-driven containers clip correctly without any manual update call.
506
+ *
507
+ * If a stencil clip is already attached to the container, calling this
508
+ * function again calls `handle.update(shape)` on the existing handle and
509
+ * returns it.
510
+ *
511
+ * @param container - The container to clip.
512
+ * @param source - Clip source in the container's local coordinate space.
513
+ * @returns A handle to modify dimensions / corner radii or remove the clip.
514
+ */
515
+ function applyStencilClip(container, source) {
516
+ const obj = container;
517
+ if (obj[STENCIL_HANDLE]) {
518
+ obj[STENCIL_HANDLE].update(source);
519
+ return obj[STENCIL_HANDLE];
520
+ }
521
+ if (container.scene.renderer.type !== Phaser.WEBGL) return {
522
+ update() {},
523
+ destroy() {}
524
+ };
525
+ const renderer = container.scene.renderer;
526
+ const gl = renderer.gl;
527
+ const glWrapper = renderer.glWrapper;
528
+ ensurePrerenderReset(gl, container.scene.game, resetFboPatchState);
529
+ ensureFboPatch(gl);
530
+ const previousArrayBuffer = glWrapper.state?.bindings?.arrayBuffer ?? null;
531
+ const vertBuf = gl.createBuffer();
532
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
533
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(16), gl.DYNAMIC_DRAW);
534
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
535
+ glWrapper.updateBindingsArrayBuffer?.({ bindings: { arrayBuffer: previousArrayBuffer } }, true);
536
+ const verts = new Float32Array(16);
537
+ let maskSource = toMaskState(source);
538
+ let destroyed = false;
539
+ const wrapper = (webglRenderer, go, drawingContext, parentMatrix, renderStep = 0, displayList, displayListIndex) => {
540
+ const renderNext = () => {
541
+ go.renderWebGLStep(webglRenderer, go, drawingContext, parentMatrix, renderStep + 1, displayList, displayListIndex);
542
+ };
543
+ if (destroyed) {
544
+ renderNext();
545
+ return;
546
+ }
547
+ const matrix = container.getWorldTransformMatrix();
548
+ const context = drawingContext;
549
+ const cameraMatrix = context.camera?.getViewMatrix(!context.useCanvas);
550
+ const rn = webglRenderer.renderNodes;
551
+ const depth = getDepth(gl);
552
+ const myDepth = depth.value++;
553
+ const logW = webglRenderer.width;
554
+ const logH = webglRenderer.height;
555
+ rn.finishBatch();
556
+ if (myDepth === 0) gl.enable(gl.STENCIL_TEST);
557
+ gl.colorMask(false, false, false, false);
558
+ gl.stencilMask(255);
559
+ gl.stencilFunc(gl.EQUAL, myDepth, 255);
560
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
561
+ drawMaskShape(gl, container.scene, matrix, cameraMatrix, maskSource, logW, logH, vertBuf, verts);
562
+ gl.colorMask(true, true, true, true);
563
+ gl.stencilFunc(gl.EQUAL, myDepth + 1, 255);
564
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
565
+ gl.stencilMask(0);
566
+ renderNext();
567
+ rn.finishBatch();
568
+ gl.colorMask(false, false, false, false);
569
+ gl.stencilMask(255);
570
+ gl.stencilFunc(gl.EQUAL, myDepth + 1, 255);
571
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);
572
+ drawMaskShape(gl, container.scene, matrix, cameraMatrix, maskSource, logW, logH, vertBuf, verts);
573
+ gl.colorMask(true, true, true, true);
574
+ depth.value--;
575
+ if (myDepth === 0) {
576
+ gl.disable(gl.STENCIL_TEST);
577
+ gl.stencilMask(255);
578
+ } else {
579
+ gl.stencilFunc(gl.EQUAL, myDepth, 255);
580
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
581
+ gl.stencilMask(0);
582
+ }
583
+ };
584
+ const handle = {
585
+ update(s) {
586
+ maskSource = mergeMaskState(maskSource, s);
587
+ },
588
+ destroy() {
589
+ if (destroyed) return;
590
+ destroyed = true;
591
+ gl.deleteBuffer(vertBuf);
592
+ const index = obj._renderSteps.indexOf(wrapper);
593
+ if (index !== -1) obj._renderSteps.splice(index, 1);
594
+ delete obj[STENCIL_HANDLE];
595
+ }
596
+ };
597
+ obj.addRenderStep(wrapper, 0);
598
+ obj[STENCIL_HANDLE] = handle;
599
+ return handle;
600
+ }
601
+ //#endregion
602
+ //#region src/clip/stencil-clip-extension.ts
603
+ function addMethod(proto, methodName, fn) {
604
+ const hadOwn = Object.prototype.hasOwnProperty.call(proto, methodName);
605
+ const previous = proto[methodName];
606
+ if (!hadOwn) proto[methodName] = fn;
607
+ return { restore: () => {
608
+ if (!hadOwn) delete proto[methodName];
609
+ else proto[methodName] = previous;
610
+ } };
611
+ }
612
+ function wrapMethod(proto, methodName, wrapper) {
613
+ const original = proto[methodName];
614
+ if (typeof original !== "function") return { restore() {} };
615
+ const wrapped = function(...args) {
616
+ return wrapper(original, this, ...args);
617
+ };
618
+ proto[methodName] = wrapped;
619
+ return { restore: () => {
620
+ proto[methodName] = original;
621
+ } };
622
+ }
623
+ var installed = false;
624
+ var restoreHandles = [];
625
+ function canCreateStencilClipSource(source) {
626
+ if (source.kind === "bitmap") return source.texture !== void 0;
627
+ return source.width !== void 0 && source.height !== void 0;
628
+ }
629
+ /** Installs stencil clip helpers on Phaser.GameObjects.Container.prototype. */
630
+ function installStencilClipExtension() {
631
+ if (installed) return;
632
+ installed = true;
633
+ const proto = Phaser.GameObjects.Container.prototype;
634
+ restoreHandles.push(addMethod(proto, "setStencilClip", function(source) {
635
+ applyStencilClip(this, source);
636
+ return this;
637
+ }));
638
+ restoreHandles.push(addMethod(proto, "updateStencilClip", function(source) {
639
+ const handle = getStencilClipHandle(this);
640
+ if (handle) handle.update(source);
641
+ else if (canCreateStencilClipSource(source)) applyStencilClip(this, source);
642
+ return this;
643
+ }));
644
+ restoreHandles.push(addMethod(proto, "clearStencilClip", function() {
645
+ clearStencilClip(this);
646
+ return this;
647
+ }));
648
+ restoreHandles.push(addMethod(proto, "getStencilClipHandle", function() {
649
+ return getStencilClipHandle(this);
650
+ }));
651
+ restoreHandles.push(wrapMethod(proto, "destroy", (original, self, ...args) => {
652
+ clearStencilClip(self);
653
+ return original.apply(self, args);
654
+ }));
655
+ }
656
+ /** Restores Phaser prototypes to their previous state. Intended for tests/HMR. */
657
+ function uninstallStencilClipExtension() {
658
+ for (const handle of [...restoreHandles].reverse()) handle.restore();
659
+ restoreHandles = [];
660
+ installed = false;
661
+ }
662
+ //#endregion
663
+ //#region src/clip/index.ts
664
+ installStencilClipExtension();
665
+ //#endregion
666
+ export { getStencilClipHandle as a, clearStencilClip as i, uninstallStencilClipExtension as n, isBitmapStencilClipSource as o, applyStencilClip as r, installStencilClipExtension as t };
667
+
668
+ //# sourceMappingURL=clip-CPufWCSD.js.map