melonjs 19.1.0 → 19.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.
- package/README.md +7 -5
- package/build/application/application.d.ts +33 -0
- package/build/application/application.d.ts.map +1 -1
- package/build/application/settings.d.ts +1 -0
- package/build/application/settings.d.ts.map +1 -1
- package/build/camera/camera2d.d.ts +45 -22
- package/build/camera/camera2d.d.ts.map +1 -1
- package/build/camera/effects/camera_effect.d.ts +45 -0
- package/build/camera/effects/camera_effect.d.ts.map +1 -0
- package/build/camera/effects/fade_effect.d.ts +60 -0
- package/build/camera/effects/fade_effect.d.ts.map +1 -0
- package/build/camera/effects/mask_effect.d.ts +88 -0
- package/build/camera/effects/mask_effect.d.ts.map +1 -0
- package/build/camera/effects/shake_effect.d.ts +47 -0
- package/build/camera/effects/shake_effect.d.ts.map +1 -0
- package/build/index.d.ts +10 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2788 -914
- package/build/index.js.map +4 -4
- package/build/level/tiled/TMXObjectFactory.d.ts.map +1 -1
- package/build/math/color_matrix.d.ts +51 -0
- package/build/math/color_matrix.d.ts.map +1 -0
- package/build/math/matrix2d.d.ts +6 -6
- package/build/math/matrix3d.d.ts +17 -0
- package/build/math/matrix3d.d.ts.map +1 -1
- package/build/particles/emitter.d.ts +19 -5
- package/build/particles/emitter.d.ts.map +1 -1
- package/build/particles/particle.d.ts +4 -1
- package/build/particles/particle.d.ts.map +1 -1
- package/build/particles/settings.d.ts +200 -31
- package/build/particles/settings.d.ts.map +1 -1
- package/build/physics/quadtree.d.ts.map +1 -1
- package/build/renderable/imagelayer.d.ts +13 -2
- package/build/renderable/imagelayer.d.ts.map +1 -1
- package/build/renderable/renderable.d.ts +54 -35
- package/build/renderable/renderable.d.ts.map +1 -1
- package/build/renderable/text/bitmaptext.d.ts +33 -5
- package/build/renderable/text/bitmaptext.d.ts.map +1 -1
- package/build/renderable/text/text.d.ts +27 -1
- package/build/renderable/text/text.d.ts.map +1 -1
- package/build/renderable/trigger.d.ts +44 -19
- package/build/renderable/trigger.d.ts.map +1 -1
- package/build/state/state.d.ts +44 -2
- package/build/state/state.d.ts.map +1 -1
- package/build/tweens/tween.d.ts +9 -0
- package/build/tweens/tween.d.ts.map +1 -1
- package/build/video/buffer/index.d.ts +40 -0
- package/build/video/buffer/index.d.ts.map +1 -0
- package/build/video/{webgl/buffer → buffer}/vertex.d.ts +3 -2
- package/build/video/buffer/vertex.d.ts.map +1 -0
- package/build/video/canvas/canvas_renderer.d.ts.map +1 -1
- package/build/video/renderer.d.ts +79 -0
- package/build/video/renderer.d.ts.map +1 -1
- package/build/video/renderstate.d.ts +7 -0
- package/build/video/renderstate.d.ts.map +1 -1
- package/build/video/rendertarget/canvasrendertarget.d.ts +26 -63
- package/build/video/rendertarget/canvasrendertarget.d.ts.map +1 -1
- package/build/video/rendertarget/render_target_pool.d.ts +73 -0
- package/build/video/rendertarget/render_target_pool.d.ts.map +1 -0
- package/build/video/rendertarget/rendertarget.d.ts +77 -0
- package/build/video/rendertarget/rendertarget.d.ts.map +1 -0
- package/build/video/rendertarget/webglrendertarget.d.ts +30 -0
- package/build/video/rendertarget/webglrendertarget.d.ts.map +1 -0
- package/build/video/webgl/batchers/batcher.d.ts +4 -4
- package/build/video/webgl/batchers/batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/quad_batcher.d.ts +15 -2
- package/build/video/webgl/batchers/quad_batcher.d.ts.map +1 -1
- package/build/video/webgl/buffer/index.d.ts +5 -34
- package/build/video/webgl/buffer/index.d.ts.map +1 -1
- package/build/video/webgl/effects/colorMatrix.d.ts +92 -0
- package/build/video/webgl/effects/colorMatrix.d.ts.map +1 -0
- package/build/video/webgl/effects/desaturate.d.ts +2 -4
- package/build/video/webgl/effects/desaturate.d.ts.map +1 -1
- package/build/video/webgl/effects/invert.d.ts +2 -2
- package/build/video/webgl/effects/invert.d.ts.map +1 -1
- package/build/video/webgl/effects/sepia.d.ts +2 -2
- package/build/video/webgl/effects/sepia.d.ts.map +1 -1
- package/build/video/webgl/effects/vignette.d.ts +42 -0
- package/build/video/webgl/effects/vignette.d.ts.map +1 -0
- package/build/video/webgl/webgl_renderer.d.ts +8 -8
- package/build/video/webgl/webgl_renderer.d.ts.map +1 -1
- package/package.json +1 -1
- package/build/video/webgl/buffer/vertex.d.ts.map +0 -1
package/build/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* melonJS Game Engine - 19.
|
|
2
|
+
* melonJS Game Engine - 19.2.0
|
|
3
3
|
* http://www.melonjs.org
|
|
4
4
|
* melonjs is licensed under the MIT License.
|
|
5
5
|
* http://www.opensource.org/licenses/mit-license
|
|
@@ -7060,31 +7060,8 @@ function unbindKey(keyCode) {
|
|
|
7060
7060
|
delete _preventDefaultForKeys[keyCode];
|
|
7061
7061
|
}
|
|
7062
7062
|
|
|
7063
|
-
// src/lang/console.js
|
|
7064
|
-
function warning(deprecated, replacement, version2) {
|
|
7065
|
-
const msg = "melonJS: %s is deprecated since version %s, please use %s";
|
|
7066
|
-
const stack = new Error().stack;
|
|
7067
|
-
if (console.groupCollapsed) {
|
|
7068
|
-
console.groupCollapsed(
|
|
7069
|
-
"%c" + msg,
|
|
7070
|
-
"font-weight:normal;color:yellow;",
|
|
7071
|
-
deprecated,
|
|
7072
|
-
version2,
|
|
7073
|
-
replacement
|
|
7074
|
-
);
|
|
7075
|
-
} else {
|
|
7076
|
-
console.warn(msg, deprecated, version2, replacement);
|
|
7077
|
-
}
|
|
7078
|
-
if (typeof stack !== "undefined") {
|
|
7079
|
-
console.warn(stack);
|
|
7080
|
-
}
|
|
7081
|
-
if (console.groupCollapsed) {
|
|
7082
|
-
console.groupEnd();
|
|
7083
|
-
}
|
|
7084
|
-
}
|
|
7085
|
-
|
|
7086
7063
|
// src/geometries/ellipse.ts
|
|
7087
|
-
var Ellipse = class
|
|
7064
|
+
var Ellipse = class {
|
|
7088
7065
|
/**
|
|
7089
7066
|
* the center coordinates of the ellipse
|
|
7090
7067
|
*/
|
|
@@ -7352,7 +7329,7 @@ var Ellipse = class _Ellipse {
|
|
|
7352
7329
|
* @returns new Ellipse
|
|
7353
7330
|
*/
|
|
7354
7331
|
clone() {
|
|
7355
|
-
const clone =
|
|
7332
|
+
const clone = ellipsePool.get(
|
|
7356
7333
|
this.pos.x,
|
|
7357
7334
|
this.pos.y,
|
|
7358
7335
|
this.radiusV.x * 2,
|
|
@@ -8986,6 +8963,73 @@ var Matrix3d = class {
|
|
|
8986
8963
|
a[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
|
8987
8964
|
return this;
|
|
8988
8965
|
}
|
|
8966
|
+
transform(b00, b01, b02, b03, b10, b11, b12, b13, b20, b21, b22, b23, b30, b31, b32, b33) {
|
|
8967
|
+
const argc = arguments.length;
|
|
8968
|
+
if (argc !== 6 && argc !== 16) {
|
|
8969
|
+
throw new Error(`transform() requires 6 or 16 arguments, got ${argc}`);
|
|
8970
|
+
}
|
|
8971
|
+
let c0, c1, c2, c3;
|
|
8972
|
+
let c4, c5, c6, c7;
|
|
8973
|
+
let c8, c9, c10, c11;
|
|
8974
|
+
let c12, c13, c14, c15;
|
|
8975
|
+
if (argc === 6) {
|
|
8976
|
+
c0 = b00;
|
|
8977
|
+
c1 = b01;
|
|
8978
|
+
c2 = 0;
|
|
8979
|
+
c3 = 0;
|
|
8980
|
+
c4 = b02;
|
|
8981
|
+
c5 = b03;
|
|
8982
|
+
c6 = 0;
|
|
8983
|
+
c7 = 0;
|
|
8984
|
+
c8 = 0;
|
|
8985
|
+
c9 = 0;
|
|
8986
|
+
c10 = 1;
|
|
8987
|
+
c11 = 0;
|
|
8988
|
+
c12 = b10;
|
|
8989
|
+
c13 = b11;
|
|
8990
|
+
c14 = 0;
|
|
8991
|
+
c15 = 1;
|
|
8992
|
+
} else {
|
|
8993
|
+
c0 = b00;
|
|
8994
|
+
c1 = b01;
|
|
8995
|
+
c2 = b02;
|
|
8996
|
+
c3 = b03;
|
|
8997
|
+
c4 = b10;
|
|
8998
|
+
c5 = b11;
|
|
8999
|
+
c6 = b12;
|
|
9000
|
+
c7 = b13;
|
|
9001
|
+
c8 = b20;
|
|
9002
|
+
c9 = b21;
|
|
9003
|
+
c10 = b22;
|
|
9004
|
+
c11 = b23;
|
|
9005
|
+
c12 = b30;
|
|
9006
|
+
c13 = b31;
|
|
9007
|
+
c14 = b32;
|
|
9008
|
+
c15 = b33;
|
|
9009
|
+
}
|
|
9010
|
+
const a = this.val;
|
|
9011
|
+
const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];
|
|
9012
|
+
const a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];
|
|
9013
|
+
const a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];
|
|
9014
|
+
const a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
|
|
9015
|
+
a[0] = c0 * a00 + c1 * a10 + c2 * a20 + c3 * a30;
|
|
9016
|
+
a[1] = c0 * a01 + c1 * a11 + c2 * a21 + c3 * a31;
|
|
9017
|
+
a[2] = c0 * a02 + c1 * a12 + c2 * a22 + c3 * a32;
|
|
9018
|
+
a[3] = c0 * a03 + c1 * a13 + c2 * a23 + c3 * a33;
|
|
9019
|
+
a[4] = c4 * a00 + c5 * a10 + c6 * a20 + c7 * a30;
|
|
9020
|
+
a[5] = c4 * a01 + c5 * a11 + c6 * a21 + c7 * a31;
|
|
9021
|
+
a[6] = c4 * a02 + c5 * a12 + c6 * a22 + c7 * a32;
|
|
9022
|
+
a[7] = c4 * a03 + c5 * a13 + c6 * a23 + c7 * a33;
|
|
9023
|
+
a[8] = c8 * a00 + c9 * a10 + c10 * a20 + c11 * a30;
|
|
9024
|
+
a[9] = c8 * a01 + c9 * a11 + c10 * a21 + c11 * a31;
|
|
9025
|
+
a[10] = c8 * a02 + c9 * a12 + c10 * a22 + c11 * a32;
|
|
9026
|
+
a[11] = c8 * a03 + c9 * a13 + c10 * a23 + c11 * a33;
|
|
9027
|
+
a[12] = c12 * a00 + c13 * a10 + c14 * a20 + c15 * a30;
|
|
9028
|
+
a[13] = c12 * a01 + c13 * a11 + c14 * a21 + c15 * a31;
|
|
9029
|
+
a[14] = c12 * a02 + c13 * a12 + c14 * a22 + c15 * a32;
|
|
9030
|
+
a[15] = c12 * a03 + c13 * a13 + c14 * a23 + c15 * a33;
|
|
9031
|
+
return this;
|
|
9032
|
+
}
|
|
8989
9033
|
/**
|
|
8990
9034
|
* Transpose the value of this matrix.
|
|
8991
9035
|
* @returns Reference to this object for method chaining
|
|
@@ -9436,12 +9480,12 @@ var Matrix2d = class {
|
|
|
9436
9480
|
}
|
|
9437
9481
|
/**
|
|
9438
9482
|
* Multiplies the current transformation with the matrix described by the arguments of this method.
|
|
9439
|
-
* @param a a component
|
|
9440
|
-
* @param b b component
|
|
9441
|
-
* @param c c component
|
|
9442
|
-
* @param d d component
|
|
9443
|
-
* @param e e component
|
|
9444
|
-
* @param f f component
|
|
9483
|
+
* @param a - a component (scale x / cos)
|
|
9484
|
+
* @param b - b component (skew y / sin)
|
|
9485
|
+
* @param c - c component (skew x / -sin)
|
|
9486
|
+
* @param d - d component (scale y / cos)
|
|
9487
|
+
* @param e - e component (translate x)
|
|
9488
|
+
* @param f - f component (translate y)
|
|
9445
9489
|
* @returns Reference to this object for method chaining
|
|
9446
9490
|
*/
|
|
9447
9491
|
transform(a, b, c, d, e, f) {
|
|
@@ -10244,6 +10288,238 @@ function unloadAll() {
|
|
|
10244
10288
|
}
|
|
10245
10289
|
}
|
|
10246
10290
|
|
|
10291
|
+
// src/camera/effects/camera_effect.ts
|
|
10292
|
+
var CameraEffect = class {
|
|
10293
|
+
/**
|
|
10294
|
+
* the camera this effect is attached to
|
|
10295
|
+
*/
|
|
10296
|
+
camera;
|
|
10297
|
+
/**
|
|
10298
|
+
* whether this effect has finished and should be removed
|
|
10299
|
+
*/
|
|
10300
|
+
isComplete;
|
|
10301
|
+
/**
|
|
10302
|
+
* whether this effect should persist across camera/game resets
|
|
10303
|
+
* (e.g. transition effects that span state changes)
|
|
10304
|
+
* @default false
|
|
10305
|
+
*/
|
|
10306
|
+
isPersistent;
|
|
10307
|
+
/**
|
|
10308
|
+
* @param camera - the camera this effect is attached to
|
|
10309
|
+
*/
|
|
10310
|
+
constructor(camera) {
|
|
10311
|
+
this.camera = camera;
|
|
10312
|
+
this.isComplete = false;
|
|
10313
|
+
this.isPersistent = false;
|
|
10314
|
+
}
|
|
10315
|
+
/**
|
|
10316
|
+
* Called each frame to update the effect state (e.g. modify camera offset, countdown duration).
|
|
10317
|
+
* @param _dt - time elapsed since last frame in milliseconds
|
|
10318
|
+
*/
|
|
10319
|
+
update(_dt) {
|
|
10320
|
+
}
|
|
10321
|
+
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
10322
|
+
/**
|
|
10323
|
+
* Called after the scene renders to draw visual overlays (e.g. color fills for fading).
|
|
10324
|
+
* @param _renderer - the renderer to draw with
|
|
10325
|
+
* @param _width - the camera viewport width
|
|
10326
|
+
* @param _height - the camera viewport height
|
|
10327
|
+
*/
|
|
10328
|
+
draw(_renderer2, _width, _height) {
|
|
10329
|
+
}
|
|
10330
|
+
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
10331
|
+
/**
|
|
10332
|
+
* Called when the effect is removed from the camera. Override to clean up resources.
|
|
10333
|
+
*/
|
|
10334
|
+
destroy() {
|
|
10335
|
+
}
|
|
10336
|
+
};
|
|
10337
|
+
|
|
10338
|
+
// src/camera/effects/fade_effect.ts
|
|
10339
|
+
var FadeEffect = class extends CameraEffect {
|
|
10340
|
+
/**
|
|
10341
|
+
* the overlay color
|
|
10342
|
+
*/
|
|
10343
|
+
color;
|
|
10344
|
+
/**
|
|
10345
|
+
* the tween controlling alpha transition
|
|
10346
|
+
*/
|
|
10347
|
+
tween;
|
|
10348
|
+
/**
|
|
10349
|
+
* fade direction: "in" fades to the color, "out" fades from the color back to transparent
|
|
10350
|
+
*/
|
|
10351
|
+
direction;
|
|
10352
|
+
/**
|
|
10353
|
+
* target alpha value for completion check
|
|
10354
|
+
* @ignore
|
|
10355
|
+
*/
|
|
10356
|
+
_targetAlpha;
|
|
10357
|
+
/**
|
|
10358
|
+
* @param camera - the camera to apply the fade to
|
|
10359
|
+
* @param options - fade parameters
|
|
10360
|
+
* @param options.color - CSS color value or Color instance
|
|
10361
|
+
* @param [options.duration=1000] - fade duration in milliseconds
|
|
10362
|
+
* @param [options.direction="in"] - "in" fades to color, "out" fades from color to transparent
|
|
10363
|
+
* @param [options.onComplete] - callback when the fade finishes
|
|
10364
|
+
*/
|
|
10365
|
+
constructor(camera, options) {
|
|
10366
|
+
super(camera);
|
|
10367
|
+
const duration = options.duration ?? 1e3;
|
|
10368
|
+
this.direction = options.direction ?? "in";
|
|
10369
|
+
this.color = colorPool.get(options.color);
|
|
10370
|
+
if (this.direction === "in") {
|
|
10371
|
+
this._targetAlpha = this.color.alpha;
|
|
10372
|
+
this.color.alpha = 0;
|
|
10373
|
+
this.tween = tweenPool.get(this.color).to({ alpha: this._targetAlpha }, { duration });
|
|
10374
|
+
} else {
|
|
10375
|
+
this._targetAlpha = 0;
|
|
10376
|
+
this.tween = tweenPool.get(this.color).to({ alpha: 0 }, { duration });
|
|
10377
|
+
}
|
|
10378
|
+
if (options.onComplete) {
|
|
10379
|
+
this.tween.onComplete(options.onComplete);
|
|
10380
|
+
}
|
|
10381
|
+
this.tween.isPersistent = true;
|
|
10382
|
+
this.tween.start();
|
|
10383
|
+
}
|
|
10384
|
+
draw(renderer2, width, height) {
|
|
10385
|
+
if (this.color.alpha === 0) {
|
|
10386
|
+
return;
|
|
10387
|
+
}
|
|
10388
|
+
const r = renderer2;
|
|
10389
|
+
r.save();
|
|
10390
|
+
r.resetTransform();
|
|
10391
|
+
r.setColor(this.color);
|
|
10392
|
+
r.fillRect(0, 0, width, height);
|
|
10393
|
+
r.restore();
|
|
10394
|
+
}
|
|
10395
|
+
update() {
|
|
10396
|
+
if (this.direction === "in" && this.color.alpha >= this._targetAlpha) {
|
|
10397
|
+
this.isComplete = true;
|
|
10398
|
+
} else if (this.direction === "out" && this.color.alpha <= 0) {
|
|
10399
|
+
this.isComplete = true;
|
|
10400
|
+
}
|
|
10401
|
+
}
|
|
10402
|
+
destroy() {
|
|
10403
|
+
this.tween.stop();
|
|
10404
|
+
tweenPool.release(this.tween);
|
|
10405
|
+
colorPool.release(this.color);
|
|
10406
|
+
}
|
|
10407
|
+
};
|
|
10408
|
+
|
|
10409
|
+
// src/camera/effects/mask_effect.ts
|
|
10410
|
+
var MaskEffect = class extends CameraEffect {
|
|
10411
|
+
/**
|
|
10412
|
+
* the transition fill color
|
|
10413
|
+
*/
|
|
10414
|
+
color;
|
|
10415
|
+
/**
|
|
10416
|
+
* the mask shape template (unit-sized, centered at origin)
|
|
10417
|
+
*/
|
|
10418
|
+
shape;
|
|
10419
|
+
/**
|
|
10420
|
+
* current progress value (0 = fully covered, 1 = fully visible)
|
|
10421
|
+
*/
|
|
10422
|
+
progress;
|
|
10423
|
+
/**
|
|
10424
|
+
* the tween controlling progress
|
|
10425
|
+
*/
|
|
10426
|
+
tween;
|
|
10427
|
+
/**
|
|
10428
|
+
* transition direction
|
|
10429
|
+
*/
|
|
10430
|
+
direction;
|
|
10431
|
+
/**
|
|
10432
|
+
* optional callback when transition completes
|
|
10433
|
+
*/
|
|
10434
|
+
onComplete;
|
|
10435
|
+
/**
|
|
10436
|
+
* pooled shape used for rendering (avoids per-frame allocation)
|
|
10437
|
+
* @ignore
|
|
10438
|
+
*/
|
|
10439
|
+
_maskShape;
|
|
10440
|
+
/**
|
|
10441
|
+
* @param camera - the camera to apply the transition to
|
|
10442
|
+
* @param options - transition parameters
|
|
10443
|
+
* @param options.shape - an Ellipse or Polygon (unit-sized, centered at origin) defining the mask shape
|
|
10444
|
+
* @param options.color - CSS color value or Color instance for the transition fill
|
|
10445
|
+
* @param [options.duration=500] - transition duration in milliseconds
|
|
10446
|
+
* @param [options.direction="hide"] - "hide" shrinks the visible area, "reveal" grows it
|
|
10447
|
+
* @param [options.onComplete] - callback when the transition finishes
|
|
10448
|
+
*/
|
|
10449
|
+
constructor(camera, options) {
|
|
10450
|
+
super(camera);
|
|
10451
|
+
this.color = colorPool.get(options.color);
|
|
10452
|
+
this.direction = options.direction ?? "hide";
|
|
10453
|
+
this.onComplete = options.onComplete;
|
|
10454
|
+
this.shape = options.shape;
|
|
10455
|
+
this._maskShape = this.shape.clone();
|
|
10456
|
+
const duration = options.duration ?? 500;
|
|
10457
|
+
if (this.direction === "hide") {
|
|
10458
|
+
this.progress = { value: 1 };
|
|
10459
|
+
this.tween = tweenPool.get(this.progress).to({ value: 0 }, { duration });
|
|
10460
|
+
} else {
|
|
10461
|
+
this.progress = { value: 0 };
|
|
10462
|
+
this.tween = tweenPool.get(this.progress).to({ value: 1 }, { duration });
|
|
10463
|
+
}
|
|
10464
|
+
this.tween.isPersistent = true;
|
|
10465
|
+
this.tween.start();
|
|
10466
|
+
}
|
|
10467
|
+
update() {
|
|
10468
|
+
if (this.direction === "hide" && this.progress.value <= 0 || this.direction === "reveal" && this.progress.value >= 1) {
|
|
10469
|
+
this.progress.value = this.direction === "hide" ? 0 : 1;
|
|
10470
|
+
this.isComplete = true;
|
|
10471
|
+
if (typeof this.onComplete === "function") {
|
|
10472
|
+
this.onComplete();
|
|
10473
|
+
}
|
|
10474
|
+
return;
|
|
10475
|
+
}
|
|
10476
|
+
const width = this.camera.width;
|
|
10477
|
+
const height = this.camera.height;
|
|
10478
|
+
const maxRadius = Math.sqrt(width * width + height * height) / 2;
|
|
10479
|
+
const scale2 = this.progress.value * maxRadius;
|
|
10480
|
+
const cx = width / 2;
|
|
10481
|
+
const cy = height / 2;
|
|
10482
|
+
if (this._maskShape.type === "Ellipse") {
|
|
10483
|
+
this._maskShape.setShape(cx, cy, scale2 * 2, scale2 * 2);
|
|
10484
|
+
} else {
|
|
10485
|
+
const mask = this._maskShape;
|
|
10486
|
+
const srcPoints = this.shape.points;
|
|
10487
|
+
for (let i = 0; i < srcPoints.length; i++) {
|
|
10488
|
+
mask.points[i].set(srcPoints[i].x * scale2, srcPoints[i].y * scale2);
|
|
10489
|
+
}
|
|
10490
|
+
mask.pos.set(cx, cy);
|
|
10491
|
+
}
|
|
10492
|
+
}
|
|
10493
|
+
draw(renderer2, width, height) {
|
|
10494
|
+
if (this.isComplete && this.direction === "reveal") {
|
|
10495
|
+
return;
|
|
10496
|
+
}
|
|
10497
|
+
const r = renderer2;
|
|
10498
|
+
r.save();
|
|
10499
|
+
r.resetTransform();
|
|
10500
|
+
if (this.progress.value <= 0) {
|
|
10501
|
+
r.setColor(this.color);
|
|
10502
|
+
r.fillRect(0, 0, width, height);
|
|
10503
|
+
} else {
|
|
10504
|
+
r.setMask(this._maskShape, true);
|
|
10505
|
+
r.setColor(this.color);
|
|
10506
|
+
r.fillRect(0, 0, width, height);
|
|
10507
|
+
r.clearMask();
|
|
10508
|
+
}
|
|
10509
|
+
r.restore();
|
|
10510
|
+
}
|
|
10511
|
+
destroy() {
|
|
10512
|
+
this.tween.stop();
|
|
10513
|
+
tweenPool.release(this.tween);
|
|
10514
|
+
colorPool.release(this.color);
|
|
10515
|
+
if (this._maskShape.type === "Ellipse") {
|
|
10516
|
+
ellipsePool.release(this._maskShape);
|
|
10517
|
+
} else {
|
|
10518
|
+
polygonPool.release(this._maskShape);
|
|
10519
|
+
}
|
|
10520
|
+
}
|
|
10521
|
+
};
|
|
10522
|
+
|
|
10247
10523
|
// src/geometries/observablePoint.ts
|
|
10248
10524
|
var ObservablePoint = class _ObservablePoint {
|
|
10249
10525
|
_callback;
|
|
@@ -11461,7 +11737,8 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11461
11737
|
this.alpha = 1;
|
|
11462
11738
|
this.ancestor = void 0;
|
|
11463
11739
|
this.mask = void 0;
|
|
11464
|
-
this.
|
|
11740
|
+
this.postEffects = [];
|
|
11741
|
+
this._postEffectManaged = false;
|
|
11465
11742
|
this.blendMode = "normal";
|
|
11466
11743
|
this.name = "";
|
|
11467
11744
|
this.isRenderable = true;
|
|
@@ -11539,6 +11816,82 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11539
11816
|
}
|
|
11540
11817
|
}
|
|
11541
11818
|
}
|
|
11819
|
+
/**
|
|
11820
|
+
* @deprecated since 19.2.0 — use {@link addPostEffect} / {@link getPostEffect} / {@link removePostEffect} instead
|
|
11821
|
+
* @type {GLShader|ShaderEffect|undefined}
|
|
11822
|
+
*/
|
|
11823
|
+
get shader() {
|
|
11824
|
+
return this.postEffects[0];
|
|
11825
|
+
}
|
|
11826
|
+
set shader(value) {
|
|
11827
|
+
for (const effect of this.postEffects) {
|
|
11828
|
+
if (typeof effect.destroy === "function") {
|
|
11829
|
+
effect.destroy();
|
|
11830
|
+
}
|
|
11831
|
+
}
|
|
11832
|
+
if (typeof value === "undefined") {
|
|
11833
|
+
this.postEffects.length = 0;
|
|
11834
|
+
} else {
|
|
11835
|
+
this.postEffects = [value];
|
|
11836
|
+
}
|
|
11837
|
+
}
|
|
11838
|
+
/**
|
|
11839
|
+
* Add a post-processing shader effect to this renderable.
|
|
11840
|
+
* @param {GLShader|ShaderEffect} effect - the effect to add
|
|
11841
|
+
* @returns {GLShader|ShaderEffect} the added effect
|
|
11842
|
+
* @example
|
|
11843
|
+
* mySprite.addPostEffect(new DesaturateEffect(renderer));
|
|
11844
|
+
*/
|
|
11845
|
+
addPostEffect(effect) {
|
|
11846
|
+
this.postEffects.push(effect);
|
|
11847
|
+
return effect;
|
|
11848
|
+
}
|
|
11849
|
+
/**
|
|
11850
|
+
* Get post-processing shader effects.
|
|
11851
|
+
* When called with a class, returns the first effect matching the given class.
|
|
11852
|
+
* When called without arguments, returns the full effects array.
|
|
11853
|
+
* @param {Function} [effectClass] - the effect class to search for
|
|
11854
|
+
* @returns {GLShader|ShaderEffect|Array|undefined} the matching effect, the effects array, or undefined
|
|
11855
|
+
* @example
|
|
11856
|
+
* const desat = sprite.getPostEffect(DesaturateEffect);
|
|
11857
|
+
* const allEffects = sprite.getPostEffect();
|
|
11858
|
+
*/
|
|
11859
|
+
getPostEffect(effectClass) {
|
|
11860
|
+
if (typeof effectClass === "undefined") {
|
|
11861
|
+
return this.postEffects;
|
|
11862
|
+
}
|
|
11863
|
+
return this.postEffects.find((fx) => {
|
|
11864
|
+
return fx instanceof effectClass;
|
|
11865
|
+
});
|
|
11866
|
+
}
|
|
11867
|
+
/**
|
|
11868
|
+
* Remove all post-processing shader effects.
|
|
11869
|
+
* @example
|
|
11870
|
+
* sprite.clearPostEffects();
|
|
11871
|
+
*/
|
|
11872
|
+
clearPostEffects() {
|
|
11873
|
+
for (const effect of this.postEffects) {
|
|
11874
|
+
if (typeof effect.destroy === "function") {
|
|
11875
|
+
effect.destroy();
|
|
11876
|
+
}
|
|
11877
|
+
}
|
|
11878
|
+
this.postEffects.length = 0;
|
|
11879
|
+
}
|
|
11880
|
+
/**
|
|
11881
|
+
* Remove a specific post-processing shader effect.
|
|
11882
|
+
* @param {GLShader|ShaderEffect} effect - the effect to remove
|
|
11883
|
+
* @example
|
|
11884
|
+
* sprite.removePostEffect(effect);
|
|
11885
|
+
*/
|
|
11886
|
+
removePostEffect(effect) {
|
|
11887
|
+
const idx = this.postEffects.indexOf(effect);
|
|
11888
|
+
if (idx !== -1) {
|
|
11889
|
+
this.postEffects.splice(idx, 1);
|
|
11890
|
+
if (typeof effect.destroy === "function") {
|
|
11891
|
+
effect.destroy();
|
|
11892
|
+
}
|
|
11893
|
+
}
|
|
11894
|
+
}
|
|
11542
11895
|
/**
|
|
11543
11896
|
* returns true if this renderable is flipped on the horizontal axis
|
|
11544
11897
|
* @public
|
|
@@ -11820,8 +12173,8 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11820
12173
|
renderer2.setMask(this.mask);
|
|
11821
12174
|
renderer2.translate(-this.pos.x, -this.pos.y);
|
|
11822
12175
|
}
|
|
11823
|
-
if (this.
|
|
11824
|
-
renderer2.
|
|
12176
|
+
if (!this._postEffectManaged) {
|
|
12177
|
+
renderer2.beginPostEffect(this);
|
|
11825
12178
|
}
|
|
11826
12179
|
if (this.autoTransform === true && !this.currentTransform.isIdentity()) {
|
|
11827
12180
|
renderer2.translate(this.pos.x, this.pos.y);
|
|
@@ -11861,8 +12214,8 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11861
12214
|
if (this.mask) {
|
|
11862
12215
|
renderer2.clearMask();
|
|
11863
12216
|
}
|
|
11864
|
-
if (this.
|
|
11865
|
-
renderer2.
|
|
12217
|
+
if (!this._postEffectManaged) {
|
|
12218
|
+
renderer2.endPostEffect(this);
|
|
11866
12219
|
}
|
|
11867
12220
|
renderer2.restore();
|
|
11868
12221
|
this.isDirty = false;
|
|
@@ -11924,10 +12277,12 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11924
12277
|
}
|
|
11925
12278
|
releaseAllPointerEvents(this);
|
|
11926
12279
|
this.onDestroyEvent.apply(this, arguments);
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
12280
|
+
for (const effect of this.postEffects) {
|
|
12281
|
+
if (typeof effect.destroy === "function") {
|
|
12282
|
+
effect.destroy();
|
|
12283
|
+
}
|
|
11930
12284
|
}
|
|
12285
|
+
this.postEffects.length = 0;
|
|
11931
12286
|
}
|
|
11932
12287
|
/**
|
|
11933
12288
|
* OnDestroy Notification function<br>
|
|
@@ -11966,6 +12321,29 @@ __export(loader_exports, {
|
|
|
11966
12321
|
withCredentials: () => withCredentials
|
|
11967
12322
|
});
|
|
11968
12323
|
|
|
12324
|
+
// src/lang/console.js
|
|
12325
|
+
function warning(deprecated, replacement, version2) {
|
|
12326
|
+
const msg = "melonJS: %s is deprecated since version %s, please use %s";
|
|
12327
|
+
const stack = new Error().stack;
|
|
12328
|
+
if (console.groupCollapsed) {
|
|
12329
|
+
console.groupCollapsed(
|
|
12330
|
+
"%c" + msg,
|
|
12331
|
+
"font-weight:normal;color:yellow;",
|
|
12332
|
+
deprecated,
|
|
12333
|
+
version2,
|
|
12334
|
+
replacement
|
|
12335
|
+
);
|
|
12336
|
+
} else {
|
|
12337
|
+
console.warn(msg, deprecated, version2, replacement);
|
|
12338
|
+
}
|
|
12339
|
+
if (typeof stack !== "undefined") {
|
|
12340
|
+
console.warn(stack);
|
|
12341
|
+
}
|
|
12342
|
+
if (console.groupCollapsed) {
|
|
12343
|
+
console.groupEnd();
|
|
12344
|
+
}
|
|
12345
|
+
}
|
|
12346
|
+
|
|
11969
12347
|
// src/utils/file.ts
|
|
11970
12348
|
var file_exports = {};
|
|
11971
12349
|
__export(file_exports, {
|
|
@@ -13805,6 +14183,97 @@ var TMX_FLIP_AD = 536870912;
|
|
|
13805
14183
|
var TMX_CLEAR_BIT_MASK = ~(TMX_FLIP_H | TMX_FLIP_V | TMX_FLIP_AD);
|
|
13806
14184
|
var COLLISION_GROUP = "collision";
|
|
13807
14185
|
|
|
14186
|
+
// src/video/rendertarget/rendertarget.ts
|
|
14187
|
+
var RenderTarget = class {
|
|
14188
|
+
/**
|
|
14189
|
+
* Bind this render target as the active draw destination.
|
|
14190
|
+
* All subsequent draw calls will render into this target until {@link unbind} is called.
|
|
14191
|
+
* No-op by default — subclasses override for GPU render targets (e.g. WebGL FBOs).
|
|
14192
|
+
*/
|
|
14193
|
+
bind() {
|
|
14194
|
+
}
|
|
14195
|
+
/**
|
|
14196
|
+
* Unbind this render target, restoring the default (screen) output.
|
|
14197
|
+
* No-op by default — subclasses override for GPU render targets.
|
|
14198
|
+
*/
|
|
14199
|
+
unbind() {
|
|
14200
|
+
}
|
|
14201
|
+
/**
|
|
14202
|
+
* Creates a Blob object representing the image contained in this render target.
|
|
14203
|
+
* @param type - a string indicating the image format (default "image/png")
|
|
14204
|
+
* @param quality - a number between 0 and 1 for lossy formats (e.g. image/jpeg)
|
|
14205
|
+
* @returns a Promise resolving to a Blob
|
|
14206
|
+
*/
|
|
14207
|
+
toBlob(type = "image/png", quality) {
|
|
14208
|
+
const imageData = this.getImageData();
|
|
14209
|
+
if (typeof OffscreenCanvas !== "undefined") {
|
|
14210
|
+
const canvas2 = new OffscreenCanvas(this.width, this.height);
|
|
14211
|
+
const ctx2 = canvas2.getContext("2d");
|
|
14212
|
+
if (!ctx2) {
|
|
14213
|
+
return Promise.reject(new Error("Failed to get 2d context"));
|
|
14214
|
+
}
|
|
14215
|
+
ctx2.putImageData(imageData, 0, 0);
|
|
14216
|
+
const options = { type };
|
|
14217
|
+
if (typeof quality !== "undefined") {
|
|
14218
|
+
options.quality = quality;
|
|
14219
|
+
}
|
|
14220
|
+
return canvas2.convertToBlob(options);
|
|
14221
|
+
}
|
|
14222
|
+
const canvas = document.createElement("canvas");
|
|
14223
|
+
canvas.width = this.width;
|
|
14224
|
+
canvas.height = this.height;
|
|
14225
|
+
const ctx = canvas.getContext("2d");
|
|
14226
|
+
if (!ctx) {
|
|
14227
|
+
return Promise.reject(new Error("Failed to get 2d context"));
|
|
14228
|
+
}
|
|
14229
|
+
ctx.putImageData(imageData, 0, 0);
|
|
14230
|
+
return new Promise((resolve, reject) => {
|
|
14231
|
+
canvas.toBlob(
|
|
14232
|
+
(blob) => {
|
|
14233
|
+
if (blob) {
|
|
14234
|
+
resolve(blob);
|
|
14235
|
+
} else {
|
|
14236
|
+
reject(new Error(`toBlob failed for type "${type}"`));
|
|
14237
|
+
}
|
|
14238
|
+
},
|
|
14239
|
+
type,
|
|
14240
|
+
quality
|
|
14241
|
+
);
|
|
14242
|
+
});
|
|
14243
|
+
}
|
|
14244
|
+
/**
|
|
14245
|
+
* Creates an ImageBitmap object from the current contents of this render target.
|
|
14246
|
+
* @returns a Promise resolving to an ImageBitmap
|
|
14247
|
+
*/
|
|
14248
|
+
toImageBitmap() {
|
|
14249
|
+
const imageData = this.getImageData();
|
|
14250
|
+
return globalThis.createImageBitmap(imageData);
|
|
14251
|
+
}
|
|
14252
|
+
/**
|
|
14253
|
+
* Returns a data URL containing a representation of the current contents.
|
|
14254
|
+
* @param type - a string indicating the image format (default "image/png")
|
|
14255
|
+
* @param quality - a number between 0 and 1 for lossy formats (e.g. image/jpeg)
|
|
14256
|
+
* @returns a Promise resolving to a data URL string
|
|
14257
|
+
*/
|
|
14258
|
+
toDataURL(type = "image/png", quality) {
|
|
14259
|
+
return this.toBlob(type, quality).then((blob) => {
|
|
14260
|
+
const reader = new FileReader();
|
|
14261
|
+
return new Promise((resolve, reject) => {
|
|
14262
|
+
reader.onload = () => {
|
|
14263
|
+
resolve(reader.result);
|
|
14264
|
+
};
|
|
14265
|
+
reader.onerror = () => {
|
|
14266
|
+
reject(new Error(reader.error?.message ?? "FileReader failed"));
|
|
14267
|
+
};
|
|
14268
|
+
reader.onabort = () => {
|
|
14269
|
+
reject(new Error("FileReader aborted"));
|
|
14270
|
+
};
|
|
14271
|
+
reader.readAsDataURL(blob);
|
|
14272
|
+
});
|
|
14273
|
+
});
|
|
14274
|
+
}
|
|
14275
|
+
};
|
|
14276
|
+
|
|
13808
14277
|
// src/video/rendertarget/canvasrendertarget.js
|
|
13809
14278
|
var defaultAttributes = {
|
|
13810
14279
|
offscreenCanvas: false,
|
|
@@ -13855,7 +14324,7 @@ function createContext(canvas, attributes) {
|
|
|
13855
14324
|
}
|
|
13856
14325
|
return context;
|
|
13857
14326
|
}
|
|
13858
|
-
var CanvasRenderTarget = class {
|
|
14327
|
+
var CanvasRenderTarget = class extends RenderTarget {
|
|
13859
14328
|
/**
|
|
13860
14329
|
* @param {number} width - the desired width of the canvas
|
|
13861
14330
|
* @param {number} height - the desired height of the canvas
|
|
@@ -13868,6 +14337,7 @@ var CanvasRenderTarget = class {
|
|
|
13868
14337
|
* @param {boolean} [attributes.antiAlias=false] - Whether to enable anti-aliasing, use false (default) for a pixelated effect.
|
|
13869
14338
|
*/
|
|
13870
14339
|
constructor(width, height, attributes = defaultAttributes) {
|
|
14340
|
+
super();
|
|
13871
14341
|
this.attributes = Object.assign({}, defaultAttributes, attributes);
|
|
13872
14342
|
if (typeof attributes.context === "undefined") {
|
|
13873
14343
|
attributes.context = "2d";
|
|
@@ -13947,64 +14417,48 @@ var CanvasRenderTarget = class {
|
|
|
13947
14417
|
return this.context.getImageData(x, y, width, height);
|
|
13948
14418
|
}
|
|
13949
14419
|
/**
|
|
13950
|
-
*
|
|
14420
|
+
* Returns a data URL directly from the canvas (avoids the getImageData/Blob round-trip).
|
|
14421
|
+
* Note: not supported by OffscreenCanvas — falls back to the base implementation.
|
|
13951
14422
|
* @param {string} [type="image/png"] - A string indicating the image format
|
|
13952
|
-
* @param {number} [quality] - A
|
|
13953
|
-
* @returns {Promise} A Promise
|
|
13954
|
-
* @example
|
|
13955
|
-
* renderTarget.convertToBlob().then((blob) => console.log(blob));
|
|
14423
|
+
* @param {number} [quality] - A number between 0 and 1 for lossy formats (image/jpeg, image/webp)
|
|
14424
|
+
* @returns {Promise<string>} A Promise resolving to a data URL string
|
|
13956
14425
|
*/
|
|
13957
|
-
|
|
13958
|
-
if (typeof this.canvas.
|
|
13959
|
-
return this.canvas.
|
|
13960
|
-
} else {
|
|
13961
|
-
return new Promise((resolve) => {
|
|
13962
|
-
this.canvas.toBlob(
|
|
13963
|
-
(blob) => {
|
|
13964
|
-
resolve(blob);
|
|
13965
|
-
},
|
|
13966
|
-
type,
|
|
13967
|
-
quality
|
|
13968
|
-
);
|
|
13969
|
-
});
|
|
14426
|
+
toDataURL(type = "image/png", quality) {
|
|
14427
|
+
if (typeof this.canvas.toDataURL === "function") {
|
|
14428
|
+
return Promise.resolve(this.canvas.toDataURL(type, quality));
|
|
13970
14429
|
}
|
|
14430
|
+
return super.toDataURL(type, quality);
|
|
13971
14431
|
}
|
|
13972
14432
|
/**
|
|
13973
|
-
*
|
|
14433
|
+
* Creates a Blob directly from the canvas (avoids the getImageData round-trip).
|
|
13974
14434
|
* @param {string} [type="image/png"] - A string indicating the image format
|
|
13975
|
-
* @param {number} [quality] - A
|
|
13976
|
-
* @returns {Promise} A Promise
|
|
13977
|
-
* @example
|
|
13978
|
-
* renderTarget.transferToImageBitmap().then((bitmap) => console.log(bitmap));
|
|
14435
|
+
* @param {number} [quality] - A number between 0 and 1 for lossy formats (image/jpeg, image/webp)
|
|
14436
|
+
* @returns {Promise<Blob>} A Promise resolving to a Blob
|
|
13979
14437
|
*/
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
14438
|
+
toBlob(type = "image/png", quality) {
|
|
14439
|
+
if (typeof this.canvas.convertToBlob === "function") {
|
|
14440
|
+
return this.canvas.convertToBlob({ type, quality });
|
|
14441
|
+
}
|
|
14442
|
+
return new Promise((resolve, reject) => {
|
|
14443
|
+
this.canvas.toBlob(
|
|
14444
|
+
(blob) => {
|
|
14445
|
+
if (blob) {
|
|
14446
|
+
resolve(blob);
|
|
14447
|
+
} else {
|
|
14448
|
+
reject(new Error(`toBlob failed for type "${type}"`));
|
|
14449
|
+
}
|
|
14450
|
+
},
|
|
14451
|
+
type,
|
|
14452
|
+
quality
|
|
14453
|
+
);
|
|
13993
14454
|
});
|
|
13994
14455
|
}
|
|
13995
14456
|
/**
|
|
13996
|
-
*
|
|
13997
|
-
*
|
|
13998
|
-
* @param {string} [type="image/png"] - A string indicating the image format
|
|
13999
|
-
* @param {number} [quality] - A Number between 0 and 1 indicating the image quality to be used when creating images using file formats that support lossy compression (such as image/jpeg or image/webp). A user agent will use its default quality value if this option is not specified, or if the number is outside the allowed range.
|
|
14000
|
-
* @returns {Promise} A Promise returning a string containing the requested data URL.
|
|
14001
|
-
* @example
|
|
14002
|
-
* renderer.toDataURL().then((dataURL) => console.log(dataURL));
|
|
14457
|
+
* Creates an ImageBitmap directly from the canvas (avoids the getImageData round-trip).
|
|
14458
|
+
* @returns {Promise<ImageBitmap>} A Promise resolving to an ImageBitmap
|
|
14003
14459
|
*/
|
|
14004
|
-
|
|
14005
|
-
return
|
|
14006
|
-
resolve(this.canvas.toDataURL(type, quality));
|
|
14007
|
-
});
|
|
14460
|
+
toImageBitmap() {
|
|
14461
|
+
return globalThis.createImageBitmap(this.canvas);
|
|
14008
14462
|
}
|
|
14009
14463
|
/**
|
|
14010
14464
|
* invalidate the current CanvasRenderTarget, and force a reupload of the corresponding texture
|
|
@@ -14867,6 +15321,7 @@ var RenderState = class {
|
|
|
14867
15321
|
this.currentGradient = null;
|
|
14868
15322
|
this.lineDash = [];
|
|
14869
15323
|
this.currentBlendMode = "none";
|
|
15324
|
+
this.currentShader = void 0;
|
|
14870
15325
|
this._stackCapacity = 32;
|
|
14871
15326
|
this._stackDepth = 0;
|
|
14872
15327
|
this._colorStack = Array.from({ length: this._stackCapacity }, () => {
|
|
@@ -14885,6 +15340,7 @@ var RenderState = class {
|
|
|
14885
15340
|
this._scissorActive = new Uint8Array(this._stackCapacity);
|
|
14886
15341
|
this._gradientStack = new Array(this._stackCapacity);
|
|
14887
15342
|
this._blendStack = new Array(this._stackCapacity);
|
|
15343
|
+
this._shaderStack = new Array(this._stackCapacity);
|
|
14888
15344
|
}
|
|
14889
15345
|
/**
|
|
14890
15346
|
* Save the current state onto the stack (zero allocations).
|
|
@@ -14901,6 +15357,7 @@ var RenderState = class {
|
|
|
14901
15357
|
this._gradientStack[depth] = this.currentGradient;
|
|
14902
15358
|
this._lineDashStack[depth] = this.lineDash;
|
|
14903
15359
|
this._blendStack[depth] = this.currentBlendMode;
|
|
15360
|
+
this._shaderStack[depth] = this.currentShader;
|
|
14904
15361
|
if (scissorTestActive) {
|
|
14905
15362
|
this._scissorStack[depth].set(this.currentScissor);
|
|
14906
15363
|
this._scissorActive[depth] = 1;
|
|
@@ -14926,6 +15383,7 @@ var RenderState = class {
|
|
|
14926
15383
|
this.currentTransform.copy(this._matrixStack[depth]);
|
|
14927
15384
|
this.currentGradient = this._gradientStack[depth];
|
|
14928
15385
|
this.lineDash = this._lineDashStack[depth];
|
|
15386
|
+
this.currentShader = this._shaderStack[depth];
|
|
14929
15387
|
const scissorActive = !!this._scissorActive[depth];
|
|
14930
15388
|
if (scissorActive) {
|
|
14931
15389
|
this.currentScissor.set(this._scissorStack[depth]);
|
|
@@ -14951,6 +15409,7 @@ var RenderState = class {
|
|
|
14951
15409
|
this.currentScissor[1] = 0;
|
|
14952
15410
|
this.currentScissor[2] = width;
|
|
14953
15411
|
this.currentScissor[3] = height;
|
|
15412
|
+
this.currentShader = void 0;
|
|
14954
15413
|
}
|
|
14955
15414
|
/** @private — doubles stack capacity when exceeded */
|
|
14956
15415
|
_growStacks() {
|
|
@@ -14964,6 +15423,7 @@ var RenderState = class {
|
|
|
14964
15423
|
this._gradientStack.push(null);
|
|
14965
15424
|
this._lineDashStack.push([]);
|
|
14966
15425
|
this._blendStack.push(void 0);
|
|
15426
|
+
this._shaderStack.push(void 0);
|
|
14967
15427
|
}
|
|
14968
15428
|
const newScissorActive = new Uint8Array(newCap);
|
|
14969
15429
|
newScissorActive.set(this._scissorActive);
|
|
@@ -14990,6 +15450,7 @@ var Renderer = class {
|
|
|
14990
15450
|
this.isContextValid = true;
|
|
14991
15451
|
this.GPURenderer = void 0;
|
|
14992
15452
|
this.customShader = void 0;
|
|
15453
|
+
this._renderTargetPool = null;
|
|
14993
15454
|
this.path2D = new path2d_default();
|
|
14994
15455
|
this.type = "Generic";
|
|
14995
15456
|
this.backgroundColor = new Color(
|
|
@@ -15120,6 +15581,95 @@ var Renderer = class {
|
|
|
15120
15581
|
}
|
|
15121
15582
|
return false;
|
|
15122
15583
|
}
|
|
15584
|
+
/**
|
|
15585
|
+
* Begin capturing rendering to an offscreen buffer for post-effect processing.
|
|
15586
|
+
* Call endPostEffect() after rendering to blit the result to the screen.
|
|
15587
|
+
* No-op on Canvas renderer.
|
|
15588
|
+
* @param {Renderable} renderable - the renderable with postEffects to apply
|
|
15589
|
+
* @returns {boolean} false (Canvas renderer does not support post-effect processing)
|
|
15590
|
+
* @ignore
|
|
15591
|
+
*/
|
|
15592
|
+
beginPostEffect(renderable) {
|
|
15593
|
+
const effects = renderable.postEffects.filter((fx) => {
|
|
15594
|
+
return fx.enabled !== false;
|
|
15595
|
+
});
|
|
15596
|
+
if (effects.length === 1) {
|
|
15597
|
+
this.customShader = effects[0];
|
|
15598
|
+
} else {
|
|
15599
|
+
this.customShader = void 0;
|
|
15600
|
+
}
|
|
15601
|
+
return false;
|
|
15602
|
+
}
|
|
15603
|
+
/**
|
|
15604
|
+
* End post-effect capture and blit the offscreen buffer to the screen
|
|
15605
|
+
* through the renderable's post-effects.
|
|
15606
|
+
* No-op on Canvas renderer.
|
|
15607
|
+
* @param {Renderable} renderable - the renderable with postEffects to apply
|
|
15608
|
+
* @ignore
|
|
15609
|
+
*/
|
|
15610
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
|
15611
|
+
endPostEffect(renderable) {
|
|
15612
|
+
}
|
|
15613
|
+
/**
|
|
15614
|
+
* Blit a texture to the screen through a shader effect.
|
|
15615
|
+
* Draws a screen-aligned quad using the given texture as source
|
|
15616
|
+
* and the given shader for post-processing (e.g. scanlines, desaturation).
|
|
15617
|
+
* No-op on Canvas renderer.
|
|
15618
|
+
* @param {WebGLTexture} source - the source texture to blit
|
|
15619
|
+
* @param {number} x - destination x position
|
|
15620
|
+
* @param {number} y - destination y position
|
|
15621
|
+
* @param {number} width - destination width
|
|
15622
|
+
* @param {number} height - destination height
|
|
15623
|
+
* @param {ShaderEffect} shader - the shader effect to apply
|
|
15624
|
+
* @param {boolean} [keepBlend=false] - if true, keep current blend mode (for sprite compositing)
|
|
15625
|
+
*/
|
|
15626
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
|
15627
|
+
blitEffect(source, x, y, width, height, shader, keepBlend) {
|
|
15628
|
+
}
|
|
15629
|
+
/**
|
|
15630
|
+
* Sets the viewport for the renderer.
|
|
15631
|
+
* Defines the affine transformation from normalized device coordinates to window coordinates.
|
|
15632
|
+
* No-op on Canvas renderer.
|
|
15633
|
+
* @param {number} [x=0] - x coordinate of the viewport origin
|
|
15634
|
+
* @param {number} [y=0] - y coordinate of the viewport origin
|
|
15635
|
+
* @param {number} [w] - width of the viewport (defaults to canvas width)
|
|
15636
|
+
* @param {number} [h] - height of the viewport (defaults to canvas height)
|
|
15637
|
+
*/
|
|
15638
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
|
15639
|
+
setViewport(x = 0, y = 0, w, h) {
|
|
15640
|
+
}
|
|
15641
|
+
/**
|
|
15642
|
+
* Clear the current render target to transparent black (color + stencil).
|
|
15643
|
+
* Used to prepare FBOs for post-effect capture.
|
|
15644
|
+
* No-op on Canvas renderer.
|
|
15645
|
+
*/
|
|
15646
|
+
clearRenderTarget() {
|
|
15647
|
+
}
|
|
15648
|
+
/**
|
|
15649
|
+
* Enable the scissor test with the given rectangle.
|
|
15650
|
+
* No-op on Canvas renderer.
|
|
15651
|
+
* @param {number} x - x coordinate of the scissor rectangle
|
|
15652
|
+
* @param {number} y - y coordinate of the scissor rectangle
|
|
15653
|
+
* @param {number} width - width of the scissor rectangle
|
|
15654
|
+
* @param {number} height - height of the scissor rectangle
|
|
15655
|
+
*/
|
|
15656
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
|
15657
|
+
enableScissor(x, y, width, height) {
|
|
15658
|
+
}
|
|
15659
|
+
/**
|
|
15660
|
+
* Disable the scissor test, allowing rendering to the full viewport.
|
|
15661
|
+
* No-op on Canvas renderer.
|
|
15662
|
+
*/
|
|
15663
|
+
disableScissor() {
|
|
15664
|
+
}
|
|
15665
|
+
/**
|
|
15666
|
+
* Enable or disable alpha blending.
|
|
15667
|
+
* No-op on Canvas renderer (Canvas always blends).
|
|
15668
|
+
* @param {boolean} enable - true to enable blending, false to disable
|
|
15669
|
+
*/
|
|
15670
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
|
15671
|
+
setBlendEnabled(enable2) {
|
|
15672
|
+
}
|
|
15123
15673
|
/**
|
|
15124
15674
|
* returns the current blend mode for this renderer
|
|
15125
15675
|
* @returns {string} blend mode
|
|
@@ -17014,6 +17564,7 @@ var CanvasRenderer = class extends Renderer {
|
|
|
17014
17564
|
if (result !== null) {
|
|
17015
17565
|
this.setBlendMode(result.blendMode);
|
|
17016
17566
|
}
|
|
17567
|
+
this.customShader = this.renderState.currentShader;
|
|
17017
17568
|
if (typeof context.fillStyle === "string") {
|
|
17018
17569
|
this.currentColor.copy(context.fillStyle);
|
|
17019
17570
|
}
|
|
@@ -17038,6 +17589,7 @@ var CanvasRenderer = class extends Renderer {
|
|
|
17038
17589
|
*/
|
|
17039
17590
|
save() {
|
|
17040
17591
|
this.getContext().save();
|
|
17592
|
+
this.renderState.currentShader = this.customShader;
|
|
17041
17593
|
this.renderState.save();
|
|
17042
17594
|
}
|
|
17043
17595
|
/**
|
|
@@ -17285,9 +17837,8 @@ var CanvasRenderer = class extends Renderer {
|
|
|
17285
17837
|
}
|
|
17286
17838
|
this.maskLevel++;
|
|
17287
17839
|
if (invert === true) {
|
|
17288
|
-
context.
|
|
17289
|
-
context.
|
|
17290
|
-
context.fill();
|
|
17840
|
+
context.rect(0, 0, this.getCanvas().width, this.getCanvas().height);
|
|
17841
|
+
context.clip("evenodd");
|
|
17291
17842
|
} else {
|
|
17292
17843
|
context.clip();
|
|
17293
17844
|
}
|
|
@@ -21368,6 +21919,723 @@ var Sprite = class extends Renderable {
|
|
|
21368
21919
|
}
|
|
21369
21920
|
};
|
|
21370
21921
|
|
|
21922
|
+
// src/math/color_matrix.ts
|
|
21923
|
+
var ColorMatrix = class extends Matrix3d {
|
|
21924
|
+
/**
|
|
21925
|
+
* Apply a brightness adjustment.
|
|
21926
|
+
* @param amount - brightness multiplier (1.0 = normal, >1 brighter, <1 darker)
|
|
21927
|
+
* @returns this instance for chaining
|
|
21928
|
+
*/
|
|
21929
|
+
brightness(amount) {
|
|
21930
|
+
return this.transform(
|
|
21931
|
+
amount,
|
|
21932
|
+
0,
|
|
21933
|
+
0,
|
|
21934
|
+
0,
|
|
21935
|
+
0,
|
|
21936
|
+
amount,
|
|
21937
|
+
0,
|
|
21938
|
+
0,
|
|
21939
|
+
0,
|
|
21940
|
+
0,
|
|
21941
|
+
amount,
|
|
21942
|
+
0,
|
|
21943
|
+
0,
|
|
21944
|
+
0,
|
|
21945
|
+
0,
|
|
21946
|
+
1
|
|
21947
|
+
);
|
|
21948
|
+
}
|
|
21949
|
+
/**
|
|
21950
|
+
* Apply a contrast adjustment.
|
|
21951
|
+
* @param amount - contrast multiplier (1.0 = normal, >1 more contrast, <1 less)
|
|
21952
|
+
* @returns this instance for chaining
|
|
21953
|
+
*/
|
|
21954
|
+
contrast(amount) {
|
|
21955
|
+
const o = (1 - amount) / 2;
|
|
21956
|
+
return this.transform(
|
|
21957
|
+
amount,
|
|
21958
|
+
0,
|
|
21959
|
+
0,
|
|
21960
|
+
0,
|
|
21961
|
+
0,
|
|
21962
|
+
amount,
|
|
21963
|
+
0,
|
|
21964
|
+
0,
|
|
21965
|
+
0,
|
|
21966
|
+
0,
|
|
21967
|
+
amount,
|
|
21968
|
+
0,
|
|
21969
|
+
o,
|
|
21970
|
+
o,
|
|
21971
|
+
o,
|
|
21972
|
+
1
|
|
21973
|
+
);
|
|
21974
|
+
}
|
|
21975
|
+
/**
|
|
21976
|
+
* Apply a saturation adjustment.
|
|
21977
|
+
* @param amount - saturation level (0.0 = grayscale, 1.0 = normal, >1 over-saturated)
|
|
21978
|
+
* @returns this instance for chaining
|
|
21979
|
+
*/
|
|
21980
|
+
saturate(amount) {
|
|
21981
|
+
const ir = 0.299 * (1 - amount);
|
|
21982
|
+
const ig = 0.587 * (1 - amount);
|
|
21983
|
+
const ib = 0.114 * (1 - amount);
|
|
21984
|
+
return this.transform(
|
|
21985
|
+
ir + amount,
|
|
21986
|
+
ir,
|
|
21987
|
+
ir,
|
|
21988
|
+
0,
|
|
21989
|
+
ig,
|
|
21990
|
+
ig + amount,
|
|
21991
|
+
ig,
|
|
21992
|
+
0,
|
|
21993
|
+
ib,
|
|
21994
|
+
ib,
|
|
21995
|
+
ib + amount,
|
|
21996
|
+
0,
|
|
21997
|
+
0,
|
|
21998
|
+
0,
|
|
21999
|
+
0,
|
|
22000
|
+
1
|
|
22001
|
+
);
|
|
22002
|
+
}
|
|
22003
|
+
/**
|
|
22004
|
+
* Apply a hue rotation.
|
|
22005
|
+
* @param angle - rotation angle in radians
|
|
22006
|
+
* @returns this instance for chaining
|
|
22007
|
+
*/
|
|
22008
|
+
hueRotate(angle) {
|
|
22009
|
+
const cos = Math.cos(angle);
|
|
22010
|
+
const sin = Math.sin(angle);
|
|
22011
|
+
const lumR = 0.299;
|
|
22012
|
+
const lumG = 0.587;
|
|
22013
|
+
const lumB = 0.114;
|
|
22014
|
+
return this.transform(
|
|
22015
|
+
lumR + cos * (1 - lumR) + sin * -lumR,
|
|
22016
|
+
lumR + cos * -lumR + sin * 0.143,
|
|
22017
|
+
lumR + cos * -lumR + sin * -(1 - lumR),
|
|
22018
|
+
0,
|
|
22019
|
+
lumG + cos * -lumG + sin * -lumG,
|
|
22020
|
+
lumG + cos * (1 - lumG) + sin * 0.14,
|
|
22021
|
+
lumG + cos * -lumG + sin * lumG,
|
|
22022
|
+
0,
|
|
22023
|
+
lumB + cos * -lumB + sin * (1 - lumB),
|
|
22024
|
+
lumB + cos * -lumB + sin * -0.283,
|
|
22025
|
+
lumB + cos * (1 - lumB) + sin * lumB,
|
|
22026
|
+
0,
|
|
22027
|
+
0,
|
|
22028
|
+
0,
|
|
22029
|
+
0,
|
|
22030
|
+
1
|
|
22031
|
+
);
|
|
22032
|
+
}
|
|
22033
|
+
/**
|
|
22034
|
+
* Apply a sepia tone.
|
|
22035
|
+
* @param amount - sepia intensity (0.0 = original, 1.0 = full sepia)
|
|
22036
|
+
* @returns this instance for chaining
|
|
22037
|
+
*/
|
|
22038
|
+
sepia(amount = 1) {
|
|
22039
|
+
if (amount >= 1) {
|
|
22040
|
+
return this.transform(
|
|
22041
|
+
0.393,
|
|
22042
|
+
0.349,
|
|
22043
|
+
0.272,
|
|
22044
|
+
0,
|
|
22045
|
+
0.769,
|
|
22046
|
+
0.686,
|
|
22047
|
+
0.534,
|
|
22048
|
+
0,
|
|
22049
|
+
0.189,
|
|
22050
|
+
0.168,
|
|
22051
|
+
0.131,
|
|
22052
|
+
0,
|
|
22053
|
+
0,
|
|
22054
|
+
0,
|
|
22055
|
+
0,
|
|
22056
|
+
1
|
|
22057
|
+
);
|
|
22058
|
+
}
|
|
22059
|
+
const a = amount;
|
|
22060
|
+
const b = 1 - a;
|
|
22061
|
+
return this.transform(
|
|
22062
|
+
b + 0.393 * a,
|
|
22063
|
+
0.349 * a,
|
|
22064
|
+
0.272 * a,
|
|
22065
|
+
0,
|
|
22066
|
+
0.769 * a,
|
|
22067
|
+
b + 0.686 * a,
|
|
22068
|
+
0.534 * a,
|
|
22069
|
+
0,
|
|
22070
|
+
0.189 * a,
|
|
22071
|
+
0.168 * a,
|
|
22072
|
+
b + 0.131 * a,
|
|
22073
|
+
0,
|
|
22074
|
+
0,
|
|
22075
|
+
0,
|
|
22076
|
+
0,
|
|
22077
|
+
1
|
|
22078
|
+
);
|
|
22079
|
+
}
|
|
22080
|
+
/**
|
|
22081
|
+
* Apply a color inversion.
|
|
22082
|
+
* @param amount - inversion amount (0.0 = original, 1.0 = fully inverted)
|
|
22083
|
+
* @returns this instance for chaining
|
|
22084
|
+
*/
|
|
22085
|
+
invertColors(amount = 1) {
|
|
22086
|
+
const c = 1 - 2 * amount;
|
|
22087
|
+
return this.transform(
|
|
22088
|
+
c,
|
|
22089
|
+
0,
|
|
22090
|
+
0,
|
|
22091
|
+
0,
|
|
22092
|
+
0,
|
|
22093
|
+
c,
|
|
22094
|
+
0,
|
|
22095
|
+
0,
|
|
22096
|
+
0,
|
|
22097
|
+
0,
|
|
22098
|
+
c,
|
|
22099
|
+
0,
|
|
22100
|
+
amount,
|
|
22101
|
+
amount,
|
|
22102
|
+
amount,
|
|
22103
|
+
1
|
|
22104
|
+
);
|
|
22105
|
+
}
|
|
22106
|
+
};
|
|
22107
|
+
|
|
22108
|
+
// src/video/webgl/utils/attributes.js
|
|
22109
|
+
function extractAttributes(gl, shader) {
|
|
22110
|
+
const attributes = {};
|
|
22111
|
+
const attrRx = /attribute\s+\w+\s+(\w+)/g;
|
|
22112
|
+
let match;
|
|
22113
|
+
let i = 0;
|
|
22114
|
+
while (match = attrRx.exec(shader.vertex)) {
|
|
22115
|
+
attributes[match[1]] = i++;
|
|
22116
|
+
}
|
|
22117
|
+
return attributes;
|
|
22118
|
+
}
|
|
22119
|
+
|
|
22120
|
+
// src/video/webgl/utils/precision.js
|
|
22121
|
+
function setPrecision(src, precision) {
|
|
22122
|
+
if (src.substring(0, 9) !== "precision") {
|
|
22123
|
+
return "precision " + precision + " float;\n" + src;
|
|
22124
|
+
}
|
|
22125
|
+
return src;
|
|
22126
|
+
}
|
|
22127
|
+
function getMaxShaderPrecision(gl, highPrecision = true) {
|
|
22128
|
+
if (highPrecision && gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) {
|
|
22129
|
+
return "highp";
|
|
22130
|
+
}
|
|
22131
|
+
if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) {
|
|
22132
|
+
return "mediump";
|
|
22133
|
+
}
|
|
22134
|
+
return "lowp";
|
|
22135
|
+
}
|
|
22136
|
+
|
|
22137
|
+
// src/video/webgl/utils/program.js
|
|
22138
|
+
function compileShader(gl, type, source) {
|
|
22139
|
+
const shader = gl.createShader(type);
|
|
22140
|
+
gl.shaderSource(shader, source);
|
|
22141
|
+
gl.compileShader(shader);
|
|
22142
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
22143
|
+
throw new Error(gl.getShaderInfoLog(shader));
|
|
22144
|
+
}
|
|
22145
|
+
return shader;
|
|
22146
|
+
}
|
|
22147
|
+
function compileProgram(gl, vertex, fragment, attributes) {
|
|
22148
|
+
const vertShader = compileShader(gl, gl.VERTEX_SHADER, vertex);
|
|
22149
|
+
const fragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragment);
|
|
22150
|
+
const program = gl.createProgram();
|
|
22151
|
+
gl.attachShader(program, vertShader);
|
|
22152
|
+
gl.attachShader(program, fragShader);
|
|
22153
|
+
for (const location in attributes) {
|
|
22154
|
+
gl.bindAttribLocation(program, attributes[location], location);
|
|
22155
|
+
}
|
|
22156
|
+
gl.linkProgram(program);
|
|
22157
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
22158
|
+
const error_msg = "Error initializing Shader " + this + "\ngl.VALIDATE_STATUS: " + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + "\ngl.getError()" + gl.getError() + "\ngl.getProgramInfoLog()" + gl.getProgramInfoLog(program);
|
|
22159
|
+
gl.deleteProgram(program);
|
|
22160
|
+
throw new Error(error_msg);
|
|
22161
|
+
}
|
|
22162
|
+
gl.useProgram(program);
|
|
22163
|
+
gl.deleteShader(vertShader);
|
|
22164
|
+
gl.deleteShader(fragShader);
|
|
22165
|
+
return program;
|
|
22166
|
+
}
|
|
22167
|
+
|
|
22168
|
+
// src/video/webgl/utils/string.js
|
|
22169
|
+
function minify(src) {
|
|
22170
|
+
src = src.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
|
|
22171
|
+
src = src.replace(/(\\n\s+)|(\s+\\n)/g, "");
|
|
22172
|
+
src = src.replace(/(\\r|\\n)+/g, "");
|
|
22173
|
+
src = src.replace(/[ \t]*([;,[\](){}\\\/\-+*|^&!=<>?~%])[ \t]*/g, "$1");
|
|
22174
|
+
return src;
|
|
22175
|
+
}
|
|
22176
|
+
|
|
22177
|
+
// src/video/webgl/utils/uniforms.js
|
|
22178
|
+
var fnHash = {
|
|
22179
|
+
bool: "1i",
|
|
22180
|
+
int: "1i",
|
|
22181
|
+
float: "1f",
|
|
22182
|
+
vec2: "2fv",
|
|
22183
|
+
vec3: "3fv",
|
|
22184
|
+
vec4: "4fv",
|
|
22185
|
+
bvec2: "2iv",
|
|
22186
|
+
bvec3: "3iv",
|
|
22187
|
+
bvec4: "4iv",
|
|
22188
|
+
ivec2: "2iv",
|
|
22189
|
+
ivec3: "3iv",
|
|
22190
|
+
ivec4: "4iv",
|
|
22191
|
+
mat2: "Matrix2fv",
|
|
22192
|
+
mat3: "Matrix3fv",
|
|
22193
|
+
mat4: "Matrix4fv",
|
|
22194
|
+
sampler2D: "1i"
|
|
22195
|
+
};
|
|
22196
|
+
function extractUniforms(gl, shader) {
|
|
22197
|
+
const uniforms = {};
|
|
22198
|
+
const uniRx = /uniform\s+(\w+)\s+(\w+)/g;
|
|
22199
|
+
const uniformsData = {};
|
|
22200
|
+
const descriptor = {};
|
|
22201
|
+
const locations = {};
|
|
22202
|
+
let match;
|
|
22203
|
+
[shader.vertex, shader.fragment].forEach((shader2) => {
|
|
22204
|
+
while (match = uniRx.exec(shader2)) {
|
|
22205
|
+
uniformsData[match[2]] = match[1];
|
|
22206
|
+
}
|
|
22207
|
+
});
|
|
22208
|
+
Object.keys(uniformsData).forEach((name) => {
|
|
22209
|
+
const type = uniformsData[name];
|
|
22210
|
+
locations[name] = gl.getUniformLocation(shader.program, name);
|
|
22211
|
+
descriptor[name] = {
|
|
22212
|
+
get: /* @__PURE__ */ (function(name2) {
|
|
22213
|
+
return function() {
|
|
22214
|
+
return locations[name2];
|
|
22215
|
+
};
|
|
22216
|
+
})(name),
|
|
22217
|
+
set: (function(name2, type2, fn) {
|
|
22218
|
+
if (/^mat/.test(type2)) {
|
|
22219
|
+
return function(val) {
|
|
22220
|
+
gl[fn](locations[name2], false, val);
|
|
22221
|
+
};
|
|
22222
|
+
} else {
|
|
22223
|
+
return function(val) {
|
|
22224
|
+
let fnv = fn;
|
|
22225
|
+
if (val.length && !/v$/.test(fn)) {
|
|
22226
|
+
fnv += "v";
|
|
22227
|
+
}
|
|
22228
|
+
gl[fnv](locations[name2], val);
|
|
22229
|
+
};
|
|
22230
|
+
}
|
|
22231
|
+
})(name, type, "uniform" + fnHash[type])
|
|
22232
|
+
};
|
|
22233
|
+
});
|
|
22234
|
+
Object.defineProperties(uniforms, descriptor);
|
|
22235
|
+
return uniforms;
|
|
22236
|
+
}
|
|
22237
|
+
|
|
22238
|
+
// src/video/webgl/glshader.js
|
|
22239
|
+
var GLShader = class {
|
|
22240
|
+
/**
|
|
22241
|
+
* @param {WebGLRenderingContext} gl - the current WebGL rendering context
|
|
22242
|
+
* @param {string} vertex - a string containing the GLSL source code to set
|
|
22243
|
+
* @param {string} fragment - a string containing the GLSL source code to set
|
|
22244
|
+
* @param {string} [precision=auto detected] - float precision ('lowp', 'mediump' or 'highp').
|
|
22245
|
+
* @see https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders
|
|
22246
|
+
* @example
|
|
22247
|
+
* // create a basic shader
|
|
22248
|
+
* let myShader = new me.GLShader(
|
|
22249
|
+
* // WebGL rendering context
|
|
22250
|
+
* gl,
|
|
22251
|
+
* // vertex shader
|
|
22252
|
+
* [
|
|
22253
|
+
* "void main() {",
|
|
22254
|
+
* " gl_Position = doMathToMakeClipspaceCoordinates;",
|
|
22255
|
+
* "}"
|
|
22256
|
+
* ].join("\n"),
|
|
22257
|
+
* // fragment shader
|
|
22258
|
+
* [
|
|
22259
|
+
* "void main() {",
|
|
22260
|
+
* " gl_FragColor = doMathToMakeAColor;",
|
|
22261
|
+
* "}"
|
|
22262
|
+
* ].join("\n")
|
|
22263
|
+
* )
|
|
22264
|
+
* // use the shader
|
|
22265
|
+
* myShader.bind();
|
|
22266
|
+
*/
|
|
22267
|
+
constructor(gl, vertex, fragment, precision) {
|
|
22268
|
+
this.gl = gl;
|
|
22269
|
+
this.vertex = setPrecision(
|
|
22270
|
+
minify(vertex),
|
|
22271
|
+
precision || getMaxShaderPrecision(this.gl)
|
|
22272
|
+
);
|
|
22273
|
+
this.fragment = setPrecision(
|
|
22274
|
+
minify(fragment),
|
|
22275
|
+
precision || getMaxShaderPrecision(this.gl)
|
|
22276
|
+
);
|
|
22277
|
+
this.attributes = extractAttributes(this.gl, this);
|
|
22278
|
+
this.program = compileProgram(
|
|
22279
|
+
this.gl,
|
|
22280
|
+
this.vertex,
|
|
22281
|
+
this.fragment,
|
|
22282
|
+
this.attributes
|
|
22283
|
+
);
|
|
22284
|
+
this.uniforms = extractUniforms(this.gl, this);
|
|
22285
|
+
on(ONCONTEXT_LOST, this.destroy, this);
|
|
22286
|
+
}
|
|
22287
|
+
/**
|
|
22288
|
+
* Installs this shader program as part of current rendering state
|
|
22289
|
+
*/
|
|
22290
|
+
bind() {
|
|
22291
|
+
this.gl.useProgram(this.program);
|
|
22292
|
+
}
|
|
22293
|
+
/**
|
|
22294
|
+
* returns the location of an attribute variable in this shader program
|
|
22295
|
+
* @param {string} name - the name of the attribute variable whose location to get.
|
|
22296
|
+
* @returns {GLint} number indicating the location of the variable name if found. Returns -1 otherwise
|
|
22297
|
+
*/
|
|
22298
|
+
getAttribLocation(name) {
|
|
22299
|
+
const attr = this.attributes[name];
|
|
22300
|
+
if (typeof attr !== "undefined") {
|
|
22301
|
+
return attr;
|
|
22302
|
+
} else {
|
|
22303
|
+
return -1;
|
|
22304
|
+
}
|
|
22305
|
+
}
|
|
22306
|
+
/**
|
|
22307
|
+
* Set the uniform to the given value
|
|
22308
|
+
* @param {string} name - the uniform name
|
|
22309
|
+
* @param {object|Float32Array} value - the value to assign to that uniform
|
|
22310
|
+
* @example
|
|
22311
|
+
* myShader.setUniform("uProjectionMatrix", this.projectionMatrix);
|
|
22312
|
+
*/
|
|
22313
|
+
setUniform(name, value) {
|
|
22314
|
+
const uniforms = this.uniforms;
|
|
22315
|
+
if (typeof uniforms[name] !== "undefined") {
|
|
22316
|
+
this.bind();
|
|
22317
|
+
if (typeof value === "object" && typeof value.toArray === "function") {
|
|
22318
|
+
uniforms[name] = value.toArray();
|
|
22319
|
+
} else {
|
|
22320
|
+
uniforms[name] = value;
|
|
22321
|
+
}
|
|
22322
|
+
} else {
|
|
22323
|
+
throw new Error("undefined (" + name + ") uniform for shader " + this);
|
|
22324
|
+
}
|
|
22325
|
+
}
|
|
22326
|
+
/**
|
|
22327
|
+
* activate the given vertex attribute for this shader
|
|
22328
|
+
* @param {WebGLRenderingContext} gl - the current WebGL rendering context
|
|
22329
|
+
* @param {object[]} attributes - an array of vertex attributes
|
|
22330
|
+
* @param {number} stride - the size of a single vertex in bytes
|
|
22331
|
+
*/
|
|
22332
|
+
setVertexAttributes(gl, attributes, stride) {
|
|
22333
|
+
for (let index = 0; index < attributes.length; ++index) {
|
|
22334
|
+
const element = attributes[index];
|
|
22335
|
+
const location = this.getAttribLocation(element.name);
|
|
22336
|
+
if (location !== -1) {
|
|
22337
|
+
gl.enableVertexAttribArray(location);
|
|
22338
|
+
gl.vertexAttribPointer(
|
|
22339
|
+
location,
|
|
22340
|
+
element.size,
|
|
22341
|
+
element.type,
|
|
22342
|
+
element.normalized,
|
|
22343
|
+
stride,
|
|
22344
|
+
element.offset
|
|
22345
|
+
);
|
|
22346
|
+
} else {
|
|
22347
|
+
gl.disableVertexAttribArray(index);
|
|
22348
|
+
}
|
|
22349
|
+
}
|
|
22350
|
+
}
|
|
22351
|
+
/**
|
|
22352
|
+
* destroy this shader objects resources (program, attributes, uniforms)
|
|
22353
|
+
*/
|
|
22354
|
+
destroy() {
|
|
22355
|
+
this.uniforms = null;
|
|
22356
|
+
this.attributes = null;
|
|
22357
|
+
this.gl.deleteProgram(this.program);
|
|
22358
|
+
this.vertex = null;
|
|
22359
|
+
this.fragment = null;
|
|
22360
|
+
}
|
|
22361
|
+
};
|
|
22362
|
+
|
|
22363
|
+
// src/video/webgl/shaders/quad.vert
|
|
22364
|
+
var quad_default = "// Current vertex point\nattribute vec2 aVertex;\nattribute vec2 aRegion;\nattribute vec4 aColor;\n\n// Projection matrix\nuniform mat4 uProjectionMatrix;\n\nvarying vec2 vRegion;\nvarying vec4 vColor;\n\nvoid main(void) {\n // Transform the vertex position by the projection matrix\n gl_Position = uProjectionMatrix * vec4(aVertex, 0.0, 1.0);\n // Pass the remaining attributes to the fragment shader\n vColor = vec4(aColor.bgr * aColor.a, aColor.a);\n vRegion = aRegion;\n}\n";
|
|
22365
|
+
|
|
22366
|
+
// src/video/webgl/shadereffect.js
|
|
22367
|
+
var ShaderEffect = class {
|
|
22368
|
+
/**
|
|
22369
|
+
* whether this effect is active (false in Canvas mode)
|
|
22370
|
+
* @type {boolean}
|
|
22371
|
+
*/
|
|
22372
|
+
enabled = false;
|
|
22373
|
+
/**
|
|
22374
|
+
* @param {WebGLRenderer|CanvasRenderer} renderer - the current renderer instance
|
|
22375
|
+
* @param {string} fragmentBody - GLSL code containing a `vec4 apply(vec4 color, vec2 uv)` function
|
|
22376
|
+
* that receives the sampled pixel color and UV coordinates, and returns the modified color.
|
|
22377
|
+
* You can declare additional `uniform` variables before the `apply()` function.
|
|
22378
|
+
* @param {string} [precision=auto detected] - float precision ('lowp', 'mediump' or 'highp')
|
|
22379
|
+
*/
|
|
22380
|
+
constructor(renderer2, fragmentBody, precision) {
|
|
22381
|
+
if (typeof renderer2.gl === "undefined") {
|
|
22382
|
+
console.warn(
|
|
22383
|
+
"ShaderEffect requires WebGL and is disabled in Canvas mode"
|
|
22384
|
+
);
|
|
22385
|
+
return;
|
|
22386
|
+
}
|
|
22387
|
+
const fragment = [
|
|
22388
|
+
"uniform sampler2D uSampler;",
|
|
22389
|
+
"varying vec4 vColor;",
|
|
22390
|
+
"varying vec2 vRegion;",
|
|
22391
|
+
// user-provided fragment body (uniforms + apply function)
|
|
22392
|
+
fragmentBody,
|
|
22393
|
+
"void main(void) {",
|
|
22394
|
+
" vec4 texColor = texture2D(uSampler, vRegion) * vColor;",
|
|
22395
|
+
" gl_FragColor = apply(texColor, vRegion);",
|
|
22396
|
+
"}"
|
|
22397
|
+
].join("\n");
|
|
22398
|
+
this._shader = new GLShader(
|
|
22399
|
+
renderer2.gl,
|
|
22400
|
+
quad_default,
|
|
22401
|
+
fragment,
|
|
22402
|
+
precision || renderer2.shaderPrecision
|
|
22403
|
+
);
|
|
22404
|
+
this.enabled = true;
|
|
22405
|
+
}
|
|
22406
|
+
/**
|
|
22407
|
+
* Set the uniform to the given value
|
|
22408
|
+
* @param {string} name - the uniform name
|
|
22409
|
+
* @param {object|Float32Array} value - the value to assign to that uniform
|
|
22410
|
+
*/
|
|
22411
|
+
setUniform(name, value) {
|
|
22412
|
+
if (this.enabled) {
|
|
22413
|
+
this._shader.setUniform(name, value);
|
|
22414
|
+
}
|
|
22415
|
+
}
|
|
22416
|
+
/** @ignore */
|
|
22417
|
+
bind() {
|
|
22418
|
+
if (this.enabled) {
|
|
22419
|
+
this._shader.bind();
|
|
22420
|
+
}
|
|
22421
|
+
}
|
|
22422
|
+
/** @ignore */
|
|
22423
|
+
getAttribLocation(name) {
|
|
22424
|
+
return this.enabled ? this._shader.getAttribLocation(name) : -1;
|
|
22425
|
+
}
|
|
22426
|
+
/** @ignore */
|
|
22427
|
+
setVertexAttributes(gl, attributes, stride) {
|
|
22428
|
+
if (this.enabled) {
|
|
22429
|
+
this._shader.setVertexAttributes(gl, attributes, stride);
|
|
22430
|
+
}
|
|
22431
|
+
}
|
|
22432
|
+
/** @ignore */
|
|
22433
|
+
get program() {
|
|
22434
|
+
return this.enabled ? this._shader.program : null;
|
|
22435
|
+
}
|
|
22436
|
+
/** @ignore */
|
|
22437
|
+
get vertex() {
|
|
22438
|
+
return this.enabled ? this._shader.vertex : null;
|
|
22439
|
+
}
|
|
22440
|
+
/** @ignore */
|
|
22441
|
+
get fragment() {
|
|
22442
|
+
return this.enabled ? this._shader.fragment : null;
|
|
22443
|
+
}
|
|
22444
|
+
/** @ignore */
|
|
22445
|
+
get attributes() {
|
|
22446
|
+
return this.enabled ? this._shader.attributes : {};
|
|
22447
|
+
}
|
|
22448
|
+
/** @ignore */
|
|
22449
|
+
get uniforms() {
|
|
22450
|
+
return this.enabled ? this._shader.uniforms : {};
|
|
22451
|
+
}
|
|
22452
|
+
/**
|
|
22453
|
+
* destroy this shader effect
|
|
22454
|
+
*/
|
|
22455
|
+
destroy() {
|
|
22456
|
+
if (this.enabled) {
|
|
22457
|
+
this._shader.destroy();
|
|
22458
|
+
this.enabled = false;
|
|
22459
|
+
}
|
|
22460
|
+
}
|
|
22461
|
+
};
|
|
22462
|
+
|
|
22463
|
+
// src/video/webgl/effects/colorMatrix.js
|
|
22464
|
+
var ColorMatrixEffect = class extends ShaderEffect {
|
|
22465
|
+
/**
|
|
22466
|
+
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
22467
|
+
* @param {object} [options] - effect options
|
|
22468
|
+
* @param {ColorMatrix} [options.matrix] - an initial color matrix. Defaults to identity.
|
|
22469
|
+
*/
|
|
22470
|
+
constructor(renderer2, options = {}) {
|
|
22471
|
+
super(
|
|
22472
|
+
renderer2,
|
|
22473
|
+
`
|
|
22474
|
+
uniform mat4 uColorMatrix;
|
|
22475
|
+
vec4 apply(vec4 color, vec2 uv) {
|
|
22476
|
+
return uColorMatrix * color;
|
|
22477
|
+
}
|
|
22478
|
+
`
|
|
22479
|
+
);
|
|
22480
|
+
this._matrix = options.matrix || new ColorMatrix();
|
|
22481
|
+
this._syncUniform();
|
|
22482
|
+
}
|
|
22483
|
+
/**
|
|
22484
|
+
* Push the current matrix values to the GPU.
|
|
22485
|
+
* @ignore
|
|
22486
|
+
*/
|
|
22487
|
+
_syncUniform() {
|
|
22488
|
+
this.setUniform("uColorMatrix", this._matrix.val);
|
|
22489
|
+
}
|
|
22490
|
+
/**
|
|
22491
|
+
* Reset the color matrix to identity (no color change).
|
|
22492
|
+
* @returns {this} this instance for chaining
|
|
22493
|
+
*/
|
|
22494
|
+
reset() {
|
|
22495
|
+
this._matrix.identity();
|
|
22496
|
+
this._syncUniform();
|
|
22497
|
+
return this;
|
|
22498
|
+
}
|
|
22499
|
+
/**
|
|
22500
|
+
* Apply a brightness adjustment.
|
|
22501
|
+
* @param {number} amount - brightness multiplier (1.0 = normal, >1 brighter, <1 darker)
|
|
22502
|
+
* @returns {this} this instance for chaining
|
|
22503
|
+
*/
|
|
22504
|
+
brightness(amount) {
|
|
22505
|
+
this._matrix.brightness(amount);
|
|
22506
|
+
this._syncUniform();
|
|
22507
|
+
return this;
|
|
22508
|
+
}
|
|
22509
|
+
/**
|
|
22510
|
+
* Apply a contrast adjustment.
|
|
22511
|
+
* @param {number} amount - contrast multiplier (1.0 = normal, >1 more contrast, <1 less)
|
|
22512
|
+
* @returns {this} this instance for chaining
|
|
22513
|
+
*/
|
|
22514
|
+
contrast(amount) {
|
|
22515
|
+
this._matrix.contrast(amount);
|
|
22516
|
+
this._syncUniform();
|
|
22517
|
+
return this;
|
|
22518
|
+
}
|
|
22519
|
+
/**
|
|
22520
|
+
* Apply a saturation adjustment.
|
|
22521
|
+
* @param {number} amount - saturation level (0.0 = grayscale, 1.0 = normal, >1 over-saturated)
|
|
22522
|
+
* @returns {this} this instance for chaining
|
|
22523
|
+
*/
|
|
22524
|
+
saturate(amount) {
|
|
22525
|
+
this._matrix.saturate(amount);
|
|
22526
|
+
this._syncUniform();
|
|
22527
|
+
return this;
|
|
22528
|
+
}
|
|
22529
|
+
/**
|
|
22530
|
+
* Apply a hue rotation.
|
|
22531
|
+
* @param {number} angle - rotation angle in radians
|
|
22532
|
+
* @returns {this} this instance for chaining
|
|
22533
|
+
*/
|
|
22534
|
+
hueRotate(angle) {
|
|
22535
|
+
this._matrix.hueRotate(angle);
|
|
22536
|
+
this._syncUniform();
|
|
22537
|
+
return this;
|
|
22538
|
+
}
|
|
22539
|
+
/**
|
|
22540
|
+
* Apply a sepia tone.
|
|
22541
|
+
* @param {number} [amount=1.0] - sepia intensity (0.0 = original, 1.0 = full sepia)
|
|
22542
|
+
* @returns {this} this instance for chaining
|
|
22543
|
+
*/
|
|
22544
|
+
sepia(amount = 1) {
|
|
22545
|
+
this._matrix.sepia(amount);
|
|
22546
|
+
this._syncUniform();
|
|
22547
|
+
return this;
|
|
22548
|
+
}
|
|
22549
|
+
/**
|
|
22550
|
+
* Apply a color inversion.
|
|
22551
|
+
* @param {number} [amount=1.0] - inversion amount (0.0 = original, 1.0 = fully inverted)
|
|
22552
|
+
* @returns {this} this instance for chaining
|
|
22553
|
+
*/
|
|
22554
|
+
invertColors(amount = 1) {
|
|
22555
|
+
this._matrix.invertColors(amount);
|
|
22556
|
+
this._syncUniform();
|
|
22557
|
+
return this;
|
|
22558
|
+
}
|
|
22559
|
+
/**
|
|
22560
|
+
* Multiply the current matrix by another color matrix.
|
|
22561
|
+
* @param {ColorMatrix} matrix - the matrix to multiply with
|
|
22562
|
+
* @returns {this} this instance for chaining
|
|
22563
|
+
*/
|
|
22564
|
+
multiply(matrix) {
|
|
22565
|
+
this._matrix.multiply(matrix);
|
|
22566
|
+
this._syncUniform();
|
|
22567
|
+
return this;
|
|
22568
|
+
}
|
|
22569
|
+
/**
|
|
22570
|
+
* Multiplies the current matrix with a transform described by individual values.
|
|
22571
|
+
* Accepts either 6 values (2D affine: a, b, c, d, e, f) or 16 values (full 4x4 column-major).
|
|
22572
|
+
* @param {...number} args - 6 or 16 numeric values
|
|
22573
|
+
* @returns {this} this instance for chaining
|
|
22574
|
+
*/
|
|
22575
|
+
transform(...args) {
|
|
22576
|
+
this._matrix.transform(...args);
|
|
22577
|
+
this._syncUniform();
|
|
22578
|
+
return this;
|
|
22579
|
+
}
|
|
22580
|
+
};
|
|
22581
|
+
|
|
22582
|
+
// src/camera/effects/shake_effect.ts
|
|
22583
|
+
var ShakeEffect = class extends CameraEffect {
|
|
22584
|
+
/**
|
|
22585
|
+
* maximum pixel offset during shake
|
|
22586
|
+
*/
|
|
22587
|
+
intensity;
|
|
22588
|
+
/**
|
|
22589
|
+
* remaining duration in milliseconds
|
|
22590
|
+
*/
|
|
22591
|
+
duration;
|
|
22592
|
+
/**
|
|
22593
|
+
* which axes to shake (use camera.AXIS constants)
|
|
22594
|
+
*/
|
|
22595
|
+
axis;
|
|
22596
|
+
/**
|
|
22597
|
+
* optional callback when shake completes
|
|
22598
|
+
*/
|
|
22599
|
+
onComplete;
|
|
22600
|
+
/**
|
|
22601
|
+
* @param camera - the camera to shake
|
|
22602
|
+
* @param options - shake parameters
|
|
22603
|
+
* @param options.intensity - maximum offset in pixels
|
|
22604
|
+
* @param options.duration - duration in milliseconds
|
|
22605
|
+
* @param [options.axis=3] - which axes (NONE=0, HORIZONTAL=1, VERTICAL=2, BOTH=3)
|
|
22606
|
+
* @param [options.onComplete] - callback when the shake finishes
|
|
22607
|
+
*/
|
|
22608
|
+
constructor(camera, options) {
|
|
22609
|
+
super(camera);
|
|
22610
|
+
this.intensity = options.intensity;
|
|
22611
|
+
this.duration = options.duration;
|
|
22612
|
+
this.axis = options.axis ?? camera.AXIS.BOTH;
|
|
22613
|
+
this.onComplete = options.onComplete;
|
|
22614
|
+
}
|
|
22615
|
+
update(dt) {
|
|
22616
|
+
this.duration -= dt;
|
|
22617
|
+
if (this.duration <= 0) {
|
|
22618
|
+
this.duration = 0;
|
|
22619
|
+
this.camera.offset.setZero();
|
|
22620
|
+
this.isComplete = true;
|
|
22621
|
+
if (typeof this.onComplete === "function") {
|
|
22622
|
+
this.onComplete();
|
|
22623
|
+
}
|
|
22624
|
+
} else {
|
|
22625
|
+
const axis = this.camera.AXIS;
|
|
22626
|
+
if (this.axis === axis.BOTH || this.axis === axis.HORIZONTAL) {
|
|
22627
|
+
this.camera.offset.x = (Math.random() - 0.5) * this.intensity;
|
|
22628
|
+
}
|
|
22629
|
+
if (this.axis === axis.BOTH || this.axis === axis.VERTICAL) {
|
|
22630
|
+
this.camera.offset.y = (Math.random() - 0.5) * this.intensity;
|
|
22631
|
+
}
|
|
22632
|
+
}
|
|
22633
|
+
}
|
|
22634
|
+
destroy() {
|
|
22635
|
+
this.camera.offset.setZero();
|
|
22636
|
+
}
|
|
22637
|
+
};
|
|
22638
|
+
|
|
21371
22639
|
// src/camera/camera2d.ts
|
|
21372
22640
|
var targetV = new Vector2d();
|
|
21373
22641
|
var Camera2d = class extends Renderable {
|
|
@@ -21458,20 +22726,23 @@ var Camera2d = class extends Renderable {
|
|
|
21458
22726
|
/** default value follow */
|
|
21459
22727
|
follow_axis;
|
|
21460
22728
|
/**
|
|
21461
|
-
* shake
|
|
21462
|
-
* @ignore
|
|
21463
|
-
*/
|
|
21464
|
-
_shake;
|
|
21465
|
-
/**
|
|
21466
|
-
* flash variables
|
|
21467
|
-
* @ignore
|
|
22729
|
+
* active camera effects (shake, fade, etc.)
|
|
21468
22730
|
*/
|
|
21469
|
-
|
|
22731
|
+
cameraEffects;
|
|
21470
22732
|
/**
|
|
21471
|
-
*
|
|
21472
|
-
*
|
|
22733
|
+
* A built-in color transformation matrix applied as the final post-processing pass.
|
|
22734
|
+
* Provides convenient color grading (brightness, contrast, saturation, etc.)
|
|
22735
|
+
* that is always applied after any effects added via {@link addPostEffect}.
|
|
22736
|
+
* When set to identity (default), no effect is applied and there is zero overhead.
|
|
22737
|
+
* @example
|
|
22738
|
+
* // warm HDR-like color grading
|
|
22739
|
+
* camera.colorMatrix.contrast(1.2).saturate(1.1);
|
|
22740
|
+
* // reset to no color grading
|
|
22741
|
+
* camera.colorMatrix.identity();
|
|
21473
22742
|
*/
|
|
21474
|
-
|
|
22743
|
+
colorMatrix;
|
|
22744
|
+
/** @ignore */
|
|
22745
|
+
_colorMatrixEffect;
|
|
21475
22746
|
/** the camera deadzone */
|
|
21476
22747
|
deadzone;
|
|
21477
22748
|
/**
|
|
@@ -21498,20 +22769,7 @@ var Camera2d = class extends Renderable {
|
|
|
21498
22769
|
this.offset = new Vector2d();
|
|
21499
22770
|
this.target = null;
|
|
21500
22771
|
this.follow_axis = this.AXIS.NONE;
|
|
21501
|
-
this.
|
|
21502
|
-
intensity: 0,
|
|
21503
|
-
duration: 0,
|
|
21504
|
-
axis: this.AXIS.BOTH,
|
|
21505
|
-
onComplete: null
|
|
21506
|
-
};
|
|
21507
|
-
this._fadeOut = {
|
|
21508
|
-
color: null,
|
|
21509
|
-
tween: null
|
|
21510
|
-
};
|
|
21511
|
-
this._fadeIn = {
|
|
21512
|
-
color: null,
|
|
21513
|
-
tween: null
|
|
21514
|
-
};
|
|
22772
|
+
this.cameraEffects = [];
|
|
21515
22773
|
this.screenX = 0;
|
|
21516
22774
|
this.screenY = 0;
|
|
21517
22775
|
this.zoom = 1;
|
|
@@ -21523,6 +22781,9 @@ var Camera2d = class extends Renderable {
|
|
|
21523
22781
|
this.setDeadzone(this.width / 6, this.height / 6);
|
|
21524
22782
|
this.anchorPoint.set(0, 0);
|
|
21525
22783
|
this.isKinematic = false;
|
|
22784
|
+
this._postEffectManaged = true;
|
|
22785
|
+
this.colorMatrix = new ColorMatrix();
|
|
22786
|
+
this._colorMatrixEffect = null;
|
|
21526
22787
|
this.bounds.setMinMax(minX, minY, maxX, maxY);
|
|
21527
22788
|
this._updateProjectionMatrix();
|
|
21528
22789
|
on(GAME_RESET, this.reset, this);
|
|
@@ -21638,6 +22899,12 @@ var Camera2d = class extends Renderable {
|
|
|
21638
22899
|
this.worldProjection.identity();
|
|
21639
22900
|
this.screenProjection.identity();
|
|
21640
22901
|
this._updateProjectionMatrix();
|
|
22902
|
+
for (let i = this.cameraEffects.length - 1; i >= 0; i--) {
|
|
22903
|
+
if (!this.cameraEffects[i].isPersistent) {
|
|
22904
|
+
this.cameraEffects[i].destroy();
|
|
22905
|
+
this.cameraEffects.splice(i, 1);
|
|
22906
|
+
}
|
|
22907
|
+
}
|
|
21641
22908
|
}
|
|
21642
22909
|
/**
|
|
21643
22910
|
* change the deadzone settings.
|
|
@@ -21796,20 +23063,14 @@ var Camera2d = class extends Renderable {
|
|
|
21796
23063
|
/** @ignore */
|
|
21797
23064
|
update(dt) {
|
|
21798
23065
|
this.updateTarget(dt);
|
|
21799
|
-
if (this.
|
|
21800
|
-
|
|
21801
|
-
|
|
21802
|
-
|
|
21803
|
-
|
|
21804
|
-
if (
|
|
21805
|
-
this.
|
|
21806
|
-
|
|
21807
|
-
} else {
|
|
21808
|
-
if (this._shake.axis === this.AXIS.BOTH || this._shake.axis === this.AXIS.HORIZONTAL) {
|
|
21809
|
-
this.offset.x = (Math.random() - 0.5) * this._shake.intensity;
|
|
21810
|
-
}
|
|
21811
|
-
if (this._shake.axis === this.AXIS.BOTH || this._shake.axis === this.AXIS.VERTICAL) {
|
|
21812
|
-
this.offset.y = (Math.random() - 0.5) * this._shake.intensity;
|
|
23066
|
+
if (this.cameraEffects.length > 0) {
|
|
23067
|
+
for (const fx of this.cameraEffects) {
|
|
23068
|
+
fx.update(dt ?? 0);
|
|
23069
|
+
}
|
|
23070
|
+
for (let i = this.cameraEffects.length - 1; i >= 0; i--) {
|
|
23071
|
+
if (this.cameraEffects[i].isComplete) {
|
|
23072
|
+
this.cameraEffects[i].destroy();
|
|
23073
|
+
this.cameraEffects.splice(i, 1);
|
|
21813
23074
|
}
|
|
21814
23075
|
}
|
|
21815
23076
|
this.isDirty = true;
|
|
@@ -21817,9 +23078,6 @@ var Camera2d = class extends Renderable {
|
|
|
21817
23078
|
if (this.isDirty) {
|
|
21818
23079
|
emit(VIEWPORT_ONCHANGE, this.pos);
|
|
21819
23080
|
}
|
|
21820
|
-
if (this._fadeIn.tween != null || this._fadeOut.tween != null) {
|
|
21821
|
-
this.isDirty = true;
|
|
21822
|
-
}
|
|
21823
23081
|
if (!this.currentTransform.isIdentity()) {
|
|
21824
23082
|
this.invCurrentTransform.copy(this.currentTransform).invert();
|
|
21825
23083
|
} else {
|
|
@@ -21840,12 +23098,21 @@ var Camera2d = class extends Renderable {
|
|
|
21840
23098
|
* app.viewport.shake(10, 500, app.viewport.AXIS.BOTH);
|
|
21841
23099
|
*/
|
|
21842
23100
|
shake(intensity, duration, axis, onComplete, force) {
|
|
21843
|
-
|
|
21844
|
-
|
|
21845
|
-
|
|
21846
|
-
|
|
21847
|
-
|
|
23101
|
+
const existing = this.getCameraEffect(ShakeEffect);
|
|
23102
|
+
if (existing && force !== true) {
|
|
23103
|
+
return;
|
|
23104
|
+
}
|
|
23105
|
+
if (existing) {
|
|
23106
|
+
this.removeCameraEffect(existing);
|
|
21848
23107
|
}
|
|
23108
|
+
this.addCameraEffect(
|
|
23109
|
+
new ShakeEffect(this, {
|
|
23110
|
+
intensity,
|
|
23111
|
+
duration,
|
|
23112
|
+
axis: axis || this.AXIS.BOTH,
|
|
23113
|
+
onComplete
|
|
23114
|
+
})
|
|
23115
|
+
);
|
|
21849
23116
|
}
|
|
21850
23117
|
/**
|
|
21851
23118
|
* fadeOut(flash) effect<p>
|
|
@@ -21862,13 +23129,14 @@ var Camera2d = class extends Renderable {
|
|
|
21862
23129
|
* });
|
|
21863
23130
|
*/
|
|
21864
23131
|
fadeOut(color, duration = 1e3, onComplete) {
|
|
21865
|
-
this.
|
|
21866
|
-
|
|
21867
|
-
|
|
21868
|
-
|
|
21869
|
-
|
|
21870
|
-
|
|
21871
|
-
|
|
23132
|
+
this.addCameraEffect(
|
|
23133
|
+
new FadeEffect(this, {
|
|
23134
|
+
color,
|
|
23135
|
+
duration,
|
|
23136
|
+
direction: "out",
|
|
23137
|
+
onComplete
|
|
23138
|
+
})
|
|
23139
|
+
);
|
|
21872
23140
|
}
|
|
21873
23141
|
/**
|
|
21874
23142
|
* fadeIn effect <p>
|
|
@@ -21881,15 +23149,49 @@ var Camera2d = class extends Renderable {
|
|
|
21881
23149
|
* app.viewport.fadeIn("#FFFFFF", 75);
|
|
21882
23150
|
*/
|
|
21883
23151
|
fadeIn(color, duration = 1e3, onComplete) {
|
|
21884
|
-
this.
|
|
21885
|
-
|
|
21886
|
-
|
|
21887
|
-
|
|
21888
|
-
|
|
21889
|
-
|
|
23152
|
+
this.addCameraEffect(
|
|
23153
|
+
new FadeEffect(this, {
|
|
23154
|
+
color,
|
|
23155
|
+
duration,
|
|
23156
|
+
direction: "in",
|
|
23157
|
+
onComplete
|
|
23158
|
+
})
|
|
23159
|
+
);
|
|
23160
|
+
}
|
|
23161
|
+
/**
|
|
23162
|
+
* Add a camera effect to this camera.
|
|
23163
|
+
* @param effect - the camera effect to add
|
|
23164
|
+
* @returns the added effect
|
|
23165
|
+
* @example
|
|
23166
|
+
* camera.addCameraEffect(new ShakeEffect(camera, { intensity: 10, duration: 500 }));
|
|
23167
|
+
*/
|
|
23168
|
+
addCameraEffect(effect) {
|
|
23169
|
+
this.cameraEffects.push(effect);
|
|
23170
|
+
return effect;
|
|
23171
|
+
}
|
|
23172
|
+
/**
|
|
23173
|
+
* Get the first camera effect matching the given class.
|
|
23174
|
+
* @param effectClass - the effect class to search for
|
|
23175
|
+
* @returns the first matching effect, or undefined
|
|
23176
|
+
* @example
|
|
23177
|
+
* const shake = camera.getCameraEffect(ShakeEffect);
|
|
23178
|
+
*/
|
|
23179
|
+
getCameraEffect(effectClass) {
|
|
23180
|
+
return this.cameraEffects.find((fx) => fx instanceof effectClass);
|
|
23181
|
+
}
|
|
23182
|
+
/**
|
|
23183
|
+
* Remove a specific camera effect instance.
|
|
23184
|
+
* @param effect - the effect to remove
|
|
23185
|
+
* @example
|
|
23186
|
+
* const fade = camera.getCameraEffect(FadeEffect);
|
|
23187
|
+
* if (fade) camera.removeCameraEffect(fade);
|
|
23188
|
+
*/
|
|
23189
|
+
removeCameraEffect(effect) {
|
|
23190
|
+
const idx = this.cameraEffects.indexOf(effect);
|
|
23191
|
+
if (idx !== -1) {
|
|
23192
|
+
effect.destroy();
|
|
23193
|
+
this.cameraEffects.splice(idx, 1);
|
|
21890
23194
|
}
|
|
21891
|
-
this._fadeIn.tween.isPersistent = true;
|
|
21892
|
-
this._fadeIn.tween.start();
|
|
21893
23195
|
}
|
|
21894
23196
|
/**
|
|
21895
23197
|
* set the camera position around the specified object
|
|
@@ -21953,30 +23255,8 @@ var Camera2d = class extends Renderable {
|
|
|
21953
23255
|
* @ignore
|
|
21954
23256
|
*/
|
|
21955
23257
|
drawFX(renderer2) {
|
|
21956
|
-
const
|
|
21957
|
-
|
|
21958
|
-
r.save();
|
|
21959
|
-
r.resetTransform();
|
|
21960
|
-
r.setColor(this._fadeIn.color);
|
|
21961
|
-
r.fillRect(0, 0, this.width, this.height);
|
|
21962
|
-
r.restore();
|
|
21963
|
-
if (this._fadeIn.color.alpha === 1) {
|
|
21964
|
-
this._fadeIn.tween = null;
|
|
21965
|
-
colorPool.release(this._fadeIn.color);
|
|
21966
|
-
this._fadeIn.color = null;
|
|
21967
|
-
}
|
|
21968
|
-
}
|
|
21969
|
-
if (this._fadeOut.tween) {
|
|
21970
|
-
r.save();
|
|
21971
|
-
r.resetTransform();
|
|
21972
|
-
r.setColor(this._fadeOut.color);
|
|
21973
|
-
r.fillRect(0, 0, this.width, this.height);
|
|
21974
|
-
r.restore();
|
|
21975
|
-
if (this._fadeOut.color.alpha === 0) {
|
|
21976
|
-
this._fadeOut.tween = null;
|
|
21977
|
-
colorPool.release(this._fadeOut.color);
|
|
21978
|
-
this._fadeOut.color = null;
|
|
21979
|
-
}
|
|
23258
|
+
for (const fx of this.cameraEffects) {
|
|
23259
|
+
fx.draw(renderer2, this.width, this.height);
|
|
21980
23260
|
}
|
|
21981
23261
|
}
|
|
21982
23262
|
/**
|
|
@@ -21990,9 +23270,19 @@ var Camera2d = class extends Renderable {
|
|
|
21990
23270
|
const containerOffsetY = isNonDefault ? container.pos.y : 0;
|
|
21991
23271
|
const translateX = this.pos.x + this.offset.x + containerOffsetX;
|
|
21992
23272
|
const translateY = this.pos.y + this.offset.y + containerOffsetY;
|
|
23273
|
+
if (!this.colorMatrix.isIdentity()) {
|
|
23274
|
+
if (!this._colorMatrixEffect) {
|
|
23275
|
+
this._colorMatrixEffect = new ColorMatrixEffect(renderer2);
|
|
23276
|
+
}
|
|
23277
|
+
this._colorMatrixEffect.reset().multiply(this.colorMatrix);
|
|
23278
|
+
this.postEffects.push(this._colorMatrixEffect);
|
|
23279
|
+
}
|
|
23280
|
+
const usePostEffect = r.beginPostEffect(this);
|
|
21993
23281
|
container.translate(-translateX, -translateY);
|
|
21994
23282
|
this.preDraw(r);
|
|
21995
|
-
|
|
23283
|
+
if (!usePostEffect) {
|
|
23284
|
+
r.clipRect(this.screenX, this.screenY, this.width, this.height);
|
|
23285
|
+
}
|
|
21996
23286
|
if (isNonDefault) {
|
|
21997
23287
|
const left = -this.screenX / this.zoom;
|
|
21998
23288
|
const top = -this.screenY / this.zoom;
|
|
@@ -22034,8 +23324,27 @@ var Camera2d = class extends Renderable {
|
|
|
22034
23324
|
this.drawFX(renderer2);
|
|
22035
23325
|
container.postDraw(r);
|
|
22036
23326
|
this.postDraw(r);
|
|
23327
|
+
r.endPostEffect(this);
|
|
23328
|
+
if (this._colorMatrixEffect) {
|
|
23329
|
+
const idx = this.postEffects.indexOf(this._colorMatrixEffect);
|
|
23330
|
+
if (idx !== -1) {
|
|
23331
|
+
this.postEffects.splice(idx, 1);
|
|
23332
|
+
}
|
|
23333
|
+
}
|
|
22037
23334
|
container.translate(translateX, translateY);
|
|
22038
23335
|
}
|
|
23336
|
+
/**
|
|
23337
|
+
* @ignore
|
|
23338
|
+
*/
|
|
23339
|
+
destroy() {
|
|
23340
|
+
if (this._colorMatrixEffect) {
|
|
23341
|
+
if (typeof this._colorMatrixEffect.destroy === "function") {
|
|
23342
|
+
this._colorMatrixEffect.destroy();
|
|
23343
|
+
}
|
|
23344
|
+
this._colorMatrixEffect = null;
|
|
23345
|
+
}
|
|
23346
|
+
super.destroy();
|
|
23347
|
+
}
|
|
22039
23348
|
};
|
|
22040
23349
|
|
|
22041
23350
|
// src/state/stage.ts
|
|
@@ -22327,13 +23636,19 @@ var _state = -1;
|
|
|
22327
23636
|
var _animFrameId = -1;
|
|
22328
23637
|
var _isPaused = false;
|
|
22329
23638
|
var _stages = {};
|
|
22330
|
-
var
|
|
23639
|
+
var _transitionType = "fade";
|
|
23640
|
+
var _transitionConfig = {
|
|
22331
23641
|
color: "",
|
|
22332
23642
|
duration: 0
|
|
22333
23643
|
};
|
|
22334
23644
|
var _onSwitchComplete = null;
|
|
22335
23645
|
var _extraArgs = null;
|
|
22336
23646
|
var _pauseTime = 0;
|
|
23647
|
+
var _freezeTimer = null;
|
|
23648
|
+
var _freezeEndsAt = 0;
|
|
23649
|
+
var _freezeMusic = false;
|
|
23650
|
+
var _freezeStartedPause = false;
|
|
23651
|
+
var _freezeResolvers = [];
|
|
22337
23652
|
function _startRunLoop() {
|
|
22338
23653
|
if (_animFrameId === -1 && _state !== -1) {
|
|
22339
23654
|
_animFrameId = globalThis.requestAnimationFrame(_renderFrame);
|
|
@@ -22347,6 +23662,32 @@ function _resumeRunLoop() {
|
|
|
22347
23662
|
function _pauseRunLoop() {
|
|
22348
23663
|
_isPaused = true;
|
|
22349
23664
|
}
|
|
23665
|
+
function _resolveFreezeWaiters() {
|
|
23666
|
+
const resolvers = _freezeResolvers;
|
|
23667
|
+
_freezeResolvers = [];
|
|
23668
|
+
for (const resolve of resolvers) {
|
|
23669
|
+
resolve();
|
|
23670
|
+
}
|
|
23671
|
+
}
|
|
23672
|
+
function _endFreeze() {
|
|
23673
|
+
_freezeTimer = null;
|
|
23674
|
+
_freezeEndsAt = 0;
|
|
23675
|
+
const wasOwnedPause = _freezeStartedPause;
|
|
23676
|
+
_freezeStartedPause = false;
|
|
23677
|
+
if (wasOwnedPause) {
|
|
23678
|
+
state.resume(_freezeMusic);
|
|
23679
|
+
}
|
|
23680
|
+
_resolveFreezeWaiters();
|
|
23681
|
+
}
|
|
23682
|
+
function _cancelFreeze() {
|
|
23683
|
+
if (_freezeTimer !== null) {
|
|
23684
|
+
clearTimeout(_freezeTimer);
|
|
23685
|
+
_freezeTimer = null;
|
|
23686
|
+
_freezeEndsAt = 0;
|
|
23687
|
+
_freezeStartedPause = false;
|
|
23688
|
+
_resolveFreezeWaiters();
|
|
23689
|
+
}
|
|
23690
|
+
}
|
|
22350
23691
|
function _renderFrame(time) {
|
|
22351
23692
|
emit(TICK, time);
|
|
22352
23693
|
if (_animFrameId !== -1) {
|
|
@@ -22373,6 +23714,7 @@ function _switchState(stateId) {
|
|
|
22373
23714
|
emit(STATE_CHANGE);
|
|
22374
23715
|
if (_onSwitchComplete) {
|
|
22375
23716
|
_onSwitchComplete();
|
|
23717
|
+
_onSwitchComplete = null;
|
|
22376
23718
|
}
|
|
22377
23719
|
}
|
|
22378
23720
|
}
|
|
@@ -22386,6 +23728,9 @@ once(BOOT, () => {
|
|
|
22386
23728
|
once(VIDEO_INIT, () => {
|
|
22387
23729
|
state.change(state.DEFAULT, true);
|
|
22388
23730
|
});
|
|
23731
|
+
on(BLUR, () => {
|
|
23732
|
+
_cancelFreeze();
|
|
23733
|
+
});
|
|
22389
23734
|
});
|
|
22390
23735
|
var state = {
|
|
22391
23736
|
/**
|
|
@@ -22444,6 +23789,7 @@ var state = {
|
|
|
22444
23789
|
*/
|
|
22445
23790
|
stop(shouldPauseTrack = false) {
|
|
22446
23791
|
if (_state !== this.LOADING && this.isRunning()) {
|
|
23792
|
+
_cancelFreeze();
|
|
22447
23793
|
_stopRunLoop();
|
|
22448
23794
|
if (shouldPauseTrack) {
|
|
22449
23795
|
pauseTrack();
|
|
@@ -22486,6 +23832,7 @@ var state = {
|
|
|
22486
23832
|
*/
|
|
22487
23833
|
resume(music = false) {
|
|
22488
23834
|
if (this.isPaused()) {
|
|
23835
|
+
_cancelFreeze();
|
|
22489
23836
|
_resumeRunLoop();
|
|
22490
23837
|
if (music) {
|
|
22491
23838
|
resumeTrack();
|
|
@@ -22494,6 +23841,59 @@ var state = {
|
|
|
22494
23841
|
emit(STATE_RESUME, _pauseTime);
|
|
22495
23842
|
}
|
|
22496
23843
|
},
|
|
23844
|
+
/**
|
|
23845
|
+
* Freeze the current stage for a fixed duration, then automatically resume.
|
|
23846
|
+
* Useful for hit-stop / hit-pause effects on impact.
|
|
23847
|
+
*
|
|
23848
|
+
* Behaviour notes:
|
|
23849
|
+
* - If `freeze()` is called again while a freeze is already active, the
|
|
23850
|
+
* freeze is *extended* to whichever end-time is later (calls do not
|
|
23851
|
+
* stack). The `music` flag from the initial call is preserved.
|
|
23852
|
+
* - If the game was already paused when `freeze()` was called, the freeze
|
|
23853
|
+
* timer will *not* unpause it on expiry — the game stays paused.
|
|
23854
|
+
* - Calling `state.resume()` or `state.stop()` while a freeze is active
|
|
23855
|
+
* cancels the timer and resolves the returned promise immediately.
|
|
23856
|
+
* - The freeze is also cancelled when the window loses focus (BLUR) since
|
|
23857
|
+
* the hit-stop's "moment" is short enough that the user has missed it
|
|
23858
|
+
* by the time they return. The regular `pauseOnBlur` behaviour still
|
|
23859
|
+
* keeps the game paused while away.
|
|
23860
|
+
* - Negative, `NaN`, and `Infinity` durations silently no-op.
|
|
23861
|
+
* @param duration - duration of the freeze in milliseconds
|
|
23862
|
+
* @param [music=false] - also pause the current music track during the freeze
|
|
23863
|
+
* @returns a Promise that resolves once the freeze ends (or is cancelled)
|
|
23864
|
+
* @example
|
|
23865
|
+
* // simple hit-stop on impact
|
|
23866
|
+
* state.freeze(80);
|
|
23867
|
+
*
|
|
23868
|
+
* // chain VFX after the freeze
|
|
23869
|
+
* await state.freeze(120);
|
|
23870
|
+
* spawnImpactParticles();
|
|
23871
|
+
*/
|
|
23872
|
+
freeze(duration, music = false) {
|
|
23873
|
+
if (!Number.isFinite(duration) || duration < 0) {
|
|
23874
|
+
return Promise.resolve();
|
|
23875
|
+
}
|
|
23876
|
+
const now = globalThis.performance.now();
|
|
23877
|
+
const newEndsAt = now + duration;
|
|
23878
|
+
if (_freezeTimer !== null) {
|
|
23879
|
+
if (newEndsAt > _freezeEndsAt) {
|
|
23880
|
+
clearTimeout(_freezeTimer);
|
|
23881
|
+
_freezeEndsAt = newEndsAt;
|
|
23882
|
+
_freezeTimer = setTimeout(_endFreeze, newEndsAt - now);
|
|
23883
|
+
}
|
|
23884
|
+
} else {
|
|
23885
|
+
_freezeMusic = music;
|
|
23886
|
+
_freezeEndsAt = newEndsAt;
|
|
23887
|
+
_freezeStartedPause = !this.isPaused();
|
|
23888
|
+
if (_freezeStartedPause) {
|
|
23889
|
+
this.pause(music);
|
|
23890
|
+
}
|
|
23891
|
+
_freezeTimer = setTimeout(_endFreeze, duration);
|
|
23892
|
+
}
|
|
23893
|
+
return new Promise((resolve) => {
|
|
23894
|
+
_freezeResolvers.push(resolve);
|
|
23895
|
+
});
|
|
23896
|
+
},
|
|
22497
23897
|
/**
|
|
22498
23898
|
* return the running state of the state manager
|
|
22499
23899
|
* @returns true if a "process is running"
|
|
@@ -22571,15 +23971,28 @@ var state = {
|
|
|
22571
23971
|
},
|
|
22572
23972
|
/**
|
|
22573
23973
|
* specify a global transition effect
|
|
22574
|
-
* @param effect -
|
|
23974
|
+
* @param effect - "fade" for a color fade, "mask" for a shape-based mask transition
|
|
22575
23975
|
* @param color - a CSS color value
|
|
22576
23976
|
* @param [duration=1000] - expressed in milliseconds
|
|
22577
|
-
|
|
22578
|
-
|
|
22579
|
-
|
|
22580
|
-
|
|
22581
|
-
|
|
22582
|
-
|
|
23977
|
+
* @param [shape] - an Ellipse or Polygon defining the mask shape (required when effect is "mask")
|
|
23978
|
+
* @example
|
|
23979
|
+
* // classic fade to black
|
|
23980
|
+
* state.transition("fade", "#000", 500);
|
|
23981
|
+
* @example
|
|
23982
|
+
* // iris (circle) mask transition
|
|
23983
|
+
* state.transition("mask", "#000", 500, new Ellipse(0, 0, 1, 1));
|
|
23984
|
+
* @example
|
|
23985
|
+
* // diamond mask transition
|
|
23986
|
+
* state.transition("mask", "#000", 400, new Polygon(0, 0, [
|
|
23987
|
+
* { x: 0, y: -1 }, { x: 1, y: 0 },
|
|
23988
|
+
* { x: 0, y: 1 }, { x: -1, y: 0 },
|
|
23989
|
+
* ]));
|
|
23990
|
+
*/
|
|
23991
|
+
transition(effect, color, duration = 1e3, shape) {
|
|
23992
|
+
_transitionType = effect;
|
|
23993
|
+
_transitionConfig.color = color;
|
|
23994
|
+
_transitionConfig.duration = duration;
|
|
23995
|
+
_transitionConfig.shape = shape;
|
|
22583
23996
|
},
|
|
22584
23997
|
/**
|
|
22585
23998
|
* enable/disable the transition to a particular state (by default enabled for all)
|
|
@@ -22605,21 +24018,74 @@ var state = {
|
|
|
22605
24018
|
}
|
|
22606
24019
|
if (!this.isCurrent(stateId)) {
|
|
22607
24020
|
_extraArgs = extraArgs.length > 0 ? extraArgs : null;
|
|
22608
|
-
if (
|
|
22609
|
-
|
|
22610
|
-
|
|
24021
|
+
if (_transitionConfig.duration && _stages[stateId].transition) {
|
|
24022
|
+
const onComplete = () => {
|
|
24023
|
+
defer(
|
|
24024
|
+
_switchState,
|
|
24025
|
+
state,
|
|
24026
|
+
stateId
|
|
24027
|
+
);
|
|
22611
24028
|
};
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
|
|
22615
|
-
|
|
22616
|
-
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22620
|
-
|
|
24029
|
+
switch (_transitionType) {
|
|
24030
|
+
case "fade": {
|
|
24031
|
+
const color = _transitionConfig.color;
|
|
24032
|
+
const duration = _transitionConfig.duration;
|
|
24033
|
+
_onSwitchComplete = () => {
|
|
24034
|
+
_app.viewport.addCameraEffect(
|
|
24035
|
+
new FadeEffect(_app.viewport, {
|
|
24036
|
+
color,
|
|
24037
|
+
duration,
|
|
24038
|
+
direction: "out"
|
|
24039
|
+
})
|
|
24040
|
+
);
|
|
24041
|
+
};
|
|
24042
|
+
const fadeEffect = new FadeEffect(_app.viewport, {
|
|
24043
|
+
color,
|
|
24044
|
+
duration,
|
|
24045
|
+
direction: "in",
|
|
24046
|
+
onComplete
|
|
24047
|
+
});
|
|
24048
|
+
fadeEffect.isPersistent = true;
|
|
24049
|
+
_app.viewport.addCameraEffect(fadeEffect);
|
|
24050
|
+
break;
|
|
22621
24051
|
}
|
|
22622
|
-
|
|
24052
|
+
case "mask": {
|
|
24053
|
+
if (!_transitionConfig.shape) {
|
|
24054
|
+
console.warn(
|
|
24055
|
+
"melonJS: mask transition requires a shape, falling back to direct switch"
|
|
24056
|
+
);
|
|
24057
|
+
onComplete();
|
|
24058
|
+
break;
|
|
24059
|
+
}
|
|
24060
|
+
const shape = _transitionConfig.shape;
|
|
24061
|
+
const color = _transitionConfig.color;
|
|
24062
|
+
const duration = _transitionConfig.duration;
|
|
24063
|
+
_onSwitchComplete = () => {
|
|
24064
|
+
_app.viewport.addCameraEffect(
|
|
24065
|
+
new MaskEffect(_app.viewport, {
|
|
24066
|
+
shape,
|
|
24067
|
+
color,
|
|
24068
|
+
duration,
|
|
24069
|
+
direction: "reveal"
|
|
24070
|
+
})
|
|
24071
|
+
);
|
|
24072
|
+
};
|
|
24073
|
+
const maskEffect = new MaskEffect(_app.viewport, {
|
|
24074
|
+
shape,
|
|
24075
|
+
color,
|
|
24076
|
+
duration,
|
|
24077
|
+
direction: "hide",
|
|
24078
|
+
onComplete
|
|
24079
|
+
});
|
|
24080
|
+
maskEffect.isPersistent = true;
|
|
24081
|
+
_app.viewport.addCameraEffect(maskEffect);
|
|
24082
|
+
break;
|
|
24083
|
+
}
|
|
24084
|
+
default:
|
|
24085
|
+
throw new Error(
|
|
24086
|
+
`Invalid transition type: ${_transitionType}`
|
|
24087
|
+
);
|
|
24088
|
+
}
|
|
22623
24089
|
} else {
|
|
22624
24090
|
if (forceChange) {
|
|
22625
24091
|
_switchState(stateId);
|
|
@@ -23143,6 +24609,7 @@ var Tween = class {
|
|
|
23143
24609
|
_yoyo;
|
|
23144
24610
|
_reversed;
|
|
23145
24611
|
_delayTime;
|
|
24612
|
+
_repeatDelayTime;
|
|
23146
24613
|
_startTime;
|
|
23147
24614
|
_easingFunction;
|
|
23148
24615
|
_interpolationFunction;
|
|
@@ -23192,6 +24659,7 @@ var Tween = class {
|
|
|
23192
24659
|
this._yoyo = false;
|
|
23193
24660
|
this._reversed = false;
|
|
23194
24661
|
this._delayTime = 0;
|
|
24662
|
+
this._repeatDelayTime = void 0;
|
|
23195
24663
|
this._startTime = null;
|
|
23196
24664
|
this._easingFunction = Easing.Linear.None;
|
|
23197
24665
|
this._interpolationFunction = Interpolation.Linear;
|
|
@@ -23279,6 +24747,7 @@ var Tween = class {
|
|
|
23279
24747
|
* @param [options.delay] - delay before starting, in milliseconds
|
|
23280
24748
|
* @param [options.yoyo] - bounce back to original values when finished (use with `repeat`)
|
|
23281
24749
|
* @param [options.repeat] - number of times to repeat (use `Infinity` for endless loops)
|
|
24750
|
+
* @param [options.repeatDelay] - delay in milliseconds before each repeat cycle
|
|
23282
24751
|
* @param [options.interpolation] - interpolation function for array values
|
|
23283
24752
|
* @param [options.autoStart] - start the tween immediately without calling `start()`
|
|
23284
24753
|
* @returns this instance for object chaining
|
|
@@ -23301,6 +24770,9 @@ var Tween = class {
|
|
|
23301
24770
|
if (options.delay !== void 0) {
|
|
23302
24771
|
this.delay(options.delay);
|
|
23303
24772
|
}
|
|
24773
|
+
if (options.repeatDelay !== void 0) {
|
|
24774
|
+
this.repeatDelay(options.repeatDelay);
|
|
24775
|
+
}
|
|
23304
24776
|
if (options.interpolation !== void 0) {
|
|
23305
24777
|
this.interpolation(options.interpolation);
|
|
23306
24778
|
}
|
|
@@ -23367,6 +24839,15 @@ var Tween = class {
|
|
|
23367
24839
|
this._repeat = times;
|
|
23368
24840
|
return this;
|
|
23369
24841
|
}
|
|
24842
|
+
/**
|
|
24843
|
+
* Set a delay before each repeat.
|
|
24844
|
+
* @param amount - delay in milliseconds before each repeat cycle
|
|
24845
|
+
* @returns this instance for object chaining
|
|
24846
|
+
*/
|
|
24847
|
+
repeatDelay(amount) {
|
|
24848
|
+
this._repeatDelayTime = amount;
|
|
24849
|
+
return this;
|
|
24850
|
+
}
|
|
23370
24851
|
/**
|
|
23371
24852
|
* Allows the tween to bounce back to their original value when finished.
|
|
23372
24853
|
* To be used together with repeat to create endless loops.
|
|
@@ -23490,7 +24971,7 @@ var Tween = class {
|
|
|
23490
24971
|
if (this._yoyo) {
|
|
23491
24972
|
this._reversed = !this._reversed;
|
|
23492
24973
|
}
|
|
23493
|
-
this._startTime = time + this._delayTime;
|
|
24974
|
+
this._startTime = time + (this._repeatDelayTime ?? this._delayTime);
|
|
23494
24975
|
return true;
|
|
23495
24976
|
} else {
|
|
23496
24977
|
this._unsubscribe();
|
|
@@ -23783,7 +25264,7 @@ var Text = class extends Renderable {
|
|
|
23783
25264
|
* @param {number} [settings.wordWrapWidth] - the maximum length in CSS pixel for a single segment of text
|
|
23784
25265
|
* @param {(string|string[])} [settings.text=""] - a string, or an array of strings
|
|
23785
25266
|
* @example
|
|
23786
|
-
* let font = new
|
|
25267
|
+
* let font = new Text(0, 0, {font: "Arial", size: 8, fillStyle: this.color});
|
|
23787
25268
|
*/
|
|
23788
25269
|
constructor(x, y, settings) {
|
|
23789
25270
|
super(x, y, settings.width || 0, settings.height || 0);
|
|
@@ -23844,6 +25325,7 @@ var Text = class extends Renderable {
|
|
|
23844
25325
|
this.canvasTexture = new canvasrendertarget_default(2, 2, {
|
|
23845
25326
|
offscreenCanvas: false
|
|
23846
25327
|
});
|
|
25328
|
+
this._visibleCharacters = -1;
|
|
23847
25329
|
this.metrics = new textmetrics_default(this);
|
|
23848
25330
|
this.setText(settings.text);
|
|
23849
25331
|
}
|
|
@@ -23942,6 +25424,53 @@ var Text = class extends Renderable {
|
|
|
23942
25424
|
this.isDirty = true;
|
|
23943
25425
|
return this;
|
|
23944
25426
|
}
|
|
25427
|
+
/**
|
|
25428
|
+
* the number of characters to display (use -1 to show all).
|
|
25429
|
+
* Useful for typewriter effects combined with Tween.
|
|
25430
|
+
* @public
|
|
25431
|
+
* @type {number}
|
|
25432
|
+
* @default -1
|
|
25433
|
+
* @see Text#visibleRatio
|
|
25434
|
+
* @example
|
|
25435
|
+
* // typewriter effect
|
|
25436
|
+
* text.visibleCharacters = 0;
|
|
25437
|
+
* new Tween(text).to({ visibleRatio: 1.0 }, { duration: 2000 }).start();
|
|
25438
|
+
*/
|
|
25439
|
+
get visibleCharacters() {
|
|
25440
|
+
return this._visibleCharacters;
|
|
25441
|
+
}
|
|
25442
|
+
set visibleCharacters(value) {
|
|
25443
|
+
if (this._visibleCharacters !== value) {
|
|
25444
|
+
this._visibleCharacters = value;
|
|
25445
|
+
this.isDirty = true;
|
|
25446
|
+
}
|
|
25447
|
+
}
|
|
25448
|
+
/**
|
|
25449
|
+
* the ratio of visible characters (0.0 to 1.0).
|
|
25450
|
+
* Setting this automatically updates {@link visibleCharacters}.
|
|
25451
|
+
* @public
|
|
25452
|
+
* @type {number}
|
|
25453
|
+
*/
|
|
25454
|
+
get visibleRatio() {
|
|
25455
|
+
if (this._visibleCharacters === -1) {
|
|
25456
|
+
return 1;
|
|
25457
|
+
}
|
|
25458
|
+
const total = this._text.reduce((sum, line) => {
|
|
25459
|
+
return sum + line.length;
|
|
25460
|
+
}, 0);
|
|
25461
|
+
return total > 0 ? this._visibleCharacters / total : 1;
|
|
25462
|
+
}
|
|
25463
|
+
set visibleRatio(value) {
|
|
25464
|
+
const clamped = Math.max(0, Math.min(1, isFinite(value) ? value : 1));
|
|
25465
|
+
if (clamped >= 1) {
|
|
25466
|
+
this.visibleCharacters = -1;
|
|
25467
|
+
} else {
|
|
25468
|
+
const total = this._text.reduce((sum, line) => {
|
|
25469
|
+
return sum + line.length;
|
|
25470
|
+
}, 0);
|
|
25471
|
+
this.visibleCharacters = Math.floor(clamped * total);
|
|
25472
|
+
}
|
|
25473
|
+
}
|
|
23945
25474
|
/**
|
|
23946
25475
|
* update the bounding box for this Text, accounting for textAlign and textBaseline.
|
|
23947
25476
|
* @param {boolean} [absolute=true] - update in absolute coordinates
|
|
@@ -23998,6 +25527,16 @@ var Text = class extends Renderable {
|
|
|
23998
25527
|
* @param {CanvasRenderer|WebGLRenderer} renderer - Reference to the destination renderer instance
|
|
23999
25528
|
*/
|
|
24000
25529
|
draw(renderer2) {
|
|
25530
|
+
if (this.isDirty) {
|
|
25531
|
+
this.canvasTexture.invalidate(renderer2);
|
|
25532
|
+
this.canvasTexture.clear();
|
|
25533
|
+
this._drawFont(
|
|
25534
|
+
this.canvasTexture.context,
|
|
25535
|
+
this._text,
|
|
25536
|
+
this.pos.x - this.metrics.x,
|
|
25537
|
+
this.pos.y - this.metrics.y
|
|
25538
|
+
);
|
|
25539
|
+
}
|
|
24001
25540
|
let x = this.metrics.x;
|
|
24002
25541
|
let y = this.metrics.y;
|
|
24003
25542
|
if (renderer2.settings.subPixel === false) {
|
|
@@ -24011,8 +25550,16 @@ var Text = class extends Renderable {
|
|
|
24011
25550
|
*/
|
|
24012
25551
|
_drawFont(context, text, x, y) {
|
|
24013
25552
|
setContextStyle(context, this);
|
|
25553
|
+
let remaining = this.visibleCharacters;
|
|
24014
25554
|
for (let i = 0; i < text.length; i++) {
|
|
24015
|
-
|
|
25555
|
+
let string = text[i].trimEnd();
|
|
25556
|
+
if (remaining !== -1) {
|
|
25557
|
+
if (remaining <= 0) {
|
|
25558
|
+
break;
|
|
25559
|
+
}
|
|
25560
|
+
string = string.substring(0, remaining);
|
|
25561
|
+
remaining -= string.length;
|
|
25562
|
+
}
|
|
24016
25563
|
if (this.fillStyle.alpha > 0) {
|
|
24017
25564
|
context.fillText(string, x, y);
|
|
24018
25565
|
}
|
|
@@ -24192,13 +25739,13 @@ var BitmapText = class extends Renderable {
|
|
|
24192
25739
|
* @param {number} [settings.wordWrapWidth] - the maximum length in CSS pixel for a single segment of text
|
|
24193
25740
|
* @param {(string|string[])} [settings.text] - a string, or an array of strings
|
|
24194
25741
|
* @example
|
|
24195
|
-
* // Use
|
|
24196
|
-
*
|
|
24197
|
-
* { name: "arial", type: "binary" src: "data/font/arial.fnt" },
|
|
24198
|
-
* { name: "arial", type: "image" src: "data/font/arial.png" },
|
|
25742
|
+
* // Use loader.preload or loader.load to load assets
|
|
25743
|
+
* loader.preload([
|
|
25744
|
+
* { name: "arial", type: "binary", src: "data/font/arial.fnt" },
|
|
25745
|
+
* { name: "arial", type: "image", src: "data/font/arial.png" },
|
|
24199
25746
|
* ])
|
|
24200
25747
|
* // Then create an instance of your bitmap font:
|
|
24201
|
-
* let myFont = new
|
|
25748
|
+
* let myFont = new BitmapText(x, y, {font:"arial", text:"Hello"});
|
|
24202
25749
|
* // two possibilities for using "myFont"
|
|
24203
25750
|
* // either call the draw function from your Renderable draw function
|
|
24204
25751
|
* myFont.draw(renderer, "Hello!", 0, 0);
|
|
@@ -24233,6 +25780,7 @@ var BitmapText = class extends Renderable {
|
|
|
24233
25780
|
} else {
|
|
24234
25781
|
this.anchorPoint.set(0, 0);
|
|
24235
25782
|
}
|
|
25783
|
+
this._visibleCharacters = -1;
|
|
24236
25784
|
this.metrics = new textmetrics_default(this);
|
|
24237
25785
|
if (typeof settings.size === "number" && settings.size !== 1) {
|
|
24238
25786
|
this.resize(settings.size);
|
|
@@ -24274,6 +25822,55 @@ var BitmapText = class extends Renderable {
|
|
|
24274
25822
|
this.updateBounds();
|
|
24275
25823
|
return this;
|
|
24276
25824
|
}
|
|
25825
|
+
/**
|
|
25826
|
+
* the number of characters to display (use -1 to show all).
|
|
25827
|
+
* Useful for typewriter effects combined with Tween.
|
|
25828
|
+
* @public
|
|
25829
|
+
* @type {number}
|
|
25830
|
+
* @default -1
|
|
25831
|
+
* @see BitmapText#visibleRatio
|
|
25832
|
+
* @example
|
|
25833
|
+
* // show only the first 5 characters
|
|
25834
|
+
* bitmapText.visibleCharacters = 5;
|
|
25835
|
+
* // typewriter effect
|
|
25836
|
+
* bitmapText.visibleCharacters = 0;
|
|
25837
|
+
* new Tween(bitmapText).to({ visibleRatio: 1.0 }, { duration: 2000 }).start();
|
|
25838
|
+
*/
|
|
25839
|
+
get visibleCharacters() {
|
|
25840
|
+
return this._visibleCharacters;
|
|
25841
|
+
}
|
|
25842
|
+
set visibleCharacters(value) {
|
|
25843
|
+
if (this._visibleCharacters !== value) {
|
|
25844
|
+
this._visibleCharacters = value;
|
|
25845
|
+
this.isDirty = true;
|
|
25846
|
+
}
|
|
25847
|
+
}
|
|
25848
|
+
/**
|
|
25849
|
+
* the ratio of visible characters (0.0 to 1.0).
|
|
25850
|
+
* Setting this automatically updates {@link visibleCharacters}.
|
|
25851
|
+
* @public
|
|
25852
|
+
* @type {number}
|
|
25853
|
+
*/
|
|
25854
|
+
get visibleRatio() {
|
|
25855
|
+
if (this._visibleCharacters === -1) {
|
|
25856
|
+
return 1;
|
|
25857
|
+
}
|
|
25858
|
+
const total = this._text.reduce((sum, line) => {
|
|
25859
|
+
return sum + line.length;
|
|
25860
|
+
}, 0);
|
|
25861
|
+
return total > 0 ? this._visibleCharacters / total : 1;
|
|
25862
|
+
}
|
|
25863
|
+
set visibleRatio(value) {
|
|
25864
|
+
const clamped = Math.max(0, Math.min(1, isFinite(value) ? value : 1));
|
|
25865
|
+
if (clamped >= 1) {
|
|
25866
|
+
this.visibleCharacters = -1;
|
|
25867
|
+
} else {
|
|
25868
|
+
const total = this._text.reduce((sum, line) => {
|
|
25869
|
+
return sum + line.length;
|
|
25870
|
+
}, 0);
|
|
25871
|
+
this.visibleCharacters = Math.floor(clamped * total);
|
|
25872
|
+
}
|
|
25873
|
+
}
|
|
24277
25874
|
/**
|
|
24278
25875
|
* update the bounding box for this Bitmap Text.
|
|
24279
25876
|
* @param {boolean} [absolute=true] - update the bounds size and position in (world) absolute coordinates
|
|
@@ -24376,6 +25973,8 @@ var BitmapText = class extends Renderable {
|
|
|
24376
25973
|
default:
|
|
24377
25974
|
break;
|
|
24378
25975
|
}
|
|
25976
|
+
let charCount = 0;
|
|
25977
|
+
const maxChars = this.visibleCharacters;
|
|
24379
25978
|
for (let i = 0; i < this._text.length; i++) {
|
|
24380
25979
|
x = lX;
|
|
24381
25980
|
const string = this._text[i].trimEnd();
|
|
@@ -24392,6 +25991,9 @@ var BitmapText = class extends Renderable {
|
|
|
24392
25991
|
}
|
|
24393
25992
|
let lastGlyph = null;
|
|
24394
25993
|
for (let c = 0, len = string.length; c < len; c++) {
|
|
25994
|
+
if (maxChars !== -1 && charCount >= maxChars) {
|
|
25995
|
+
return;
|
|
25996
|
+
}
|
|
24395
25997
|
const ch = string.charCodeAt(c);
|
|
24396
25998
|
const glyph = this.fontData.glyphs[ch];
|
|
24397
25999
|
if (typeof glyph !== "undefined") {
|
|
@@ -24420,6 +26022,7 @@ var BitmapText = class extends Renderable {
|
|
|
24420
26022
|
"BitmapText: no defined Glyph in for " + String.fromCharCode(ch)
|
|
24421
26023
|
);
|
|
24422
26024
|
}
|
|
26025
|
+
charCount++;
|
|
24423
26026
|
}
|
|
24424
26027
|
y += stringHeight;
|
|
24425
26028
|
}
|
|
@@ -24496,7 +26099,9 @@ function registerTiledObjectFactory(type, factory) {
|
|
|
24496
26099
|
throw new Error("invalid factory function for " + type);
|
|
24497
26100
|
}
|
|
24498
26101
|
if (typeof factories.get(type) !== "undefined") {
|
|
24499
|
-
|
|
26102
|
+
console.warn(
|
|
26103
|
+
"melonJS: overriding Tiled object factory for " + type + " type"
|
|
26104
|
+
);
|
|
24500
26105
|
}
|
|
24501
26106
|
factories.set(type, factory);
|
|
24502
26107
|
}
|
|
@@ -24587,18 +26192,22 @@ var Particle = class extends Renderable {
|
|
|
24587
26192
|
wind;
|
|
24588
26193
|
followTrajectory;
|
|
24589
26194
|
onlyInViewport;
|
|
26195
|
+
accurateBounds;
|
|
24590
26196
|
_deltaInv;
|
|
26197
|
+
_halfW;
|
|
26198
|
+
_halfH;
|
|
24591
26199
|
_angle;
|
|
24592
26200
|
alive;
|
|
24593
26201
|
/**
|
|
24594
26202
|
* @param emitter - the particle emitter
|
|
24595
26203
|
*/
|
|
24596
26204
|
constructor(emitter) {
|
|
26205
|
+
const image = emitter.settings.image;
|
|
24597
26206
|
super(
|
|
24598
26207
|
emitter.getRandomPointX(),
|
|
24599
26208
|
emitter.getRandomPointY(),
|
|
24600
|
-
|
|
24601
|
-
|
|
26209
|
+
image.width,
|
|
26210
|
+
image.height
|
|
24602
26211
|
);
|
|
24603
26212
|
this.vel = vector2dPool.get();
|
|
24604
26213
|
this.onResetEvent(emitter, true);
|
|
@@ -24607,13 +26216,17 @@ var Particle = class extends Renderable {
|
|
|
24607
26216
|
* @ignore
|
|
24608
26217
|
*/
|
|
24609
26218
|
onResetEvent(emitter, newInstance = false) {
|
|
26219
|
+
const image = emitter.settings.image;
|
|
24610
26220
|
if (!newInstance) {
|
|
24611
26221
|
this.pos.set(emitter.getRandomPointX(), emitter.getRandomPointY());
|
|
24612
|
-
this.resize(
|
|
26222
|
+
this.resize(image.width, image.height);
|
|
24613
26223
|
this.currentTransform.identity();
|
|
24614
26224
|
}
|
|
24615
|
-
this.image =
|
|
26225
|
+
this.image = image;
|
|
26226
|
+
this._halfW = this.width / 2;
|
|
26227
|
+
this._halfH = this.height / 2;
|
|
24616
26228
|
this.alwaysUpdate = true;
|
|
26229
|
+
this.anchorPoint.set(0, 0);
|
|
24617
26230
|
if (typeof emitter.settings.tint === "string") {
|
|
24618
26231
|
this.tint.parseCSS(emitter.settings.tint);
|
|
24619
26232
|
}
|
|
@@ -24621,21 +26234,16 @@ var Particle = class extends Renderable {
|
|
|
24621
26234
|
if (emitter.settings.blendMode !== "normal") {
|
|
24622
26235
|
this.blendMode = emitter.settings.blendMode;
|
|
24623
26236
|
}
|
|
24624
|
-
const angle = emitter.settings.angle + (
|
|
24625
|
-
const speed = emitter.settings.speed + (
|
|
26237
|
+
const angle = emitter.settings.angle + (Math.random() * 2 - 1) * emitter.settings.angleVariation;
|
|
26238
|
+
const speed = emitter.settings.speed + (Math.random() * 2 - 1) * emitter.settings.speedVariation;
|
|
24626
26239
|
this.vel.set(speed * Math.cos(angle), -speed * Math.sin(angle));
|
|
24627
26240
|
this.life = randomFloat(emitter.settings.minLife, emitter.settings.maxLife);
|
|
24628
26241
|
this.startLife = this.life;
|
|
24629
|
-
this.startScale =
|
|
24630
|
-
randomFloat(
|
|
24631
|
-
emitter.settings.minStartScale,
|
|
24632
|
-
emitter.settings.maxStartScale
|
|
24633
|
-
),
|
|
26242
|
+
this.startScale = randomFloat(
|
|
24634
26243
|
emitter.settings.minStartScale,
|
|
24635
26244
|
emitter.settings.maxStartScale
|
|
24636
26245
|
);
|
|
24637
|
-
this.endScale =
|
|
24638
|
-
randomFloat(emitter.settings.minEndScale, emitter.settings.maxEndScale),
|
|
26246
|
+
this.endScale = randomFloat(
|
|
24639
26247
|
emitter.settings.minEndScale,
|
|
24640
26248
|
emitter.settings.maxEndScale
|
|
24641
26249
|
);
|
|
@@ -24643,7 +26251,8 @@ var Particle = class extends Renderable {
|
|
|
24643
26251
|
this.wind = emitter.settings.wind;
|
|
24644
26252
|
this.followTrajectory = emitter.settings.followTrajectory;
|
|
24645
26253
|
this.onlyInViewport = emitter.settings.onlyInViewport;
|
|
24646
|
-
this.
|
|
26254
|
+
this.accurateBounds = emitter.settings.accurateBounds;
|
|
26255
|
+
this._deltaInv = emitter._deltaInv;
|
|
24647
26256
|
if (!emitter.settings.followTrajectory) {
|
|
24648
26257
|
this._angle = randomFloat(
|
|
24649
26258
|
emitter.settings.minRotation,
|
|
@@ -24683,24 +26292,33 @@ var Particle = class extends Renderable {
|
|
|
24683
26292
|
const angle = this.followTrajectory ? Math.atan2(this.vel.y, this.vel.x) : this._angle;
|
|
24684
26293
|
this.pos.x += this.vel.x * skew;
|
|
24685
26294
|
this.pos.y += this.vel.y * skew;
|
|
26295
|
+
const halfW = this._halfW;
|
|
26296
|
+
const halfH = this._halfH;
|
|
26297
|
+
const cos = Math.cos(angle);
|
|
26298
|
+
const sin = Math.sin(angle);
|
|
26299
|
+
const sCos = scale2 * cos;
|
|
26300
|
+
const sSin = scale2 * sin;
|
|
24686
26301
|
this.currentTransform.setTransform(
|
|
24687
|
-
|
|
24688
|
-
|
|
26302
|
+
sCos,
|
|
26303
|
+
sSin,
|
|
24689
26304
|
0,
|
|
24690
26305
|
0,
|
|
24691
|
-
|
|
24692
|
-
|
|
26306
|
+
-sSin,
|
|
26307
|
+
sCos,
|
|
24693
26308
|
0,
|
|
24694
26309
|
0,
|
|
24695
26310
|
0,
|
|
24696
26311
|
0,
|
|
24697
26312
|
1,
|
|
24698
26313
|
0,
|
|
24699
|
-
this.pos.x,
|
|
24700
|
-
this.pos.y,
|
|
26314
|
+
this.pos.x - scale2 * (halfW * cos - halfH * sin),
|
|
26315
|
+
this.pos.y - scale2 * (halfW * sin + halfH * cos),
|
|
24701
26316
|
0,
|
|
24702
26317
|
1
|
|
24703
|
-
)
|
|
26318
|
+
);
|
|
26319
|
+
if (this.accurateBounds) {
|
|
26320
|
+
this.updateBounds();
|
|
26321
|
+
}
|
|
24704
26322
|
this.isDirty = this.inViewport || !this.onlyInViewport;
|
|
24705
26323
|
return super.update(dt);
|
|
24706
26324
|
}
|
|
@@ -24710,7 +26328,7 @@ var Particle = class extends Renderable {
|
|
|
24710
26328
|
draw(renderer2) {
|
|
24711
26329
|
const w = this.width;
|
|
24712
26330
|
const h = this.height;
|
|
24713
|
-
renderer2.drawImage(this.image, 0, 0, w, h,
|
|
26331
|
+
renderer2.drawImage(this.image, 0, 0, w, h, 0, 0, w, h);
|
|
24714
26332
|
}
|
|
24715
26333
|
};
|
|
24716
26334
|
var particlePool = createPool(
|
|
@@ -25112,13 +26730,27 @@ var ImageLayer = class extends Sprite {
|
|
|
25112
26730
|
this.isDirty = true;
|
|
25113
26731
|
}
|
|
25114
26732
|
/**
|
|
25115
|
-
*
|
|
25116
|
-
*
|
|
26733
|
+
* Override the default preDraw to skip the base class's anchor offset
|
|
26734
|
+
* translation and `autoTransform` application — `ImageLayer.draw()`
|
|
26735
|
+
* computes its own world-space position from the viewport, the parallax
|
|
26736
|
+
* `ratio`, anchor, and zoom, so applying anchor/transform here would
|
|
26737
|
+
* double-translate the layer.
|
|
26738
|
+
*
|
|
26739
|
+
* Coordinate-sensitive setup (flip, stencil mask) is intentionally
|
|
26740
|
+
* deferred to `draw()` where it runs *after* the per-camera zoom
|
|
26741
|
+
* translate/scale — that way it stays correctly aligned at any
|
|
26742
|
+
* `viewport.zoom` and across multiple cameras. Coordinate-independent
|
|
26743
|
+
* setup (alpha, post-effects, tint, blend) stays here. The inherited
|
|
26744
|
+
* `Renderable.postDraw` cleans up symmetrically (`clearTint` /
|
|
26745
|
+
* `clearMask` / `endPostEffect` / `restore`).
|
|
25117
26746
|
* @ignore
|
|
25118
26747
|
*/
|
|
25119
26748
|
preDraw(renderer2) {
|
|
25120
26749
|
renderer2.save();
|
|
25121
26750
|
renderer2.setGlobalAlpha(renderer2.globalAlpha() * this.getOpacity());
|
|
26751
|
+
if (!this._postEffectManaged) {
|
|
26752
|
+
renderer2.beginPostEffect(this);
|
|
26753
|
+
}
|
|
25122
26754
|
renderer2.setTint(this.tint);
|
|
25123
26755
|
if (this.blendMode !== renderer2.getBlendMode()) {
|
|
25124
26756
|
renderer2.setBlendMode(this.blendMode);
|
|
@@ -25156,6 +26788,16 @@ var ImageLayer = class extends Sprite {
|
|
|
25156
26788
|
}
|
|
25157
26789
|
renderer2.translate(x * vZoom, y * vZoom);
|
|
25158
26790
|
renderer2.scale(vZoom, vZoom);
|
|
26791
|
+
if (this._flip.x || this._flip.y) {
|
|
26792
|
+
const px = viewport.width;
|
|
26793
|
+
const py = viewport.height;
|
|
26794
|
+
renderer2.translate(px, py);
|
|
26795
|
+
renderer2.scale(this._flip.x ? -1 : 1, this._flip.y ? -1 : 1);
|
|
26796
|
+
renderer2.translate(-px, -py);
|
|
26797
|
+
}
|
|
26798
|
+
if (this.mask) {
|
|
26799
|
+
renderer2.setMask(this.mask);
|
|
26800
|
+
}
|
|
25159
26801
|
renderer2.drawPattern(
|
|
25160
26802
|
this._pattern,
|
|
25161
26803
|
0,
|
|
@@ -25578,8 +27220,10 @@ var Trigger = class extends Renderable {
|
|
|
25578
27220
|
* @param {number} [settings.width] - width of the trigger area
|
|
25579
27221
|
* @param {number} [settings.height] - height of the trigger area
|
|
25580
27222
|
* @param {Rect[]|Polygon[]|Line[]|Ellipse[]} [settings.shapes] - collision shape(s) that will trigger the event
|
|
25581
|
-
* @param {
|
|
25582
|
-
* @param {string|Color} [settings.color] -
|
|
27223
|
+
* @param {number} [settings.duration] - Transition duration (in ms)
|
|
27224
|
+
* @param {string|Color} [settings.color] - Transition color (also accepts legacy `fade` property)
|
|
27225
|
+
* @param {string} [settings.transition="fade"] - Transition type: "fade" for a color fade, "mask" for a shape-based mask transition
|
|
27226
|
+
* @param {Ellipse|Polygon} [settings.shape] - Mask shape for "mask" transition type (e.g. an Ellipse for iris, a Polygon for diamond/star)
|
|
25583
27227
|
* @param {string} [settings.event="level"] - the type of event to trigger (only "level" supported for now)
|
|
25584
27228
|
* @param {string} [settings.to] - level to load if level trigger
|
|
25585
27229
|
* @param {string|Container} [settings.container] - Target container. See {@link level.load}
|
|
@@ -25587,41 +27231,64 @@ var Trigger = class extends Renderable {
|
|
|
25587
27231
|
* @param {boolean} [settings.flatten] - Flatten all objects into the target container. See {@link level.load}
|
|
25588
27232
|
* @param {boolean} [settings.setViewportBounds] - Resize the viewport to match the level. See {@link level.load}
|
|
25589
27233
|
* @example
|
|
25590
|
-
*
|
|
25591
|
-
*
|
|
25592
|
-
*
|
|
25593
|
-
*
|
|
25594
|
-
*
|
|
25595
|
-
*
|
|
25596
|
-
*
|
|
25597
|
-
*
|
|
27234
|
+
* // fade transition (default)
|
|
27235
|
+
* world.addChild(new Trigger(x, y, {
|
|
27236
|
+
* shapes: [new Rect(0, 0, 100, 100)],
|
|
27237
|
+
* color: "#000",
|
|
27238
|
+
* duration: 250,
|
|
27239
|
+
* to: "mymap2",
|
|
27240
|
+
* }));
|
|
27241
|
+
* @example
|
|
27242
|
+
* // mask transition with iris (ellipse) shape
|
|
27243
|
+
* world.addChild(new Trigger(x, y, {
|
|
27244
|
+
* shapes: [new Rect(0, 0, 100, 100)],
|
|
27245
|
+
* transition: "mask",
|
|
27246
|
+
* shape: new Ellipse(0, 0, 1, 1),
|
|
27247
|
+
* color: "#000",
|
|
27248
|
+
* duration: 500,
|
|
27249
|
+
* to: "mymap2",
|
|
27250
|
+
* }));
|
|
27251
|
+
* @example
|
|
27252
|
+
* // mask transition with diamond polygon
|
|
27253
|
+
* world.addChild(new Trigger(x, y, {
|
|
27254
|
+
* shapes: [new Rect(0, 0, 100, 100)],
|
|
27255
|
+
* transition: "mask",
|
|
27256
|
+
* shape: new Polygon(0, 0, [
|
|
27257
|
+
* { x: 0, y: -1 }, { x: 1, y: 0 },
|
|
27258
|
+
* { x: 0, y: 1 }, { x: -1, y: 0 },
|
|
27259
|
+
* ]),
|
|
27260
|
+
* color: "#000",
|
|
27261
|
+
* duration: 400,
|
|
27262
|
+
* to: "mymap2",
|
|
27263
|
+
* }));
|
|
25598
27264
|
*/
|
|
25599
27265
|
constructor(x, y, settings) {
|
|
25600
27266
|
super(x, y, settings.width || 0, settings.height || 0);
|
|
25601
27267
|
this.anchorPoint.set(0, 0);
|
|
25602
|
-
this.
|
|
27268
|
+
this.color = settings.color || settings.fade;
|
|
25603
27269
|
this.duration = settings.duration;
|
|
27270
|
+
this.transition = settings.transition || "fade";
|
|
27271
|
+
this.transitionShape = settings.shape;
|
|
25604
27272
|
this.fading = false;
|
|
25605
27273
|
this.name = "Trigger";
|
|
25606
27274
|
this.type = settings.type;
|
|
25607
27275
|
this.id = settings.id;
|
|
25608
27276
|
this.gotolevel = settings.to;
|
|
25609
27277
|
this.triggerSettings = {
|
|
25610
|
-
// the default (and only for now) action
|
|
25611
27278
|
event: "level"
|
|
25612
27279
|
};
|
|
25613
|
-
[
|
|
27280
|
+
for (const property of [
|
|
25614
27281
|
"type",
|
|
25615
27282
|
"container",
|
|
25616
27283
|
"onLoaded",
|
|
25617
27284
|
"flatten",
|
|
25618
27285
|
"setViewportBounds",
|
|
25619
27286
|
"to"
|
|
25620
|
-
]
|
|
27287
|
+
]) {
|
|
25621
27288
|
if (typeof settings[property] !== "undefined") {
|
|
25622
27289
|
this.triggerSettings[property] = settings[property];
|
|
25623
27290
|
}
|
|
25624
|
-
}
|
|
27291
|
+
}
|
|
25625
27292
|
let shape = settings.shapes;
|
|
25626
27293
|
if (typeof shape === "undefined") {
|
|
25627
27294
|
shape = polygonPool.get(0, 0, [
|
|
@@ -25649,28 +27316,73 @@ var Trigger = class extends Renderable {
|
|
|
25649
27316
|
return this.triggerSettings;
|
|
25650
27317
|
}
|
|
25651
27318
|
/**
|
|
25652
|
-
*
|
|
25653
|
-
*/
|
|
25654
|
-
onFadeComplete() {
|
|
25655
|
-
const world = this.ancestor.getRootAncestor();
|
|
25656
|
-
level.load(this.gotolevel, this.getTriggerSettings());
|
|
25657
|
-
world.app.viewport.fadeOut(this.fade, this.duration);
|
|
25658
|
-
}
|
|
25659
|
-
/**
|
|
25660
|
-
* trigger this event
|
|
27319
|
+
* Trigger this event. Override in subclasses to customize behavior.
|
|
25661
27320
|
* @protected
|
|
25662
27321
|
*/
|
|
25663
27322
|
triggerEvent() {
|
|
25664
27323
|
const triggerSettings = this.getTriggerSettings();
|
|
25665
27324
|
const world = this.ancestor.getRootAncestor();
|
|
27325
|
+
const app = world.app;
|
|
27326
|
+
const viewport = app.viewport;
|
|
25666
27327
|
if (triggerSettings.event === "level") {
|
|
25667
27328
|
this.gotolevel = triggerSettings.to;
|
|
25668
|
-
if (this.
|
|
27329
|
+
if (this.color && this.duration) {
|
|
25669
27330
|
if (!this.fading) {
|
|
25670
27331
|
this.fading = true;
|
|
25671
|
-
|
|
25672
|
-
|
|
25673
|
-
|
|
27332
|
+
const gotolevel = this.gotolevel;
|
|
27333
|
+
const settings = this.getTriggerSettings();
|
|
27334
|
+
const color = this.color;
|
|
27335
|
+
const duration = this.duration;
|
|
27336
|
+
const useMask = this.transition === "mask" && this.transitionShape;
|
|
27337
|
+
const shape = this.transitionShape;
|
|
27338
|
+
const userOnLoaded = settings.onLoaded;
|
|
27339
|
+
settings.onLoaded = function(levelId) {
|
|
27340
|
+
const vp = app.viewport;
|
|
27341
|
+
if (useMask) {
|
|
27342
|
+
vp.addCameraEffect(
|
|
27343
|
+
new MaskEffect(vp, {
|
|
27344
|
+
shape,
|
|
27345
|
+
color,
|
|
27346
|
+
duration,
|
|
27347
|
+
direction: "reveal"
|
|
27348
|
+
})
|
|
27349
|
+
);
|
|
27350
|
+
} else {
|
|
27351
|
+
vp.addCameraEffect(
|
|
27352
|
+
new FadeEffect(vp, {
|
|
27353
|
+
color,
|
|
27354
|
+
duration,
|
|
27355
|
+
direction: "out"
|
|
27356
|
+
})
|
|
27357
|
+
);
|
|
27358
|
+
}
|
|
27359
|
+
if (typeof userOnLoaded === "function") {
|
|
27360
|
+
userOnLoaded.call(this, levelId);
|
|
27361
|
+
}
|
|
27362
|
+
};
|
|
27363
|
+
const onComplete = () => {
|
|
27364
|
+
level.load(gotolevel, settings);
|
|
27365
|
+
};
|
|
27366
|
+
if (useMask) {
|
|
27367
|
+
viewport.addCameraEffect(
|
|
27368
|
+
new MaskEffect(viewport, {
|
|
27369
|
+
shape,
|
|
27370
|
+
color,
|
|
27371
|
+
duration,
|
|
27372
|
+
direction: "hide",
|
|
27373
|
+
onComplete
|
|
27374
|
+
})
|
|
27375
|
+
);
|
|
27376
|
+
} else {
|
|
27377
|
+
viewport.addCameraEffect(
|
|
27378
|
+
new FadeEffect(viewport, {
|
|
27379
|
+
color,
|
|
27380
|
+
duration,
|
|
27381
|
+
direction: "in",
|
|
27382
|
+
onComplete
|
|
27383
|
+
})
|
|
27384
|
+
);
|
|
27385
|
+
}
|
|
25674
27386
|
}
|
|
25675
27387
|
} else {
|
|
25676
27388
|
level.load(this.gotolevel, triggerSettings);
|
|
@@ -25687,14 +27399,14 @@ var Trigger = class extends Renderable {
|
|
|
25687
27399
|
*/
|
|
25688
27400
|
onCollision() {
|
|
25689
27401
|
if (this.name === "Trigger") {
|
|
25690
|
-
this.triggerEvent
|
|
27402
|
+
this.triggerEvent();
|
|
25691
27403
|
}
|
|
25692
27404
|
return false;
|
|
25693
27405
|
}
|
|
25694
27406
|
};
|
|
25695
27407
|
|
|
25696
27408
|
// src/version.ts
|
|
25697
|
-
var version = "19.
|
|
27409
|
+
var version = "19.2.0";
|
|
25698
27410
|
|
|
25699
27411
|
// src/system/bootstrap.ts
|
|
25700
27412
|
var initialized = false;
|
|
@@ -27558,7 +29270,7 @@ var QuadTree = class {
|
|
|
27558
29270
|
* @param {Container} container - group of objects to be added
|
|
27559
29271
|
*/
|
|
27560
29272
|
insertContainer(container) {
|
|
27561
|
-
const children = container.
|
|
29273
|
+
const children = container.getChildren();
|
|
27562
29274
|
const childrenLength = children.length;
|
|
27563
29275
|
for (let i = childrenLength, child; i--, child = children[i]; ) {
|
|
27564
29276
|
if (child.isKinematic !== true) {
|
|
@@ -27834,6 +29546,327 @@ var World = class extends Container {
|
|
|
27834
29546
|
}
|
|
27835
29547
|
};
|
|
27836
29548
|
|
|
29549
|
+
// src/video/rendertarget/render_target_pool.js
|
|
29550
|
+
var RenderTargetPool = class {
|
|
29551
|
+
/**
|
|
29552
|
+
* @param {function(number, number): RenderTarget} factory - creates a RenderTarget with the given width and height
|
|
29553
|
+
*/
|
|
29554
|
+
constructor(factory) {
|
|
29555
|
+
this._factory = factory;
|
|
29556
|
+
this._pool = [];
|
|
29557
|
+
this._activeBase = -1;
|
|
29558
|
+
this._previousBase = -1;
|
|
29559
|
+
}
|
|
29560
|
+
/**
|
|
29561
|
+
* Get or create a render target at the given pool index, resized to the given dimensions.
|
|
29562
|
+
* @param {number} index - pool index
|
|
29563
|
+
* @param {number} width - desired width in pixels
|
|
29564
|
+
* @param {number} height - desired height in pixels
|
|
29565
|
+
* @returns {RenderTarget} the render target
|
|
29566
|
+
*/
|
|
29567
|
+
get(index, width, height) {
|
|
29568
|
+
if (!this._pool[index]) {
|
|
29569
|
+
this._pool[index] = this._factory(width, height);
|
|
29570
|
+
} else {
|
|
29571
|
+
this._pool[index].resize(width, height);
|
|
29572
|
+
}
|
|
29573
|
+
return this._pool[index];
|
|
29574
|
+
}
|
|
29575
|
+
/**
|
|
29576
|
+
* Prepare render targets for a post-effect pass.
|
|
29577
|
+
* Allocates/resizes the capture target and optionally the ping-pong target.
|
|
29578
|
+
* @param {boolean} isCamera - true for camera effects (indices 0+1), false for sprite (indices 2+3)
|
|
29579
|
+
* @param {number} effectCount - number of enabled effects
|
|
29580
|
+
* @param {number} width - target width in pixels
|
|
29581
|
+
* @param {number} height - target height in pixels
|
|
29582
|
+
* @returns {RenderTarget} the capture target (ready to bind)
|
|
29583
|
+
*/
|
|
29584
|
+
begin(isCamera, effectCount, width, height) {
|
|
29585
|
+
const newBase = isCamera ? 0 : 2;
|
|
29586
|
+
if (!isCamera && this._activeBase === newBase) {
|
|
29587
|
+
return this.get(this._activeBase, width, height);
|
|
29588
|
+
}
|
|
29589
|
+
this._previousBase = this._activeBase;
|
|
29590
|
+
this._activeBase = newBase;
|
|
29591
|
+
const rt = this.get(this._activeBase, width, height);
|
|
29592
|
+
if (effectCount > 1) {
|
|
29593
|
+
this.get(this._activeBase + 1, width, height);
|
|
29594
|
+
}
|
|
29595
|
+
return rt;
|
|
29596
|
+
}
|
|
29597
|
+
/**
|
|
29598
|
+
* Get the capture render target for the current active pass.
|
|
29599
|
+
* @returns {RenderTarget|undefined} the capture target, or undefined if no active pass
|
|
29600
|
+
*/
|
|
29601
|
+
getCaptureTarget() {
|
|
29602
|
+
if (this._activeBase < 0) {
|
|
29603
|
+
return void 0;
|
|
29604
|
+
}
|
|
29605
|
+
return this._pool[this._activeBase];
|
|
29606
|
+
}
|
|
29607
|
+
/**
|
|
29608
|
+
* Get the ping-pong render target for the current active pass.
|
|
29609
|
+
* @returns {RenderTarget|undefined} the ping-pong target, or undefined if no active pass
|
|
29610
|
+
*/
|
|
29611
|
+
getPingPongTarget() {
|
|
29612
|
+
if (this._activeBase < 0) {
|
|
29613
|
+
return void 0;
|
|
29614
|
+
}
|
|
29615
|
+
return this._pool[this._activeBase + 1];
|
|
29616
|
+
}
|
|
29617
|
+
/**
|
|
29618
|
+
* End the current pass and restore the previous active base.
|
|
29619
|
+
* Returns the parent render target to rebind (or null for screen).
|
|
29620
|
+
* @returns {RenderTarget|null} the parent target, or null if returning to screen
|
|
29621
|
+
*/
|
|
29622
|
+
end() {
|
|
29623
|
+
this._activeBase = this._previousBase;
|
|
29624
|
+
this._previousBase = -1;
|
|
29625
|
+
if (this._activeBase >= 0 && this._pool[this._activeBase]) {
|
|
29626
|
+
return this._pool[this._activeBase];
|
|
29627
|
+
}
|
|
29628
|
+
return null;
|
|
29629
|
+
}
|
|
29630
|
+
/**
|
|
29631
|
+
* Resize all existing render targets in the pool to the given dimensions.
|
|
29632
|
+
* @param {number} width - new width in pixels
|
|
29633
|
+
* @param {number} height - new height in pixels
|
|
29634
|
+
*/
|
|
29635
|
+
resizeAll(width, height) {
|
|
29636
|
+
for (const rt of this._pool) {
|
|
29637
|
+
if (rt) {
|
|
29638
|
+
rt.resize(width, height);
|
|
29639
|
+
}
|
|
29640
|
+
}
|
|
29641
|
+
}
|
|
29642
|
+
/**
|
|
29643
|
+
* Destroy all render targets and clear the pool.
|
|
29644
|
+
*/
|
|
29645
|
+
destroy() {
|
|
29646
|
+
for (const rt of this._pool) {
|
|
29647
|
+
if (rt) {
|
|
29648
|
+
rt.destroy();
|
|
29649
|
+
}
|
|
29650
|
+
}
|
|
29651
|
+
this._pool.length = 0;
|
|
29652
|
+
this._activeBase = -1;
|
|
29653
|
+
this._previousBase = -1;
|
|
29654
|
+
}
|
|
29655
|
+
};
|
|
29656
|
+
|
|
29657
|
+
// src/video/rendertarget/webglrendertarget.js
|
|
29658
|
+
var DEPTH_STENCIL = 34041;
|
|
29659
|
+
var DEPTH_STENCIL_ATTACHMENT = 33306;
|
|
29660
|
+
function attachDepthStencil(gl, framebuffer, renderbuffer, width, height) {
|
|
29661
|
+
const depthStencil = gl.DEPTH_STENCIL ?? DEPTH_STENCIL;
|
|
29662
|
+
const depthStencilAttachment = gl.DEPTH_STENCIL_ATTACHMENT ?? DEPTH_STENCIL_ATTACHMENT;
|
|
29663
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
|
|
29664
|
+
gl.renderbufferStorage(gl.RENDERBUFFER, depthStencil, width, height);
|
|
29665
|
+
gl.framebufferRenderbuffer(
|
|
29666
|
+
gl.FRAMEBUFFER,
|
|
29667
|
+
depthStencilAttachment,
|
|
29668
|
+
gl.RENDERBUFFER,
|
|
29669
|
+
renderbuffer
|
|
29670
|
+
);
|
|
29671
|
+
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
|
|
29672
|
+
return { hasStencil: true, isComplete: true };
|
|
29673
|
+
}
|
|
29674
|
+
gl.framebufferRenderbuffer(
|
|
29675
|
+
gl.FRAMEBUFFER,
|
|
29676
|
+
depthStencilAttachment,
|
|
29677
|
+
gl.RENDERBUFFER,
|
|
29678
|
+
null
|
|
29679
|
+
);
|
|
29680
|
+
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
|
|
29681
|
+
gl.framebufferRenderbuffer(
|
|
29682
|
+
gl.FRAMEBUFFER,
|
|
29683
|
+
gl.DEPTH_ATTACHMENT,
|
|
29684
|
+
gl.RENDERBUFFER,
|
|
29685
|
+
renderbuffer
|
|
29686
|
+
);
|
|
29687
|
+
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
29688
|
+
return {
|
|
29689
|
+
hasStencil: false,
|
|
29690
|
+
isComplete: status === gl.FRAMEBUFFER_COMPLETE
|
|
29691
|
+
};
|
|
29692
|
+
}
|
|
29693
|
+
var WebGLRenderTarget = class extends RenderTarget {
|
|
29694
|
+
/**
|
|
29695
|
+
* @param {WebGLRenderingContext|WebGL2RenderingContext} gl - the WebGL context
|
|
29696
|
+
* @param {number} width - initial width in pixels
|
|
29697
|
+
* @param {number} height - initial height in pixels
|
|
29698
|
+
*/
|
|
29699
|
+
constructor(gl, width, height) {
|
|
29700
|
+
super();
|
|
29701
|
+
this.gl = gl;
|
|
29702
|
+
this.width = width;
|
|
29703
|
+
this.height = height;
|
|
29704
|
+
this.framebuffer = gl.createFramebuffer();
|
|
29705
|
+
const prevUnit = gl.getParameter(gl.ACTIVE_TEXTURE);
|
|
29706
|
+
this.texture = gl.createTexture();
|
|
29707
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
29708
|
+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
29709
|
+
gl.texImage2D(
|
|
29710
|
+
gl.TEXTURE_2D,
|
|
29711
|
+
0,
|
|
29712
|
+
gl.RGBA,
|
|
29713
|
+
width,
|
|
29714
|
+
height,
|
|
29715
|
+
0,
|
|
29716
|
+
gl.RGBA,
|
|
29717
|
+
gl.UNSIGNED_BYTE,
|
|
29718
|
+
null
|
|
29719
|
+
);
|
|
29720
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
29721
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
29722
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
29723
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
29724
|
+
this.depthStencilBuffer = gl.createRenderbuffer();
|
|
29725
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
|
29726
|
+
gl.framebufferTexture2D(
|
|
29727
|
+
gl.FRAMEBUFFER,
|
|
29728
|
+
gl.COLOR_ATTACHMENT0,
|
|
29729
|
+
gl.TEXTURE_2D,
|
|
29730
|
+
this.texture,
|
|
29731
|
+
0
|
|
29732
|
+
);
|
|
29733
|
+
this._applyDepthStencil(width, height);
|
|
29734
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
29735
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
|
29736
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
29737
|
+
gl.activeTexture(prevUnit);
|
|
29738
|
+
}
|
|
29739
|
+
/**
|
|
29740
|
+
* (Re)attach the depth/stencil renderbuffer at the given size and
|
|
29741
|
+
* update `_hasStencil` based on the resulting framebuffer status.
|
|
29742
|
+
* Falls back to depth-only when packed depth+stencil fails; warns
|
|
29743
|
+
* once if even depth-only is incomplete.
|
|
29744
|
+
* @ignore
|
|
29745
|
+
*/
|
|
29746
|
+
_applyDepthStencil(width, height) {
|
|
29747
|
+
const result = attachDepthStencil(
|
|
29748
|
+
this.gl,
|
|
29749
|
+
this.framebuffer,
|
|
29750
|
+
this.depthStencilBuffer,
|
|
29751
|
+
width,
|
|
29752
|
+
height
|
|
29753
|
+
);
|
|
29754
|
+
this._hasStencil = result.hasStencil;
|
|
29755
|
+
if (!result.isComplete) {
|
|
29756
|
+
console.warn(
|
|
29757
|
+
"WebGLRenderTarget: framebuffer incomplete after depth-only fallback \u2014 rendering into this target may fail"
|
|
29758
|
+
);
|
|
29759
|
+
} else if (!result.hasStencil) {
|
|
29760
|
+
console.warn(
|
|
29761
|
+
"WebGLRenderTarget: depth+stencil attachment failed; using depth-only \u2014 stencil masking disabled for this target"
|
|
29762
|
+
);
|
|
29763
|
+
}
|
|
29764
|
+
}
|
|
29765
|
+
/**
|
|
29766
|
+
* Bind this FBO as the active render target.
|
|
29767
|
+
* All subsequent draw calls will render into this FBO's texture.
|
|
29768
|
+
*/
|
|
29769
|
+
bind() {
|
|
29770
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer);
|
|
29771
|
+
}
|
|
29772
|
+
/**
|
|
29773
|
+
* Unbind this FBO and restore rendering to the screen.
|
|
29774
|
+
*/
|
|
29775
|
+
unbind() {
|
|
29776
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
|
29777
|
+
}
|
|
29778
|
+
/**
|
|
29779
|
+
* Resize the FBO texture and renderbuffer.
|
|
29780
|
+
* @param {number} width - new width in pixels
|
|
29781
|
+
* @param {number} height - new height in pixels
|
|
29782
|
+
*/
|
|
29783
|
+
resize(width, height) {
|
|
29784
|
+
if (this.width === width && this.height === height) {
|
|
29785
|
+
return;
|
|
29786
|
+
}
|
|
29787
|
+
const gl = this.gl;
|
|
29788
|
+
this.width = width;
|
|
29789
|
+
this.height = height;
|
|
29790
|
+
const prevUnit = gl.getParameter(gl.ACTIVE_TEXTURE);
|
|
29791
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
29792
|
+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
29793
|
+
gl.texImage2D(
|
|
29794
|
+
gl.TEXTURE_2D,
|
|
29795
|
+
0,
|
|
29796
|
+
gl.RGBA,
|
|
29797
|
+
width,
|
|
29798
|
+
height,
|
|
29799
|
+
0,
|
|
29800
|
+
gl.RGBA,
|
|
29801
|
+
gl.UNSIGNED_BYTE,
|
|
29802
|
+
null
|
|
29803
|
+
);
|
|
29804
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
|
29805
|
+
this._applyDepthStencil(width, height);
|
|
29806
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
29807
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
29808
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
|
29809
|
+
gl.activeTexture(prevUnit);
|
|
29810
|
+
}
|
|
29811
|
+
/**
|
|
29812
|
+
* Clear the FBO contents to transparent black.
|
|
29813
|
+
*/
|
|
29814
|
+
clear() {
|
|
29815
|
+
const gl = this.gl;
|
|
29816
|
+
this.bind();
|
|
29817
|
+
gl.clearColor(0, 0, 0, 0);
|
|
29818
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
|
|
29819
|
+
this.unbind();
|
|
29820
|
+
}
|
|
29821
|
+
/**
|
|
29822
|
+
* Returns an ImageData object representing the pixel contents of this render target.
|
|
29823
|
+
* @param {number} [x=0] - x coordinate of the top-left corner
|
|
29824
|
+
* @param {number} [y=0] - y coordinate of the top-left corner
|
|
29825
|
+
* @param {number} [width=this.width] - width of the area to read
|
|
29826
|
+
* @param {number} [height=this.height] - height of the area to read
|
|
29827
|
+
* @returns {ImageData} the pixel data
|
|
29828
|
+
*/
|
|
29829
|
+
getImageData(x = 0, y = 0, width = this.width, height = this.height) {
|
|
29830
|
+
const gl = this.gl;
|
|
29831
|
+
x = Math.max(0, Math.min(Math.floor(x), this.width - 1));
|
|
29832
|
+
y = Math.max(0, Math.min(Math.floor(y), this.height - 1));
|
|
29833
|
+
width = Math.max(1, Math.min(width, this.width - x));
|
|
29834
|
+
height = Math.max(1, Math.min(height, this.height - y));
|
|
29835
|
+
const pixels = new Uint8ClampedArray(width * height * 4);
|
|
29836
|
+
this.bind();
|
|
29837
|
+
gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
29838
|
+
this.unbind();
|
|
29839
|
+
const rowSize = width * 4;
|
|
29840
|
+
const temp = new Uint8ClampedArray(rowSize);
|
|
29841
|
+
for (let i = 0; i < Math.floor(height / 2); i++) {
|
|
29842
|
+
const topOffset = i * rowSize;
|
|
29843
|
+
const bottomOffset = (height - 1 - i) * rowSize;
|
|
29844
|
+
temp.set(pixels.subarray(topOffset, topOffset + rowSize));
|
|
29845
|
+
pixels.copyWithin(topOffset, bottomOffset, bottomOffset + rowSize);
|
|
29846
|
+
pixels.set(temp, bottomOffset);
|
|
29847
|
+
}
|
|
29848
|
+
return new ImageData(pixels, width, height);
|
|
29849
|
+
}
|
|
29850
|
+
/**
|
|
29851
|
+
* Release all GPU resources.
|
|
29852
|
+
*/
|
|
29853
|
+
destroy() {
|
|
29854
|
+
const gl = this.gl;
|
|
29855
|
+
if (this.framebuffer) {
|
|
29856
|
+
gl.deleteFramebuffer(this.framebuffer);
|
|
29857
|
+
this.framebuffer = null;
|
|
29858
|
+
}
|
|
29859
|
+
if (this.texture) {
|
|
29860
|
+
gl.deleteTexture(this.texture);
|
|
29861
|
+
this.texture = null;
|
|
29862
|
+
}
|
|
29863
|
+
if (this.depthStencilBuffer) {
|
|
29864
|
+
gl.deleteRenderbuffer(this.depthStencilBuffer);
|
|
29865
|
+
this.depthStencilBuffer = null;
|
|
29866
|
+
}
|
|
29867
|
+
}
|
|
29868
|
+
};
|
|
29869
|
+
|
|
27837
29870
|
// src/video/utils/dash.js
|
|
27838
29871
|
var _dashPathResult = [];
|
|
27839
29872
|
function dashPath(pts, pattern) {
|
|
@@ -27981,96 +30014,7 @@ var mesh_default = "uniform sampler2D uSampler;\nvarying vec4 vColor;\nvarying v
|
|
|
27981
30014
|
// src/video/webgl/shaders/mesh.vert
|
|
27982
30015
|
var mesh_default2 = "// Current vertex point (3D position for mesh rendering)\nattribute vec3 aVertex;\nattribute vec2 aRegion;\nattribute vec4 aColor;\n\n// Projection matrix\nuniform mat4 uProjectionMatrix;\n\nvarying vec2 vRegion;\nvarying vec4 vColor;\n\nvoid main(void) {\n // Transform the vertex position by the projection matrix\n gl_Position = uProjectionMatrix * vec4(aVertex, 1.0);\n // Pass the remaining attributes to the fragment shader\n vColor = vec4(aColor.bgr * aColor.a, aColor.a);\n vRegion = aRegion;\n}\n";
|
|
27983
30016
|
|
|
27984
|
-
// src/video/
|
|
27985
|
-
var IndexBuffer = class {
|
|
27986
|
-
/**
|
|
27987
|
-
* @param {WebGLRenderingContext|WebGL2RenderingContext} gl - the WebGL context
|
|
27988
|
-
* @param {number} maxIndices - maximum number of indices this buffer can hold
|
|
27989
|
-
* @param {boolean} [useUint32=false] - use Uint32 indices (WebGL2) instead of Uint16 (WebGL1)
|
|
27990
|
-
* @param {boolean} [dynamic=false] - if true, use STREAM_DRAW for frequent updates; if false, use STATIC_DRAW
|
|
27991
|
-
*/
|
|
27992
|
-
constructor(gl, maxIndices, useUint32 = false, dynamic = false) {
|
|
27993
|
-
this.gl = gl;
|
|
27994
|
-
this.dynamic = dynamic;
|
|
27995
|
-
if (useUint32) {
|
|
27996
|
-
this.type = gl.UNSIGNED_INT;
|
|
27997
|
-
this.data = new Uint32Array(maxIndices);
|
|
27998
|
-
} else {
|
|
27999
|
-
this.type = gl.UNSIGNED_SHORT;
|
|
28000
|
-
this.data = new Uint16Array(maxIndices);
|
|
28001
|
-
}
|
|
28002
|
-
this.length = 0;
|
|
28003
|
-
this.buffer = gl.createBuffer();
|
|
28004
|
-
}
|
|
28005
|
-
/**
|
|
28006
|
-
* Fill the buffer with a repeating quad index pattern [0,1,2, 2,1,3, 4,5,6, ...]
|
|
28007
|
-
* and upload as a static buffer.
|
|
28008
|
-
* @param {number} maxQuads - number of quads to generate indices for
|
|
28009
|
-
*/
|
|
28010
|
-
fillQuadPattern(maxQuads) {
|
|
28011
|
-
for (let i = 0, vertex = 0; i < maxQuads * 6; i += 6, vertex += 4) {
|
|
28012
|
-
this.data[i] = vertex;
|
|
28013
|
-
this.data[i + 1] = vertex + 1;
|
|
28014
|
-
this.data[i + 2] = vertex + 2;
|
|
28015
|
-
this.data[i + 3] = vertex + 2;
|
|
28016
|
-
this.data[i + 4] = vertex + 1;
|
|
28017
|
-
this.data[i + 5] = vertex + 3;
|
|
28018
|
-
}
|
|
28019
|
-
this.length = maxQuads * 6;
|
|
28020
|
-
this.bind();
|
|
28021
|
-
this.gl.bufferData(
|
|
28022
|
-
this.gl.ELEMENT_ARRAY_BUFFER,
|
|
28023
|
-
this.data,
|
|
28024
|
-
this.gl.STATIC_DRAW
|
|
28025
|
-
);
|
|
28026
|
-
}
|
|
28027
|
-
/**
|
|
28028
|
-
* Reset the index count (for dynamic buffers)
|
|
28029
|
-
*/
|
|
28030
|
-
clear() {
|
|
28031
|
-
this.length = 0;
|
|
28032
|
-
}
|
|
28033
|
-
/**
|
|
28034
|
-
* Add indices to the buffer, rebased by the given vertex offset
|
|
28035
|
-
* @param {number[]} indices - source indices to add
|
|
28036
|
-
* @param {number} vertexOffset - value to add to each index (vertex count at time of insertion)
|
|
28037
|
-
*/
|
|
28038
|
-
add(indices, vertexOffset) {
|
|
28039
|
-
for (let i = 0; i < indices.length; i++) {
|
|
28040
|
-
this.data[this.length + i] = indices[i] + vertexOffset;
|
|
28041
|
-
}
|
|
28042
|
-
this.length += indices.length;
|
|
28043
|
-
}
|
|
28044
|
-
/**
|
|
28045
|
-
* Add pre-computed absolute indices to the buffer (no rebasing)
|
|
28046
|
-
* @param {number[]} indices - absolute index values to add
|
|
28047
|
-
*/
|
|
28048
|
-
addRaw(indices) {
|
|
28049
|
-
for (let i = 0; i < indices.length; i++) {
|
|
28050
|
-
this.data[this.length + i] = indices[i];
|
|
28051
|
-
}
|
|
28052
|
-
this.length += indices.length;
|
|
28053
|
-
}
|
|
28054
|
-
/**
|
|
28055
|
-
* Upload the current index data to the GPU (for dynamic buffers)
|
|
28056
|
-
*/
|
|
28057
|
-
upload() {
|
|
28058
|
-
this.bind();
|
|
28059
|
-
this.gl.bufferData(
|
|
28060
|
-
this.gl.ELEMENT_ARRAY_BUFFER,
|
|
28061
|
-
this.data.subarray(0, this.length),
|
|
28062
|
-
this.gl.STREAM_DRAW
|
|
28063
|
-
);
|
|
28064
|
-
}
|
|
28065
|
-
/**
|
|
28066
|
-
* bind this index buffer
|
|
28067
|
-
*/
|
|
28068
|
-
bind() {
|
|
28069
|
-
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffer);
|
|
28070
|
-
}
|
|
28071
|
-
};
|
|
28072
|
-
|
|
28073
|
-
// src/video/webgl/buffer/vertex.js
|
|
30017
|
+
// src/video/buffer/vertex.js
|
|
28074
30018
|
var VertexArrayBuffer = class {
|
|
28075
30019
|
constructor(vertexSize, maxVertex) {
|
|
28076
30020
|
this.vertexSize = vertexSize;
|
|
@@ -28173,258 +30117,102 @@ var VertexArrayBuffer = class {
|
|
|
28173
30117
|
}
|
|
28174
30118
|
};
|
|
28175
30119
|
|
|
28176
|
-
// src/video/
|
|
28177
|
-
|
|
28178
|
-
|
|
28179
|
-
|
|
28180
|
-
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
|
|
28184
|
-
|
|
28185
|
-
return attributes;
|
|
28186
|
-
}
|
|
28187
|
-
|
|
28188
|
-
// src/video/webgl/utils/precision.js
|
|
28189
|
-
function setPrecision(src, precision) {
|
|
28190
|
-
if (src.substring(0, 9) !== "precision") {
|
|
28191
|
-
return "precision " + precision + " float;\n" + src;
|
|
28192
|
-
}
|
|
28193
|
-
return src;
|
|
28194
|
-
}
|
|
28195
|
-
function getMaxShaderPrecision(gl, highPrecision = true) {
|
|
28196
|
-
if (highPrecision && gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) {
|
|
28197
|
-
return "highp";
|
|
28198
|
-
}
|
|
28199
|
-
if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) {
|
|
28200
|
-
return "mediump";
|
|
28201
|
-
}
|
|
28202
|
-
return "lowp";
|
|
28203
|
-
}
|
|
28204
|
-
|
|
28205
|
-
// src/video/webgl/utils/program.js
|
|
28206
|
-
function compileShader(gl, type, source) {
|
|
28207
|
-
const shader = gl.createShader(type);
|
|
28208
|
-
gl.shaderSource(shader, source);
|
|
28209
|
-
gl.compileShader(shader);
|
|
28210
|
-
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
28211
|
-
throw new Error(gl.getShaderInfoLog(shader));
|
|
28212
|
-
}
|
|
28213
|
-
return shader;
|
|
28214
|
-
}
|
|
28215
|
-
function compileProgram(gl, vertex, fragment, attributes) {
|
|
28216
|
-
const vertShader = compileShader(gl, gl.VERTEX_SHADER, vertex);
|
|
28217
|
-
const fragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragment);
|
|
28218
|
-
const program = gl.createProgram();
|
|
28219
|
-
gl.attachShader(program, vertShader);
|
|
28220
|
-
gl.attachShader(program, fragShader);
|
|
28221
|
-
for (const location in attributes) {
|
|
28222
|
-
gl.bindAttribLocation(program, attributes[location], location);
|
|
28223
|
-
}
|
|
28224
|
-
gl.linkProgram(program);
|
|
28225
|
-
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
28226
|
-
const error_msg = "Error initializing Shader " + this + "\ngl.VALIDATE_STATUS: " + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + "\ngl.getError()" + gl.getError() + "\ngl.getProgramInfoLog()" + gl.getProgramInfoLog(program);
|
|
28227
|
-
gl.deleteProgram(program);
|
|
28228
|
-
throw new Error(error_msg);
|
|
30120
|
+
// src/video/buffer/index.js
|
|
30121
|
+
var IndexBuffer = class {
|
|
30122
|
+
/**
|
|
30123
|
+
* @param {number} maxIndices - maximum number of indices this buffer can hold
|
|
30124
|
+
* @param {boolean} [useUint32=false] - use Uint32 indices instead of Uint16
|
|
30125
|
+
*/
|
|
30126
|
+
constructor(maxIndices, useUint32 = false) {
|
|
30127
|
+
this.data = useUint32 ? new Uint32Array(maxIndices) : new Uint16Array(maxIndices);
|
|
30128
|
+
this.length = 0;
|
|
28229
30129
|
}
|
|
28230
|
-
gl.useProgram(program);
|
|
28231
|
-
gl.deleteShader(vertShader);
|
|
28232
|
-
gl.deleteShader(fragShader);
|
|
28233
|
-
return program;
|
|
28234
|
-
}
|
|
28235
|
-
|
|
28236
|
-
// src/video/webgl/utils/string.js
|
|
28237
|
-
function minify(src) {
|
|
28238
|
-
src = src.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
|
|
28239
|
-
src = src.replace(/(\\n\s+)|(\s+\\n)/g, "");
|
|
28240
|
-
src = src.replace(/(\\r|\\n)+/g, "");
|
|
28241
|
-
src = src.replace(/[ \t]*([;,[\](){}\\\/\-+*|^&!=<>?~%])[ \t]*/g, "$1");
|
|
28242
|
-
return src;
|
|
28243
|
-
}
|
|
28244
|
-
|
|
28245
|
-
// src/video/webgl/utils/uniforms.js
|
|
28246
|
-
var fnHash = {
|
|
28247
|
-
bool: "1i",
|
|
28248
|
-
int: "1i",
|
|
28249
|
-
float: "1f",
|
|
28250
|
-
vec2: "2fv",
|
|
28251
|
-
vec3: "3fv",
|
|
28252
|
-
vec4: "4fv",
|
|
28253
|
-
bvec2: "2iv",
|
|
28254
|
-
bvec3: "3iv",
|
|
28255
|
-
bvec4: "4iv",
|
|
28256
|
-
ivec2: "2iv",
|
|
28257
|
-
ivec3: "3iv",
|
|
28258
|
-
ivec4: "4iv",
|
|
28259
|
-
mat2: "Matrix2fv",
|
|
28260
|
-
mat3: "Matrix3fv",
|
|
28261
|
-
mat4: "Matrix4fv",
|
|
28262
|
-
sampler2D: "1i"
|
|
28263
|
-
};
|
|
28264
|
-
function extractUniforms(gl, shader) {
|
|
28265
|
-
const uniforms = {};
|
|
28266
|
-
const uniRx = /uniform\s+(\w+)\s+(\w+)/g;
|
|
28267
|
-
const uniformsData = {};
|
|
28268
|
-
const descriptor = {};
|
|
28269
|
-
const locations = {};
|
|
28270
|
-
let match;
|
|
28271
|
-
[shader.vertex, shader.fragment].forEach((shader2) => {
|
|
28272
|
-
while (match = uniRx.exec(shader2)) {
|
|
28273
|
-
uniformsData[match[2]] = match[1];
|
|
28274
|
-
}
|
|
28275
|
-
});
|
|
28276
|
-
Object.keys(uniformsData).forEach((name) => {
|
|
28277
|
-
const type = uniformsData[name];
|
|
28278
|
-
locations[name] = gl.getUniformLocation(shader.program, name);
|
|
28279
|
-
descriptor[name] = {
|
|
28280
|
-
get: /* @__PURE__ */ (function(name2) {
|
|
28281
|
-
return function() {
|
|
28282
|
-
return locations[name2];
|
|
28283
|
-
};
|
|
28284
|
-
})(name),
|
|
28285
|
-
set: (function(name2, type2, fn) {
|
|
28286
|
-
if (/^mat/.test(type2)) {
|
|
28287
|
-
return function(val) {
|
|
28288
|
-
gl[fn](locations[name2], false, val);
|
|
28289
|
-
};
|
|
28290
|
-
} else {
|
|
28291
|
-
return function(val) {
|
|
28292
|
-
let fnv = fn;
|
|
28293
|
-
if (val.length && !/v$/.test(fn)) {
|
|
28294
|
-
fnv += "v";
|
|
28295
|
-
}
|
|
28296
|
-
gl[fnv](locations[name2], val);
|
|
28297
|
-
};
|
|
28298
|
-
}
|
|
28299
|
-
})(name, type, "uniform" + fnHash[type])
|
|
28300
|
-
};
|
|
28301
|
-
});
|
|
28302
|
-
Object.defineProperties(uniforms, descriptor);
|
|
28303
|
-
return uniforms;
|
|
28304
|
-
}
|
|
28305
|
-
|
|
28306
|
-
// src/video/webgl/glshader.js
|
|
28307
|
-
var GLShader = class {
|
|
28308
30130
|
/**
|
|
28309
|
-
*
|
|
28310
|
-
* @param {
|
|
28311
|
-
* @param {string} fragment - a string containing the GLSL source code to set
|
|
28312
|
-
* @param {string} [precision=auto detected] - float precision ('lowp', 'mediump' or 'highp').
|
|
28313
|
-
* @see https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders
|
|
28314
|
-
* @example
|
|
28315
|
-
* // create a basic shader
|
|
28316
|
-
* let myShader = new me.GLShader(
|
|
28317
|
-
* // WebGL rendering context
|
|
28318
|
-
* gl,
|
|
28319
|
-
* // vertex shader
|
|
28320
|
-
* [
|
|
28321
|
-
* "void main() {",
|
|
28322
|
-
* " gl_Position = doMathToMakeClipspaceCoordinates;",
|
|
28323
|
-
* "}"
|
|
28324
|
-
* ].join("\n"),
|
|
28325
|
-
* // fragment shader
|
|
28326
|
-
* [
|
|
28327
|
-
* "void main() {",
|
|
28328
|
-
* " gl_FragColor = doMathToMakeAColor;",
|
|
28329
|
-
* "}"
|
|
28330
|
-
* ].join("\n")
|
|
28331
|
-
* )
|
|
28332
|
-
* // use the shader
|
|
28333
|
-
* myShader.bind();
|
|
30131
|
+
* Fill the buffer with a repeating quad index pattern [0,1,2, 2,1,3, 4,5,6, ...]
|
|
30132
|
+
* @param {number} maxQuads - number of quads to generate indices for
|
|
28334
30133
|
*/
|
|
28335
|
-
|
|
28336
|
-
|
|
28337
|
-
|
|
28338
|
-
|
|
28339
|
-
|
|
28340
|
-
|
|
28341
|
-
|
|
28342
|
-
|
|
28343
|
-
|
|
28344
|
-
|
|
28345
|
-
this.attributes = extractAttributes(this.gl, this);
|
|
28346
|
-
this.program = compileProgram(
|
|
28347
|
-
this.gl,
|
|
28348
|
-
this.vertex,
|
|
28349
|
-
this.fragment,
|
|
28350
|
-
this.attributes
|
|
28351
|
-
);
|
|
28352
|
-
this.uniforms = extractUniforms(this.gl, this);
|
|
28353
|
-
on(ONCONTEXT_LOST, this.destroy, this);
|
|
30134
|
+
fillQuadPattern(maxQuads) {
|
|
30135
|
+
for (let i = 0, vertex = 0; i < maxQuads * 6; i += 6, vertex += 4) {
|
|
30136
|
+
this.data[i] = vertex;
|
|
30137
|
+
this.data[i + 1] = vertex + 1;
|
|
30138
|
+
this.data[i + 2] = vertex + 2;
|
|
30139
|
+
this.data[i + 3] = vertex + 2;
|
|
30140
|
+
this.data[i + 4] = vertex + 1;
|
|
30141
|
+
this.data[i + 5] = vertex + 3;
|
|
30142
|
+
}
|
|
30143
|
+
this.length = maxQuads * 6;
|
|
28354
30144
|
}
|
|
28355
30145
|
/**
|
|
28356
|
-
*
|
|
30146
|
+
* Reset the index count
|
|
28357
30147
|
*/
|
|
28358
|
-
|
|
28359
|
-
this.
|
|
30148
|
+
clear() {
|
|
30149
|
+
this.length = 0;
|
|
28360
30150
|
}
|
|
28361
30151
|
/**
|
|
28362
|
-
*
|
|
28363
|
-
* @param {
|
|
28364
|
-
* @
|
|
30152
|
+
* Add indices to the buffer, rebased by the given vertex offset
|
|
30153
|
+
* @param {number[]} indices - source indices to add
|
|
30154
|
+
* @param {number} vertexOffset - value to add to each index
|
|
28365
30155
|
*/
|
|
28366
|
-
|
|
28367
|
-
|
|
28368
|
-
|
|
28369
|
-
return attr;
|
|
28370
|
-
} else {
|
|
28371
|
-
return -1;
|
|
30156
|
+
add(indices, vertexOffset) {
|
|
30157
|
+
for (let i = 0; i < indices.length; i++) {
|
|
30158
|
+
this.data[this.length + i] = indices[i] + vertexOffset;
|
|
28372
30159
|
}
|
|
30160
|
+
this.length += indices.length;
|
|
28373
30161
|
}
|
|
28374
30162
|
/**
|
|
28375
|
-
*
|
|
28376
|
-
* @param {
|
|
28377
|
-
* @param {object|Float32Array} value - the value to assign to that uniform
|
|
28378
|
-
* @example
|
|
28379
|
-
* myShader.setUniform("uProjectionMatrix", this.projectionMatrix);
|
|
30163
|
+
* Add pre-computed absolute indices to the buffer (no rebasing)
|
|
30164
|
+
* @param {number[]} indices - absolute index values to add
|
|
28380
30165
|
*/
|
|
28381
|
-
|
|
28382
|
-
|
|
28383
|
-
|
|
28384
|
-
this.bind();
|
|
28385
|
-
if (typeof value === "object" && typeof value.toArray === "function") {
|
|
28386
|
-
uniforms[name] = value.toArray();
|
|
28387
|
-
} else {
|
|
28388
|
-
uniforms[name] = value;
|
|
28389
|
-
}
|
|
28390
|
-
} else {
|
|
28391
|
-
throw new Error("undefined (" + name + ") uniform for shader " + this);
|
|
30166
|
+
addRaw(indices) {
|
|
30167
|
+
for (let i = 0; i < indices.length; i++) {
|
|
30168
|
+
this.data[this.length + i] = indices[i];
|
|
28392
30169
|
}
|
|
30170
|
+
this.length += indices.length;
|
|
28393
30171
|
}
|
|
30172
|
+
};
|
|
30173
|
+
|
|
30174
|
+
// src/video/webgl/buffer/index.js
|
|
30175
|
+
var WebGLIndexBuffer = class extends IndexBuffer {
|
|
28394
30176
|
/**
|
|
28395
|
-
*
|
|
28396
|
-
* @param {
|
|
28397
|
-
* @param {
|
|
28398
|
-
* @param {number} stride - the size of a single vertex in bytes
|
|
30177
|
+
* @param {WebGLRenderingContext|WebGL2RenderingContext} gl - the WebGL context
|
|
30178
|
+
* @param {number} maxIndices - maximum number of indices this buffer can hold
|
|
30179
|
+
* @param {boolean} [useUint32=false] - use Uint32 indices (WebGL2) instead of Uint16 (WebGL1)
|
|
28399
30180
|
*/
|
|
28400
|
-
|
|
28401
|
-
|
|
28402
|
-
|
|
28403
|
-
|
|
28404
|
-
|
|
28405
|
-
gl.enableVertexAttribArray(location);
|
|
28406
|
-
gl.vertexAttribPointer(
|
|
28407
|
-
location,
|
|
28408
|
-
element.size,
|
|
28409
|
-
element.type,
|
|
28410
|
-
element.normalized,
|
|
28411
|
-
stride,
|
|
28412
|
-
element.offset
|
|
28413
|
-
);
|
|
28414
|
-
} else {
|
|
28415
|
-
gl.disableVertexAttribArray(index);
|
|
28416
|
-
}
|
|
28417
|
-
}
|
|
30181
|
+
constructor(gl, maxIndices, useUint32 = false) {
|
|
30182
|
+
super(maxIndices, useUint32);
|
|
30183
|
+
this.gl = gl;
|
|
30184
|
+
this.type = useUint32 ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
|
|
30185
|
+
this.buffer = gl.createBuffer();
|
|
28418
30186
|
}
|
|
28419
30187
|
/**
|
|
28420
|
-
*
|
|
30188
|
+
* Fill the buffer with a repeating quad index pattern and upload as static.
|
|
30189
|
+
* @param {number} maxQuads - number of quads to generate indices for
|
|
28421
30190
|
*/
|
|
28422
|
-
|
|
28423
|
-
|
|
28424
|
-
this.
|
|
28425
|
-
this.gl.
|
|
28426
|
-
|
|
28427
|
-
|
|
30191
|
+
fillQuadPattern(maxQuads) {
|
|
30192
|
+
super.fillQuadPattern(maxQuads);
|
|
30193
|
+
this.bind();
|
|
30194
|
+
this.gl.bufferData(
|
|
30195
|
+
this.gl.ELEMENT_ARRAY_BUFFER,
|
|
30196
|
+
this.data,
|
|
30197
|
+
this.gl.STATIC_DRAW
|
|
30198
|
+
);
|
|
30199
|
+
}
|
|
30200
|
+
/**
|
|
30201
|
+
* Upload the current index data to the GPU (for dynamic buffers)
|
|
30202
|
+
*/
|
|
30203
|
+
upload() {
|
|
30204
|
+
this.bind();
|
|
30205
|
+
this.gl.bufferData(
|
|
30206
|
+
this.gl.ELEMENT_ARRAY_BUFFER,
|
|
30207
|
+
this.data.subarray(0, this.length),
|
|
30208
|
+
this.gl.STREAM_DRAW
|
|
30209
|
+
);
|
|
30210
|
+
}
|
|
30211
|
+
/**
|
|
30212
|
+
* Bind this index buffer
|
|
30213
|
+
*/
|
|
30214
|
+
bind() {
|
|
30215
|
+
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffer);
|
|
28428
30216
|
}
|
|
28429
30217
|
};
|
|
28430
30218
|
|
|
@@ -28497,7 +30285,7 @@ var Batcher = class {
|
|
|
28497
30285
|
if (this.useIndexBuffer) {
|
|
28498
30286
|
const gl = this.gl;
|
|
28499
30287
|
this.glVertexBuffer = gl.createBuffer();
|
|
28500
|
-
this.indexBuffer = new
|
|
30288
|
+
this.indexBuffer = new WebGLIndexBuffer(gl, maxVertices * 3, false);
|
|
28501
30289
|
}
|
|
28502
30290
|
}
|
|
28503
30291
|
/**
|
|
@@ -29239,7 +31027,7 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29239
31027
|
}
|
|
29240
31028
|
this.useMultiTexture = true;
|
|
29241
31029
|
const maxQuads = this.vertexData.maxVertex / 4;
|
|
29242
|
-
this.indexBuffer = new
|
|
31030
|
+
this.indexBuffer = new WebGLIndexBuffer(
|
|
29243
31031
|
this.gl,
|
|
29244
31032
|
maxQuads * 6,
|
|
29245
31033
|
this.renderer.WebGLVersion > 1
|
|
@@ -29251,7 +31039,8 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29251
31039
|
* Multi-texture batching is automatically enabled when the default
|
|
29252
31040
|
* shader is active, and disabled for custom ShaderEffect shaders.
|
|
29253
31041
|
* @see GLShader
|
|
29254
|
-
* @
|
|
31042
|
+
* @see ShaderEffect
|
|
31043
|
+
* @param {GLShader|ShaderEffect} shader - a reference to a GLShader or ShaderEffect instance
|
|
29255
31044
|
*/
|
|
29256
31045
|
useShader(shader) {
|
|
29257
31046
|
super.useShader(shader);
|
|
@@ -29264,7 +31053,7 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29264
31053
|
reset() {
|
|
29265
31054
|
super.reset();
|
|
29266
31055
|
const maxQuads = this.vertexData.maxVertex / 4;
|
|
29267
|
-
this.indexBuffer = new
|
|
31056
|
+
this.indexBuffer = new WebGLIndexBuffer(
|
|
29268
31057
|
this.gl,
|
|
29269
31058
|
maxQuads * 6,
|
|
29270
31059
|
this.renderer.WebGLVersion > 1
|
|
@@ -29306,6 +31095,34 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29306
31095
|
vertex.clear();
|
|
29307
31096
|
}
|
|
29308
31097
|
}
|
|
31098
|
+
/**
|
|
31099
|
+
* Draw a screen-aligned quad with the given raw WebGL texture through the given shader.
|
|
31100
|
+
* Binds the texture to unit 0, pushes 4 vertices (Y-flipped UVs), flushes,
|
|
31101
|
+
* then unbinds the texture.
|
|
31102
|
+
* @param {WebGLTexture} source - the raw GL texture to blit
|
|
31103
|
+
* @param {number} x - destination x
|
|
31104
|
+
* @param {number} y - destination y
|
|
31105
|
+
* @param {number} width - destination width
|
|
31106
|
+
* @param {number} height - destination height
|
|
31107
|
+
* @param {GLShader|ShaderEffect} shader - the shader effect to apply
|
|
31108
|
+
*/
|
|
31109
|
+
blitTexture(source, x, y, width, height, shader) {
|
|
31110
|
+
const gl = this.gl;
|
|
31111
|
+
this.useShader(shader);
|
|
31112
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
31113
|
+
gl.bindTexture(gl.TEXTURE_2D, source);
|
|
31114
|
+
shader.setUniform("uSampler", 0);
|
|
31115
|
+
const tint = 4294967295;
|
|
31116
|
+
this.vertexData.push(x, y, 0, 1, tint, 0);
|
|
31117
|
+
this.vertexData.push(x + width, y, 1, 1, tint, 0);
|
|
31118
|
+
this.vertexData.push(x, y + height, 0, 0, tint, 0);
|
|
31119
|
+
this.vertexData.push(x + width, y + height, 1, 0, tint, 0);
|
|
31120
|
+
this.flush();
|
|
31121
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
31122
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
31123
|
+
delete this.boundTextures[0];
|
|
31124
|
+
this.useShader(this.defaultShader);
|
|
31125
|
+
}
|
|
29309
31126
|
/**
|
|
29310
31127
|
* Add a textured quad
|
|
29311
31128
|
* @param {TextureAtlas} texture - Source texture atlas
|
|
@@ -29361,6 +31178,8 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29361
31178
|
|
|
29362
31179
|
// src/video/webgl/webgl_renderer.js
|
|
29363
31180
|
var _tempMatrix = new Matrix3d();
|
|
31181
|
+
var _savedTransform = new Matrix3d();
|
|
31182
|
+
var _savedProjection = new Matrix3d();
|
|
29364
31183
|
var supportedCompressedTextureFormats;
|
|
29365
31184
|
var WebGLRenderer = class extends Renderer {
|
|
29366
31185
|
/**
|
|
@@ -29371,6 +31190,10 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29371
31190
|
this.GPUVendor = void 0;
|
|
29372
31191
|
this.GPURenderer = void 0;
|
|
29373
31192
|
this.gl = this.renderTarget.context;
|
|
31193
|
+
this._renderTargetPool = new RenderTargetPool((w, h) => {
|
|
31194
|
+
return new WebGLRenderTarget(this.gl, w, h);
|
|
31195
|
+
});
|
|
31196
|
+
this._savedEffectProjection = new Matrix3d();
|
|
29374
31197
|
this.lineWidth = 1;
|
|
29375
31198
|
this.lineJoin = "round";
|
|
29376
31199
|
this.vertexBuffer = this.gl.createBuffer();
|
|
@@ -29508,6 +31331,7 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29508
31331
|
this.setBatcher("quad");
|
|
29509
31332
|
this.gl.disable(this.gl.SCISSOR_TEST);
|
|
29510
31333
|
this._scissorActive = false;
|
|
31334
|
+
this._renderTargetPool.destroy();
|
|
29511
31335
|
}
|
|
29512
31336
|
/**
|
|
29513
31337
|
* add a new batcher to this renderer
|
|
@@ -29594,6 +31418,148 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29594
31418
|
flush() {
|
|
29595
31419
|
this.currentBatcher.flush();
|
|
29596
31420
|
}
|
|
31421
|
+
/**
|
|
31422
|
+
* Begin capturing rendering to an offscreen FBO for post-effect processing.
|
|
31423
|
+
* @param {Renderable} renderable - the renderable requesting post-effect processing
|
|
31424
|
+
* @returns {boolean} true if FBO capture started, false if skipped
|
|
31425
|
+
* @ignore
|
|
31426
|
+
*/
|
|
31427
|
+
beginPostEffect(renderable) {
|
|
31428
|
+
const effects = renderable.postEffects.filter((fx) => {
|
|
31429
|
+
return fx.enabled !== false;
|
|
31430
|
+
});
|
|
31431
|
+
if (effects.length === 0) {
|
|
31432
|
+
this.customShader = void 0;
|
|
31433
|
+
return false;
|
|
31434
|
+
}
|
|
31435
|
+
if (effects.length === 1 && !renderable._postEffectManaged) {
|
|
31436
|
+
this.customShader = effects[0];
|
|
31437
|
+
return false;
|
|
31438
|
+
}
|
|
31439
|
+
this.customShader = void 0;
|
|
31440
|
+
const isCamera = renderable._postEffectManaged;
|
|
31441
|
+
const canvas = this.getCanvas();
|
|
31442
|
+
const w = canvas.width;
|
|
31443
|
+
const h = canvas.height;
|
|
31444
|
+
this.flush();
|
|
31445
|
+
this.save();
|
|
31446
|
+
this._savedEffectProjection.copy(this.projectionMatrix);
|
|
31447
|
+
const rt = this._renderTargetPool.begin(isCamera, effects.length, w, h);
|
|
31448
|
+
if (this.currentBatcher && this.currentBatcher.boundTextures) {
|
|
31449
|
+
delete this.currentBatcher.boundTextures[0];
|
|
31450
|
+
}
|
|
31451
|
+
rt.bind();
|
|
31452
|
+
this.setViewport(0, 0, w, h);
|
|
31453
|
+
this.disableScissor();
|
|
31454
|
+
this.setGlobalAlpha(1);
|
|
31455
|
+
this.setBlendMode("normal");
|
|
31456
|
+
if (isCamera) {
|
|
31457
|
+
this.clear();
|
|
31458
|
+
} else {
|
|
31459
|
+
this.clearRenderTarget();
|
|
31460
|
+
}
|
|
31461
|
+
return true;
|
|
31462
|
+
}
|
|
31463
|
+
/** @ignore */
|
|
31464
|
+
endPostEffect(renderable) {
|
|
31465
|
+
const effects = renderable.postEffects.filter((fx) => {
|
|
31466
|
+
return fx.enabled !== false;
|
|
31467
|
+
});
|
|
31468
|
+
if (effects.length === 0) {
|
|
31469
|
+
return;
|
|
31470
|
+
}
|
|
31471
|
+
if (effects.length === 1 && !renderable._postEffectManaged) {
|
|
31472
|
+
return;
|
|
31473
|
+
}
|
|
31474
|
+
const isCamera = renderable._postEffectManaged;
|
|
31475
|
+
const rt1 = this._renderTargetPool.getCaptureTarget();
|
|
31476
|
+
const rt2 = this._renderTargetPool.getPingPongTarget();
|
|
31477
|
+
const keepBlend = !isCamera;
|
|
31478
|
+
const canvas = this.getCanvas();
|
|
31479
|
+
const w = canvas.width;
|
|
31480
|
+
const h = canvas.height;
|
|
31481
|
+
this.flush();
|
|
31482
|
+
rt1.unbind();
|
|
31483
|
+
const parentRT = this._renderTargetPool.end();
|
|
31484
|
+
if (isCamera && renderable.isDefault === false) {
|
|
31485
|
+
this.clipRect(
|
|
31486
|
+
renderable.screenX,
|
|
31487
|
+
renderable.screenY,
|
|
31488
|
+
renderable.width,
|
|
31489
|
+
renderable.height
|
|
31490
|
+
);
|
|
31491
|
+
}
|
|
31492
|
+
if (parentRT) {
|
|
31493
|
+
parentRT.bind();
|
|
31494
|
+
}
|
|
31495
|
+
this.setViewport(0, 0, w, h);
|
|
31496
|
+
if (effects.length === 1) {
|
|
31497
|
+
this.blitEffect(rt1.texture, 0, 0, w, h, effects[0], keepBlend);
|
|
31498
|
+
} else {
|
|
31499
|
+
let src = rt1;
|
|
31500
|
+
let dst = rt2;
|
|
31501
|
+
for (let i = 0; i < effects.length - 1; i++) {
|
|
31502
|
+
dst.bind();
|
|
31503
|
+
this.setViewport(0, 0, w, h);
|
|
31504
|
+
this.clearRenderTarget();
|
|
31505
|
+
this.blitEffect(src.texture, 0, 0, w, h, effects[i]);
|
|
31506
|
+
dst.unbind();
|
|
31507
|
+
const tmp = src;
|
|
31508
|
+
src = dst;
|
|
31509
|
+
dst = tmp;
|
|
31510
|
+
}
|
|
31511
|
+
if (parentRT) {
|
|
31512
|
+
parentRT.bind();
|
|
31513
|
+
}
|
|
31514
|
+
this.setViewport(0, 0, w, h);
|
|
31515
|
+
this.blitEffect(
|
|
31516
|
+
src.texture,
|
|
31517
|
+
0,
|
|
31518
|
+
0,
|
|
31519
|
+
w,
|
|
31520
|
+
h,
|
|
31521
|
+
effects[effects.length - 1],
|
|
31522
|
+
keepBlend
|
|
31523
|
+
);
|
|
31524
|
+
}
|
|
31525
|
+
if (isCamera && renderable.isDefault === false) {
|
|
31526
|
+
this.disableScissor();
|
|
31527
|
+
}
|
|
31528
|
+
this.restore();
|
|
31529
|
+
this.projectionMatrix.copy(this._savedEffectProjection);
|
|
31530
|
+
this.currentBatcher.setProjection(this.projectionMatrix);
|
|
31531
|
+
}
|
|
31532
|
+
/**
|
|
31533
|
+
* Blit a texture to the screen through a shader effect.
|
|
31534
|
+
* Draws a screen-aligned quad using the given texture as source
|
|
31535
|
+
* and the given shader for post-processing (e.g. scanlines, desaturation).
|
|
31536
|
+
* @param {WebGLTexture} source - the source texture to blit
|
|
31537
|
+
* @param {number} x - destination x position
|
|
31538
|
+
* @param {number} y - destination y position
|
|
31539
|
+
* @param {number} width - destination width
|
|
31540
|
+
* @param {number} height - destination height
|
|
31541
|
+
* @param {ShaderEffect} shader - the shader effect to apply
|
|
31542
|
+
* @param {boolean} [keepBlend=false] - if true, keep current blend mode (for sprite compositing)
|
|
31543
|
+
*/
|
|
31544
|
+
blitEffect(source, x, y, width, height, shader, keepBlend = false) {
|
|
31545
|
+
this.flush();
|
|
31546
|
+
const batcher = this.setBatcher("quad");
|
|
31547
|
+
_savedTransform.copy(this.currentTransform);
|
|
31548
|
+
_savedProjection.copy(this.projectionMatrix);
|
|
31549
|
+
this.currentTransform.identity();
|
|
31550
|
+
this.projectionMatrix.ortho(0, width, height, 0, -1, 1);
|
|
31551
|
+
batcher.setProjection(this.projectionMatrix);
|
|
31552
|
+
if (!keepBlend) {
|
|
31553
|
+
this.setBlendEnabled(false);
|
|
31554
|
+
}
|
|
31555
|
+
batcher.blitTexture(source, x, y, width, height, shader);
|
|
31556
|
+
if (!keepBlend) {
|
|
31557
|
+
this.setBlendEnabled(true);
|
|
31558
|
+
}
|
|
31559
|
+
this.currentTransform.copy(_savedTransform);
|
|
31560
|
+
this.projectionMatrix.copy(_savedProjection);
|
|
31561
|
+
batcher.setProjection(this.projectionMatrix);
|
|
31562
|
+
}
|
|
29597
31563
|
/**
|
|
29598
31564
|
* set/change the current projection matrix (WebGL only)
|
|
29599
31565
|
* @param {Matrix3d} matrix - the new projection matrix
|
|
@@ -29613,6 +31579,61 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29613
31579
|
setViewport(x = 0, y = 0, w = this.getCanvas().width, h = this.getCanvas().height) {
|
|
29614
31580
|
this.gl.viewport(x, y, w, h);
|
|
29615
31581
|
}
|
|
31582
|
+
/**
|
|
31583
|
+
* Clear the current render target to transparent black.
|
|
31584
|
+
*
|
|
31585
|
+
* Only clears the color buffer — `setMask()` clears `STENCIL_BUFFER_BIT`
|
|
31586
|
+
* itself when starting a mask, and including it here would emit a WebGL
|
|
31587
|
+
* `Clear called for non-existing buffers` warning when the active FBO
|
|
31588
|
+
* has no stencil attachment (rare, but happens on drivers that fail
|
|
31589
|
+
* the depth+stencil renderbuffer attachment for the FBO).
|
|
31590
|
+
*/
|
|
31591
|
+
clearRenderTarget() {
|
|
31592
|
+
const gl = this.gl;
|
|
31593
|
+
gl.clearColor(0, 0, 0, 0);
|
|
31594
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
31595
|
+
}
|
|
31596
|
+
/**
|
|
31597
|
+
* Enable the scissor test with the given rectangle.
|
|
31598
|
+
* @param {number} x - x coordinate of the scissor rectangle
|
|
31599
|
+
* @param {number} y - y coordinate of the scissor rectangle
|
|
31600
|
+
* @param {number} width - width of the scissor rectangle
|
|
31601
|
+
* @param {number} height - height of the scissor rectangle
|
|
31602
|
+
*/
|
|
31603
|
+
enableScissor(x, y, width, height) {
|
|
31604
|
+
const gl = this.gl;
|
|
31605
|
+
this.flush();
|
|
31606
|
+
gl.enable(gl.SCISSOR_TEST);
|
|
31607
|
+
this._scissorActive = true;
|
|
31608
|
+
gl.scissor(
|
|
31609
|
+
x + this.currentTransform.tx,
|
|
31610
|
+
this.getCanvas().height - height - y - this.currentTransform.ty,
|
|
31611
|
+
width,
|
|
31612
|
+
height
|
|
31613
|
+
);
|
|
31614
|
+
this.currentScissor[0] = x;
|
|
31615
|
+
this.currentScissor[1] = y;
|
|
31616
|
+
this.currentScissor[2] = width;
|
|
31617
|
+
this.currentScissor[3] = height;
|
|
31618
|
+
}
|
|
31619
|
+
/**
|
|
31620
|
+
* Disable the scissor test, allowing rendering to the full viewport.
|
|
31621
|
+
*/
|
|
31622
|
+
disableScissor() {
|
|
31623
|
+
this.gl.disable(this.gl.SCISSOR_TEST);
|
|
31624
|
+
this._scissorActive = false;
|
|
31625
|
+
}
|
|
31626
|
+
/**
|
|
31627
|
+
* Enable or disable alpha blending.
|
|
31628
|
+
* @param {boolean} enable - true to enable blending, false to disable
|
|
31629
|
+
*/
|
|
31630
|
+
setBlendEnabled(enable2) {
|
|
31631
|
+
if (enable2) {
|
|
31632
|
+
this.gl.enable(this.gl.BLEND);
|
|
31633
|
+
} else {
|
|
31634
|
+
this.gl.disable(this.gl.BLEND);
|
|
31635
|
+
}
|
|
31636
|
+
}
|
|
29616
31637
|
/**
|
|
29617
31638
|
* Clear the frame buffer
|
|
29618
31639
|
*/
|
|
@@ -30040,6 +32061,7 @@ var WebGLRenderer = class extends Renderer {
|
|
|
30040
32061
|
}
|
|
30041
32062
|
}
|
|
30042
32063
|
this._currentGradient = this.renderState.currentGradient;
|
|
32064
|
+
this.customShader = this.renderState.currentShader;
|
|
30043
32065
|
}
|
|
30044
32066
|
/**
|
|
30045
32067
|
* saves the entire state of the renderer by pushing the current state onto a stack.
|
|
@@ -30055,6 +32077,7 @@ var WebGLRenderer = class extends Renderer {
|
|
|
30055
32077
|
* renderer.restore();
|
|
30056
32078
|
*/
|
|
30057
32079
|
save() {
|
|
32080
|
+
this.renderState.currentShader = this.customShader;
|
|
30058
32081
|
this.renderState.save(this._scissorActive === true);
|
|
30059
32082
|
}
|
|
30060
32083
|
/**
|
|
@@ -31218,6 +33241,45 @@ var Application = class {
|
|
|
31218
33241
|
repaint() {
|
|
31219
33242
|
this.isDirty = true;
|
|
31220
33243
|
}
|
|
33244
|
+
/**
|
|
33245
|
+
* Pause the current stage. Convenience proxy for {@link state.pause}.
|
|
33246
|
+
* @param [music=false] - also pause the current music track
|
|
33247
|
+
* @example
|
|
33248
|
+
* app.pause(); // pause game updates, keep music playing
|
|
33249
|
+
* app.pause(true); // pause game updates and music
|
|
33250
|
+
*/
|
|
33251
|
+
pause(music = false) {
|
|
33252
|
+
state_default.pause(music);
|
|
33253
|
+
}
|
|
33254
|
+
/**
|
|
33255
|
+
* Resume the current stage. Convenience proxy for {@link state.resume}.
|
|
33256
|
+
* @param [music=false] - also resume the current music track
|
|
33257
|
+
*/
|
|
33258
|
+
resume(music = false) {
|
|
33259
|
+
state_default.resume(music);
|
|
33260
|
+
}
|
|
33261
|
+
/**
|
|
33262
|
+
* Freeze the current stage for a fixed duration, then automatically resume.
|
|
33263
|
+
* Useful for hit-stop / hit-pause effects on impact.
|
|
33264
|
+
*
|
|
33265
|
+
* Convenience proxy for {@link state.freeze}; see that method's
|
|
33266
|
+
* documentation for the full behaviour matrix (extend-not-stack semantics,
|
|
33267
|
+
* interaction with manual `state.pause()` / `state.resume()`, automatic
|
|
33268
|
+
* cancellation on window blur, etc.).
|
|
33269
|
+
* @param duration - duration of the freeze in milliseconds
|
|
33270
|
+
* @param [music=false] - also pause the current music track during the freeze
|
|
33271
|
+
* @returns a Promise that resolves once the freeze ends (or is cancelled)
|
|
33272
|
+
* @example
|
|
33273
|
+
* // simple hit-stop on impact
|
|
33274
|
+
* app.freeze(80);
|
|
33275
|
+
*
|
|
33276
|
+
* // chain VFX after the freeze
|
|
33277
|
+
* await app.freeze(120);
|
|
33278
|
+
* spawnImpactParticles();
|
|
33279
|
+
*/
|
|
33280
|
+
freeze(duration, music = false) {
|
|
33281
|
+
return state_default.freeze(duration, music);
|
|
33282
|
+
}
|
|
31221
33283
|
/** @ignore */
|
|
31222
33284
|
_tick(time) {
|
|
31223
33285
|
this.update(time);
|
|
@@ -31290,197 +33352,42 @@ function setDefaultGame(app) {
|
|
|
31290
33352
|
game = app;
|
|
31291
33353
|
}
|
|
31292
33354
|
|
|
31293
|
-
// src/particles/settings.
|
|
31294
|
-
var
|
|
31295
|
-
/**
|
|
31296
|
-
* Width of the particle spawn area.
|
|
31297
|
-
* @type {number}
|
|
31298
|
-
* @default 1
|
|
31299
|
-
*/
|
|
33355
|
+
// src/particles/settings.ts
|
|
33356
|
+
var defaultParticleEmitterSettings = {
|
|
31300
33357
|
width: 1,
|
|
31301
|
-
/**
|
|
31302
|
-
* Height of the particle spawn area
|
|
31303
|
-
* @type {number}
|
|
31304
|
-
* @default 1
|
|
31305
|
-
*/
|
|
31306
33358
|
height: 1,
|
|
31307
|
-
/**
|
|
31308
|
-
* image used for particles texture
|
|
31309
|
-
* (by default melonJS will create a white 8x8 texture image)
|
|
31310
|
-
* @type {HTMLCanvasElement}
|
|
31311
|
-
* @default undefined
|
|
31312
|
-
* @see {@link textureSize}
|
|
31313
|
-
*/
|
|
31314
33359
|
image: void 0,
|
|
31315
|
-
/**
|
|
31316
|
-
* default texture size used for particles if no image is specified
|
|
31317
|
-
* (by default melonJS will create a white 8x8 texture image)
|
|
31318
|
-
* @type {number}
|
|
31319
|
-
* @default 8
|
|
31320
|
-
* @see {@link image}
|
|
31321
|
-
*/
|
|
31322
33360
|
textureSize: 8,
|
|
31323
|
-
/**
|
|
31324
|
-
* tint to be applied to particles
|
|
31325
|
-
* @type {string}
|
|
31326
|
-
* @default "#fff"
|
|
31327
|
-
*/
|
|
31328
33361
|
tint: "#fff",
|
|
31329
|
-
/**
|
|
31330
|
-
* Total number of particles in the emitter
|
|
31331
|
-
* @type {number}
|
|
31332
|
-
* @default 50
|
|
31333
|
-
*/
|
|
31334
33362
|
totalParticles: 50,
|
|
31335
|
-
/**
|
|
31336
|
-
* Start angle for particle launch in Radians
|
|
31337
|
-
* @type {number}
|
|
31338
|
-
* @default Math.PI / 2
|
|
31339
|
-
*/
|
|
31340
33363
|
angle: Math.PI / 2,
|
|
31341
|
-
/**
|
|
31342
|
-
* letiation in the start angle for particle launch in Radians.
|
|
31343
|
-
* @type {number}
|
|
31344
|
-
* @default 0
|
|
31345
|
-
*/
|
|
31346
33364
|
angleVariation: 0,
|
|
31347
|
-
/**
|
|
31348
|
-
* Minimum time each particle lives once it is emitted in ms.
|
|
31349
|
-
* @type {number}
|
|
31350
|
-
* @default 1000
|
|
31351
|
-
*/
|
|
31352
33365
|
minLife: 1e3,
|
|
31353
|
-
/**
|
|
31354
|
-
* Maximum time each particle lives once it is emitted in ms.
|
|
31355
|
-
* @type {number}
|
|
31356
|
-
* @default 3000
|
|
31357
|
-
*/
|
|
31358
33366
|
maxLife: 3e3,
|
|
31359
|
-
/**
|
|
31360
|
-
* Start speed of particles.<br>
|
|
31361
|
-
* @type {number}
|
|
31362
|
-
* @default 2
|
|
31363
|
-
*/
|
|
31364
33367
|
speed: 2,
|
|
31365
|
-
/**
|
|
31366
|
-
* letiation in the start speed of particles
|
|
31367
|
-
* @type {number}
|
|
31368
|
-
* @default 1
|
|
31369
|
-
*/
|
|
31370
33368
|
speedVariation: 1,
|
|
31371
|
-
/**
|
|
31372
|
-
* Minimum start rotation for particles sprites in Radians
|
|
31373
|
-
* @type {number}
|
|
31374
|
-
* @default 0
|
|
31375
|
-
*/
|
|
31376
33369
|
minRotation: 0,
|
|
31377
|
-
/**
|
|
31378
|
-
* Maximum start rotation for particles sprites in Radians
|
|
31379
|
-
* @type {number}
|
|
31380
|
-
* @default 0
|
|
31381
|
-
*/
|
|
31382
33370
|
maxRotation: 0,
|
|
31383
|
-
/**
|
|
31384
|
-
* Minimum start scale ratio for particles (1 = no scaling)
|
|
31385
|
-
* @type {number}
|
|
31386
|
-
* @default 1
|
|
31387
|
-
*/
|
|
31388
33371
|
minStartScale: 1,
|
|
31389
|
-
/**
|
|
31390
|
-
* Maximum start scale ratio for particles (1 = no scaling)
|
|
31391
|
-
* @type {number}
|
|
31392
|
-
* @default 1
|
|
31393
|
-
*/
|
|
31394
33372
|
maxStartScale: 1,
|
|
31395
|
-
/**
|
|
31396
|
-
* Minimum end scale ratio for particles
|
|
31397
|
-
* @type {number}
|
|
31398
|
-
* @default 0
|
|
31399
|
-
*/
|
|
31400
33373
|
minEndScale: 0,
|
|
31401
|
-
/**
|
|
31402
|
-
* Maximum end scale ratio for particles
|
|
31403
|
-
* @type {number}
|
|
31404
|
-
* @default 0
|
|
31405
|
-
*/
|
|
31406
33374
|
maxEndScale: 0,
|
|
31407
|
-
/**
|
|
31408
|
-
* Vertical force (Gravity) for each particle
|
|
31409
|
-
* @type {number}
|
|
31410
|
-
* @default 0
|
|
31411
|
-
* @see {@link World.gravity}
|
|
31412
|
-
*/
|
|
31413
33375
|
gravity: 0,
|
|
31414
|
-
/**
|
|
31415
|
-
* Horizontal force (like a Wind) for each particle
|
|
31416
|
-
* @type {number}
|
|
31417
|
-
* @default 0
|
|
31418
|
-
*/
|
|
31419
33376
|
wind: 0,
|
|
31420
|
-
/**
|
|
31421
|
-
* Update the rotation of particle in accordance the particle trajectory.<br>
|
|
31422
|
-
* The particle sprite should aim at zero angle (draw from left to right).<br>
|
|
31423
|
-
* Override the particle minRotation and maxRotation.<br>
|
|
31424
|
-
* @type {boolean}
|
|
31425
|
-
* @default false
|
|
31426
|
-
*/
|
|
31427
33377
|
followTrajectory: false,
|
|
31428
|
-
/**
|
|
31429
|
-
* Enable the Texture Additive by composite operation ("additive" blendMode)
|
|
31430
|
-
* @type {boolean}
|
|
31431
|
-
* @default false
|
|
31432
|
-
* @see {@link blendMode}
|
|
31433
|
-
*/
|
|
31434
33378
|
textureAdditive: false,
|
|
31435
|
-
/**
|
|
31436
|
-
* the blend mode to be applied when rendering particles.
|
|
31437
|
-
* (note: this will superseed the `textureAdditive` setting if different than "normal")
|
|
31438
|
-
* @type {string}
|
|
31439
|
-
* @default normal
|
|
31440
|
-
* @see {@link CanvasRenderer#setBlendMode}
|
|
31441
|
-
* @see {@link WebGLRenderer#setBlendMode}
|
|
31442
|
-
*/
|
|
31443
33379
|
blendMode: "normal",
|
|
31444
|
-
/**
|
|
31445
|
-
* Update particles only in the viewport, remove it when out of viewport.
|
|
31446
|
-
* @type {boolean}
|
|
31447
|
-
* @default true
|
|
31448
|
-
*/
|
|
31449
33380
|
onlyInViewport: true,
|
|
31450
|
-
/**
|
|
31451
|
-
* Render particles in screen space.
|
|
31452
|
-
* @type {boolean}
|
|
31453
|
-
* @default false
|
|
31454
|
-
*/
|
|
31455
33381
|
floating: false,
|
|
31456
|
-
/**
|
|
31457
|
-
* Maximum number of particles launched each time in this emitter (used only if emitter is Stream).
|
|
31458
|
-
* @type {number}
|
|
31459
|
-
* @default 10
|
|
31460
|
-
*/
|
|
31461
33382
|
maxParticles: 10,
|
|
31462
|
-
/**
|
|
31463
|
-
* How often a particle is emitted in ms (used only if emitter is a Stream).
|
|
31464
|
-
* @type {number}
|
|
31465
|
-
* @default 100
|
|
31466
|
-
*/
|
|
31467
33383
|
frequency: 100,
|
|
31468
|
-
/**
|
|
31469
|
-
* Duration that the emitter releases particles in ms (used only if emitter is Stream).
|
|
31470
|
-
* After this period, the emitter stop the launch of particles.
|
|
31471
|
-
* @type {number}
|
|
31472
|
-
* @default Infinity
|
|
31473
|
-
*/
|
|
31474
33384
|
duration: Infinity,
|
|
31475
|
-
|
|
31476
|
-
|
|
31477
|
-
|
|
31478
|
-
|
|
31479
|
-
* @default 0
|
|
31480
|
-
*/
|
|
31481
|
-
framesToSkip: 0
|
|
33385
|
+
framesToSkip: 0,
|
|
33386
|
+
accurateBounds: false,
|
|
33387
|
+
autoDestroyOnComplete: false,
|
|
33388
|
+
onComplete: void 0
|
|
31482
33389
|
};
|
|
31483
|
-
var settings_default =
|
|
33390
|
+
var settings_default = defaultParticleEmitterSettings;
|
|
31484
33391
|
|
|
31485
33392
|
// src/particles/emitter.ts
|
|
31486
33393
|
function createDefaultParticleTexture(w = 8, h = 8) {
|
|
@@ -31491,9 +33398,14 @@ function createDefaultParticleTexture(w = 8, h = 8) {
|
|
|
31491
33398
|
defaultParticleTexture.context.fillRect(0, 0, w, h);
|
|
31492
33399
|
return defaultParticleTexture;
|
|
31493
33400
|
}
|
|
33401
|
+
function clampMinToMax(settings, minKey, maxKey) {
|
|
33402
|
+
if (settings[minKey] > settings[maxKey]) {
|
|
33403
|
+
settings[minKey] = settings[maxKey];
|
|
33404
|
+
}
|
|
33405
|
+
}
|
|
31494
33406
|
var ParticleEmitter = class extends Container {
|
|
31495
33407
|
/**
|
|
31496
|
-
* the current (active) emitter settings
|
|
33408
|
+
* the current (active) emitter settings (with defaults merged in)
|
|
31497
33409
|
*/
|
|
31498
33410
|
settings;
|
|
31499
33411
|
/** @ignore */
|
|
@@ -31510,6 +33422,19 @@ var ParticleEmitter = class extends Container {
|
|
|
31510
33422
|
_dt;
|
|
31511
33423
|
/** @ignore */
|
|
31512
33424
|
_defaultParticle;
|
|
33425
|
+
/**
|
|
33426
|
+
* whether at least one particle has been spawned by this emitter — used as
|
|
33427
|
+
* the precondition for completion detection (a brand-new emitter with zero
|
|
33428
|
+
* children must not count as "complete")
|
|
33429
|
+
* @ignore
|
|
33430
|
+
*/
|
|
33431
|
+
_hasSpawned;
|
|
33432
|
+
/**
|
|
33433
|
+
* cached `timer.maxfps / 1000` — particles read this directly instead of
|
|
33434
|
+
* recomputing it on every spawn.
|
|
33435
|
+
* @ignore
|
|
33436
|
+
*/
|
|
33437
|
+
_deltaInv;
|
|
31513
33438
|
/**
|
|
31514
33439
|
* @param x - x position of the particle emitter
|
|
31515
33440
|
* @param y - y position of the particle emitter
|
|
@@ -31541,8 +33466,8 @@ var ParticleEmitter = class extends Container {
|
|
|
31541
33466
|
* app.world.removeChild(emitter);
|
|
31542
33467
|
*/
|
|
31543
33468
|
constructor(x, y, settings = {}) {
|
|
31544
|
-
super(x, y, settings.width
|
|
31545
|
-
this.settings = {};
|
|
33469
|
+
super(x, y, settings.width ?? 1, settings.height ?? 1);
|
|
33470
|
+
this.settings = { ...settings_default };
|
|
31546
33471
|
this.centerOn(x, y);
|
|
31547
33472
|
this._stream = false;
|
|
31548
33473
|
this._frequencyTimer = 0;
|
|
@@ -31552,18 +33477,29 @@ var ParticleEmitter = class extends Container {
|
|
|
31552
33477
|
this.autoSort = false;
|
|
31553
33478
|
this._updateCount = 0;
|
|
31554
33479
|
this._dt = 0;
|
|
33480
|
+
this._hasSpawned = false;
|
|
33481
|
+
this._deltaInv = timer_default.maxfps / 1e3;
|
|
31555
33482
|
this.reset(settings);
|
|
31556
33483
|
}
|
|
31557
33484
|
/**
|
|
31558
33485
|
* Reset the emitter with particle emitter settings.
|
|
31559
|
-
* @param settings -
|
|
33486
|
+
* @param settings - object with emitter settings. See {@link ParticleEmitterSettings}
|
|
31560
33487
|
*/
|
|
31561
33488
|
reset(settings = {}) {
|
|
31562
33489
|
Object.assign(this.settings, settings_default, settings);
|
|
33490
|
+
clampMinToMax(this.settings, "minLife", "maxLife");
|
|
33491
|
+
clampMinToMax(this.settings, "minStartScale", "maxStartScale");
|
|
33492
|
+
clampMinToMax(this.settings, "minEndScale", "maxEndScale");
|
|
33493
|
+
clampMinToMax(this.settings, "minRotation", "maxRotation");
|
|
33494
|
+
this._deltaInv = timer_default.maxfps / 1e3;
|
|
33495
|
+
if (typeof this._defaultParticle !== "undefined") {
|
|
33496
|
+
this._defaultParticle.destroy();
|
|
33497
|
+
this._defaultParticle = void 0;
|
|
33498
|
+
}
|
|
31563
33499
|
if (typeof this.settings.image === "undefined") {
|
|
31564
33500
|
this._defaultParticle = createDefaultParticleTexture(
|
|
31565
|
-
settings.textureSize,
|
|
31566
|
-
settings.textureSize
|
|
33501
|
+
this.settings.textureSize,
|
|
33502
|
+
this.settings.textureSize
|
|
31567
33503
|
);
|
|
31568
33504
|
this.settings.image = this._defaultParticle.canvas;
|
|
31569
33505
|
}
|
|
@@ -31587,8 +33523,12 @@ var ParticleEmitter = class extends Container {
|
|
|
31587
33523
|
// Add count particles in the game world
|
|
31588
33524
|
/** @ignore */
|
|
31589
33525
|
addParticles(count) {
|
|
33526
|
+
const z = this.pos.z;
|
|
31590
33527
|
for (let i = 0; i < count; i++) {
|
|
31591
|
-
this.addChild(particlePool.get(this),
|
|
33528
|
+
this.addChild(particlePool.get(this), z);
|
|
33529
|
+
}
|
|
33530
|
+
if (count > 0) {
|
|
33531
|
+
this._hasSpawned = true;
|
|
31592
33532
|
}
|
|
31593
33533
|
this.isDirty = true;
|
|
31594
33534
|
}
|
|
@@ -31631,15 +33571,17 @@ var ParticleEmitter = class extends Container {
|
|
|
31631
33571
|
* @ignore
|
|
31632
33572
|
*/
|
|
31633
33573
|
update(dt) {
|
|
31634
|
-
if (
|
|
31635
|
-
this._updateCount
|
|
31636
|
-
|
|
31637
|
-
|
|
31638
|
-
this.
|
|
31639
|
-
|
|
33574
|
+
if (this.settings.framesToSkip > 0) {
|
|
33575
|
+
if (++this._updateCount > this.settings.framesToSkip) {
|
|
33576
|
+
this._updateCount = 0;
|
|
33577
|
+
}
|
|
33578
|
+
if (this._updateCount > 0) {
|
|
33579
|
+
this._dt += dt;
|
|
33580
|
+
return this.isDirty;
|
|
33581
|
+
}
|
|
33582
|
+
dt += this._dt;
|
|
33583
|
+
this._dt = 0;
|
|
31640
33584
|
}
|
|
31641
|
-
dt += this._dt;
|
|
31642
|
-
this._dt = 0;
|
|
31643
33585
|
this.isDirty = this.isDirty || super.update(dt);
|
|
31644
33586
|
if (this._enabled && this._stream) {
|
|
31645
33587
|
if (this._durationTimer !== Infinity) {
|
|
@@ -31650,17 +33592,27 @@ var ParticleEmitter = class extends Container {
|
|
|
31650
33592
|
}
|
|
31651
33593
|
}
|
|
31652
33594
|
this._frequencyTimer += dt;
|
|
31653
|
-
const particlesCount = this.
|
|
33595
|
+
const particlesCount = this.getChildren().length;
|
|
31654
33596
|
if (particlesCount < this.settings.totalParticles && this._frequencyTimer >= this.settings.frequency) {
|
|
31655
|
-
|
|
31656
|
-
|
|
31657
|
-
|
|
31658
|
-
|
|
31659
|
-
|
|
33597
|
+
this.addParticles(
|
|
33598
|
+
Math.min(
|
|
33599
|
+
this.settings.maxParticles,
|
|
33600
|
+
this.settings.totalParticles - particlesCount
|
|
33601
|
+
)
|
|
33602
|
+
);
|
|
31660
33603
|
this._frequencyTimer = 0;
|
|
31661
33604
|
this.isDirty = true;
|
|
31662
33605
|
}
|
|
31663
33606
|
}
|
|
33607
|
+
if (this._hasSpawned && !this._enabled && this.getChildren().length === 0) {
|
|
33608
|
+
this._hasSpawned = false;
|
|
33609
|
+
if (typeof this.settings.onComplete === "function") {
|
|
33610
|
+
this.settings.onComplete.call(this);
|
|
33611
|
+
}
|
|
33612
|
+
if (this.settings.autoDestroyOnComplete && this.ancestor) {
|
|
33613
|
+
this.ancestor.removeChild(this);
|
|
33614
|
+
}
|
|
33615
|
+
}
|
|
31664
33616
|
return this.isDirty;
|
|
31665
33617
|
}
|
|
31666
33618
|
/**
|
|
@@ -33068,106 +35020,6 @@ var UITextButton = class extends UIBaseElement {
|
|
|
33068
35020
|
}
|
|
33069
35021
|
};
|
|
33070
35022
|
|
|
33071
|
-
// src/video/webgl/shaders/quad.vert
|
|
33072
|
-
var quad_default = "// Current vertex point\nattribute vec2 aVertex;\nattribute vec2 aRegion;\nattribute vec4 aColor;\n\n// Projection matrix\nuniform mat4 uProjectionMatrix;\n\nvarying vec2 vRegion;\nvarying vec4 vColor;\n\nvoid main(void) {\n // Transform the vertex position by the projection matrix\n gl_Position = uProjectionMatrix * vec4(aVertex, 0.0, 1.0);\n // Pass the remaining attributes to the fragment shader\n vColor = vec4(aColor.bgr * aColor.a, aColor.a);\n vRegion = aRegion;\n}\n";
|
|
33073
|
-
|
|
33074
|
-
// src/video/webgl/shadereffect.js
|
|
33075
|
-
var ShaderEffect = class {
|
|
33076
|
-
/**
|
|
33077
|
-
* whether this effect is active (false in Canvas mode)
|
|
33078
|
-
* @type {boolean}
|
|
33079
|
-
*/
|
|
33080
|
-
enabled = false;
|
|
33081
|
-
/**
|
|
33082
|
-
* @param {WebGLRenderer|CanvasRenderer} renderer - the current renderer instance
|
|
33083
|
-
* @param {string} fragmentBody - GLSL code containing a `vec4 apply(vec4 color, vec2 uv)` function
|
|
33084
|
-
* that receives the sampled pixel color and UV coordinates, and returns the modified color.
|
|
33085
|
-
* You can declare additional `uniform` variables before the `apply()` function.
|
|
33086
|
-
* @param {string} [precision=auto detected] - float precision ('lowp', 'mediump' or 'highp')
|
|
33087
|
-
*/
|
|
33088
|
-
constructor(renderer2, fragmentBody, precision) {
|
|
33089
|
-
if (typeof renderer2.gl === "undefined") {
|
|
33090
|
-
console.warn(
|
|
33091
|
-
"ShaderEffect requires WebGL and is disabled in Canvas mode"
|
|
33092
|
-
);
|
|
33093
|
-
return;
|
|
33094
|
-
}
|
|
33095
|
-
const fragment = [
|
|
33096
|
-
"uniform sampler2D uSampler;",
|
|
33097
|
-
"varying vec4 vColor;",
|
|
33098
|
-
"varying vec2 vRegion;",
|
|
33099
|
-
// user-provided fragment body (uniforms + apply function)
|
|
33100
|
-
fragmentBody,
|
|
33101
|
-
"void main(void) {",
|
|
33102
|
-
" vec4 texColor = texture2D(uSampler, vRegion) * vColor;",
|
|
33103
|
-
" gl_FragColor = apply(texColor, vRegion);",
|
|
33104
|
-
"}"
|
|
33105
|
-
].join("\n");
|
|
33106
|
-
this._shader = new GLShader(
|
|
33107
|
-
renderer2.gl,
|
|
33108
|
-
quad_default,
|
|
33109
|
-
fragment,
|
|
33110
|
-
precision || renderer2.shaderPrecision
|
|
33111
|
-
);
|
|
33112
|
-
this.enabled = true;
|
|
33113
|
-
}
|
|
33114
|
-
/**
|
|
33115
|
-
* Set the uniform to the given value
|
|
33116
|
-
* @param {string} name - the uniform name
|
|
33117
|
-
* @param {object|Float32Array} value - the value to assign to that uniform
|
|
33118
|
-
*/
|
|
33119
|
-
setUniform(name, value) {
|
|
33120
|
-
if (this.enabled) {
|
|
33121
|
-
this._shader.setUniform(name, value);
|
|
33122
|
-
}
|
|
33123
|
-
}
|
|
33124
|
-
/** @ignore */
|
|
33125
|
-
bind() {
|
|
33126
|
-
if (this.enabled) {
|
|
33127
|
-
this._shader.bind();
|
|
33128
|
-
}
|
|
33129
|
-
}
|
|
33130
|
-
/** @ignore */
|
|
33131
|
-
getAttribLocation(name) {
|
|
33132
|
-
return this.enabled ? this._shader.getAttribLocation(name) : -1;
|
|
33133
|
-
}
|
|
33134
|
-
/** @ignore */
|
|
33135
|
-
setVertexAttributes(gl, attributes, stride) {
|
|
33136
|
-
if (this.enabled) {
|
|
33137
|
-
this._shader.setVertexAttributes(gl, attributes, stride);
|
|
33138
|
-
}
|
|
33139
|
-
}
|
|
33140
|
-
/** @ignore */
|
|
33141
|
-
get program() {
|
|
33142
|
-
return this.enabled ? this._shader.program : null;
|
|
33143
|
-
}
|
|
33144
|
-
/** @ignore */
|
|
33145
|
-
get vertex() {
|
|
33146
|
-
return this.enabled ? this._shader.vertex : null;
|
|
33147
|
-
}
|
|
33148
|
-
/** @ignore */
|
|
33149
|
-
get fragment() {
|
|
33150
|
-
return this.enabled ? this._shader.fragment : null;
|
|
33151
|
-
}
|
|
33152
|
-
/** @ignore */
|
|
33153
|
-
get attributes() {
|
|
33154
|
-
return this.enabled ? this._shader.attributes : {};
|
|
33155
|
-
}
|
|
33156
|
-
/** @ignore */
|
|
33157
|
-
get uniforms() {
|
|
33158
|
-
return this.enabled ? this._shader.uniforms : {};
|
|
33159
|
-
}
|
|
33160
|
-
/**
|
|
33161
|
-
* destroy this shader effect
|
|
33162
|
-
*/
|
|
33163
|
-
destroy() {
|
|
33164
|
-
if (this.enabled) {
|
|
33165
|
-
this._shader.destroy();
|
|
33166
|
-
this.enabled = false;
|
|
33167
|
-
}
|
|
33168
|
-
}
|
|
33169
|
-
};
|
|
33170
|
-
|
|
33171
35023
|
// src/video/webgl/effects/blur.js
|
|
33172
35024
|
var BlurEffect = class extends ShaderEffect {
|
|
33173
35025
|
/**
|
|
@@ -33270,25 +35122,16 @@ var ChromaticAberrationEffect = class extends ShaderEffect {
|
|
|
33270
35122
|
};
|
|
33271
35123
|
|
|
33272
35124
|
// src/video/webgl/effects/desaturate.js
|
|
33273
|
-
var DesaturateEffect = class extends
|
|
35125
|
+
var DesaturateEffect = class extends ColorMatrixEffect {
|
|
33274
35126
|
/**
|
|
33275
35127
|
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
33276
35128
|
* @param {object} [options] - effect options
|
|
33277
35129
|
* @param {number} [options.intensity=1.0] - desaturation intensity (0.0 = full color, 1.0 = grayscale)
|
|
33278
35130
|
*/
|
|
33279
35131
|
constructor(renderer2, options = {}) {
|
|
33280
|
-
super(
|
|
33281
|
-
renderer2,
|
|
33282
|
-
`
|
|
33283
|
-
uniform float uDesatIntensity;
|
|
33284
|
-
vec4 apply(vec4 color, vec2 uv) {
|
|
33285
|
-
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
|
|
33286
|
-
return vec4(mix(color.rgb, vec3(gray), uDesatIntensity), color.a);
|
|
33287
|
-
}
|
|
33288
|
-
`
|
|
33289
|
-
);
|
|
35132
|
+
super(renderer2);
|
|
33290
35133
|
this.intensity = typeof options.intensity === "number" ? options.intensity : 1;
|
|
33291
|
-
this.
|
|
35134
|
+
this.saturate(1 - this.intensity);
|
|
33292
35135
|
}
|
|
33293
35136
|
/**
|
|
33294
35137
|
* set the desaturation intensity
|
|
@@ -33296,7 +35139,7 @@ var DesaturateEffect = class extends ShaderEffect {
|
|
|
33296
35139
|
*/
|
|
33297
35140
|
setIntensity(value) {
|
|
33298
35141
|
this.intensity = Math.max(0, Math.min(1, value));
|
|
33299
|
-
this.
|
|
35142
|
+
this.reset().saturate(1 - this.intensity);
|
|
33300
35143
|
}
|
|
33301
35144
|
};
|
|
33302
35145
|
|
|
@@ -33607,25 +35450,16 @@ var HologramEffect = class extends ShaderEffect {
|
|
|
33607
35450
|
};
|
|
33608
35451
|
|
|
33609
35452
|
// src/video/webgl/effects/invert.js
|
|
33610
|
-
var InvertEffect = class extends
|
|
35453
|
+
var InvertEffect = class extends ColorMatrixEffect {
|
|
33611
35454
|
/**
|
|
33612
35455
|
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
33613
35456
|
* @param {object} [options] - effect options
|
|
33614
35457
|
* @param {number} [options.intensity=1.0] - inversion intensity (0.0 = original, 1.0 = fully inverted)
|
|
33615
35458
|
*/
|
|
33616
35459
|
constructor(renderer2, options = {}) {
|
|
33617
|
-
super(
|
|
33618
|
-
renderer2,
|
|
33619
|
-
`
|
|
33620
|
-
uniform float uInvertIntensity;
|
|
33621
|
-
vec4 apply(vec4 color, vec2 uv) {
|
|
33622
|
-
vec3 inverted = vec3(color.a) - color.rgb;
|
|
33623
|
-
return vec4(mix(color.rgb, inverted, uInvertIntensity), color.a);
|
|
33624
|
-
}
|
|
33625
|
-
`
|
|
33626
|
-
);
|
|
35460
|
+
super(renderer2);
|
|
33627
35461
|
this.intensity = typeof options.intensity === "number" ? options.intensity : 1;
|
|
33628
|
-
this.
|
|
35462
|
+
this.invertColors(this.intensity);
|
|
33629
35463
|
}
|
|
33630
35464
|
/**
|
|
33631
35465
|
* set the inversion intensity
|
|
@@ -33633,7 +35467,7 @@ var InvertEffect = class extends ShaderEffect {
|
|
|
33633
35467
|
*/
|
|
33634
35468
|
setIntensity(value) {
|
|
33635
35469
|
this.intensity = Math.max(0, Math.min(1, value));
|
|
33636
|
-
this.
|
|
35470
|
+
this.reset().invertColors(this.intensity);
|
|
33637
35471
|
}
|
|
33638
35472
|
};
|
|
33639
35473
|
|
|
@@ -33823,28 +35657,16 @@ var ScanlineEffect = class extends ShaderEffect {
|
|
|
33823
35657
|
};
|
|
33824
35658
|
|
|
33825
35659
|
// src/video/webgl/effects/sepia.js
|
|
33826
|
-
var SepiaEffect = class extends
|
|
35660
|
+
var SepiaEffect = class extends ColorMatrixEffect {
|
|
33827
35661
|
/**
|
|
33828
35662
|
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
33829
35663
|
* @param {object} [options] - effect options
|
|
33830
35664
|
* @param {number} [options.intensity=1.0] - sepia intensity (0.0 = original, 1.0 = full sepia)
|
|
33831
35665
|
*/
|
|
33832
35666
|
constructor(renderer2, options = {}) {
|
|
33833
|
-
super(
|
|
33834
|
-
renderer2,
|
|
33835
|
-
`
|
|
33836
|
-
uniform float uSepiaIntensity;
|
|
33837
|
-
vec4 apply(vec4 color, vec2 uv) {
|
|
33838
|
-
vec3 sepia;
|
|
33839
|
-
sepia.r = dot(color.rgb, vec3(0.393, 0.769, 0.189));
|
|
33840
|
-
sepia.g = dot(color.rgb, vec3(0.349, 0.686, 0.168));
|
|
33841
|
-
sepia.b = dot(color.rgb, vec3(0.272, 0.534, 0.131));
|
|
33842
|
-
return vec4(mix(color.rgb, sepia, uSepiaIntensity), color.a);
|
|
33843
|
-
}
|
|
33844
|
-
`
|
|
33845
|
-
);
|
|
35667
|
+
super(renderer2);
|
|
33846
35668
|
this.intensity = typeof options.intensity === "number" ? options.intensity : 1;
|
|
33847
|
-
this.
|
|
35669
|
+
this.sepia(this.intensity);
|
|
33848
35670
|
}
|
|
33849
35671
|
/**
|
|
33850
35672
|
* set the sepia intensity
|
|
@@ -33852,7 +35674,7 @@ var SepiaEffect = class extends ShaderEffect {
|
|
|
33852
35674
|
*/
|
|
33853
35675
|
setIntensity(value) {
|
|
33854
35676
|
this.intensity = Math.max(0, Math.min(1, value));
|
|
33855
|
-
this.
|
|
35677
|
+
this.reset().sepia(this.intensity);
|
|
33856
35678
|
}
|
|
33857
35679
|
};
|
|
33858
35680
|
|
|
@@ -33901,6 +35723,50 @@ var TintPulseEffect = class extends ShaderEffect {
|
|
|
33901
35723
|
}
|
|
33902
35724
|
};
|
|
33903
35725
|
|
|
35726
|
+
// src/video/webgl/effects/vignette.js
|
|
35727
|
+
var VignetteEffect = class extends ShaderEffect {
|
|
35728
|
+
/**
|
|
35729
|
+
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
35730
|
+
* @param {object} [options] - effect options
|
|
35731
|
+
* @param {number} [options.strength=0.15] - edge darkening power (lower = stronger darkening, higher = softer falloff)
|
|
35732
|
+
* @param {number} [options.size=25.0] - vignette spread multiplier (higher = smaller dark area)
|
|
35733
|
+
*/
|
|
35734
|
+
constructor(renderer2, options = {}) {
|
|
35735
|
+
super(
|
|
35736
|
+
renderer2,
|
|
35737
|
+
`
|
|
35738
|
+
uniform float uStrength;
|
|
35739
|
+
uniform float uSize;
|
|
35740
|
+
vec4 apply(vec4 color, vec2 uv) {
|
|
35741
|
+
vec2 vig = uv * (1.0 - uv);
|
|
35742
|
+
float v = clamp(pow(vig.x * vig.y * uSize, uStrength), 0.0, 1.0);
|
|
35743
|
+
return vec4(color.rgb * v, color.a);
|
|
35744
|
+
}
|
|
35745
|
+
`
|
|
35746
|
+
);
|
|
35747
|
+
this.strength = options.strength ?? 0.15;
|
|
35748
|
+
this.size = options.size ?? 25;
|
|
35749
|
+
this.setUniform("uStrength", this.strength);
|
|
35750
|
+
this.setUniform("uSize", this.size);
|
|
35751
|
+
}
|
|
35752
|
+
/**
|
|
35753
|
+
* set the vignette strength
|
|
35754
|
+
* @param {number} strength - edge darkening power (lower = stronger, higher = softer)
|
|
35755
|
+
*/
|
|
35756
|
+
setStrength(strength) {
|
|
35757
|
+
this.strength = Math.max(0, strength);
|
|
35758
|
+
this.setUniform("uStrength", this.strength);
|
|
35759
|
+
}
|
|
35760
|
+
/**
|
|
35761
|
+
* set the vignette size
|
|
35762
|
+
* @param {number} size - spread multiplier (higher = smaller dark area)
|
|
35763
|
+
*/
|
|
35764
|
+
setSize(size) {
|
|
35765
|
+
this.size = Math.max(0, size);
|
|
35766
|
+
this.setUniform("uSize", this.size);
|
|
35767
|
+
}
|
|
35768
|
+
};
|
|
35769
|
+
|
|
33904
35770
|
// src/video/webgl/effects/wave.js
|
|
33905
35771
|
var WaveEffect = class extends ShaderEffect {
|
|
33906
35772
|
/**
|
|
@@ -34485,6 +36351,7 @@ export {
|
|
|
34485
36351
|
Bounds,
|
|
34486
36352
|
CANVAS,
|
|
34487
36353
|
Camera2d,
|
|
36354
|
+
CameraEffect,
|
|
34488
36355
|
canvasrendertarget_default as CanvasRenderTarget,
|
|
34489
36356
|
CanvasRenderer,
|
|
34490
36357
|
CanvasTexture,
|
|
@@ -34492,6 +36359,8 @@ export {
|
|
|
34492
36359
|
Collectable,
|
|
34493
36360
|
Color,
|
|
34494
36361
|
ColorLayer,
|
|
36362
|
+
ColorMatrix,
|
|
36363
|
+
ColorMatrixEffect,
|
|
34495
36364
|
Compositor,
|
|
34496
36365
|
Container,
|
|
34497
36366
|
DesaturateEffect,
|
|
@@ -34501,6 +36370,7 @@ export {
|
|
|
34501
36370
|
DropTarget,
|
|
34502
36371
|
Ellipse,
|
|
34503
36372
|
Entity,
|
|
36373
|
+
FadeEffect,
|
|
34504
36374
|
FlashEffect,
|
|
34505
36375
|
GLShader,
|
|
34506
36376
|
GlowEffect,
|
|
@@ -34510,6 +36380,7 @@ export {
|
|
|
34510
36380
|
InvertEffect,
|
|
34511
36381
|
Light2d,
|
|
34512
36382
|
Line,
|
|
36383
|
+
MaskEffect,
|
|
34513
36384
|
math_exports as Math,
|
|
34514
36385
|
Matrix2d,
|
|
34515
36386
|
Matrix3d,
|
|
@@ -34533,6 +36404,7 @@ export {
|
|
|
34533
36404
|
QuadTree,
|
|
34534
36405
|
Rect,
|
|
34535
36406
|
RenderState,
|
|
36407
|
+
RenderTarget,
|
|
34536
36408
|
Renderable,
|
|
34537
36409
|
Renderer,
|
|
34538
36410
|
RoundRect,
|
|
@@ -34540,6 +36412,7 @@ export {
|
|
|
34540
36412
|
ScanlineEffect,
|
|
34541
36413
|
SepiaEffect,
|
|
34542
36414
|
ShaderEffect,
|
|
36415
|
+
ShakeEffect,
|
|
34543
36416
|
Sprite,
|
|
34544
36417
|
Stage,
|
|
34545
36418
|
TMXHexagonalRenderer,
|
|
@@ -34564,6 +36437,7 @@ export {
|
|
|
34564
36437
|
UITextButton,
|
|
34565
36438
|
Vector2d,
|
|
34566
36439
|
Vector3d,
|
|
36440
|
+
VignetteEffect,
|
|
34567
36441
|
WEBGL,
|
|
34568
36442
|
WaveEffect,
|
|
34569
36443
|
WebGLRenderer,
|