diff --git a/src/platforms/browser/WebPlatform.mjs b/src/platforms/browser/WebPlatform.mjs index 5245622d..9ec88747 100644 --- a/src/platforms/browser/WebPlatform.mjs +++ b/src/platforms/browser/WebPlatform.mjs @@ -33,8 +33,7 @@ export default class WebPlatform { // Alternative handler to avoid RAF when idle this._loopHandler = null; this._idleLoopCounter = 0; - this._idleLoopDelay = 60; - this._onIdle = false; + this._idleLoopDelay = 30; if (this.stage.getOption("useImageWorker")) { if (!window.createImageBitmap || !window.Worker) { @@ -52,6 +51,7 @@ export default class WebPlatform { this._imageWorker.destroy(); } + this._looping = false; clearInterval(this._loopHandler); this._removeKeyHandler(); @@ -75,44 +75,41 @@ export default class WebPlatform { this._looping = false; } - switchLoop() { - if (this._onIdle === false) { - this._onIdle = true; - this.stage.onIdle(); - } - - if (this._idleLoopCounter < this._idleLoopDelay) { - this._idleLoopCounter++; - return; - } - if (!this.stage.ctx.hasRenderUpdates()) { - this.stopLoop(); - this._loopHandler = setInterval(() => { - this.stage.updateFrame(); - this.stage.idleFrame(); - if (this.stage.ctx.hasRenderUpdates()) { - clearInterval(this._loopHandler); - this.startLoop(); - }; - }, 1000 / 60); - } else { + switchLoop(hasChanges) { + if (hasChanges) { this._idleLoopCounter = 0; + return false; } + if (++this._idleLoopCounter < this._idleLoopDelay) { + return false; + } + + this.stopLoop(); + this._loopHandler = setInterval(() => { + this.stage.updateFrame(); + const hasChanges = this.stage.renderFrame(); + if (hasChanges) { + clearInterval(this._loopHandler); + this.startLoop(); + } + }, 1000 / 30); + + this.stage.onIdle(); + return true; } loop() { - let self = this; - let lp = function () { - self._awaitingLoop = false; - self._onIdle = false; - if (self._looping) { - self.stage.updateFrame(); - if (self.stage.getOption("pauseRafLoopOnIdle")) { - self.switchLoop(); + const pauseRafLoopOnIdle = this.stage.getOption("pauseRafLoopOnIdle"); + const lp = () => { + this._awaitingLoop = false; + if (this._looping) { + this.stage.updateFrame(); + const hasChanges = this.stage.renderFrame(); + if (pauseRafLoopOnIdle && this.switchLoop(hasChanges)) { + return; } - self.stage.renderFrame(); requestAnimationFrame(lp); - self._awaitingLoop = true; + this._awaitingLoop = true; } } requestAnimationFrame(lp); diff --git a/src/tree/Stage.d.mts b/src/tree/Stage.d.mts index 17e2f530..2b95823c 100644 --- a/src/tree/Stage.d.mts +++ b/src/tree/Stage.d.mts @@ -427,7 +427,7 @@ declare class Stage extends EventEmitter { */ isUpdatingFrame(): boolean; - // renderFrame(): void; + // renderFrame(): boolean; // - Only used internally /** diff --git a/src/tree/Stage.mjs b/src/tree/Stage.mjs index fae433bc..c0fd4803 100644 --- a/src/tree/Stage.mjs +++ b/src/tree/Stage.mjs @@ -170,7 +170,7 @@ export default class Stage extends EventEmitter { _setOptions(o) { this._options = {}; - let opt = (name, def) => { + const opt = (name, def) => { let value = o[name]; if (value === undefined) { @@ -315,7 +315,7 @@ export default class Stage extends EventEmitter { this._updateSourceTextures.forEach(texture => { texture._performUpdateSource(); }); - this._updateSourceTextures = new Set(); + this._updateSourceTextures.clear(); } } @@ -337,12 +337,6 @@ export default class Stage extends EventEmitter { this.emit('update'); } - idleFrame() { - this.textureThrottler.processSome(); - this.emit('frameEnd'); - this.frameCounter++; - } - onIdle() { this.emit('idle'); } @@ -366,6 +360,8 @@ export default class Stage extends EventEmitter { this.emit('frameEnd'); this.frameCounter++; + + return changes; } isUpdatingFrame() {