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