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