melonjs 19.0.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/defaultApplicationSettings.d.ts +1 -0
- package/build/application/defaultApplicationSettings.d.ts.map +1 -1
- package/build/application/settings.d.ts +47 -1
- 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 +2928 -935
- 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 +11 -4
- 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/texture/cache.d.ts +6 -0
- package/build/video/texture/cache.d.ts.map +1 -1
- 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/material_batcher.d.ts +3 -3
- package/build/video/webgl/batchers/material_batcher.d.ts.map +1 -1
- package/build/video/webgl/batchers/quad_batcher.d.ts +34 -0
- 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/shadereffect.d.ts.map +1 -1
- package/build/video/webgl/shaders/multitexture.d.ts +10 -0
- package/build/video/webgl/shaders/multitexture.d.ts.map +1 -0
- package/build/video/webgl/utils/precision.d.ts +4 -3
- package/build/video/webgl/utils/precision.d.ts.map +1 -1
- package/build/video/webgl/webgl_renderer.d.ts +15 -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
|
|
@@ -6228,6 +6228,7 @@ var defaultApplicationSettings = {
|
|
|
6228
6228
|
blendMode: "normal",
|
|
6229
6229
|
physic: "builtin",
|
|
6230
6230
|
failIfMajorPerformanceCaveat: true,
|
|
6231
|
+
highPrecisionShader: true,
|
|
6231
6232
|
subPixel: false,
|
|
6232
6233
|
verbose: false,
|
|
6233
6234
|
legacy: false,
|
|
@@ -7059,31 +7060,8 @@ function unbindKey(keyCode) {
|
|
|
7059
7060
|
delete _preventDefaultForKeys[keyCode];
|
|
7060
7061
|
}
|
|
7061
7062
|
|
|
7062
|
-
// src/lang/console.js
|
|
7063
|
-
function warning(deprecated, replacement, version2) {
|
|
7064
|
-
const msg = "melonJS: %s is deprecated since version %s, please use %s";
|
|
7065
|
-
const stack = new Error().stack;
|
|
7066
|
-
if (console.groupCollapsed) {
|
|
7067
|
-
console.groupCollapsed(
|
|
7068
|
-
"%c" + msg,
|
|
7069
|
-
"font-weight:normal;color:yellow;",
|
|
7070
|
-
deprecated,
|
|
7071
|
-
version2,
|
|
7072
|
-
replacement
|
|
7073
|
-
);
|
|
7074
|
-
} else {
|
|
7075
|
-
console.warn(msg, deprecated, version2, replacement);
|
|
7076
|
-
}
|
|
7077
|
-
if (typeof stack !== "undefined") {
|
|
7078
|
-
console.warn(stack);
|
|
7079
|
-
}
|
|
7080
|
-
if (console.groupCollapsed) {
|
|
7081
|
-
console.groupEnd();
|
|
7082
|
-
}
|
|
7083
|
-
}
|
|
7084
|
-
|
|
7085
7063
|
// src/geometries/ellipse.ts
|
|
7086
|
-
var Ellipse = class
|
|
7064
|
+
var Ellipse = class {
|
|
7087
7065
|
/**
|
|
7088
7066
|
* the center coordinates of the ellipse
|
|
7089
7067
|
*/
|
|
@@ -7351,7 +7329,7 @@ var Ellipse = class _Ellipse {
|
|
|
7351
7329
|
* @returns new Ellipse
|
|
7352
7330
|
*/
|
|
7353
7331
|
clone() {
|
|
7354
|
-
const clone =
|
|
7332
|
+
const clone = ellipsePool.get(
|
|
7355
7333
|
this.pos.x,
|
|
7356
7334
|
this.pos.y,
|
|
7357
7335
|
this.radiusV.x * 2,
|
|
@@ -8985,6 +8963,73 @@ var Matrix3d = class {
|
|
|
8985
8963
|
a[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
|
8986
8964
|
return this;
|
|
8987
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
|
+
}
|
|
8988
9033
|
/**
|
|
8989
9034
|
* Transpose the value of this matrix.
|
|
8990
9035
|
* @returns Reference to this object for method chaining
|
|
@@ -9435,12 +9480,12 @@ var Matrix2d = class {
|
|
|
9435
9480
|
}
|
|
9436
9481
|
/**
|
|
9437
9482
|
* Multiplies the current transformation with the matrix described by the arguments of this method.
|
|
9438
|
-
* @param a a component
|
|
9439
|
-
* @param b b component
|
|
9440
|
-
* @param c c component
|
|
9441
|
-
* @param d d component
|
|
9442
|
-
* @param e e component
|
|
9443
|
-
* @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)
|
|
9444
9489
|
* @returns Reference to this object for method chaining
|
|
9445
9490
|
*/
|
|
9446
9491
|
transform(a, b, c, d, e, f) {
|
|
@@ -10243,6 +10288,238 @@ function unloadAll() {
|
|
|
10243
10288
|
}
|
|
10244
10289
|
}
|
|
10245
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
|
+
|
|
10246
10523
|
// src/geometries/observablePoint.ts
|
|
10247
10524
|
var ObservablePoint = class _ObservablePoint {
|
|
10248
10525
|
_callback;
|
|
@@ -11460,7 +11737,8 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11460
11737
|
this.alpha = 1;
|
|
11461
11738
|
this.ancestor = void 0;
|
|
11462
11739
|
this.mask = void 0;
|
|
11463
|
-
this.
|
|
11740
|
+
this.postEffects = [];
|
|
11741
|
+
this._postEffectManaged = false;
|
|
11464
11742
|
this.blendMode = "normal";
|
|
11465
11743
|
this.name = "";
|
|
11466
11744
|
this.isRenderable = true;
|
|
@@ -11538,6 +11816,82 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11538
11816
|
}
|
|
11539
11817
|
}
|
|
11540
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
|
+
}
|
|
11541
11895
|
/**
|
|
11542
11896
|
* returns true if this renderable is flipped on the horizontal axis
|
|
11543
11897
|
* @public
|
|
@@ -11819,8 +12173,8 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11819
12173
|
renderer2.setMask(this.mask);
|
|
11820
12174
|
renderer2.translate(-this.pos.x, -this.pos.y);
|
|
11821
12175
|
}
|
|
11822
|
-
if (this.
|
|
11823
|
-
renderer2.
|
|
12176
|
+
if (!this._postEffectManaged) {
|
|
12177
|
+
renderer2.beginPostEffect(this);
|
|
11824
12178
|
}
|
|
11825
12179
|
if (this.autoTransform === true && !this.currentTransform.isIdentity()) {
|
|
11826
12180
|
renderer2.translate(this.pos.x, this.pos.y);
|
|
@@ -11860,8 +12214,8 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11860
12214
|
if (this.mask) {
|
|
11861
12215
|
renderer2.clearMask();
|
|
11862
12216
|
}
|
|
11863
|
-
if (this.
|
|
11864
|
-
renderer2.
|
|
12217
|
+
if (!this._postEffectManaged) {
|
|
12218
|
+
renderer2.endPostEffect(this);
|
|
11865
12219
|
}
|
|
11866
12220
|
renderer2.restore();
|
|
11867
12221
|
this.isDirty = false;
|
|
@@ -11923,10 +12277,12 @@ var Renderable = class _Renderable extends Rect {
|
|
|
11923
12277
|
}
|
|
11924
12278
|
releaseAllPointerEvents(this);
|
|
11925
12279
|
this.onDestroyEvent.apply(this, arguments);
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
12280
|
+
for (const effect of this.postEffects) {
|
|
12281
|
+
if (typeof effect.destroy === "function") {
|
|
12282
|
+
effect.destroy();
|
|
12283
|
+
}
|
|
11929
12284
|
}
|
|
12285
|
+
this.postEffects.length = 0;
|
|
11930
12286
|
}
|
|
11931
12287
|
/**
|
|
11932
12288
|
* OnDestroy Notification function<br>
|
|
@@ -11965,6 +12321,29 @@ __export(loader_exports, {
|
|
|
11965
12321
|
withCredentials: () => withCredentials
|
|
11966
12322
|
});
|
|
11967
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
|
+
|
|
11968
12347
|
// src/utils/file.ts
|
|
11969
12348
|
var file_exports = {};
|
|
11970
12349
|
__export(file_exports, {
|
|
@@ -13804,6 +14183,97 @@ var TMX_FLIP_AD = 536870912;
|
|
|
13804
14183
|
var TMX_CLEAR_BIT_MASK = ~(TMX_FLIP_H | TMX_FLIP_V | TMX_FLIP_AD);
|
|
13805
14184
|
var COLLISION_GROUP = "collision";
|
|
13806
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
|
+
|
|
13807
14277
|
// src/video/rendertarget/canvasrendertarget.js
|
|
13808
14278
|
var defaultAttributes = {
|
|
13809
14279
|
offscreenCanvas: false,
|
|
@@ -13854,7 +14324,7 @@ function createContext(canvas, attributes) {
|
|
|
13854
14324
|
}
|
|
13855
14325
|
return context;
|
|
13856
14326
|
}
|
|
13857
|
-
var CanvasRenderTarget = class {
|
|
14327
|
+
var CanvasRenderTarget = class extends RenderTarget {
|
|
13858
14328
|
/**
|
|
13859
14329
|
* @param {number} width - the desired width of the canvas
|
|
13860
14330
|
* @param {number} height - the desired height of the canvas
|
|
@@ -13867,6 +14337,7 @@ var CanvasRenderTarget = class {
|
|
|
13867
14337
|
* @param {boolean} [attributes.antiAlias=false] - Whether to enable anti-aliasing, use false (default) for a pixelated effect.
|
|
13868
14338
|
*/
|
|
13869
14339
|
constructor(width, height, attributes = defaultAttributes) {
|
|
14340
|
+
super();
|
|
13870
14341
|
this.attributes = Object.assign({}, defaultAttributes, attributes);
|
|
13871
14342
|
if (typeof attributes.context === "undefined") {
|
|
13872
14343
|
attributes.context = "2d";
|
|
@@ -13946,64 +14417,48 @@ var CanvasRenderTarget = class {
|
|
|
13946
14417
|
return this.context.getImageData(x, y, width, height);
|
|
13947
14418
|
}
|
|
13948
14419
|
/**
|
|
13949
|
-
*
|
|
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.
|
|
13950
14422
|
* @param {string} [type="image/png"] - A string indicating the image format
|
|
13951
|
-
* @param {number} [quality] - A
|
|
13952
|
-
* @returns {Promise} A Promise
|
|
13953
|
-
* @example
|
|
13954
|
-
* 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
|
|
13955
14425
|
*/
|
|
13956
|
-
|
|
13957
|
-
if (typeof this.canvas.
|
|
13958
|
-
return this.canvas.
|
|
13959
|
-
} else {
|
|
13960
|
-
return new Promise((resolve) => {
|
|
13961
|
-
this.canvas.toBlob(
|
|
13962
|
-
(blob) => {
|
|
13963
|
-
resolve(blob);
|
|
13964
|
-
},
|
|
13965
|
-
type,
|
|
13966
|
-
quality
|
|
13967
|
-
);
|
|
13968
|
-
});
|
|
14426
|
+
toDataURL(type = "image/png", quality) {
|
|
14427
|
+
if (typeof this.canvas.toDataURL === "function") {
|
|
14428
|
+
return Promise.resolve(this.canvas.toDataURL(type, quality));
|
|
13969
14429
|
}
|
|
14430
|
+
return super.toDataURL(type, quality);
|
|
13970
14431
|
}
|
|
13971
14432
|
/**
|
|
13972
|
-
*
|
|
14433
|
+
* Creates a Blob directly from the canvas (avoids the getImageData round-trip).
|
|
13973
14434
|
* @param {string} [type="image/png"] - A string indicating the image format
|
|
13974
|
-
* @param {number} [quality] - A
|
|
13975
|
-
* @returns {Promise} A Promise
|
|
13976
|
-
* @example
|
|
13977
|
-
* 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
|
|
13978
14437
|
*/
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
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
|
+
);
|
|
13992
14454
|
});
|
|
13993
14455
|
}
|
|
13994
14456
|
/**
|
|
13995
|
-
*
|
|
13996
|
-
*
|
|
13997
|
-
* @param {string} [type="image/png"] - A string indicating the image format
|
|
13998
|
-
* @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.
|
|
13999
|
-
* @returns {Promise} A Promise returning a string containing the requested data URL.
|
|
14000
|
-
* @example
|
|
14001
|
-
* 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
|
|
14002
14459
|
*/
|
|
14003
|
-
|
|
14004
|
-
return
|
|
14005
|
-
resolve(this.canvas.toDataURL(type, quality));
|
|
14006
|
-
});
|
|
14460
|
+
toImageBitmap() {
|
|
14461
|
+
return globalThis.createImageBitmap(this.canvas);
|
|
14007
14462
|
}
|
|
14008
14463
|
/**
|
|
14009
14464
|
* invalidate the current CanvasRenderTarget, and force a reupload of the corresponding texture
|
|
@@ -14012,6 +14467,7 @@ var CanvasRenderTarget = class {
|
|
|
14012
14467
|
*/
|
|
14013
14468
|
invalidate(renderer2) {
|
|
14014
14469
|
if (typeof renderer2.gl !== "undefined") {
|
|
14470
|
+
renderer2.flush();
|
|
14015
14471
|
renderer2.setBatcher("quad");
|
|
14016
14472
|
this.glTextureUnit = renderer2.cache.getUnit(
|
|
14017
14473
|
renderer2.cache.get(this.canvas)
|
|
@@ -14865,6 +15321,7 @@ var RenderState = class {
|
|
|
14865
15321
|
this.currentGradient = null;
|
|
14866
15322
|
this.lineDash = [];
|
|
14867
15323
|
this.currentBlendMode = "none";
|
|
15324
|
+
this.currentShader = void 0;
|
|
14868
15325
|
this._stackCapacity = 32;
|
|
14869
15326
|
this._stackDepth = 0;
|
|
14870
15327
|
this._colorStack = Array.from({ length: this._stackCapacity }, () => {
|
|
@@ -14883,6 +15340,7 @@ var RenderState = class {
|
|
|
14883
15340
|
this._scissorActive = new Uint8Array(this._stackCapacity);
|
|
14884
15341
|
this._gradientStack = new Array(this._stackCapacity);
|
|
14885
15342
|
this._blendStack = new Array(this._stackCapacity);
|
|
15343
|
+
this._shaderStack = new Array(this._stackCapacity);
|
|
14886
15344
|
}
|
|
14887
15345
|
/**
|
|
14888
15346
|
* Save the current state onto the stack (zero allocations).
|
|
@@ -14899,6 +15357,7 @@ var RenderState = class {
|
|
|
14899
15357
|
this._gradientStack[depth] = this.currentGradient;
|
|
14900
15358
|
this._lineDashStack[depth] = this.lineDash;
|
|
14901
15359
|
this._blendStack[depth] = this.currentBlendMode;
|
|
15360
|
+
this._shaderStack[depth] = this.currentShader;
|
|
14902
15361
|
if (scissorTestActive) {
|
|
14903
15362
|
this._scissorStack[depth].set(this.currentScissor);
|
|
14904
15363
|
this._scissorActive[depth] = 1;
|
|
@@ -14924,6 +15383,7 @@ var RenderState = class {
|
|
|
14924
15383
|
this.currentTransform.copy(this._matrixStack[depth]);
|
|
14925
15384
|
this.currentGradient = this._gradientStack[depth];
|
|
14926
15385
|
this.lineDash = this._lineDashStack[depth];
|
|
15386
|
+
this.currentShader = this._shaderStack[depth];
|
|
14927
15387
|
const scissorActive = !!this._scissorActive[depth];
|
|
14928
15388
|
if (scissorActive) {
|
|
14929
15389
|
this.currentScissor.set(this._scissorStack[depth]);
|
|
@@ -14949,6 +15409,7 @@ var RenderState = class {
|
|
|
14949
15409
|
this.currentScissor[1] = 0;
|
|
14950
15410
|
this.currentScissor[2] = width;
|
|
14951
15411
|
this.currentScissor[3] = height;
|
|
15412
|
+
this.currentShader = void 0;
|
|
14952
15413
|
}
|
|
14953
15414
|
/** @private — doubles stack capacity when exceeded */
|
|
14954
15415
|
_growStacks() {
|
|
@@ -14962,6 +15423,7 @@ var RenderState = class {
|
|
|
14962
15423
|
this._gradientStack.push(null);
|
|
14963
15424
|
this._lineDashStack.push([]);
|
|
14964
15425
|
this._blendStack.push(void 0);
|
|
15426
|
+
this._shaderStack.push(void 0);
|
|
14965
15427
|
}
|
|
14966
15428
|
const newScissorActive = new Uint8Array(newCap);
|
|
14967
15429
|
newScissorActive.set(this._scissorActive);
|
|
@@ -14988,6 +15450,7 @@ var Renderer = class {
|
|
|
14988
15450
|
this.isContextValid = true;
|
|
14989
15451
|
this.GPURenderer = void 0;
|
|
14990
15452
|
this.customShader = void 0;
|
|
15453
|
+
this._renderTargetPool = null;
|
|
14991
15454
|
this.path2D = new path2d_default();
|
|
14992
15455
|
this.type = "Generic";
|
|
14993
15456
|
this.backgroundColor = new Color(
|
|
@@ -15106,14 +15569,107 @@ var Renderer = class {
|
|
|
15106
15569
|
hasSupportedCompressedFormats(format) {
|
|
15107
15570
|
const supportedFormats = this.getSupportedCompressedTextureFormats();
|
|
15108
15571
|
for (const supportedFormat in supportedFormats) {
|
|
15109
|
-
|
|
15110
|
-
|
|
15572
|
+
const entry = supportedFormats[supportedFormat];
|
|
15573
|
+
if (entry === null || typeof entry === "undefined") {
|
|
15574
|
+
continue;
|
|
15575
|
+
}
|
|
15576
|
+
for (const extension in entry) {
|
|
15577
|
+
if (format === entry[extension]) {
|
|
15111
15578
|
return true;
|
|
15112
15579
|
}
|
|
15113
15580
|
}
|
|
15114
15581
|
}
|
|
15115
15582
|
return false;
|
|
15116
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
|
+
}
|
|
15117
15673
|
/**
|
|
15118
15674
|
* returns the current blend mode for this renderer
|
|
15119
15675
|
* @returns {string} blend mode
|
|
@@ -16128,6 +16684,19 @@ var TextureCache = class {
|
|
|
16128
16684
|
this.usedUnits.add(0);
|
|
16129
16685
|
return 0;
|
|
16130
16686
|
}
|
|
16687
|
+
/**
|
|
16688
|
+
* Reset all texture unit assignments without clearing the texture cache.
|
|
16689
|
+
* Used by multi-texture batching when the shader's sampler range is exceeded.
|
|
16690
|
+
* @ignore
|
|
16691
|
+
*/
|
|
16692
|
+
resetUnitAssignments() {
|
|
16693
|
+
if (this.renderer.currentBatcher) {
|
|
16694
|
+
this.renderer.currentBatcher.boundTextures.length = 0;
|
|
16695
|
+
this.renderer.currentBatcher.currentTextureUnit = -1;
|
|
16696
|
+
}
|
|
16697
|
+
this.units.clear();
|
|
16698
|
+
this.usedUnits.clear();
|
|
16699
|
+
}
|
|
16131
16700
|
/**
|
|
16132
16701
|
* @ignore
|
|
16133
16702
|
*/
|
|
@@ -16995,6 +17564,7 @@ var CanvasRenderer = class extends Renderer {
|
|
|
16995
17564
|
if (result !== null) {
|
|
16996
17565
|
this.setBlendMode(result.blendMode);
|
|
16997
17566
|
}
|
|
17567
|
+
this.customShader = this.renderState.currentShader;
|
|
16998
17568
|
if (typeof context.fillStyle === "string") {
|
|
16999
17569
|
this.currentColor.copy(context.fillStyle);
|
|
17000
17570
|
}
|
|
@@ -17019,6 +17589,7 @@ var CanvasRenderer = class extends Renderer {
|
|
|
17019
17589
|
*/
|
|
17020
17590
|
save() {
|
|
17021
17591
|
this.getContext().save();
|
|
17592
|
+
this.renderState.currentShader = this.customShader;
|
|
17022
17593
|
this.renderState.save();
|
|
17023
17594
|
}
|
|
17024
17595
|
/**
|
|
@@ -17266,9 +17837,8 @@ var CanvasRenderer = class extends Renderer {
|
|
|
17266
17837
|
}
|
|
17267
17838
|
this.maskLevel++;
|
|
17268
17839
|
if (invert === true) {
|
|
17269
|
-
context.
|
|
17270
|
-
context.
|
|
17271
|
-
context.fill();
|
|
17840
|
+
context.rect(0, 0, this.getCanvas().width, this.getCanvas().height);
|
|
17841
|
+
context.clip("evenodd");
|
|
17272
17842
|
} else {
|
|
17273
17843
|
context.clip();
|
|
17274
17844
|
}
|
|
@@ -21349,6 +21919,723 @@ var Sprite = class extends Renderable {
|
|
|
21349
21919
|
}
|
|
21350
21920
|
};
|
|
21351
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
|
+
|
|
21352
22639
|
// src/camera/camera2d.ts
|
|
21353
22640
|
var targetV = new Vector2d();
|
|
21354
22641
|
var Camera2d = class extends Renderable {
|
|
@@ -21439,20 +22726,23 @@ var Camera2d = class extends Renderable {
|
|
|
21439
22726
|
/** default value follow */
|
|
21440
22727
|
follow_axis;
|
|
21441
22728
|
/**
|
|
21442
|
-
* shake
|
|
21443
|
-
* @ignore
|
|
22729
|
+
* active camera effects (shake, fade, etc.)
|
|
21444
22730
|
*/
|
|
21445
|
-
|
|
22731
|
+
cameraEffects;
|
|
21446
22732
|
/**
|
|
21447
|
-
*
|
|
21448
|
-
*
|
|
21449
|
-
|
|
21450
|
-
|
|
21451
|
-
|
|
21452
|
-
*
|
|
21453
|
-
*
|
|
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();
|
|
21454
22742
|
*/
|
|
21455
|
-
|
|
22743
|
+
colorMatrix;
|
|
22744
|
+
/** @ignore */
|
|
22745
|
+
_colorMatrixEffect;
|
|
21456
22746
|
/** the camera deadzone */
|
|
21457
22747
|
deadzone;
|
|
21458
22748
|
/**
|
|
@@ -21479,20 +22769,7 @@ var Camera2d = class extends Renderable {
|
|
|
21479
22769
|
this.offset = new Vector2d();
|
|
21480
22770
|
this.target = null;
|
|
21481
22771
|
this.follow_axis = this.AXIS.NONE;
|
|
21482
|
-
this.
|
|
21483
|
-
intensity: 0,
|
|
21484
|
-
duration: 0,
|
|
21485
|
-
axis: this.AXIS.BOTH,
|
|
21486
|
-
onComplete: null
|
|
21487
|
-
};
|
|
21488
|
-
this._fadeOut = {
|
|
21489
|
-
color: null,
|
|
21490
|
-
tween: null
|
|
21491
|
-
};
|
|
21492
|
-
this._fadeIn = {
|
|
21493
|
-
color: null,
|
|
21494
|
-
tween: null
|
|
21495
|
-
};
|
|
22772
|
+
this.cameraEffects = [];
|
|
21496
22773
|
this.screenX = 0;
|
|
21497
22774
|
this.screenY = 0;
|
|
21498
22775
|
this.zoom = 1;
|
|
@@ -21504,6 +22781,9 @@ var Camera2d = class extends Renderable {
|
|
|
21504
22781
|
this.setDeadzone(this.width / 6, this.height / 6);
|
|
21505
22782
|
this.anchorPoint.set(0, 0);
|
|
21506
22783
|
this.isKinematic = false;
|
|
22784
|
+
this._postEffectManaged = true;
|
|
22785
|
+
this.colorMatrix = new ColorMatrix();
|
|
22786
|
+
this._colorMatrixEffect = null;
|
|
21507
22787
|
this.bounds.setMinMax(minX, minY, maxX, maxY);
|
|
21508
22788
|
this._updateProjectionMatrix();
|
|
21509
22789
|
on(GAME_RESET, this.reset, this);
|
|
@@ -21619,6 +22899,12 @@ var Camera2d = class extends Renderable {
|
|
|
21619
22899
|
this.worldProjection.identity();
|
|
21620
22900
|
this.screenProjection.identity();
|
|
21621
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
|
+
}
|
|
21622
22908
|
}
|
|
21623
22909
|
/**
|
|
21624
22910
|
* change the deadzone settings.
|
|
@@ -21777,20 +23063,14 @@ var Camera2d = class extends Renderable {
|
|
|
21777
23063
|
/** @ignore */
|
|
21778
23064
|
update(dt) {
|
|
21779
23065
|
this.updateTarget(dt);
|
|
21780
|
-
if (this.
|
|
21781
|
-
|
|
21782
|
-
|
|
21783
|
-
|
|
21784
|
-
|
|
21785
|
-
if (
|
|
21786
|
-
this.
|
|
21787
|
-
|
|
21788
|
-
} else {
|
|
21789
|
-
if (this._shake.axis === this.AXIS.BOTH || this._shake.axis === this.AXIS.HORIZONTAL) {
|
|
21790
|
-
this.offset.x = (Math.random() - 0.5) * this._shake.intensity;
|
|
21791
|
-
}
|
|
21792
|
-
if (this._shake.axis === this.AXIS.BOTH || this._shake.axis === this.AXIS.VERTICAL) {
|
|
21793
|
-
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);
|
|
21794
23074
|
}
|
|
21795
23075
|
}
|
|
21796
23076
|
this.isDirty = true;
|
|
@@ -21798,9 +23078,6 @@ var Camera2d = class extends Renderable {
|
|
|
21798
23078
|
if (this.isDirty) {
|
|
21799
23079
|
emit(VIEWPORT_ONCHANGE, this.pos);
|
|
21800
23080
|
}
|
|
21801
|
-
if (this._fadeIn.tween != null || this._fadeOut.tween != null) {
|
|
21802
|
-
this.isDirty = true;
|
|
21803
|
-
}
|
|
21804
23081
|
if (!this.currentTransform.isIdentity()) {
|
|
21805
23082
|
this.invCurrentTransform.copy(this.currentTransform).invert();
|
|
21806
23083
|
} else {
|
|
@@ -21821,12 +23098,21 @@ var Camera2d = class extends Renderable {
|
|
|
21821
23098
|
* app.viewport.shake(10, 500, app.viewport.AXIS.BOTH);
|
|
21822
23099
|
*/
|
|
21823
23100
|
shake(intensity, duration, axis, onComplete, force) {
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
|
|
23101
|
+
const existing = this.getCameraEffect(ShakeEffect);
|
|
23102
|
+
if (existing && force !== true) {
|
|
23103
|
+
return;
|
|
23104
|
+
}
|
|
23105
|
+
if (existing) {
|
|
23106
|
+
this.removeCameraEffect(existing);
|
|
21829
23107
|
}
|
|
23108
|
+
this.addCameraEffect(
|
|
23109
|
+
new ShakeEffect(this, {
|
|
23110
|
+
intensity,
|
|
23111
|
+
duration,
|
|
23112
|
+
axis: axis || this.AXIS.BOTH,
|
|
23113
|
+
onComplete
|
|
23114
|
+
})
|
|
23115
|
+
);
|
|
21830
23116
|
}
|
|
21831
23117
|
/**
|
|
21832
23118
|
* fadeOut(flash) effect<p>
|
|
@@ -21843,13 +23129,14 @@ var Camera2d = class extends Renderable {
|
|
|
21843
23129
|
* });
|
|
21844
23130
|
*/
|
|
21845
23131
|
fadeOut(color, duration = 1e3, onComplete) {
|
|
21846
|
-
this.
|
|
21847
|
-
|
|
21848
|
-
|
|
21849
|
-
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
23132
|
+
this.addCameraEffect(
|
|
23133
|
+
new FadeEffect(this, {
|
|
23134
|
+
color,
|
|
23135
|
+
duration,
|
|
23136
|
+
direction: "out",
|
|
23137
|
+
onComplete
|
|
23138
|
+
})
|
|
23139
|
+
);
|
|
21853
23140
|
}
|
|
21854
23141
|
/**
|
|
21855
23142
|
* fadeIn effect <p>
|
|
@@ -21862,15 +23149,49 @@ var Camera2d = class extends Renderable {
|
|
|
21862
23149
|
* app.viewport.fadeIn("#FFFFFF", 75);
|
|
21863
23150
|
*/
|
|
21864
23151
|
fadeIn(color, duration = 1e3, onComplete) {
|
|
21865
|
-
this.
|
|
21866
|
-
|
|
21867
|
-
|
|
21868
|
-
|
|
21869
|
-
|
|
21870
|
-
|
|
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);
|
|
21871
23194
|
}
|
|
21872
|
-
this._fadeIn.tween.isPersistent = true;
|
|
21873
|
-
this._fadeIn.tween.start();
|
|
21874
23195
|
}
|
|
21875
23196
|
/**
|
|
21876
23197
|
* set the camera position around the specified object
|
|
@@ -21934,30 +23255,8 @@ var Camera2d = class extends Renderable {
|
|
|
21934
23255
|
* @ignore
|
|
21935
23256
|
*/
|
|
21936
23257
|
drawFX(renderer2) {
|
|
21937
|
-
const
|
|
21938
|
-
|
|
21939
|
-
r.save();
|
|
21940
|
-
r.resetTransform();
|
|
21941
|
-
r.setColor(this._fadeIn.color);
|
|
21942
|
-
r.fillRect(0, 0, this.width, this.height);
|
|
21943
|
-
r.restore();
|
|
21944
|
-
if (this._fadeIn.color.alpha === 1) {
|
|
21945
|
-
this._fadeIn.tween = null;
|
|
21946
|
-
colorPool.release(this._fadeIn.color);
|
|
21947
|
-
this._fadeIn.color = null;
|
|
21948
|
-
}
|
|
21949
|
-
}
|
|
21950
|
-
if (this._fadeOut.tween) {
|
|
21951
|
-
r.save();
|
|
21952
|
-
r.resetTransform();
|
|
21953
|
-
r.setColor(this._fadeOut.color);
|
|
21954
|
-
r.fillRect(0, 0, this.width, this.height);
|
|
21955
|
-
r.restore();
|
|
21956
|
-
if (this._fadeOut.color.alpha === 0) {
|
|
21957
|
-
this._fadeOut.tween = null;
|
|
21958
|
-
colorPool.release(this._fadeOut.color);
|
|
21959
|
-
this._fadeOut.color = null;
|
|
21960
|
-
}
|
|
23258
|
+
for (const fx of this.cameraEffects) {
|
|
23259
|
+
fx.draw(renderer2, this.width, this.height);
|
|
21961
23260
|
}
|
|
21962
23261
|
}
|
|
21963
23262
|
/**
|
|
@@ -21971,9 +23270,19 @@ var Camera2d = class extends Renderable {
|
|
|
21971
23270
|
const containerOffsetY = isNonDefault ? container.pos.y : 0;
|
|
21972
23271
|
const translateX = this.pos.x + this.offset.x + containerOffsetX;
|
|
21973
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);
|
|
21974
23281
|
container.translate(-translateX, -translateY);
|
|
21975
23282
|
this.preDraw(r);
|
|
21976
|
-
|
|
23283
|
+
if (!usePostEffect) {
|
|
23284
|
+
r.clipRect(this.screenX, this.screenY, this.width, this.height);
|
|
23285
|
+
}
|
|
21977
23286
|
if (isNonDefault) {
|
|
21978
23287
|
const left = -this.screenX / this.zoom;
|
|
21979
23288
|
const top = -this.screenY / this.zoom;
|
|
@@ -22015,8 +23324,27 @@ var Camera2d = class extends Renderable {
|
|
|
22015
23324
|
this.drawFX(renderer2);
|
|
22016
23325
|
container.postDraw(r);
|
|
22017
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
|
+
}
|
|
22018
23334
|
container.translate(translateX, translateY);
|
|
22019
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
|
+
}
|
|
22020
23348
|
};
|
|
22021
23349
|
|
|
22022
23350
|
// src/state/stage.ts
|
|
@@ -22308,13 +23636,19 @@ var _state = -1;
|
|
|
22308
23636
|
var _animFrameId = -1;
|
|
22309
23637
|
var _isPaused = false;
|
|
22310
23638
|
var _stages = {};
|
|
22311
|
-
var
|
|
23639
|
+
var _transitionType = "fade";
|
|
23640
|
+
var _transitionConfig = {
|
|
22312
23641
|
color: "",
|
|
22313
23642
|
duration: 0
|
|
22314
23643
|
};
|
|
22315
23644
|
var _onSwitchComplete = null;
|
|
22316
23645
|
var _extraArgs = null;
|
|
22317
23646
|
var _pauseTime = 0;
|
|
23647
|
+
var _freezeTimer = null;
|
|
23648
|
+
var _freezeEndsAt = 0;
|
|
23649
|
+
var _freezeMusic = false;
|
|
23650
|
+
var _freezeStartedPause = false;
|
|
23651
|
+
var _freezeResolvers = [];
|
|
22318
23652
|
function _startRunLoop() {
|
|
22319
23653
|
if (_animFrameId === -1 && _state !== -1) {
|
|
22320
23654
|
_animFrameId = globalThis.requestAnimationFrame(_renderFrame);
|
|
@@ -22328,6 +23662,32 @@ function _resumeRunLoop() {
|
|
|
22328
23662
|
function _pauseRunLoop() {
|
|
22329
23663
|
_isPaused = true;
|
|
22330
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
|
+
}
|
|
22331
23691
|
function _renderFrame(time) {
|
|
22332
23692
|
emit(TICK, time);
|
|
22333
23693
|
if (_animFrameId !== -1) {
|
|
@@ -22354,6 +23714,7 @@ function _switchState(stateId) {
|
|
|
22354
23714
|
emit(STATE_CHANGE);
|
|
22355
23715
|
if (_onSwitchComplete) {
|
|
22356
23716
|
_onSwitchComplete();
|
|
23717
|
+
_onSwitchComplete = null;
|
|
22357
23718
|
}
|
|
22358
23719
|
}
|
|
22359
23720
|
}
|
|
@@ -22367,6 +23728,9 @@ once(BOOT, () => {
|
|
|
22367
23728
|
once(VIDEO_INIT, () => {
|
|
22368
23729
|
state.change(state.DEFAULT, true);
|
|
22369
23730
|
});
|
|
23731
|
+
on(BLUR, () => {
|
|
23732
|
+
_cancelFreeze();
|
|
23733
|
+
});
|
|
22370
23734
|
});
|
|
22371
23735
|
var state = {
|
|
22372
23736
|
/**
|
|
@@ -22425,6 +23789,7 @@ var state = {
|
|
|
22425
23789
|
*/
|
|
22426
23790
|
stop(shouldPauseTrack = false) {
|
|
22427
23791
|
if (_state !== this.LOADING && this.isRunning()) {
|
|
23792
|
+
_cancelFreeze();
|
|
22428
23793
|
_stopRunLoop();
|
|
22429
23794
|
if (shouldPauseTrack) {
|
|
22430
23795
|
pauseTrack();
|
|
@@ -22467,6 +23832,7 @@ var state = {
|
|
|
22467
23832
|
*/
|
|
22468
23833
|
resume(music = false) {
|
|
22469
23834
|
if (this.isPaused()) {
|
|
23835
|
+
_cancelFreeze();
|
|
22470
23836
|
_resumeRunLoop();
|
|
22471
23837
|
if (music) {
|
|
22472
23838
|
resumeTrack();
|
|
@@ -22475,6 +23841,59 @@ var state = {
|
|
|
22475
23841
|
emit(STATE_RESUME, _pauseTime);
|
|
22476
23842
|
}
|
|
22477
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
|
+
},
|
|
22478
23897
|
/**
|
|
22479
23898
|
* return the running state of the state manager
|
|
22480
23899
|
* @returns true if a "process is running"
|
|
@@ -22552,15 +23971,28 @@ var state = {
|
|
|
22552
23971
|
},
|
|
22553
23972
|
/**
|
|
22554
23973
|
* specify a global transition effect
|
|
22555
|
-
* @param effect -
|
|
23974
|
+
* @param effect - "fade" for a color fade, "mask" for a shape-based mask transition
|
|
22556
23975
|
* @param color - a CSS color value
|
|
22557
23976
|
* @param [duration=1000] - expressed in milliseconds
|
|
22558
|
-
|
|
22559
|
-
|
|
22560
|
-
|
|
22561
|
-
|
|
22562
|
-
|
|
22563
|
-
|
|
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;
|
|
22564
23996
|
},
|
|
22565
23997
|
/**
|
|
22566
23998
|
* enable/disable the transition to a particular state (by default enabled for all)
|
|
@@ -22586,21 +24018,74 @@ var state = {
|
|
|
22586
24018
|
}
|
|
22587
24019
|
if (!this.isCurrent(stateId)) {
|
|
22588
24020
|
_extraArgs = extraArgs.length > 0 ? extraArgs : null;
|
|
22589
|
-
if (
|
|
22590
|
-
|
|
22591
|
-
|
|
24021
|
+
if (_transitionConfig.duration && _stages[stateId].transition) {
|
|
24022
|
+
const onComplete = () => {
|
|
24023
|
+
defer(
|
|
24024
|
+
_switchState,
|
|
24025
|
+
state,
|
|
24026
|
+
stateId
|
|
24027
|
+
);
|
|
22592
24028
|
};
|
|
22593
|
-
|
|
22594
|
-
|
|
22595
|
-
|
|
22596
|
-
|
|
22597
|
-
|
|
22598
|
-
|
|
22599
|
-
|
|
22600
|
-
|
|
22601
|
-
|
|
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;
|
|
22602
24051
|
}
|
|
22603
|
-
|
|
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
|
+
}
|
|
22604
24089
|
} else {
|
|
22605
24090
|
if (forceChange) {
|
|
22606
24091
|
_switchState(stateId);
|
|
@@ -23124,6 +24609,7 @@ var Tween = class {
|
|
|
23124
24609
|
_yoyo;
|
|
23125
24610
|
_reversed;
|
|
23126
24611
|
_delayTime;
|
|
24612
|
+
_repeatDelayTime;
|
|
23127
24613
|
_startTime;
|
|
23128
24614
|
_easingFunction;
|
|
23129
24615
|
_interpolationFunction;
|
|
@@ -23173,6 +24659,7 @@ var Tween = class {
|
|
|
23173
24659
|
this._yoyo = false;
|
|
23174
24660
|
this._reversed = false;
|
|
23175
24661
|
this._delayTime = 0;
|
|
24662
|
+
this._repeatDelayTime = void 0;
|
|
23176
24663
|
this._startTime = null;
|
|
23177
24664
|
this._easingFunction = Easing.Linear.None;
|
|
23178
24665
|
this._interpolationFunction = Interpolation.Linear;
|
|
@@ -23260,6 +24747,7 @@ var Tween = class {
|
|
|
23260
24747
|
* @param [options.delay] - delay before starting, in milliseconds
|
|
23261
24748
|
* @param [options.yoyo] - bounce back to original values when finished (use with `repeat`)
|
|
23262
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
|
|
23263
24751
|
* @param [options.interpolation] - interpolation function for array values
|
|
23264
24752
|
* @param [options.autoStart] - start the tween immediately without calling `start()`
|
|
23265
24753
|
* @returns this instance for object chaining
|
|
@@ -23282,6 +24770,9 @@ var Tween = class {
|
|
|
23282
24770
|
if (options.delay !== void 0) {
|
|
23283
24771
|
this.delay(options.delay);
|
|
23284
24772
|
}
|
|
24773
|
+
if (options.repeatDelay !== void 0) {
|
|
24774
|
+
this.repeatDelay(options.repeatDelay);
|
|
24775
|
+
}
|
|
23285
24776
|
if (options.interpolation !== void 0) {
|
|
23286
24777
|
this.interpolation(options.interpolation);
|
|
23287
24778
|
}
|
|
@@ -23348,6 +24839,15 @@ var Tween = class {
|
|
|
23348
24839
|
this._repeat = times;
|
|
23349
24840
|
return this;
|
|
23350
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
|
+
}
|
|
23351
24851
|
/**
|
|
23352
24852
|
* Allows the tween to bounce back to their original value when finished.
|
|
23353
24853
|
* To be used together with repeat to create endless loops.
|
|
@@ -23471,7 +24971,7 @@ var Tween = class {
|
|
|
23471
24971
|
if (this._yoyo) {
|
|
23472
24972
|
this._reversed = !this._reversed;
|
|
23473
24973
|
}
|
|
23474
|
-
this._startTime = time + this._delayTime;
|
|
24974
|
+
this._startTime = time + (this._repeatDelayTime ?? this._delayTime);
|
|
23475
24975
|
return true;
|
|
23476
24976
|
} else {
|
|
23477
24977
|
this._unsubscribe();
|
|
@@ -23764,7 +25264,7 @@ var Text = class extends Renderable {
|
|
|
23764
25264
|
* @param {number} [settings.wordWrapWidth] - the maximum length in CSS pixel for a single segment of text
|
|
23765
25265
|
* @param {(string|string[])} [settings.text=""] - a string, or an array of strings
|
|
23766
25266
|
* @example
|
|
23767
|
-
* let font = new
|
|
25267
|
+
* let font = new Text(0, 0, {font: "Arial", size: 8, fillStyle: this.color});
|
|
23768
25268
|
*/
|
|
23769
25269
|
constructor(x, y, settings) {
|
|
23770
25270
|
super(x, y, settings.width || 0, settings.height || 0);
|
|
@@ -23825,6 +25325,7 @@ var Text = class extends Renderable {
|
|
|
23825
25325
|
this.canvasTexture = new canvasrendertarget_default(2, 2, {
|
|
23826
25326
|
offscreenCanvas: false
|
|
23827
25327
|
});
|
|
25328
|
+
this._visibleCharacters = -1;
|
|
23828
25329
|
this.metrics = new textmetrics_default(this);
|
|
23829
25330
|
this.setText(settings.text);
|
|
23830
25331
|
}
|
|
@@ -23923,6 +25424,53 @@ var Text = class extends Renderable {
|
|
|
23923
25424
|
this.isDirty = true;
|
|
23924
25425
|
return this;
|
|
23925
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
|
+
}
|
|
23926
25474
|
/**
|
|
23927
25475
|
* update the bounding box for this Text, accounting for textAlign and textBaseline.
|
|
23928
25476
|
* @param {boolean} [absolute=true] - update in absolute coordinates
|
|
@@ -23979,6 +25527,16 @@ var Text = class extends Renderable {
|
|
|
23979
25527
|
* @param {CanvasRenderer|WebGLRenderer} renderer - Reference to the destination renderer instance
|
|
23980
25528
|
*/
|
|
23981
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
|
+
}
|
|
23982
25540
|
let x = this.metrics.x;
|
|
23983
25541
|
let y = this.metrics.y;
|
|
23984
25542
|
if (renderer2.settings.subPixel === false) {
|
|
@@ -23992,8 +25550,16 @@ var Text = class extends Renderable {
|
|
|
23992
25550
|
*/
|
|
23993
25551
|
_drawFont(context, text, x, y) {
|
|
23994
25552
|
setContextStyle(context, this);
|
|
25553
|
+
let remaining = this.visibleCharacters;
|
|
23995
25554
|
for (let i = 0; i < text.length; i++) {
|
|
23996
|
-
|
|
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
|
+
}
|
|
23997
25563
|
if (this.fillStyle.alpha > 0) {
|
|
23998
25564
|
context.fillText(string, x, y);
|
|
23999
25565
|
}
|
|
@@ -24173,13 +25739,13 @@ var BitmapText = class extends Renderable {
|
|
|
24173
25739
|
* @param {number} [settings.wordWrapWidth] - the maximum length in CSS pixel for a single segment of text
|
|
24174
25740
|
* @param {(string|string[])} [settings.text] - a string, or an array of strings
|
|
24175
25741
|
* @example
|
|
24176
|
-
* // Use
|
|
24177
|
-
*
|
|
24178
|
-
* { name: "arial", type: "binary" src: "data/font/arial.fnt" },
|
|
24179
|
-
* { 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" },
|
|
24180
25746
|
* ])
|
|
24181
25747
|
* // Then create an instance of your bitmap font:
|
|
24182
|
-
* let myFont = new
|
|
25748
|
+
* let myFont = new BitmapText(x, y, {font:"arial", text:"Hello"});
|
|
24183
25749
|
* // two possibilities for using "myFont"
|
|
24184
25750
|
* // either call the draw function from your Renderable draw function
|
|
24185
25751
|
* myFont.draw(renderer, "Hello!", 0, 0);
|
|
@@ -24214,6 +25780,7 @@ var BitmapText = class extends Renderable {
|
|
|
24214
25780
|
} else {
|
|
24215
25781
|
this.anchorPoint.set(0, 0);
|
|
24216
25782
|
}
|
|
25783
|
+
this._visibleCharacters = -1;
|
|
24217
25784
|
this.metrics = new textmetrics_default(this);
|
|
24218
25785
|
if (typeof settings.size === "number" && settings.size !== 1) {
|
|
24219
25786
|
this.resize(settings.size);
|
|
@@ -24255,6 +25822,55 @@ var BitmapText = class extends Renderable {
|
|
|
24255
25822
|
this.updateBounds();
|
|
24256
25823
|
return this;
|
|
24257
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
|
+
}
|
|
24258
25874
|
/**
|
|
24259
25875
|
* update the bounding box for this Bitmap Text.
|
|
24260
25876
|
* @param {boolean} [absolute=true] - update the bounds size and position in (world) absolute coordinates
|
|
@@ -24357,6 +25973,8 @@ var BitmapText = class extends Renderable {
|
|
|
24357
25973
|
default:
|
|
24358
25974
|
break;
|
|
24359
25975
|
}
|
|
25976
|
+
let charCount = 0;
|
|
25977
|
+
const maxChars = this.visibleCharacters;
|
|
24360
25978
|
for (let i = 0; i < this._text.length; i++) {
|
|
24361
25979
|
x = lX;
|
|
24362
25980
|
const string = this._text[i].trimEnd();
|
|
@@ -24373,6 +25991,9 @@ var BitmapText = class extends Renderable {
|
|
|
24373
25991
|
}
|
|
24374
25992
|
let lastGlyph = null;
|
|
24375
25993
|
for (let c = 0, len = string.length; c < len; c++) {
|
|
25994
|
+
if (maxChars !== -1 && charCount >= maxChars) {
|
|
25995
|
+
return;
|
|
25996
|
+
}
|
|
24376
25997
|
const ch = string.charCodeAt(c);
|
|
24377
25998
|
const glyph = this.fontData.glyphs[ch];
|
|
24378
25999
|
if (typeof glyph !== "undefined") {
|
|
@@ -24401,6 +26022,7 @@ var BitmapText = class extends Renderable {
|
|
|
24401
26022
|
"BitmapText: no defined Glyph in for " + String.fromCharCode(ch)
|
|
24402
26023
|
);
|
|
24403
26024
|
}
|
|
26025
|
+
charCount++;
|
|
24404
26026
|
}
|
|
24405
26027
|
y += stringHeight;
|
|
24406
26028
|
}
|
|
@@ -24477,7 +26099,9 @@ function registerTiledObjectFactory(type, factory) {
|
|
|
24477
26099
|
throw new Error("invalid factory function for " + type);
|
|
24478
26100
|
}
|
|
24479
26101
|
if (typeof factories.get(type) !== "undefined") {
|
|
24480
|
-
|
|
26102
|
+
console.warn(
|
|
26103
|
+
"melonJS: overriding Tiled object factory for " + type + " type"
|
|
26104
|
+
);
|
|
24481
26105
|
}
|
|
24482
26106
|
factories.set(type, factory);
|
|
24483
26107
|
}
|
|
@@ -24568,18 +26192,22 @@ var Particle = class extends Renderable {
|
|
|
24568
26192
|
wind;
|
|
24569
26193
|
followTrajectory;
|
|
24570
26194
|
onlyInViewport;
|
|
26195
|
+
accurateBounds;
|
|
24571
26196
|
_deltaInv;
|
|
26197
|
+
_halfW;
|
|
26198
|
+
_halfH;
|
|
24572
26199
|
_angle;
|
|
24573
26200
|
alive;
|
|
24574
26201
|
/**
|
|
24575
26202
|
* @param emitter - the particle emitter
|
|
24576
26203
|
*/
|
|
24577
26204
|
constructor(emitter) {
|
|
26205
|
+
const image = emitter.settings.image;
|
|
24578
26206
|
super(
|
|
24579
26207
|
emitter.getRandomPointX(),
|
|
24580
26208
|
emitter.getRandomPointY(),
|
|
24581
|
-
|
|
24582
|
-
|
|
26209
|
+
image.width,
|
|
26210
|
+
image.height
|
|
24583
26211
|
);
|
|
24584
26212
|
this.vel = vector2dPool.get();
|
|
24585
26213
|
this.onResetEvent(emitter, true);
|
|
@@ -24588,13 +26216,17 @@ var Particle = class extends Renderable {
|
|
|
24588
26216
|
* @ignore
|
|
24589
26217
|
*/
|
|
24590
26218
|
onResetEvent(emitter, newInstance = false) {
|
|
26219
|
+
const image = emitter.settings.image;
|
|
24591
26220
|
if (!newInstance) {
|
|
24592
26221
|
this.pos.set(emitter.getRandomPointX(), emitter.getRandomPointY());
|
|
24593
|
-
this.resize(
|
|
26222
|
+
this.resize(image.width, image.height);
|
|
24594
26223
|
this.currentTransform.identity();
|
|
24595
26224
|
}
|
|
24596
|
-
this.image =
|
|
26225
|
+
this.image = image;
|
|
26226
|
+
this._halfW = this.width / 2;
|
|
26227
|
+
this._halfH = this.height / 2;
|
|
24597
26228
|
this.alwaysUpdate = true;
|
|
26229
|
+
this.anchorPoint.set(0, 0);
|
|
24598
26230
|
if (typeof emitter.settings.tint === "string") {
|
|
24599
26231
|
this.tint.parseCSS(emitter.settings.tint);
|
|
24600
26232
|
}
|
|
@@ -24602,21 +26234,16 @@ var Particle = class extends Renderable {
|
|
|
24602
26234
|
if (emitter.settings.blendMode !== "normal") {
|
|
24603
26235
|
this.blendMode = emitter.settings.blendMode;
|
|
24604
26236
|
}
|
|
24605
|
-
const angle = emitter.settings.angle + (
|
|
24606
|
-
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;
|
|
24607
26239
|
this.vel.set(speed * Math.cos(angle), -speed * Math.sin(angle));
|
|
24608
26240
|
this.life = randomFloat(emitter.settings.minLife, emitter.settings.maxLife);
|
|
24609
26241
|
this.startLife = this.life;
|
|
24610
|
-
this.startScale =
|
|
24611
|
-
randomFloat(
|
|
24612
|
-
emitter.settings.minStartScale,
|
|
24613
|
-
emitter.settings.maxStartScale
|
|
24614
|
-
),
|
|
26242
|
+
this.startScale = randomFloat(
|
|
24615
26243
|
emitter.settings.minStartScale,
|
|
24616
26244
|
emitter.settings.maxStartScale
|
|
24617
26245
|
);
|
|
24618
|
-
this.endScale =
|
|
24619
|
-
randomFloat(emitter.settings.minEndScale, emitter.settings.maxEndScale),
|
|
26246
|
+
this.endScale = randomFloat(
|
|
24620
26247
|
emitter.settings.minEndScale,
|
|
24621
26248
|
emitter.settings.maxEndScale
|
|
24622
26249
|
);
|
|
@@ -24624,7 +26251,8 @@ var Particle = class extends Renderable {
|
|
|
24624
26251
|
this.wind = emitter.settings.wind;
|
|
24625
26252
|
this.followTrajectory = emitter.settings.followTrajectory;
|
|
24626
26253
|
this.onlyInViewport = emitter.settings.onlyInViewport;
|
|
24627
|
-
this.
|
|
26254
|
+
this.accurateBounds = emitter.settings.accurateBounds;
|
|
26255
|
+
this._deltaInv = emitter._deltaInv;
|
|
24628
26256
|
if (!emitter.settings.followTrajectory) {
|
|
24629
26257
|
this._angle = randomFloat(
|
|
24630
26258
|
emitter.settings.minRotation,
|
|
@@ -24664,24 +26292,33 @@ var Particle = class extends Renderable {
|
|
|
24664
26292
|
const angle = this.followTrajectory ? Math.atan2(this.vel.y, this.vel.x) : this._angle;
|
|
24665
26293
|
this.pos.x += this.vel.x * skew;
|
|
24666
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;
|
|
24667
26301
|
this.currentTransform.setTransform(
|
|
24668
|
-
|
|
24669
|
-
|
|
26302
|
+
sCos,
|
|
26303
|
+
sSin,
|
|
24670
26304
|
0,
|
|
24671
26305
|
0,
|
|
24672
|
-
|
|
24673
|
-
|
|
26306
|
+
-sSin,
|
|
26307
|
+
sCos,
|
|
24674
26308
|
0,
|
|
24675
26309
|
0,
|
|
24676
26310
|
0,
|
|
24677
26311
|
0,
|
|
24678
26312
|
1,
|
|
24679
26313
|
0,
|
|
24680
|
-
this.pos.x,
|
|
24681
|
-
this.pos.y,
|
|
26314
|
+
this.pos.x - scale2 * (halfW * cos - halfH * sin),
|
|
26315
|
+
this.pos.y - scale2 * (halfW * sin + halfH * cos),
|
|
24682
26316
|
0,
|
|
24683
26317
|
1
|
|
24684
|
-
)
|
|
26318
|
+
);
|
|
26319
|
+
if (this.accurateBounds) {
|
|
26320
|
+
this.updateBounds();
|
|
26321
|
+
}
|
|
24685
26322
|
this.isDirty = this.inViewport || !this.onlyInViewport;
|
|
24686
26323
|
return super.update(dt);
|
|
24687
26324
|
}
|
|
@@ -24691,7 +26328,7 @@ var Particle = class extends Renderable {
|
|
|
24691
26328
|
draw(renderer2) {
|
|
24692
26329
|
const w = this.width;
|
|
24693
26330
|
const h = this.height;
|
|
24694
|
-
renderer2.drawImage(this.image, 0, 0, w, h,
|
|
26331
|
+
renderer2.drawImage(this.image, 0, 0, w, h, 0, 0, w, h);
|
|
24695
26332
|
}
|
|
24696
26333
|
};
|
|
24697
26334
|
var particlePool = createPool(
|
|
@@ -25093,13 +26730,27 @@ var ImageLayer = class extends Sprite {
|
|
|
25093
26730
|
this.isDirty = true;
|
|
25094
26731
|
}
|
|
25095
26732
|
/**
|
|
25096
|
-
*
|
|
25097
|
-
*
|
|
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`).
|
|
25098
26746
|
* @ignore
|
|
25099
26747
|
*/
|
|
25100
26748
|
preDraw(renderer2) {
|
|
25101
26749
|
renderer2.save();
|
|
25102
26750
|
renderer2.setGlobalAlpha(renderer2.globalAlpha() * this.getOpacity());
|
|
26751
|
+
if (!this._postEffectManaged) {
|
|
26752
|
+
renderer2.beginPostEffect(this);
|
|
26753
|
+
}
|
|
25103
26754
|
renderer2.setTint(this.tint);
|
|
25104
26755
|
if (this.blendMode !== renderer2.getBlendMode()) {
|
|
25105
26756
|
renderer2.setBlendMode(this.blendMode);
|
|
@@ -25137,6 +26788,16 @@ var ImageLayer = class extends Sprite {
|
|
|
25137
26788
|
}
|
|
25138
26789
|
renderer2.translate(x * vZoom, y * vZoom);
|
|
25139
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
|
+
}
|
|
25140
26801
|
renderer2.drawPattern(
|
|
25141
26802
|
this._pattern,
|
|
25142
26803
|
0,
|
|
@@ -25559,8 +27220,10 @@ var Trigger = class extends Renderable {
|
|
|
25559
27220
|
* @param {number} [settings.width] - width of the trigger area
|
|
25560
27221
|
* @param {number} [settings.height] - height of the trigger area
|
|
25561
27222
|
* @param {Rect[]|Polygon[]|Line[]|Ellipse[]} [settings.shapes] - collision shape(s) that will trigger the event
|
|
25562
|
-
* @param {
|
|
25563
|
-
* @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)
|
|
25564
27227
|
* @param {string} [settings.event="level"] - the type of event to trigger (only "level" supported for now)
|
|
25565
27228
|
* @param {string} [settings.to] - level to load if level trigger
|
|
25566
27229
|
* @param {string|Container} [settings.container] - Target container. See {@link level.load}
|
|
@@ -25568,41 +27231,64 @@ var Trigger = class extends Renderable {
|
|
|
25568
27231
|
* @param {boolean} [settings.flatten] - Flatten all objects into the target container. See {@link level.load}
|
|
25569
27232
|
* @param {boolean} [settings.setViewportBounds] - Resize the viewport to match the level. See {@link level.load}
|
|
25570
27233
|
* @example
|
|
25571
|
-
*
|
|
25572
|
-
*
|
|
25573
|
-
*
|
|
25574
|
-
*
|
|
25575
|
-
*
|
|
25576
|
-
*
|
|
25577
|
-
*
|
|
25578
|
-
*
|
|
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
|
+
* }));
|
|
25579
27264
|
*/
|
|
25580
27265
|
constructor(x, y, settings) {
|
|
25581
27266
|
super(x, y, settings.width || 0, settings.height || 0);
|
|
25582
27267
|
this.anchorPoint.set(0, 0);
|
|
25583
|
-
this.
|
|
27268
|
+
this.color = settings.color || settings.fade;
|
|
25584
27269
|
this.duration = settings.duration;
|
|
27270
|
+
this.transition = settings.transition || "fade";
|
|
27271
|
+
this.transitionShape = settings.shape;
|
|
25585
27272
|
this.fading = false;
|
|
25586
27273
|
this.name = "Trigger";
|
|
25587
27274
|
this.type = settings.type;
|
|
25588
27275
|
this.id = settings.id;
|
|
25589
27276
|
this.gotolevel = settings.to;
|
|
25590
27277
|
this.triggerSettings = {
|
|
25591
|
-
// the default (and only for now) action
|
|
25592
27278
|
event: "level"
|
|
25593
27279
|
};
|
|
25594
|
-
[
|
|
27280
|
+
for (const property of [
|
|
25595
27281
|
"type",
|
|
25596
27282
|
"container",
|
|
25597
27283
|
"onLoaded",
|
|
25598
27284
|
"flatten",
|
|
25599
27285
|
"setViewportBounds",
|
|
25600
27286
|
"to"
|
|
25601
|
-
]
|
|
27287
|
+
]) {
|
|
25602
27288
|
if (typeof settings[property] !== "undefined") {
|
|
25603
27289
|
this.triggerSettings[property] = settings[property];
|
|
25604
27290
|
}
|
|
25605
|
-
}
|
|
27291
|
+
}
|
|
25606
27292
|
let shape = settings.shapes;
|
|
25607
27293
|
if (typeof shape === "undefined") {
|
|
25608
27294
|
shape = polygonPool.get(0, 0, [
|
|
@@ -25630,28 +27316,73 @@ var Trigger = class extends Renderable {
|
|
|
25630
27316
|
return this.triggerSettings;
|
|
25631
27317
|
}
|
|
25632
27318
|
/**
|
|
25633
|
-
*
|
|
25634
|
-
*/
|
|
25635
|
-
onFadeComplete() {
|
|
25636
|
-
const world = this.ancestor.getRootAncestor();
|
|
25637
|
-
level.load(this.gotolevel, this.getTriggerSettings());
|
|
25638
|
-
world.app.viewport.fadeOut(this.fade, this.duration);
|
|
25639
|
-
}
|
|
25640
|
-
/**
|
|
25641
|
-
* trigger this event
|
|
27319
|
+
* Trigger this event. Override in subclasses to customize behavior.
|
|
25642
27320
|
* @protected
|
|
25643
27321
|
*/
|
|
25644
27322
|
triggerEvent() {
|
|
25645
27323
|
const triggerSettings = this.getTriggerSettings();
|
|
25646
27324
|
const world = this.ancestor.getRootAncestor();
|
|
27325
|
+
const app = world.app;
|
|
27326
|
+
const viewport = app.viewport;
|
|
25647
27327
|
if (triggerSettings.event === "level") {
|
|
25648
27328
|
this.gotolevel = triggerSettings.to;
|
|
25649
|
-
if (this.
|
|
27329
|
+
if (this.color && this.duration) {
|
|
25650
27330
|
if (!this.fading) {
|
|
25651
27331
|
this.fading = true;
|
|
25652
|
-
|
|
25653
|
-
|
|
25654
|
-
|
|
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
|
+
}
|
|
25655
27386
|
}
|
|
25656
27387
|
} else {
|
|
25657
27388
|
level.load(this.gotolevel, triggerSettings);
|
|
@@ -25668,14 +27399,14 @@ var Trigger = class extends Renderable {
|
|
|
25668
27399
|
*/
|
|
25669
27400
|
onCollision() {
|
|
25670
27401
|
if (this.name === "Trigger") {
|
|
25671
|
-
this.triggerEvent
|
|
27402
|
+
this.triggerEvent();
|
|
25672
27403
|
}
|
|
25673
27404
|
return false;
|
|
25674
27405
|
}
|
|
25675
27406
|
};
|
|
25676
27407
|
|
|
25677
27408
|
// src/version.ts
|
|
25678
|
-
var version = "19.
|
|
27409
|
+
var version = "19.2.0";
|
|
25679
27410
|
|
|
25680
27411
|
// src/system/bootstrap.ts
|
|
25681
27412
|
var initialized = false;
|
|
@@ -27539,7 +29270,7 @@ var QuadTree = class {
|
|
|
27539
29270
|
* @param {Container} container - group of objects to be added
|
|
27540
29271
|
*/
|
|
27541
29272
|
insertContainer(container) {
|
|
27542
|
-
const children = container.
|
|
29273
|
+
const children = container.getChildren();
|
|
27543
29274
|
const childrenLength = children.length;
|
|
27544
29275
|
for (let i = childrenLength, child; i--, child = children[i]; ) {
|
|
27545
29276
|
if (child.isKinematic !== true) {
|
|
@@ -27815,6 +29546,327 @@ var World = class extends Container {
|
|
|
27815
29546
|
}
|
|
27816
29547
|
};
|
|
27817
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
|
+
|
|
27818
29870
|
// src/video/utils/dash.js
|
|
27819
29871
|
var _dashPathResult = [];
|
|
27820
29872
|
function dashPath(pts, pattern) {
|
|
@@ -27962,96 +30014,7 @@ var mesh_default = "uniform sampler2D uSampler;\nvarying vec4 vColor;\nvarying v
|
|
|
27962
30014
|
// src/video/webgl/shaders/mesh.vert
|
|
27963
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";
|
|
27964
30016
|
|
|
27965
|
-
// src/video/
|
|
27966
|
-
var IndexBuffer = class {
|
|
27967
|
-
/**
|
|
27968
|
-
* @param {WebGLRenderingContext|WebGL2RenderingContext} gl - the WebGL context
|
|
27969
|
-
* @param {number} maxIndices - maximum number of indices this buffer can hold
|
|
27970
|
-
* @param {boolean} [useUint32=false] - use Uint32 indices (WebGL2) instead of Uint16 (WebGL1)
|
|
27971
|
-
* @param {boolean} [dynamic=false] - if true, use STREAM_DRAW for frequent updates; if false, use STATIC_DRAW
|
|
27972
|
-
*/
|
|
27973
|
-
constructor(gl, maxIndices, useUint32 = false, dynamic = false) {
|
|
27974
|
-
this.gl = gl;
|
|
27975
|
-
this.dynamic = dynamic;
|
|
27976
|
-
if (useUint32) {
|
|
27977
|
-
this.type = gl.UNSIGNED_INT;
|
|
27978
|
-
this.data = new Uint32Array(maxIndices);
|
|
27979
|
-
} else {
|
|
27980
|
-
this.type = gl.UNSIGNED_SHORT;
|
|
27981
|
-
this.data = new Uint16Array(maxIndices);
|
|
27982
|
-
}
|
|
27983
|
-
this.length = 0;
|
|
27984
|
-
this.buffer = gl.createBuffer();
|
|
27985
|
-
}
|
|
27986
|
-
/**
|
|
27987
|
-
* Fill the buffer with a repeating quad index pattern [0,1,2, 2,1,3, 4,5,6, ...]
|
|
27988
|
-
* and upload as a static buffer.
|
|
27989
|
-
* @param {number} maxQuads - number of quads to generate indices for
|
|
27990
|
-
*/
|
|
27991
|
-
fillQuadPattern(maxQuads) {
|
|
27992
|
-
for (let i = 0, vertex = 0; i < maxQuads * 6; i += 6, vertex += 4) {
|
|
27993
|
-
this.data[i] = vertex;
|
|
27994
|
-
this.data[i + 1] = vertex + 1;
|
|
27995
|
-
this.data[i + 2] = vertex + 2;
|
|
27996
|
-
this.data[i + 3] = vertex + 2;
|
|
27997
|
-
this.data[i + 4] = vertex + 1;
|
|
27998
|
-
this.data[i + 5] = vertex + 3;
|
|
27999
|
-
}
|
|
28000
|
-
this.length = maxQuads * 6;
|
|
28001
|
-
this.bind();
|
|
28002
|
-
this.gl.bufferData(
|
|
28003
|
-
this.gl.ELEMENT_ARRAY_BUFFER,
|
|
28004
|
-
this.data,
|
|
28005
|
-
this.gl.STATIC_DRAW
|
|
28006
|
-
);
|
|
28007
|
-
}
|
|
28008
|
-
/**
|
|
28009
|
-
* Reset the index count (for dynamic buffers)
|
|
28010
|
-
*/
|
|
28011
|
-
clear() {
|
|
28012
|
-
this.length = 0;
|
|
28013
|
-
}
|
|
28014
|
-
/**
|
|
28015
|
-
* Add indices to the buffer, rebased by the given vertex offset
|
|
28016
|
-
* @param {number[]} indices - source indices to add
|
|
28017
|
-
* @param {number} vertexOffset - value to add to each index (vertex count at time of insertion)
|
|
28018
|
-
*/
|
|
28019
|
-
add(indices, vertexOffset) {
|
|
28020
|
-
for (let i = 0; i < indices.length; i++) {
|
|
28021
|
-
this.data[this.length + i] = indices[i] + vertexOffset;
|
|
28022
|
-
}
|
|
28023
|
-
this.length += indices.length;
|
|
28024
|
-
}
|
|
28025
|
-
/**
|
|
28026
|
-
* Add pre-computed absolute indices to the buffer (no rebasing)
|
|
28027
|
-
* @param {number[]} indices - absolute index values to add
|
|
28028
|
-
*/
|
|
28029
|
-
addRaw(indices) {
|
|
28030
|
-
for (let i = 0; i < indices.length; i++) {
|
|
28031
|
-
this.data[this.length + i] = indices[i];
|
|
28032
|
-
}
|
|
28033
|
-
this.length += indices.length;
|
|
28034
|
-
}
|
|
28035
|
-
/**
|
|
28036
|
-
* Upload the current index data to the GPU (for dynamic buffers)
|
|
28037
|
-
*/
|
|
28038
|
-
upload() {
|
|
28039
|
-
this.bind();
|
|
28040
|
-
this.gl.bufferData(
|
|
28041
|
-
this.gl.ELEMENT_ARRAY_BUFFER,
|
|
28042
|
-
this.data.subarray(0, this.length),
|
|
28043
|
-
this.gl.STREAM_DRAW
|
|
28044
|
-
);
|
|
28045
|
-
}
|
|
28046
|
-
/**
|
|
28047
|
-
* bind this index buffer
|
|
28048
|
-
*/
|
|
28049
|
-
bind() {
|
|
28050
|
-
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.buffer);
|
|
28051
|
-
}
|
|
28052
|
-
};
|
|
28053
|
-
|
|
28054
|
-
// src/video/webgl/buffer/vertex.js
|
|
30017
|
+
// src/video/buffer/vertex.js
|
|
28055
30018
|
var VertexArrayBuffer = class {
|
|
28056
30019
|
constructor(vertexSize, maxVertex) {
|
|
28057
30020
|
this.vertexSize = vertexSize;
|
|
@@ -28078,16 +30041,25 @@ var VertexArrayBuffer = class {
|
|
|
28078
30041
|
return this.vertexCount + vertex >= this.maxVertex;
|
|
28079
30042
|
}
|
|
28080
30043
|
/**
|
|
28081
|
-
* push a new vertex to the buffer
|
|
30044
|
+
* push a new vertex to the buffer
|
|
30045
|
+
* @param {number} x - x position
|
|
30046
|
+
* @param {number} y - y position
|
|
30047
|
+
* @param {number} u - texture U coordinate
|
|
30048
|
+
* @param {number} v - texture V coordinate
|
|
30049
|
+
* @param {number} tint - tint color in UINT32 (argb) format
|
|
30050
|
+
* @param {number} [textureId] - texture unit index for multi-texture batching
|
|
28082
30051
|
* @ignore
|
|
28083
30052
|
*/
|
|
28084
|
-
push(x, y, u, v, tint) {
|
|
30053
|
+
push(x, y, u, v, tint, textureId) {
|
|
28085
30054
|
const offset = this.vertexCount * this.vertexSize;
|
|
28086
30055
|
this.bufferF32[offset] = x;
|
|
28087
30056
|
this.bufferF32[offset + 1] = y;
|
|
28088
30057
|
this.bufferF32[offset + 2] = u;
|
|
28089
30058
|
this.bufferF32[offset + 3] = v;
|
|
28090
30059
|
this.bufferU32[offset + 4] = tint;
|
|
30060
|
+
if (this.vertexSize > 5) {
|
|
30061
|
+
this.bufferF32[offset + 5] = textureId || 0;
|
|
30062
|
+
}
|
|
28091
30063
|
this.vertexCount++;
|
|
28092
30064
|
return this;
|
|
28093
30065
|
}
|
|
@@ -28145,258 +30117,102 @@ var VertexArrayBuffer = class {
|
|
|
28145
30117
|
}
|
|
28146
30118
|
};
|
|
28147
30119
|
|
|
28148
|
-
// src/video/
|
|
28149
|
-
|
|
28150
|
-
|
|
28151
|
-
|
|
28152
|
-
|
|
28153
|
-
|
|
28154
|
-
|
|
28155
|
-
|
|
28156
|
-
|
|
28157
|
-
return attributes;
|
|
28158
|
-
}
|
|
28159
|
-
|
|
28160
|
-
// src/video/webgl/utils/precision.js
|
|
28161
|
-
function setPrecision(src, precision) {
|
|
28162
|
-
if (src.substring(0, 9) !== "precision") {
|
|
28163
|
-
return "precision " + precision + " float;\n" + src;
|
|
28164
|
-
}
|
|
28165
|
-
return src;
|
|
28166
|
-
}
|
|
28167
|
-
function getMaxShaderPrecision(gl) {
|
|
28168
|
-
if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) {
|
|
28169
|
-
return "highp";
|
|
28170
|
-
}
|
|
28171
|
-
if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) {
|
|
28172
|
-
return "mediump";
|
|
28173
|
-
}
|
|
28174
|
-
return "lowp";
|
|
28175
|
-
}
|
|
28176
|
-
|
|
28177
|
-
// src/video/webgl/utils/program.js
|
|
28178
|
-
function compileShader(gl, type, source) {
|
|
28179
|
-
const shader = gl.createShader(type);
|
|
28180
|
-
gl.shaderSource(shader, source);
|
|
28181
|
-
gl.compileShader(shader);
|
|
28182
|
-
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
28183
|
-
throw new Error(gl.getShaderInfoLog(shader));
|
|
28184
|
-
}
|
|
28185
|
-
return shader;
|
|
28186
|
-
}
|
|
28187
|
-
function compileProgram(gl, vertex, fragment, attributes) {
|
|
28188
|
-
const vertShader = compileShader(gl, gl.VERTEX_SHADER, vertex);
|
|
28189
|
-
const fragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragment);
|
|
28190
|
-
const program = gl.createProgram();
|
|
28191
|
-
gl.attachShader(program, vertShader);
|
|
28192
|
-
gl.attachShader(program, fragShader);
|
|
28193
|
-
for (const location in attributes) {
|
|
28194
|
-
gl.bindAttribLocation(program, attributes[location], location);
|
|
28195
|
-
}
|
|
28196
|
-
gl.linkProgram(program);
|
|
28197
|
-
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
28198
|
-
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);
|
|
28199
|
-
gl.deleteProgram(program);
|
|
28200
|
-
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;
|
|
28201
30129
|
}
|
|
28202
|
-
gl.useProgram(program);
|
|
28203
|
-
gl.deleteShader(vertShader);
|
|
28204
|
-
gl.deleteShader(fragShader);
|
|
28205
|
-
return program;
|
|
28206
|
-
}
|
|
28207
|
-
|
|
28208
|
-
// src/video/webgl/utils/string.js
|
|
28209
|
-
function minify(src) {
|
|
28210
|
-
src = src.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
|
|
28211
|
-
src = src.replace(/(\\n\s+)|(\s+\\n)/g, "");
|
|
28212
|
-
src = src.replace(/(\\r|\\n)+/g, "");
|
|
28213
|
-
src = src.replace(/[ \t]*([;,[\](){}\\\/\-+*|^&!=<>?~%])[ \t]*/g, "$1");
|
|
28214
|
-
return src;
|
|
28215
|
-
}
|
|
28216
|
-
|
|
28217
|
-
// src/video/webgl/utils/uniforms.js
|
|
28218
|
-
var fnHash = {
|
|
28219
|
-
bool: "1i",
|
|
28220
|
-
int: "1i",
|
|
28221
|
-
float: "1f",
|
|
28222
|
-
vec2: "2fv",
|
|
28223
|
-
vec3: "3fv",
|
|
28224
|
-
vec4: "4fv",
|
|
28225
|
-
bvec2: "2iv",
|
|
28226
|
-
bvec3: "3iv",
|
|
28227
|
-
bvec4: "4iv",
|
|
28228
|
-
ivec2: "2iv",
|
|
28229
|
-
ivec3: "3iv",
|
|
28230
|
-
ivec4: "4iv",
|
|
28231
|
-
mat2: "Matrix2fv",
|
|
28232
|
-
mat3: "Matrix3fv",
|
|
28233
|
-
mat4: "Matrix4fv",
|
|
28234
|
-
sampler2D: "1i"
|
|
28235
|
-
};
|
|
28236
|
-
function extractUniforms(gl, shader) {
|
|
28237
|
-
const uniforms = {};
|
|
28238
|
-
const uniRx = /uniform\s+(\w+)\s+(\w+)/g;
|
|
28239
|
-
const uniformsData = {};
|
|
28240
|
-
const descriptor = {};
|
|
28241
|
-
const locations = {};
|
|
28242
|
-
let match;
|
|
28243
|
-
[shader.vertex, shader.fragment].forEach((shader2) => {
|
|
28244
|
-
while (match = uniRx.exec(shader2)) {
|
|
28245
|
-
uniformsData[match[2]] = match[1];
|
|
28246
|
-
}
|
|
28247
|
-
});
|
|
28248
|
-
Object.keys(uniformsData).forEach((name) => {
|
|
28249
|
-
const type = uniformsData[name];
|
|
28250
|
-
locations[name] = gl.getUniformLocation(shader.program, name);
|
|
28251
|
-
descriptor[name] = {
|
|
28252
|
-
get: /* @__PURE__ */ (function(name2) {
|
|
28253
|
-
return function() {
|
|
28254
|
-
return locations[name2];
|
|
28255
|
-
};
|
|
28256
|
-
})(name),
|
|
28257
|
-
set: (function(name2, type2, fn) {
|
|
28258
|
-
if (/^mat/.test(type2)) {
|
|
28259
|
-
return function(val) {
|
|
28260
|
-
gl[fn](locations[name2], false, val);
|
|
28261
|
-
};
|
|
28262
|
-
} else {
|
|
28263
|
-
return function(val) {
|
|
28264
|
-
let fnv = fn;
|
|
28265
|
-
if (val.length && !/v$/.test(fn)) {
|
|
28266
|
-
fnv += "v";
|
|
28267
|
-
}
|
|
28268
|
-
gl[fnv](locations[name2], val);
|
|
28269
|
-
};
|
|
28270
|
-
}
|
|
28271
|
-
})(name, type, "uniform" + fnHash[type])
|
|
28272
|
-
};
|
|
28273
|
-
});
|
|
28274
|
-
Object.defineProperties(uniforms, descriptor);
|
|
28275
|
-
return uniforms;
|
|
28276
|
-
}
|
|
28277
|
-
|
|
28278
|
-
// src/video/webgl/glshader.js
|
|
28279
|
-
var GLShader = class {
|
|
28280
30130
|
/**
|
|
28281
|
-
*
|
|
28282
|
-
* @param {
|
|
28283
|
-
* @param {string} fragment - a string containing the GLSL source code to set
|
|
28284
|
-
* @param {string} [precision=auto detected] - float precision ('lowp', 'mediump' or 'highp').
|
|
28285
|
-
* @see https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders
|
|
28286
|
-
* @example
|
|
28287
|
-
* // create a basic shader
|
|
28288
|
-
* let myShader = new me.GLShader(
|
|
28289
|
-
* // WebGL rendering context
|
|
28290
|
-
* gl,
|
|
28291
|
-
* // vertex shader
|
|
28292
|
-
* [
|
|
28293
|
-
* "void main() {",
|
|
28294
|
-
* " gl_Position = doMathToMakeClipspaceCoordinates;",
|
|
28295
|
-
* "}"
|
|
28296
|
-
* ].join("\n"),
|
|
28297
|
-
* // fragment shader
|
|
28298
|
-
* [
|
|
28299
|
-
* "void main() {",
|
|
28300
|
-
* " gl_FragColor = doMathToMakeAColor;",
|
|
28301
|
-
* "}"
|
|
28302
|
-
* ].join("\n")
|
|
28303
|
-
* )
|
|
28304
|
-
* // use the shader
|
|
28305
|
-
* 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
|
|
28306
30133
|
*/
|
|
28307
|
-
|
|
28308
|
-
|
|
28309
|
-
|
|
28310
|
-
|
|
28311
|
-
|
|
28312
|
-
|
|
28313
|
-
|
|
28314
|
-
|
|
28315
|
-
|
|
28316
|
-
|
|
28317
|
-
this.attributes = extractAttributes(this.gl, this);
|
|
28318
|
-
this.program = compileProgram(
|
|
28319
|
-
this.gl,
|
|
28320
|
-
this.vertex,
|
|
28321
|
-
this.fragment,
|
|
28322
|
-
this.attributes
|
|
28323
|
-
);
|
|
28324
|
-
this.uniforms = extractUniforms(this.gl, this);
|
|
28325
|
-
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;
|
|
28326
30144
|
}
|
|
28327
30145
|
/**
|
|
28328
|
-
*
|
|
30146
|
+
* Reset the index count
|
|
28329
30147
|
*/
|
|
28330
|
-
|
|
28331
|
-
this.
|
|
30148
|
+
clear() {
|
|
30149
|
+
this.length = 0;
|
|
28332
30150
|
}
|
|
28333
30151
|
/**
|
|
28334
|
-
*
|
|
28335
|
-
* @param {
|
|
28336
|
-
* @
|
|
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
|
|
28337
30155
|
*/
|
|
28338
|
-
|
|
28339
|
-
|
|
28340
|
-
|
|
28341
|
-
return attr;
|
|
28342
|
-
} else {
|
|
28343
|
-
return -1;
|
|
30156
|
+
add(indices, vertexOffset) {
|
|
30157
|
+
for (let i = 0; i < indices.length; i++) {
|
|
30158
|
+
this.data[this.length + i] = indices[i] + vertexOffset;
|
|
28344
30159
|
}
|
|
30160
|
+
this.length += indices.length;
|
|
28345
30161
|
}
|
|
28346
30162
|
/**
|
|
28347
|
-
*
|
|
28348
|
-
* @param {
|
|
28349
|
-
* @param {object|Float32Array} value - the value to assign to that uniform
|
|
28350
|
-
* @example
|
|
28351
|
-
* 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
|
|
28352
30165
|
*/
|
|
28353
|
-
|
|
28354
|
-
|
|
28355
|
-
|
|
28356
|
-
this.bind();
|
|
28357
|
-
if (typeof value === "object" && typeof value.toArray === "function") {
|
|
28358
|
-
uniforms[name] = value.toArray();
|
|
28359
|
-
} else {
|
|
28360
|
-
uniforms[name] = value;
|
|
28361
|
-
}
|
|
28362
|
-
} else {
|
|
28363
|
-
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];
|
|
28364
30169
|
}
|
|
30170
|
+
this.length += indices.length;
|
|
28365
30171
|
}
|
|
30172
|
+
};
|
|
30173
|
+
|
|
30174
|
+
// src/video/webgl/buffer/index.js
|
|
30175
|
+
var WebGLIndexBuffer = class extends IndexBuffer {
|
|
28366
30176
|
/**
|
|
28367
|
-
*
|
|
28368
|
-
* @param {
|
|
28369
|
-
* @param {
|
|
28370
|
-
* @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)
|
|
28371
30180
|
*/
|
|
28372
|
-
|
|
28373
|
-
|
|
28374
|
-
|
|
28375
|
-
|
|
28376
|
-
|
|
28377
|
-
gl.enableVertexAttribArray(location);
|
|
28378
|
-
gl.vertexAttribPointer(
|
|
28379
|
-
location,
|
|
28380
|
-
element.size,
|
|
28381
|
-
element.type,
|
|
28382
|
-
element.normalized,
|
|
28383
|
-
stride,
|
|
28384
|
-
element.offset
|
|
28385
|
-
);
|
|
28386
|
-
} else {
|
|
28387
|
-
gl.disableVertexAttribArray(index);
|
|
28388
|
-
}
|
|
28389
|
-
}
|
|
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();
|
|
28390
30186
|
}
|
|
28391
30187
|
/**
|
|
28392
|
-
*
|
|
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
|
|
28393
30190
|
*/
|
|
28394
|
-
|
|
28395
|
-
|
|
28396
|
-
this.
|
|
28397
|
-
this.gl.
|
|
28398
|
-
|
|
28399
|
-
|
|
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);
|
|
28400
30216
|
}
|
|
28401
30217
|
};
|
|
28402
30218
|
|
|
@@ -28456,7 +30272,8 @@ var Batcher = class {
|
|
|
28456
30272
|
this.defaultShader = new GLShader(
|
|
28457
30273
|
this.gl,
|
|
28458
30274
|
settings.shader.vertex,
|
|
28459
|
-
settings.shader.fragment
|
|
30275
|
+
settings.shader.fragment,
|
|
30276
|
+
this.renderer.shaderPrecision
|
|
28460
30277
|
);
|
|
28461
30278
|
} else {
|
|
28462
30279
|
throw new Error("shader definition missing");
|
|
@@ -28468,7 +30285,7 @@ var Batcher = class {
|
|
|
28468
30285
|
if (this.useIndexBuffer) {
|
|
28469
30286
|
const gl = this.gl;
|
|
28470
30287
|
this.glVertexBuffer = gl.createBuffer();
|
|
28471
|
-
this.indexBuffer = new
|
|
30288
|
+
this.indexBuffer = new WebGLIndexBuffer(gl, maxVertices * 3, false);
|
|
28472
30289
|
}
|
|
28473
30290
|
}
|
|
28474
30291
|
/**
|
|
@@ -28672,7 +30489,7 @@ var MaterialBatcher = class extends Batcher {
|
|
|
28672
30489
|
* @param {boolean} [mipmap=true] - Whether mipmap levels should be generated
|
|
28673
30490
|
* @returns {WebGLTexture} a WebGL texture
|
|
28674
30491
|
*/
|
|
28675
|
-
createTexture2D(unit, pixels = null, filter, repeat = "no-repeat", w = pixels.width, h = pixels.height, premultipliedAlpha = true, mipmap = true, texture) {
|
|
30492
|
+
createTexture2D(unit, pixels = null, filter, repeat = "no-repeat", w = pixels.width, h = pixels.height, premultipliedAlpha = true, mipmap = true, texture, flush = true) {
|
|
28676
30493
|
const gl = this.gl;
|
|
28677
30494
|
const isPOT = isPowerOfTwo(w) && isPowerOfTwo(h);
|
|
28678
30495
|
const rs = repeat.search(/^repeat(-x)?$/) === 0 && (isPOT || this.renderer.WebGLVersion > 1) ? gl.REPEAT : gl.CLAMP_TO_EDGE;
|
|
@@ -28681,7 +30498,7 @@ var MaterialBatcher = class extends Batcher {
|
|
|
28681
30498
|
if (!currentTexture) {
|
|
28682
30499
|
currentTexture = gl.createTexture();
|
|
28683
30500
|
}
|
|
28684
|
-
this.bindTexture2D(currentTexture, unit);
|
|
30501
|
+
this.bindTexture2D(currentTexture, unit, flush);
|
|
28685
30502
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, rs);
|
|
28686
30503
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, rt);
|
|
28687
30504
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
@@ -28786,10 +30603,12 @@ var MaterialBatcher = class extends Batcher {
|
|
|
28786
30603
|
* @param {WebGLTexture} texture - a WebGL texture
|
|
28787
30604
|
* @param {number} unit - Texture unit to which the given texture is bound
|
|
28788
30605
|
*/
|
|
28789
|
-
bindTexture2D(texture, unit) {
|
|
30606
|
+
bindTexture2D(texture, unit, flush = true) {
|
|
28790
30607
|
const gl = this.gl;
|
|
28791
30608
|
if (texture !== this.boundTextures[unit]) {
|
|
28792
|
-
|
|
30609
|
+
if (flush) {
|
|
30610
|
+
this.flush();
|
|
30611
|
+
}
|
|
28793
30612
|
if (this.currentTextureUnit !== unit) {
|
|
28794
30613
|
this.currentTextureUnit = unit;
|
|
28795
30614
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
@@ -28797,7 +30616,9 @@ var MaterialBatcher = class extends Batcher {
|
|
|
28797
30616
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
28798
30617
|
this.boundTextures[unit] = texture;
|
|
28799
30618
|
} else if (this.currentTextureUnit !== unit) {
|
|
28800
|
-
|
|
30619
|
+
if (flush) {
|
|
30620
|
+
this.flush();
|
|
30621
|
+
}
|
|
28801
30622
|
this.currentTextureUnit = unit;
|
|
28802
30623
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
28803
30624
|
}
|
|
@@ -28823,7 +30644,7 @@ var MaterialBatcher = class extends Batcher {
|
|
|
28823
30644
|
/**
|
|
28824
30645
|
* @ignore
|
|
28825
30646
|
*/
|
|
28826
|
-
uploadTexture(texture, w, h, force = false) {
|
|
30647
|
+
uploadTexture(texture, w, h, force = false, flush = true) {
|
|
28827
30648
|
const unit = this.renderer.cache.getUnit(texture);
|
|
28828
30649
|
const texture2D = this.boundTextures[unit];
|
|
28829
30650
|
if (typeof texture2D === "undefined" || force) {
|
|
@@ -28836,12 +30657,13 @@ var MaterialBatcher = class extends Batcher {
|
|
|
28836
30657
|
h,
|
|
28837
30658
|
texture.premultipliedAlpha,
|
|
28838
30659
|
void 0,
|
|
28839
|
-
texture2D
|
|
30660
|
+
texture2D,
|
|
30661
|
+
flush
|
|
28840
30662
|
);
|
|
28841
30663
|
} else {
|
|
28842
|
-
this.bindTexture2D(texture2D, unit);
|
|
30664
|
+
this.bindTexture2D(texture2D, unit, flush);
|
|
28843
30665
|
}
|
|
28844
|
-
return this.currentTextureUnit;
|
|
30666
|
+
return flush ? this.currentTextureUnit : unit;
|
|
28845
30667
|
}
|
|
28846
30668
|
};
|
|
28847
30669
|
|
|
@@ -29118,11 +30940,37 @@ var PrimitiveBatcher = class extends Batcher {
|
|
|
29118
30940
|
}
|
|
29119
30941
|
};
|
|
29120
30942
|
|
|
29121
|
-
// src/video/webgl/shaders/
|
|
29122
|
-
|
|
30943
|
+
// src/video/webgl/shaders/multitexture.js
|
|
30944
|
+
function buildMultiTextureFragment(maxTextures) {
|
|
30945
|
+
const count = Math.max(maxTextures, 1);
|
|
30946
|
+
const lines = [];
|
|
30947
|
+
for (let i = 0; i < count; i++) {
|
|
30948
|
+
lines.push("uniform sampler2D uSampler" + i + ";");
|
|
30949
|
+
}
|
|
30950
|
+
lines.push("varying vec4 vColor;");
|
|
30951
|
+
lines.push("varying vec2 vRegion;");
|
|
30952
|
+
lines.push("varying float vTextureId;");
|
|
30953
|
+
lines.push("");
|
|
30954
|
+
lines.push("void main(void) {");
|
|
30955
|
+
lines.push(" vec4 color;");
|
|
30956
|
+
for (let i = 0; i < count; i++) {
|
|
30957
|
+
if (i === 0) {
|
|
30958
|
+
lines.push(" if (vTextureId < 0.5) {");
|
|
30959
|
+
} else {
|
|
30960
|
+
lines.push(" } else if (vTextureId < " + (i + 0.5) + ") {");
|
|
30961
|
+
}
|
|
30962
|
+
lines.push(" color = texture2D(uSampler" + i + ", vRegion);");
|
|
30963
|
+
}
|
|
30964
|
+
lines.push(" } else {");
|
|
30965
|
+
lines.push(" color = texture2D(uSampler0, vRegion);");
|
|
30966
|
+
lines.push(" }");
|
|
30967
|
+
lines.push(" gl_FragColor = color * vColor;");
|
|
30968
|
+
lines.push("}");
|
|
30969
|
+
return lines.join("\n");
|
|
30970
|
+
}
|
|
29123
30971
|
|
|
29124
|
-
// src/video/webgl/shaders/quad.vert
|
|
29125
|
-
var
|
|
30972
|
+
// src/video/webgl/shaders/quad-multi.vert
|
|
30973
|
+
var quad_multi_default = "// Current vertex point\nattribute vec2 aVertex;\nattribute vec2 aRegion;\nattribute vec4 aColor;\nattribute float aTextureId;\n\n// Projection matrix\nuniform mat4 uProjectionMatrix;\n\nvarying vec2 vRegion;\nvarying vec4 vColor;\nvarying float vTextureId;\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 vTextureId = aTextureId;\n}\n";
|
|
29126
30974
|
|
|
29127
30975
|
// src/video/webgl/batchers/quad_batcher.js
|
|
29128
30976
|
var V_ARRAY = [
|
|
@@ -29137,6 +30985,7 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29137
30985
|
* @ignore
|
|
29138
30986
|
*/
|
|
29139
30987
|
init(renderer2) {
|
|
30988
|
+
this.maxBatchTextures = Math.min(renderer2.maxTextures, 16);
|
|
29140
30989
|
super.init(renderer2, {
|
|
29141
30990
|
attributes: [
|
|
29142
30991
|
{
|
|
@@ -29159,21 +31008,44 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29159
31008
|
type: renderer2.gl.UNSIGNED_BYTE,
|
|
29160
31009
|
normalized: true,
|
|
29161
31010
|
offset: 4 * Float32Array.BYTES_PER_ELEMENT
|
|
31011
|
+
},
|
|
31012
|
+
{
|
|
31013
|
+
name: "aTextureId",
|
|
31014
|
+
size: 1,
|
|
31015
|
+
type: renderer2.gl.FLOAT,
|
|
31016
|
+
normalized: false,
|
|
31017
|
+
offset: 5 * Float32Array.BYTES_PER_ELEMENT
|
|
29162
31018
|
}
|
|
29163
31019
|
],
|
|
29164
31020
|
shader: {
|
|
29165
|
-
vertex:
|
|
29166
|
-
fragment:
|
|
31021
|
+
vertex: quad_multi_default,
|
|
31022
|
+
fragment: buildMultiTextureFragment(this.maxBatchTextures)
|
|
29167
31023
|
}
|
|
29168
31024
|
});
|
|
31025
|
+
for (let i = 0; i < this.maxBatchTextures; i++) {
|
|
31026
|
+
this.defaultShader.setUniform("uSampler" + i, i);
|
|
31027
|
+
}
|
|
31028
|
+
this.useMultiTexture = true;
|
|
29169
31029
|
const maxQuads = this.vertexData.maxVertex / 4;
|
|
29170
|
-
this.indexBuffer = new
|
|
31030
|
+
this.indexBuffer = new WebGLIndexBuffer(
|
|
29171
31031
|
this.gl,
|
|
29172
31032
|
maxQuads * 6,
|
|
29173
31033
|
this.renderer.WebGLVersion > 1
|
|
29174
31034
|
);
|
|
29175
31035
|
this.indexBuffer.fillQuadPattern(maxQuads);
|
|
29176
31036
|
}
|
|
31037
|
+
/**
|
|
31038
|
+
* Select the shader to use for compositing.
|
|
31039
|
+
* Multi-texture batching is automatically enabled when the default
|
|
31040
|
+
* shader is active, and disabled for custom ShaderEffect shaders.
|
|
31041
|
+
* @see GLShader
|
|
31042
|
+
* @see ShaderEffect
|
|
31043
|
+
* @param {GLShader|ShaderEffect} shader - a reference to a GLShader or ShaderEffect instance
|
|
31044
|
+
*/
|
|
31045
|
+
useShader(shader) {
|
|
31046
|
+
super.useShader(shader);
|
|
31047
|
+
this.useMultiTexture = shader === this.defaultShader;
|
|
31048
|
+
}
|
|
29177
31049
|
/**
|
|
29178
31050
|
* Reset compositor internal state
|
|
29179
31051
|
* @ignore
|
|
@@ -29181,12 +31053,16 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29181
31053
|
reset() {
|
|
29182
31054
|
super.reset();
|
|
29183
31055
|
const maxQuads = this.vertexData.maxVertex / 4;
|
|
29184
|
-
this.indexBuffer = new
|
|
31056
|
+
this.indexBuffer = new WebGLIndexBuffer(
|
|
29185
31057
|
this.gl,
|
|
29186
31058
|
maxQuads * 6,
|
|
29187
31059
|
this.renderer.WebGLVersion > 1
|
|
29188
31060
|
);
|
|
29189
31061
|
this.indexBuffer.fillQuadPattern(maxQuads);
|
|
31062
|
+
for (let i = 0; i < this.maxBatchTextures; i++) {
|
|
31063
|
+
this.defaultShader.setUniform("uSampler" + i, i);
|
|
31064
|
+
}
|
|
31065
|
+
this.useMultiTexture = true;
|
|
29190
31066
|
}
|
|
29191
31067
|
/**
|
|
29192
31068
|
* Flush batched texture data to the GPU using indexed drawing.
|
|
@@ -29219,6 +31095,34 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29219
31095
|
vertex.clear();
|
|
29220
31096
|
}
|
|
29221
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
|
+
}
|
|
29222
31126
|
/**
|
|
29223
31127
|
* Add a textured quad
|
|
29224
31128
|
* @param {TextureAtlas} texture - Source texture atlas
|
|
@@ -29238,10 +31142,20 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29238
31142
|
if (vertexData.isFull(4)) {
|
|
29239
31143
|
this.flush();
|
|
29240
31144
|
}
|
|
29241
|
-
|
|
29242
|
-
if (
|
|
29243
|
-
this.
|
|
29244
|
-
this.
|
|
31145
|
+
let unit;
|
|
31146
|
+
if (this.useMultiTexture) {
|
|
31147
|
+
unit = this.uploadTexture(texture, w, h, reupload, false);
|
|
31148
|
+
if (unit >= this.maxBatchTextures) {
|
|
31149
|
+
this.flush();
|
|
31150
|
+
this.renderer.cache.resetUnitAssignments();
|
|
31151
|
+
unit = this.uploadTexture(texture, w, h, reupload, false);
|
|
31152
|
+
}
|
|
31153
|
+
} else {
|
|
31154
|
+
unit = this.uploadTexture(texture, w, h, reupload);
|
|
31155
|
+
if (unit !== this.currentSamplerUnit) {
|
|
31156
|
+
this.currentShader.setUniform("uSampler", unit);
|
|
31157
|
+
this.currentSamplerUnit = unit;
|
|
31158
|
+
}
|
|
29245
31159
|
}
|
|
29246
31160
|
const m = this.viewMatrix;
|
|
29247
31161
|
const vec0 = V_ARRAY[0].set(x, y);
|
|
@@ -29254,15 +31168,18 @@ var QuadBatcher = class extends MaterialBatcher {
|
|
|
29254
31168
|
m.apply(vec2);
|
|
29255
31169
|
m.apply(vec3);
|
|
29256
31170
|
}
|
|
29257
|
-
|
|
29258
|
-
vertexData.push(
|
|
29259
|
-
vertexData.push(
|
|
29260
|
-
vertexData.push(
|
|
31171
|
+
const textureId = this.useMultiTexture ? unit : 0;
|
|
31172
|
+
vertexData.push(vec0.x, vec0.y, u0, v0, tint, textureId);
|
|
31173
|
+
vertexData.push(vec1.x, vec1.y, u1, v0, tint, textureId);
|
|
31174
|
+
vertexData.push(vec2.x, vec2.y, u0, v1, tint, textureId);
|
|
31175
|
+
vertexData.push(vec3.x, vec3.y, u1, v1, tint, textureId);
|
|
29261
31176
|
}
|
|
29262
31177
|
};
|
|
29263
31178
|
|
|
29264
31179
|
// src/video/webgl/webgl_renderer.js
|
|
29265
31180
|
var _tempMatrix = new Matrix3d();
|
|
31181
|
+
var _savedTransform = new Matrix3d();
|
|
31182
|
+
var _savedProjection = new Matrix3d();
|
|
29266
31183
|
var supportedCompressedTextureFormats;
|
|
29267
31184
|
var WebGLRenderer = class extends Renderer {
|
|
29268
31185
|
/**
|
|
@@ -29273,10 +31190,18 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29273
31190
|
this.GPUVendor = void 0;
|
|
29274
31191
|
this.GPURenderer = void 0;
|
|
29275
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();
|
|
29276
31197
|
this.lineWidth = 1;
|
|
29277
31198
|
this.lineJoin = "round";
|
|
29278
31199
|
this.vertexBuffer = this.gl.createBuffer();
|
|
29279
31200
|
this.maxTextures = this.gl.getParameter(this.gl.MAX_TEXTURE_IMAGE_UNITS);
|
|
31201
|
+
this.shaderPrecision = getMaxShaderPrecision(
|
|
31202
|
+
this.gl,
|
|
31203
|
+
this.settings.highPrecisionShader !== false
|
|
31204
|
+
);
|
|
29280
31205
|
this._rectTriangles = Array.from({ length: 6 }, () => {
|
|
29281
31206
|
return { x: 0, y: 0 };
|
|
29282
31207
|
});
|
|
@@ -29294,6 +31219,7 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29294
31219
|
this.gl.disable(this.gl.DEPTH_TEST);
|
|
29295
31220
|
this.gl.depthMask(false);
|
|
29296
31221
|
this.gl.disable(this.gl.SCISSOR_TEST);
|
|
31222
|
+
this._scissorActive = false;
|
|
29297
31223
|
this.gl.enable(this.gl.BLEND);
|
|
29298
31224
|
this.setBlendMode(this.settings.blendMode);
|
|
29299
31225
|
const debugInfo = this.gl.getExtension("WEBGL_debug_renderer_info");
|
|
@@ -29346,6 +31272,9 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29346
31272
|
getSupportedCompressedTextureFormats() {
|
|
29347
31273
|
if (typeof supportedCompressedTextureFormats === "undefined") {
|
|
29348
31274
|
const gl = this.gl;
|
|
31275
|
+
if (typeof gl === "undefined" || gl === null) {
|
|
31276
|
+
return super.getSupportedCompressedTextureFormats();
|
|
31277
|
+
}
|
|
29349
31278
|
supportedCompressedTextureFormats = {
|
|
29350
31279
|
astc: gl.getExtension("WEBGL_compressed_texture_astc") || this._gl.getExtension("WEBKIT_WEBGL_compressed_texture_astc"),
|
|
29351
31280
|
bptc: gl.getExtension("EXT_texture_compression_bptc") || this._gl.getExtension("WEBKIT_EXT_texture_compression_bptc"),
|
|
@@ -29401,6 +31330,8 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29401
31330
|
});
|
|
29402
31331
|
this.setBatcher("quad");
|
|
29403
31332
|
this.gl.disable(this.gl.SCISSOR_TEST);
|
|
31333
|
+
this._scissorActive = false;
|
|
31334
|
+
this._renderTargetPool.destroy();
|
|
29404
31335
|
}
|
|
29405
31336
|
/**
|
|
29406
31337
|
* add a new batcher to this renderer
|
|
@@ -29487,6 +31418,148 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29487
31418
|
flush() {
|
|
29488
31419
|
this.currentBatcher.flush();
|
|
29489
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
|
+
}
|
|
29490
31563
|
/**
|
|
29491
31564
|
* set/change the current projection matrix (WebGL only)
|
|
29492
31565
|
* @param {Matrix3d} matrix - the new projection matrix
|
|
@@ -29506,6 +31579,61 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29506
31579
|
setViewport(x = 0, y = 0, w = this.getCanvas().width, h = this.getCanvas().height) {
|
|
29507
31580
|
this.gl.viewport(x, y, w, h);
|
|
29508
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
|
+
}
|
|
29509
31637
|
/**
|
|
29510
31638
|
* Clear the frame buffer
|
|
29511
31639
|
*/
|
|
@@ -29920,6 +32048,7 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29920
32048
|
const gl = this.gl;
|
|
29921
32049
|
const s = this.currentScissor;
|
|
29922
32050
|
gl.enable(gl.SCISSOR_TEST);
|
|
32051
|
+
this._scissorActive = true;
|
|
29923
32052
|
gl.scissor(
|
|
29924
32053
|
s[0] + this.currentTransform.tx,
|
|
29925
32054
|
canvas.height - s[3] - s[1] - this.currentTransform.ty,
|
|
@@ -29928,9 +32057,11 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29928
32057
|
);
|
|
29929
32058
|
} else {
|
|
29930
32059
|
this.gl.disable(this.gl.SCISSOR_TEST);
|
|
32060
|
+
this._scissorActive = false;
|
|
29931
32061
|
}
|
|
29932
32062
|
}
|
|
29933
32063
|
this._currentGradient = this.renderState.currentGradient;
|
|
32064
|
+
this.customShader = this.renderState.currentShader;
|
|
29934
32065
|
}
|
|
29935
32066
|
/**
|
|
29936
32067
|
* saves the entire state of the renderer by pushing the current state onto a stack.
|
|
@@ -29946,7 +32077,8 @@ var WebGLRenderer = class extends Renderer {
|
|
|
29946
32077
|
* renderer.restore();
|
|
29947
32078
|
*/
|
|
29948
32079
|
save() {
|
|
29949
|
-
this.renderState.
|
|
32080
|
+
this.renderState.currentShader = this.customShader;
|
|
32081
|
+
this.renderState.save(this._scissorActive === true);
|
|
29950
32082
|
}
|
|
29951
32083
|
/**
|
|
29952
32084
|
* adds a rotation to the transformation matrix.
|
|
@@ -30596,13 +32728,14 @@ var WebGLRenderer = class extends Renderer {
|
|
|
30596
32728
|
const gl = this.gl;
|
|
30597
32729
|
if (x !== 0 || y !== 0 || width !== canvas.width || height !== canvas.height) {
|
|
30598
32730
|
const currentScissor = this.currentScissor;
|
|
30599
|
-
if (
|
|
32731
|
+
if (this._scissorActive) {
|
|
30600
32732
|
if (currentScissor[0] === x && currentScissor[1] === y && currentScissor[2] === width && currentScissor[3] === height) {
|
|
30601
32733
|
return;
|
|
30602
32734
|
}
|
|
30603
32735
|
}
|
|
30604
32736
|
this.flush();
|
|
30605
32737
|
gl.enable(this.gl.SCISSOR_TEST);
|
|
32738
|
+
this._scissorActive = true;
|
|
30606
32739
|
gl.scissor(
|
|
30607
32740
|
// scissor does not account for currentTransform, so manually adjust
|
|
30608
32741
|
x + this.currentTransform.tx,
|
|
@@ -30616,6 +32749,7 @@ var WebGLRenderer = class extends Renderer {
|
|
|
30616
32749
|
currentScissor[3] = height;
|
|
30617
32750
|
} else {
|
|
30618
32751
|
gl.disable(gl.SCISSOR_TEST);
|
|
32752
|
+
this._scissorActive = false;
|
|
30619
32753
|
}
|
|
30620
32754
|
}
|
|
30621
32755
|
/**
|
|
@@ -31107,6 +33241,45 @@ var Application = class {
|
|
|
31107
33241
|
repaint() {
|
|
31108
33242
|
this.isDirty = true;
|
|
31109
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
|
+
}
|
|
31110
33283
|
/** @ignore */
|
|
31111
33284
|
_tick(time) {
|
|
31112
33285
|
this.update(time);
|
|
@@ -31179,197 +33352,42 @@ function setDefaultGame(app) {
|
|
|
31179
33352
|
game = app;
|
|
31180
33353
|
}
|
|
31181
33354
|
|
|
31182
|
-
// src/particles/settings.
|
|
31183
|
-
var
|
|
31184
|
-
/**
|
|
31185
|
-
* Width of the particle spawn area.
|
|
31186
|
-
* @type {number}
|
|
31187
|
-
* @default 1
|
|
31188
|
-
*/
|
|
33355
|
+
// src/particles/settings.ts
|
|
33356
|
+
var defaultParticleEmitterSettings = {
|
|
31189
33357
|
width: 1,
|
|
31190
|
-
/**
|
|
31191
|
-
* Height of the particle spawn area
|
|
31192
|
-
* @type {number}
|
|
31193
|
-
* @default 1
|
|
31194
|
-
*/
|
|
31195
33358
|
height: 1,
|
|
31196
|
-
/**
|
|
31197
|
-
* image used for particles texture
|
|
31198
|
-
* (by default melonJS will create a white 8x8 texture image)
|
|
31199
|
-
* @type {HTMLCanvasElement}
|
|
31200
|
-
* @default undefined
|
|
31201
|
-
* @see {@link textureSize}
|
|
31202
|
-
*/
|
|
31203
33359
|
image: void 0,
|
|
31204
|
-
/**
|
|
31205
|
-
* default texture size used for particles if no image is specified
|
|
31206
|
-
* (by default melonJS will create a white 8x8 texture image)
|
|
31207
|
-
* @type {number}
|
|
31208
|
-
* @default 8
|
|
31209
|
-
* @see {@link image}
|
|
31210
|
-
*/
|
|
31211
33360
|
textureSize: 8,
|
|
31212
|
-
/**
|
|
31213
|
-
* tint to be applied to particles
|
|
31214
|
-
* @type {string}
|
|
31215
|
-
* @default "#fff"
|
|
31216
|
-
*/
|
|
31217
33361
|
tint: "#fff",
|
|
31218
|
-
/**
|
|
31219
|
-
* Total number of particles in the emitter
|
|
31220
|
-
* @type {number}
|
|
31221
|
-
* @default 50
|
|
31222
|
-
*/
|
|
31223
33362
|
totalParticles: 50,
|
|
31224
|
-
/**
|
|
31225
|
-
* Start angle for particle launch in Radians
|
|
31226
|
-
* @type {number}
|
|
31227
|
-
* @default Math.PI / 2
|
|
31228
|
-
*/
|
|
31229
33363
|
angle: Math.PI / 2,
|
|
31230
|
-
/**
|
|
31231
|
-
* letiation in the start angle for particle launch in Radians.
|
|
31232
|
-
* @type {number}
|
|
31233
|
-
* @default 0
|
|
31234
|
-
*/
|
|
31235
33364
|
angleVariation: 0,
|
|
31236
|
-
/**
|
|
31237
|
-
* Minimum time each particle lives once it is emitted in ms.
|
|
31238
|
-
* @type {number}
|
|
31239
|
-
* @default 1000
|
|
31240
|
-
*/
|
|
31241
33365
|
minLife: 1e3,
|
|
31242
|
-
/**
|
|
31243
|
-
* Maximum time each particle lives once it is emitted in ms.
|
|
31244
|
-
* @type {number}
|
|
31245
|
-
* @default 3000
|
|
31246
|
-
*/
|
|
31247
33366
|
maxLife: 3e3,
|
|
31248
|
-
/**
|
|
31249
|
-
* Start speed of particles.<br>
|
|
31250
|
-
* @type {number}
|
|
31251
|
-
* @default 2
|
|
31252
|
-
*/
|
|
31253
33367
|
speed: 2,
|
|
31254
|
-
/**
|
|
31255
|
-
* letiation in the start speed of particles
|
|
31256
|
-
* @type {number}
|
|
31257
|
-
* @default 1
|
|
31258
|
-
*/
|
|
31259
33368
|
speedVariation: 1,
|
|
31260
|
-
/**
|
|
31261
|
-
* Minimum start rotation for particles sprites in Radians
|
|
31262
|
-
* @type {number}
|
|
31263
|
-
* @default 0
|
|
31264
|
-
*/
|
|
31265
33369
|
minRotation: 0,
|
|
31266
|
-
/**
|
|
31267
|
-
* Maximum start rotation for particles sprites in Radians
|
|
31268
|
-
* @type {number}
|
|
31269
|
-
* @default 0
|
|
31270
|
-
*/
|
|
31271
33370
|
maxRotation: 0,
|
|
31272
|
-
/**
|
|
31273
|
-
* Minimum start scale ratio for particles (1 = no scaling)
|
|
31274
|
-
* @type {number}
|
|
31275
|
-
* @default 1
|
|
31276
|
-
*/
|
|
31277
33371
|
minStartScale: 1,
|
|
31278
|
-
/**
|
|
31279
|
-
* Maximum start scale ratio for particles (1 = no scaling)
|
|
31280
|
-
* @type {number}
|
|
31281
|
-
* @default 1
|
|
31282
|
-
*/
|
|
31283
33372
|
maxStartScale: 1,
|
|
31284
|
-
/**
|
|
31285
|
-
* Minimum end scale ratio for particles
|
|
31286
|
-
* @type {number}
|
|
31287
|
-
* @default 0
|
|
31288
|
-
*/
|
|
31289
33373
|
minEndScale: 0,
|
|
31290
|
-
/**
|
|
31291
|
-
* Maximum end scale ratio for particles
|
|
31292
|
-
* @type {number}
|
|
31293
|
-
* @default 0
|
|
31294
|
-
*/
|
|
31295
33374
|
maxEndScale: 0,
|
|
31296
|
-
/**
|
|
31297
|
-
* Vertical force (Gravity) for each particle
|
|
31298
|
-
* @type {number}
|
|
31299
|
-
* @default 0
|
|
31300
|
-
* @see {@link World.gravity}
|
|
31301
|
-
*/
|
|
31302
33375
|
gravity: 0,
|
|
31303
|
-
/**
|
|
31304
|
-
* Horizontal force (like a Wind) for each particle
|
|
31305
|
-
* @type {number}
|
|
31306
|
-
* @default 0
|
|
31307
|
-
*/
|
|
31308
33376
|
wind: 0,
|
|
31309
|
-
/**
|
|
31310
|
-
* Update the rotation of particle in accordance the particle trajectory.<br>
|
|
31311
|
-
* The particle sprite should aim at zero angle (draw from left to right).<br>
|
|
31312
|
-
* Override the particle minRotation and maxRotation.<br>
|
|
31313
|
-
* @type {boolean}
|
|
31314
|
-
* @default false
|
|
31315
|
-
*/
|
|
31316
33377
|
followTrajectory: false,
|
|
31317
|
-
/**
|
|
31318
|
-
* Enable the Texture Additive by composite operation ("additive" blendMode)
|
|
31319
|
-
* @type {boolean}
|
|
31320
|
-
* @default false
|
|
31321
|
-
* @see {@link blendMode}
|
|
31322
|
-
*/
|
|
31323
33378
|
textureAdditive: false,
|
|
31324
|
-
/**
|
|
31325
|
-
* the blend mode to be applied when rendering particles.
|
|
31326
|
-
* (note: this will superseed the `textureAdditive` setting if different than "normal")
|
|
31327
|
-
* @type {string}
|
|
31328
|
-
* @default normal
|
|
31329
|
-
* @see {@link CanvasRenderer#setBlendMode}
|
|
31330
|
-
* @see {@link WebGLRenderer#setBlendMode}
|
|
31331
|
-
*/
|
|
31332
33379
|
blendMode: "normal",
|
|
31333
|
-
/**
|
|
31334
|
-
* Update particles only in the viewport, remove it when out of viewport.
|
|
31335
|
-
* @type {boolean}
|
|
31336
|
-
* @default true
|
|
31337
|
-
*/
|
|
31338
33380
|
onlyInViewport: true,
|
|
31339
|
-
/**
|
|
31340
|
-
* Render particles in screen space.
|
|
31341
|
-
* @type {boolean}
|
|
31342
|
-
* @default false
|
|
31343
|
-
*/
|
|
31344
33381
|
floating: false,
|
|
31345
|
-
/**
|
|
31346
|
-
* Maximum number of particles launched each time in this emitter (used only if emitter is Stream).
|
|
31347
|
-
* @type {number}
|
|
31348
|
-
* @default 10
|
|
31349
|
-
*/
|
|
31350
33382
|
maxParticles: 10,
|
|
31351
|
-
/**
|
|
31352
|
-
* How often a particle is emitted in ms (used only if emitter is a Stream).
|
|
31353
|
-
* @type {number}
|
|
31354
|
-
* @default 100
|
|
31355
|
-
*/
|
|
31356
33383
|
frequency: 100,
|
|
31357
|
-
/**
|
|
31358
|
-
* Duration that the emitter releases particles in ms (used only if emitter is Stream).
|
|
31359
|
-
* After this period, the emitter stop the launch of particles.
|
|
31360
|
-
* @type {number}
|
|
31361
|
-
* @default Infinity
|
|
31362
|
-
*/
|
|
31363
33384
|
duration: Infinity,
|
|
31364
|
-
|
|
31365
|
-
|
|
31366
|
-
|
|
31367
|
-
|
|
31368
|
-
* @default 0
|
|
31369
|
-
*/
|
|
31370
|
-
framesToSkip: 0
|
|
33385
|
+
framesToSkip: 0,
|
|
33386
|
+
accurateBounds: false,
|
|
33387
|
+
autoDestroyOnComplete: false,
|
|
33388
|
+
onComplete: void 0
|
|
31371
33389
|
};
|
|
31372
|
-
var settings_default =
|
|
33390
|
+
var settings_default = defaultParticleEmitterSettings;
|
|
31373
33391
|
|
|
31374
33392
|
// src/particles/emitter.ts
|
|
31375
33393
|
function createDefaultParticleTexture(w = 8, h = 8) {
|
|
@@ -31380,9 +33398,14 @@ function createDefaultParticleTexture(w = 8, h = 8) {
|
|
|
31380
33398
|
defaultParticleTexture.context.fillRect(0, 0, w, h);
|
|
31381
33399
|
return defaultParticleTexture;
|
|
31382
33400
|
}
|
|
33401
|
+
function clampMinToMax(settings, minKey, maxKey) {
|
|
33402
|
+
if (settings[minKey] > settings[maxKey]) {
|
|
33403
|
+
settings[minKey] = settings[maxKey];
|
|
33404
|
+
}
|
|
33405
|
+
}
|
|
31383
33406
|
var ParticleEmitter = class extends Container {
|
|
31384
33407
|
/**
|
|
31385
|
-
* the current (active) emitter settings
|
|
33408
|
+
* the current (active) emitter settings (with defaults merged in)
|
|
31386
33409
|
*/
|
|
31387
33410
|
settings;
|
|
31388
33411
|
/** @ignore */
|
|
@@ -31399,6 +33422,19 @@ var ParticleEmitter = class extends Container {
|
|
|
31399
33422
|
_dt;
|
|
31400
33423
|
/** @ignore */
|
|
31401
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;
|
|
31402
33438
|
/**
|
|
31403
33439
|
* @param x - x position of the particle emitter
|
|
31404
33440
|
* @param y - y position of the particle emitter
|
|
@@ -31430,8 +33466,8 @@ var ParticleEmitter = class extends Container {
|
|
|
31430
33466
|
* app.world.removeChild(emitter);
|
|
31431
33467
|
*/
|
|
31432
33468
|
constructor(x, y, settings = {}) {
|
|
31433
|
-
super(x, y, settings.width
|
|
31434
|
-
this.settings = {};
|
|
33469
|
+
super(x, y, settings.width ?? 1, settings.height ?? 1);
|
|
33470
|
+
this.settings = { ...settings_default };
|
|
31435
33471
|
this.centerOn(x, y);
|
|
31436
33472
|
this._stream = false;
|
|
31437
33473
|
this._frequencyTimer = 0;
|
|
@@ -31441,18 +33477,29 @@ var ParticleEmitter = class extends Container {
|
|
|
31441
33477
|
this.autoSort = false;
|
|
31442
33478
|
this._updateCount = 0;
|
|
31443
33479
|
this._dt = 0;
|
|
33480
|
+
this._hasSpawned = false;
|
|
33481
|
+
this._deltaInv = timer_default.maxfps / 1e3;
|
|
31444
33482
|
this.reset(settings);
|
|
31445
33483
|
}
|
|
31446
33484
|
/**
|
|
31447
33485
|
* Reset the emitter with particle emitter settings.
|
|
31448
|
-
* @param settings -
|
|
33486
|
+
* @param settings - object with emitter settings. See {@link ParticleEmitterSettings}
|
|
31449
33487
|
*/
|
|
31450
33488
|
reset(settings = {}) {
|
|
31451
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
|
+
}
|
|
31452
33499
|
if (typeof this.settings.image === "undefined") {
|
|
31453
33500
|
this._defaultParticle = createDefaultParticleTexture(
|
|
31454
|
-
settings.textureSize,
|
|
31455
|
-
settings.textureSize
|
|
33501
|
+
this.settings.textureSize,
|
|
33502
|
+
this.settings.textureSize
|
|
31456
33503
|
);
|
|
31457
33504
|
this.settings.image = this._defaultParticle.canvas;
|
|
31458
33505
|
}
|
|
@@ -31476,8 +33523,12 @@ var ParticleEmitter = class extends Container {
|
|
|
31476
33523
|
// Add count particles in the game world
|
|
31477
33524
|
/** @ignore */
|
|
31478
33525
|
addParticles(count) {
|
|
33526
|
+
const z = this.pos.z;
|
|
31479
33527
|
for (let i = 0; i < count; i++) {
|
|
31480
|
-
this.addChild(particlePool.get(this),
|
|
33528
|
+
this.addChild(particlePool.get(this), z);
|
|
33529
|
+
}
|
|
33530
|
+
if (count > 0) {
|
|
33531
|
+
this._hasSpawned = true;
|
|
31481
33532
|
}
|
|
31482
33533
|
this.isDirty = true;
|
|
31483
33534
|
}
|
|
@@ -31520,15 +33571,17 @@ var ParticleEmitter = class extends Container {
|
|
|
31520
33571
|
* @ignore
|
|
31521
33572
|
*/
|
|
31522
33573
|
update(dt) {
|
|
31523
|
-
if (
|
|
31524
|
-
this._updateCount
|
|
31525
|
-
|
|
31526
|
-
|
|
31527
|
-
this.
|
|
31528
|
-
|
|
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;
|
|
31529
33584
|
}
|
|
31530
|
-
dt += this._dt;
|
|
31531
|
-
this._dt = 0;
|
|
31532
33585
|
this.isDirty = this.isDirty || super.update(dt);
|
|
31533
33586
|
if (this._enabled && this._stream) {
|
|
31534
33587
|
if (this._durationTimer !== Infinity) {
|
|
@@ -31539,17 +33592,27 @@ var ParticleEmitter = class extends Container {
|
|
|
31539
33592
|
}
|
|
31540
33593
|
}
|
|
31541
33594
|
this._frequencyTimer += dt;
|
|
31542
|
-
const particlesCount = this.
|
|
33595
|
+
const particlesCount = this.getChildren().length;
|
|
31543
33596
|
if (particlesCount < this.settings.totalParticles && this._frequencyTimer >= this.settings.frequency) {
|
|
31544
|
-
|
|
31545
|
-
|
|
31546
|
-
|
|
31547
|
-
|
|
31548
|
-
|
|
33597
|
+
this.addParticles(
|
|
33598
|
+
Math.min(
|
|
33599
|
+
this.settings.maxParticles,
|
|
33600
|
+
this.settings.totalParticles - particlesCount
|
|
33601
|
+
)
|
|
33602
|
+
);
|
|
31549
33603
|
this._frequencyTimer = 0;
|
|
31550
33604
|
this.isDirty = true;
|
|
31551
33605
|
}
|
|
31552
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
|
+
}
|
|
31553
33616
|
return this.isDirty;
|
|
31554
33617
|
}
|
|
31555
33618
|
/**
|
|
@@ -32957,98 +35020,6 @@ var UITextButton = class extends UIBaseElement {
|
|
|
32957
35020
|
}
|
|
32958
35021
|
};
|
|
32959
35022
|
|
|
32960
|
-
// src/video/webgl/shadereffect.js
|
|
32961
|
-
var ShaderEffect = class {
|
|
32962
|
-
/**
|
|
32963
|
-
* whether this effect is active (false in Canvas mode)
|
|
32964
|
-
* @type {boolean}
|
|
32965
|
-
*/
|
|
32966
|
-
enabled = false;
|
|
32967
|
-
/**
|
|
32968
|
-
* @param {WebGLRenderer|CanvasRenderer} renderer - the current renderer instance
|
|
32969
|
-
* @param {string} fragmentBody - GLSL code containing a `vec4 apply(vec4 color, vec2 uv)` function
|
|
32970
|
-
* that receives the sampled pixel color and UV coordinates, and returns the modified color.
|
|
32971
|
-
* You can declare additional `uniform` variables before the `apply()` function.
|
|
32972
|
-
* @param {string} [precision=auto detected] - float precision ('lowp', 'mediump' or 'highp')
|
|
32973
|
-
*/
|
|
32974
|
-
constructor(renderer2, fragmentBody, precision) {
|
|
32975
|
-
if (typeof renderer2.gl === "undefined") {
|
|
32976
|
-
console.warn(
|
|
32977
|
-
"ShaderEffect requires WebGL and is disabled in Canvas mode"
|
|
32978
|
-
);
|
|
32979
|
-
return;
|
|
32980
|
-
}
|
|
32981
|
-
const fragment = [
|
|
32982
|
-
"uniform sampler2D uSampler;",
|
|
32983
|
-
"varying vec4 vColor;",
|
|
32984
|
-
"varying vec2 vRegion;",
|
|
32985
|
-
// user-provided fragment body (uniforms + apply function)
|
|
32986
|
-
fragmentBody,
|
|
32987
|
-
"void main(void) {",
|
|
32988
|
-
" vec4 texColor = texture2D(uSampler, vRegion) * vColor;",
|
|
32989
|
-
" gl_FragColor = apply(texColor, vRegion);",
|
|
32990
|
-
"}"
|
|
32991
|
-
].join("\n");
|
|
32992
|
-
this._shader = new GLShader(renderer2.gl, quad_default2, fragment, precision);
|
|
32993
|
-
this.enabled = true;
|
|
32994
|
-
}
|
|
32995
|
-
/**
|
|
32996
|
-
* Set the uniform to the given value
|
|
32997
|
-
* @param {string} name - the uniform name
|
|
32998
|
-
* @param {object|Float32Array} value - the value to assign to that uniform
|
|
32999
|
-
*/
|
|
33000
|
-
setUniform(name, value) {
|
|
33001
|
-
if (this.enabled) {
|
|
33002
|
-
this._shader.setUniform(name, value);
|
|
33003
|
-
}
|
|
33004
|
-
}
|
|
33005
|
-
/** @ignore */
|
|
33006
|
-
bind() {
|
|
33007
|
-
if (this.enabled) {
|
|
33008
|
-
this._shader.bind();
|
|
33009
|
-
}
|
|
33010
|
-
}
|
|
33011
|
-
/** @ignore */
|
|
33012
|
-
getAttribLocation(name) {
|
|
33013
|
-
return this.enabled ? this._shader.getAttribLocation(name) : -1;
|
|
33014
|
-
}
|
|
33015
|
-
/** @ignore */
|
|
33016
|
-
setVertexAttributes(gl, attributes, stride) {
|
|
33017
|
-
if (this.enabled) {
|
|
33018
|
-
this._shader.setVertexAttributes(gl, attributes, stride);
|
|
33019
|
-
}
|
|
33020
|
-
}
|
|
33021
|
-
/** @ignore */
|
|
33022
|
-
get program() {
|
|
33023
|
-
return this.enabled ? this._shader.program : null;
|
|
33024
|
-
}
|
|
33025
|
-
/** @ignore */
|
|
33026
|
-
get vertex() {
|
|
33027
|
-
return this.enabled ? this._shader.vertex : null;
|
|
33028
|
-
}
|
|
33029
|
-
/** @ignore */
|
|
33030
|
-
get fragment() {
|
|
33031
|
-
return this.enabled ? this._shader.fragment : null;
|
|
33032
|
-
}
|
|
33033
|
-
/** @ignore */
|
|
33034
|
-
get attributes() {
|
|
33035
|
-
return this.enabled ? this._shader.attributes : {};
|
|
33036
|
-
}
|
|
33037
|
-
/** @ignore */
|
|
33038
|
-
get uniforms() {
|
|
33039
|
-
return this.enabled ? this._shader.uniforms : {};
|
|
33040
|
-
}
|
|
33041
|
-
/**
|
|
33042
|
-
* destroy this shader effect
|
|
33043
|
-
*/
|
|
33044
|
-
destroy() {
|
|
33045
|
-
if (this.enabled) {
|
|
33046
|
-
this._shader.destroy();
|
|
33047
|
-
this.enabled = false;
|
|
33048
|
-
}
|
|
33049
|
-
}
|
|
33050
|
-
};
|
|
33051
|
-
|
|
33052
35023
|
// src/video/webgl/effects/blur.js
|
|
33053
35024
|
var BlurEffect = class extends ShaderEffect {
|
|
33054
35025
|
/**
|
|
@@ -33151,25 +35122,16 @@ var ChromaticAberrationEffect = class extends ShaderEffect {
|
|
|
33151
35122
|
};
|
|
33152
35123
|
|
|
33153
35124
|
// src/video/webgl/effects/desaturate.js
|
|
33154
|
-
var DesaturateEffect = class extends
|
|
35125
|
+
var DesaturateEffect = class extends ColorMatrixEffect {
|
|
33155
35126
|
/**
|
|
33156
35127
|
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
33157
35128
|
* @param {object} [options] - effect options
|
|
33158
35129
|
* @param {number} [options.intensity=1.0] - desaturation intensity (0.0 = full color, 1.0 = grayscale)
|
|
33159
35130
|
*/
|
|
33160
35131
|
constructor(renderer2, options = {}) {
|
|
33161
|
-
super(
|
|
33162
|
-
renderer2,
|
|
33163
|
-
`
|
|
33164
|
-
uniform float uDesatIntensity;
|
|
33165
|
-
vec4 apply(vec4 color, vec2 uv) {
|
|
33166
|
-
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
|
|
33167
|
-
return vec4(mix(color.rgb, vec3(gray), uDesatIntensity), color.a);
|
|
33168
|
-
}
|
|
33169
|
-
`
|
|
33170
|
-
);
|
|
35132
|
+
super(renderer2);
|
|
33171
35133
|
this.intensity = typeof options.intensity === "number" ? options.intensity : 1;
|
|
33172
|
-
this.
|
|
35134
|
+
this.saturate(1 - this.intensity);
|
|
33173
35135
|
}
|
|
33174
35136
|
/**
|
|
33175
35137
|
* set the desaturation intensity
|
|
@@ -33177,7 +35139,7 @@ var DesaturateEffect = class extends ShaderEffect {
|
|
|
33177
35139
|
*/
|
|
33178
35140
|
setIntensity(value) {
|
|
33179
35141
|
this.intensity = Math.max(0, Math.min(1, value));
|
|
33180
|
-
this.
|
|
35142
|
+
this.reset().saturate(1 - this.intensity);
|
|
33181
35143
|
}
|
|
33182
35144
|
};
|
|
33183
35145
|
|
|
@@ -33488,25 +35450,16 @@ var HologramEffect = class extends ShaderEffect {
|
|
|
33488
35450
|
};
|
|
33489
35451
|
|
|
33490
35452
|
// src/video/webgl/effects/invert.js
|
|
33491
|
-
var InvertEffect = class extends
|
|
35453
|
+
var InvertEffect = class extends ColorMatrixEffect {
|
|
33492
35454
|
/**
|
|
33493
35455
|
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
33494
35456
|
* @param {object} [options] - effect options
|
|
33495
35457
|
* @param {number} [options.intensity=1.0] - inversion intensity (0.0 = original, 1.0 = fully inverted)
|
|
33496
35458
|
*/
|
|
33497
35459
|
constructor(renderer2, options = {}) {
|
|
33498
|
-
super(
|
|
33499
|
-
renderer2,
|
|
33500
|
-
`
|
|
33501
|
-
uniform float uInvertIntensity;
|
|
33502
|
-
vec4 apply(vec4 color, vec2 uv) {
|
|
33503
|
-
vec3 inverted = vec3(color.a) - color.rgb;
|
|
33504
|
-
return vec4(mix(color.rgb, inverted, uInvertIntensity), color.a);
|
|
33505
|
-
}
|
|
33506
|
-
`
|
|
33507
|
-
);
|
|
35460
|
+
super(renderer2);
|
|
33508
35461
|
this.intensity = typeof options.intensity === "number" ? options.intensity : 1;
|
|
33509
|
-
this.
|
|
35462
|
+
this.invertColors(this.intensity);
|
|
33510
35463
|
}
|
|
33511
35464
|
/**
|
|
33512
35465
|
* set the inversion intensity
|
|
@@ -33514,7 +35467,7 @@ var InvertEffect = class extends ShaderEffect {
|
|
|
33514
35467
|
*/
|
|
33515
35468
|
setIntensity(value) {
|
|
33516
35469
|
this.intensity = Math.max(0, Math.min(1, value));
|
|
33517
|
-
this.
|
|
35470
|
+
this.reset().invertColors(this.intensity);
|
|
33518
35471
|
}
|
|
33519
35472
|
};
|
|
33520
35473
|
|
|
@@ -33704,28 +35657,16 @@ var ScanlineEffect = class extends ShaderEffect {
|
|
|
33704
35657
|
};
|
|
33705
35658
|
|
|
33706
35659
|
// src/video/webgl/effects/sepia.js
|
|
33707
|
-
var SepiaEffect = class extends
|
|
35660
|
+
var SepiaEffect = class extends ColorMatrixEffect {
|
|
33708
35661
|
/**
|
|
33709
35662
|
* @param {import("../webgl_renderer.js").default} renderer - the current renderer instance
|
|
33710
35663
|
* @param {object} [options] - effect options
|
|
33711
35664
|
* @param {number} [options.intensity=1.0] - sepia intensity (0.0 = original, 1.0 = full sepia)
|
|
33712
35665
|
*/
|
|
33713
35666
|
constructor(renderer2, options = {}) {
|
|
33714
|
-
super(
|
|
33715
|
-
renderer2,
|
|
33716
|
-
`
|
|
33717
|
-
uniform float uSepiaIntensity;
|
|
33718
|
-
vec4 apply(vec4 color, vec2 uv) {
|
|
33719
|
-
vec3 sepia;
|
|
33720
|
-
sepia.r = dot(color.rgb, vec3(0.393, 0.769, 0.189));
|
|
33721
|
-
sepia.g = dot(color.rgb, vec3(0.349, 0.686, 0.168));
|
|
33722
|
-
sepia.b = dot(color.rgb, vec3(0.272, 0.534, 0.131));
|
|
33723
|
-
return vec4(mix(color.rgb, sepia, uSepiaIntensity), color.a);
|
|
33724
|
-
}
|
|
33725
|
-
`
|
|
33726
|
-
);
|
|
35667
|
+
super(renderer2);
|
|
33727
35668
|
this.intensity = typeof options.intensity === "number" ? options.intensity : 1;
|
|
33728
|
-
this.
|
|
35669
|
+
this.sepia(this.intensity);
|
|
33729
35670
|
}
|
|
33730
35671
|
/**
|
|
33731
35672
|
* set the sepia intensity
|
|
@@ -33733,7 +35674,7 @@ var SepiaEffect = class extends ShaderEffect {
|
|
|
33733
35674
|
*/
|
|
33734
35675
|
setIntensity(value) {
|
|
33735
35676
|
this.intensity = Math.max(0, Math.min(1, value));
|
|
33736
|
-
this.
|
|
35677
|
+
this.reset().sepia(this.intensity);
|
|
33737
35678
|
}
|
|
33738
35679
|
};
|
|
33739
35680
|
|
|
@@ -33782,6 +35723,50 @@ var TintPulseEffect = class extends ShaderEffect {
|
|
|
33782
35723
|
}
|
|
33783
35724
|
};
|
|
33784
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
|
+
|
|
33785
35770
|
// src/video/webgl/effects/wave.js
|
|
33786
35771
|
var WaveEffect = class extends ShaderEffect {
|
|
33787
35772
|
/**
|
|
@@ -34366,6 +36351,7 @@ export {
|
|
|
34366
36351
|
Bounds,
|
|
34367
36352
|
CANVAS,
|
|
34368
36353
|
Camera2d,
|
|
36354
|
+
CameraEffect,
|
|
34369
36355
|
canvasrendertarget_default as CanvasRenderTarget,
|
|
34370
36356
|
CanvasRenderer,
|
|
34371
36357
|
CanvasTexture,
|
|
@@ -34373,6 +36359,8 @@ export {
|
|
|
34373
36359
|
Collectable,
|
|
34374
36360
|
Color,
|
|
34375
36361
|
ColorLayer,
|
|
36362
|
+
ColorMatrix,
|
|
36363
|
+
ColorMatrixEffect,
|
|
34376
36364
|
Compositor,
|
|
34377
36365
|
Container,
|
|
34378
36366
|
DesaturateEffect,
|
|
@@ -34382,6 +36370,7 @@ export {
|
|
|
34382
36370
|
DropTarget,
|
|
34383
36371
|
Ellipse,
|
|
34384
36372
|
Entity,
|
|
36373
|
+
FadeEffect,
|
|
34385
36374
|
FlashEffect,
|
|
34386
36375
|
GLShader,
|
|
34387
36376
|
GlowEffect,
|
|
@@ -34391,6 +36380,7 @@ export {
|
|
|
34391
36380
|
InvertEffect,
|
|
34392
36381
|
Light2d,
|
|
34393
36382
|
Line,
|
|
36383
|
+
MaskEffect,
|
|
34394
36384
|
math_exports as Math,
|
|
34395
36385
|
Matrix2d,
|
|
34396
36386
|
Matrix3d,
|
|
@@ -34414,6 +36404,7 @@ export {
|
|
|
34414
36404
|
QuadTree,
|
|
34415
36405
|
Rect,
|
|
34416
36406
|
RenderState,
|
|
36407
|
+
RenderTarget,
|
|
34417
36408
|
Renderable,
|
|
34418
36409
|
Renderer,
|
|
34419
36410
|
RoundRect,
|
|
@@ -34421,6 +36412,7 @@ export {
|
|
|
34421
36412
|
ScanlineEffect,
|
|
34422
36413
|
SepiaEffect,
|
|
34423
36414
|
ShaderEffect,
|
|
36415
|
+
ShakeEffect,
|
|
34424
36416
|
Sprite,
|
|
34425
36417
|
Stage,
|
|
34426
36418
|
TMXHexagonalRenderer,
|
|
@@ -34445,6 +36437,7 @@ export {
|
|
|
34445
36437
|
UITextButton,
|
|
34446
36438
|
Vector2d,
|
|
34447
36439
|
Vector3d,
|
|
36440
|
+
VignetteEffect,
|
|
34448
36441
|
WEBGL,
|
|
34449
36442
|
WaveEffect,
|
|
34450
36443
|
WebGLRenderer,
|