melonjs 19.5.0 → 19.6.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/build/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * melonJS Game Engine - 19.5.0
2
+ * melonJS Game Engine - 19.6.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
@@ -24177,13 +24177,38 @@ var GLShader = class {
24177
24177
  */
24178
24178
  constructor(gl, vertex, fragment, precision) {
24179
24179
  this.gl = gl;
24180
+ this.destroyed = false;
24181
+ this.suspended = false;
24182
+ this._sourceVertex = vertex;
24183
+ this._sourceFragment = fragment;
24184
+ this._precision = precision;
24185
+ this._uniformCache = /* @__PURE__ */ Object.create(null);
24186
+ if (gl.isContextLost()) {
24187
+ this.suspended = true;
24188
+ this.program = null;
24189
+ this.uniforms = null;
24190
+ this.attributes = null;
24191
+ } else {
24192
+ this._compile();
24193
+ }
24194
+ on(ONCONTEXT_LOST, this._onContextLost, this);
24195
+ on(ONCONTEXT_RESTORED, this._onContextRestored, this);
24196
+ }
24197
+ /**
24198
+ * (Re)compile the shader program against `this.gl` from the
24199
+ * preserved source. Called from the constructor and from
24200
+ * {@link _onContextRestored}. Replays any cached uniform values
24201
+ * against the freshly-extracted uniforms proxy.
24202
+ * @private
24203
+ */
24204
+ _compile() {
24180
24205
  this.vertex = setPrecision(
24181
- minify(vertex),
24182
- precision || getMaxShaderPrecision(this.gl)
24206
+ minify(this._sourceVertex),
24207
+ this._precision || getMaxShaderPrecision(this.gl)
24183
24208
  );
24184
24209
  this.fragment = setPrecision(
24185
- minify(fragment),
24186
- precision || getMaxShaderPrecision(this.gl)
24210
+ minify(this._sourceFragment),
24211
+ this._precision || getMaxShaderPrecision(this.gl)
24187
24212
  );
24188
24213
  this.attributes = extractAttributes(this.gl, this);
24189
24214
  this.program = compileProgram(
@@ -24193,12 +24218,54 @@ var GLShader = class {
24193
24218
  this.attributes
24194
24219
  );
24195
24220
  this.uniforms = extractUniforms(this.gl, this);
24196
- on(ONCONTEXT_LOST, this.destroy, this);
24221
+ this.suspended = false;
24222
+ for (const name of Object.keys(this._uniformCache)) {
24223
+ if (typeof this.uniforms[name] !== "undefined") {
24224
+ this.bind();
24225
+ this.uniforms[name] = this._uniformCache[name];
24226
+ }
24227
+ }
24228
+ }
24229
+ /**
24230
+ * Handler for {@link ONCONTEXT_LOST}. Tears down the GL program
24231
+ * but preserves the shader source + cached uniform values so the
24232
+ * shader can be transparently rebuilt on context restore.
24233
+ * @private
24234
+ */
24235
+ _onContextLost() {
24236
+ if (this.destroyed || this.suspended) {
24237
+ return;
24238
+ }
24239
+ this.suspended = true;
24240
+ this.uniforms = null;
24241
+ this.attributes = null;
24242
+ if (this.program !== null) {
24243
+ try {
24244
+ this.gl.deleteProgram(this.program);
24245
+ } catch {
24246
+ }
24247
+ this.program = null;
24248
+ }
24249
+ }
24250
+ /**
24251
+ * Handler for {@link ONCONTEXT_RESTORED}. Re-compiles and
24252
+ * re-links the shader against the new GL context, then replays
24253
+ * any cached uniform values via {@link _compile}.
24254
+ * @private
24255
+ */
24256
+ _onContextRestored() {
24257
+ if (this.destroyed) {
24258
+ return;
24259
+ }
24260
+ this._compile();
24197
24261
  }
24198
24262
  /**
24199
24263
  * Installs this shader program as part of current rendering state
24200
24264
  */
24201
24265
  bind() {
24266
+ if (this.destroyed || this.suspended) {
24267
+ return;
24268
+ }
24202
24269
  this.gl.useProgram(this.program);
24203
24270
  }
24204
24271
  /**
@@ -24207,6 +24274,9 @@ var GLShader = class {
24207
24274
  * @returns {GLint} number indicating the location of the variable name if found. Returns -1 otherwise
24208
24275
  */
24209
24276
  getAttribLocation(name) {
24277
+ if (this.destroyed || this.suspended) {
24278
+ return -1;
24279
+ }
24210
24280
  const attr = this.attributes[name];
24211
24281
  if (typeof attr !== "undefined") {
24212
24282
  return attr;
@@ -24222,14 +24292,35 @@ var GLShader = class {
24222
24292
  * myShader.setUniform("uProjectionMatrix", this.projectionMatrix);
24223
24293
  */
24224
24294
  setUniform(name, value) {
24295
+ if (this.destroyed) {
24296
+ return;
24297
+ }
24298
+ let cached;
24299
+ let glValue;
24300
+ if (typeof value === "object" && value !== null) {
24301
+ if (typeof value.toArray === "function") {
24302
+ const arr = value.toArray();
24303
+ cached = captureValue(this._uniformCache[name], arr);
24304
+ glValue = arr;
24305
+ } else if (Array.isArray(value) || ArrayBuffer.isView(value)) {
24306
+ cached = captureValue(this._uniformCache[name], value);
24307
+ glValue = value;
24308
+ } else {
24309
+ cached = value;
24310
+ glValue = value;
24311
+ }
24312
+ } else {
24313
+ cached = value;
24314
+ glValue = value;
24315
+ }
24316
+ this._uniformCache[name] = cached;
24317
+ if (this.suspended) {
24318
+ return;
24319
+ }
24225
24320
  const uniforms = this.uniforms;
24226
24321
  if (typeof uniforms[name] !== "undefined") {
24227
24322
  this.bind();
24228
- if (typeof value === "object" && typeof value.toArray === "function") {
24229
- uniforms[name] = value.toArray();
24230
- } else {
24231
- uniforms[name] = value;
24232
- }
24323
+ uniforms[name] = glValue;
24233
24324
  } else {
24234
24325
  throw new Error("undefined (" + name + ") uniform for shader " + this);
24235
24326
  }
@@ -24258,14 +24349,32 @@ var GLShader = class {
24258
24349
  }
24259
24350
  }
24260
24351
  /**
24261
- * destroy this shader objects resources (program, attributes, uniforms)
24352
+ * destroy this shader objects resources (program, attributes, uniforms).
24353
+ * Idempotent — calling destroy twice (or after a context-lost suspend)
24354
+ * is safe. Unsubscribes from the renderer's context lost / restored
24355
+ * events so a destroyed shader is never automatically resurrected.
24262
24356
  */
24263
24357
  destroy() {
24358
+ if (this.destroyed) {
24359
+ return;
24360
+ }
24361
+ this.destroyed = true;
24362
+ off(ONCONTEXT_LOST, this._onContextLost, this);
24363
+ off(ONCONTEXT_RESTORED, this._onContextRestored, this);
24264
24364
  this.uniforms = null;
24265
24365
  this.attributes = null;
24266
- this.gl.deleteProgram(this.program);
24366
+ if (this.program !== null) {
24367
+ try {
24368
+ this.gl.deleteProgram(this.program);
24369
+ } catch {
24370
+ }
24371
+ this.program = null;
24372
+ }
24267
24373
  this.vertex = null;
24268
24374
  this.fragment = null;
24375
+ this._sourceVertex = null;
24376
+ this._sourceFragment = null;
24377
+ this._uniformCache = null;
24269
24378
  }
24270
24379
  };
24271
24380
 
@@ -24275,10 +24384,22 @@ var quad_default = "// Current vertex point\nattribute vec2 aVertex;\nattribute
24275
24384
  // src/video/webgl/shadereffect.js
24276
24385
  var ShaderEffect = class {
24277
24386
  /**
24278
- * whether this effect is active (false in Canvas mode)
24387
+ * whether this effect is active (false in Canvas mode, false after
24388
+ * {@link destroy}, and false while the WebGL context is suspended
24389
+ * between an `ONCONTEXT_LOST` and the matching `ONCONTEXT_RESTORED`
24390
+ * event).
24279
24391
  * @type {boolean}
24280
24392
  */
24281
24393
  enabled = false;
24394
+ /**
24395
+ * `true` once {@link destroy} has been called. Distinct from
24396
+ * `enabled` — which also toggles transiently across a context
24397
+ * lost / restored cycle — to give callers a stable signal for
24398
+ * "this effect has been explicitly released."
24399
+ * @type {boolean}
24400
+ * @readonly
24401
+ */
24402
+ destroyed = false;
24282
24403
  /**
24283
24404
  * @param {WebGLRenderer|CanvasRenderer} renderer - the current renderer instance
24284
24405
  * @param {string} fragmentBody - GLSL code containing a `vec4 apply(vec4 color, vec2 uv)` function
@@ -24297,7 +24418,6 @@ var ShaderEffect = class {
24297
24418
  "uniform sampler2D uSampler;",
24298
24419
  "varying vec4 vColor;",
24299
24420
  "varying vec2 vRegion;",
24300
- // user-provided fragment body (uniforms + apply function)
24301
24421
  fragmentBody,
24302
24422
  "void main(void) {",
24303
24423
  " vec4 texColor = texture2D(uSampler, vRegion) * vColor;",
@@ -24311,6 +24431,24 @@ var ShaderEffect = class {
24311
24431
  precision || renderer2.shaderPrecision
24312
24432
  );
24313
24433
  this.enabled = true;
24434
+ on(ONCONTEXT_LOST, this._onContextLost, this);
24435
+ on(ONCONTEXT_RESTORED, this._onContextRestored, this);
24436
+ }
24437
+ /** @private */
24438
+ _onContextLost() {
24439
+ if (this.destroyed) {
24440
+ return;
24441
+ }
24442
+ this._enabledBeforeSuspend = this.enabled;
24443
+ this.enabled = false;
24444
+ }
24445
+ /** @private */
24446
+ _onContextRestored() {
24447
+ if (this.destroyed) {
24448
+ return;
24449
+ }
24450
+ this.enabled = this._enabledBeforeSuspend !== false;
24451
+ this._enabledBeforeSuspend = void 0;
24314
24452
  }
24315
24453
  /**
24316
24454
  * Set the uniform to the given value
@@ -24359,12 +24497,20 @@ var ShaderEffect = class {
24359
24497
  return this.enabled ? this._shader.uniforms : {};
24360
24498
  }
24361
24499
  /**
24362
- * destroy this shader effect
24500
+ * destroy this shader effect. Idempotent — calling destroy twice
24501
+ * is safe. Unsubscribes from the renderer's context-lost / restored
24502
+ * events so a destroyed effect is not auto-reactivated.
24363
24503
  */
24364
24504
  destroy() {
24365
- if (this.enabled) {
24505
+ if (this.destroyed) {
24506
+ return;
24507
+ }
24508
+ this.destroyed = true;
24509
+ this.enabled = false;
24510
+ off(ONCONTEXT_LOST, this._onContextLost, this);
24511
+ off(ONCONTEXT_RESTORED, this._onContextRestored, this);
24512
+ if (this._shader) {
24366
24513
  this._shader.destroy();
24367
- this.enabled = false;
24368
24514
  }
24369
24515
  }
24370
24516
  };
@@ -29440,7 +29586,7 @@ var Trigger = class extends Renderable {
29440
29586
  };
29441
29587
 
29442
29588
  // src/version.ts
29443
- var version = "19.5.0";
29589
+ var version = "19.6.0";
29444
29590
 
29445
29591
  // src/system/bootstrap.ts
29446
29592
  var initialized = false;
@@ -34828,6 +34974,7 @@ var WebGLRenderer = class extends Renderer {
34828
34974
  (e) => {
34829
34975
  e.preventDefault();
34830
34976
  this.isContextValid = false;
34977
+ this.vertexBuffer = null;
34831
34978
  emit(ONCONTEXT_LOST, this);
34832
34979
  },
34833
34980
  false
@@ -34835,7 +34982,17 @@ var WebGLRenderer = class extends Renderer {
34835
34982
  this.getCanvas().addEventListener(
34836
34983
  "webglcontextrestored",
34837
34984
  () => {
34985
+ this.vertexBuffer = this.gl.createBuffer();
34986
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
34987
+ this.gl.disable(this.gl.DEPTH_TEST);
34988
+ this.gl.depthMask(false);
34989
+ this.gl.disable(this.gl.SCISSOR_TEST);
34990
+ this._scissorActive = false;
34991
+ this.gl.enable(this.gl.BLEND);
34992
+ this.setBlendMode(this.settings.blendMode);
34838
34993
  this.reset();
34994
+ this.cache.units.clear();
34995
+ this.cache.usedUnits.clear();
34839
34996
  this.isContextValid = true;
34840
34997
  emit(ONCONTEXT_RESTORED, this);
34841
34998
  },