Browse Source

refactor(loop): use explicit variables for stop/pause states

Peter 10 months ago
parent
commit
c81924b385
1 changed files with 37 additions and 18 deletions
  1. 37 18
      src/core/loop.ts

+ 37 - 18
src/core/loop.ts

@@ -44,8 +44,11 @@ export interface RendererLoop {
 }
 
 export function createRenderLoop(): RendererLoop {
+  let isReady = true
+  let isStopped = true
+  let isPaused = false
   const clock = new Clock(false)
-  const isActive = ref(false)
+  const isActive = ref(clock.running)
   const isRenderPaused = ref(false)
   let animationFrameId: number
   const loopId = MathUtils.generateUUID()
@@ -53,7 +56,8 @@ export function createRenderLoop(): RendererLoop {
   const subscribersBefore = createPriorityEventHook<LoopCallbackWithCtx>()
   const subscriberRender = createPriorityEventHook<LoopCallbackWithCtx>()
   const subscribersAfter = createPriorityEventHook<LoopCallbackWithCtx>()
-  let isReady = true
+
+  _syncState()
 
   // Context to be passed to callbacks
   let context: Record<string, any> = {}
@@ -78,29 +82,31 @@ export function createRenderLoop(): RendererLoop {
   }
 
   function start() {
-    if (!isActive.value) {
-      clock.start()
-      isActive.value = true
-      loop()
-    }
+    // NOTE: `loop()` produces side effects on each call.
+    // Those side effects are only desired if `isStopped` goes
+    // from `true` to `false` below.  So while we don't need
+    // a guard in `stop`, `resume`, and `pause`, we do need
+    // a guard here.
+    if (!isStopped) { return }
+    isStopped = false
+    _syncState()
+    loop()
   }
 
   function stop() {
-    if (isActive.value) {
-      clock.stop()
-      cancelAnimationFrame(animationFrameId)
-      isActive.value = false
-    }
+    isStopped = true
+    _syncState()
+    cancelAnimationFrame(animationFrameId)
   }
 
-  function pause() {
-    clock.stop()
-    isActive.value = false
+  function resume() {
+    isPaused = false
+    _syncState()
   }
 
-  function resume() {
-    clock.start()
-    isActive.value = true
+  function pause() {
+    isPaused = true
+    _syncState()
   }
 
   function pauseRender() {
@@ -151,6 +157,19 @@ export function createRenderLoop(): RendererLoop {
     animationFrameId = requestAnimationFrame(loop)
   }
 
+  function _syncState() {
+    const shouldClockBeRunning = !isStopped && !isPaused
+    if (clock.running !== shouldClockBeRunning) {
+      if (!clock.running) {
+        clock.start()
+      }
+      else {
+        clock.stop()
+      }
+    }
+    isActive.value = clock.running
+  }
+
   return {
     loopId,
     register: (callback: LoopCallbackFn, stage: 'before' | 'render' | 'after', index) => registerCallback(callback, stage, index),