Bläddra i källkod

feat: 974-createsetup-devtools (#975)

* feat: integrate devtools setup for performance monitoring

- Added a new `setupDevtools` function to manage performance metrics such as FPS and memory usage.
- Integrated the `setupDevtools` function into the `useTresContextProvider` to enhance the development experience.
- Updated the `index.vue` page to utilize the `useControls` for FPS graphing.
- Cleaned up unused performance-related code to streamline the context provider logic.

* Update src/devtools/setupDevtools.ts

Co-authored-by: Damien Montastier <montastier.damien@gmail.com>

* Update src/devtools/setupDevtools.ts

Co-authored-by: Damien Montastier <montastier.damien@gmail.com>

* refactor: improve readability in setupDevtools.ts

- Adjusted indentation and formatting in the `setupDevtools` function to enhance code clarity.
- Ensured consistent use of braces for conditional statements to improve maintainability and readability.

* refactor: added boundedPush util

- Introduced a new utility function `boundedPush` in `perf.ts` to streamline the logic for maintaining a fixed-length array for performance metrics.
- Updated `setupDevtools.ts` to utilize `boundedPush` for both FPS and memory usage tracking, enhancing code clarity and reducing redundancy.

---------

Co-authored-by: Damien Montastier <montastier.damien@gmail.com>
Alvaro Saburido 1 månad sedan
förälder
incheckning
1d83f7b96e

+ 2 - 0
playground/vue/src/pages/events/index.vue

@@ -16,6 +16,8 @@ const gl = {
   toneMapping: NoToneMapping,
 }
 
+useControls('fpsgraph')
+
 const { stopPropagation } = useControls({
   stopPropagation: false,
 })

+ 2 - 67
src/composables/useTresContextProvider/index.ts

@@ -3,18 +3,17 @@ import type { ComputedRef, DeepReadonly, MaybeRef, MaybeRefOrGetter, Ref, Shallo
 import type { RendererLoop } from '../../core/loop'
 import type { EmitEventFn, TresControl, TresObject, TresScene } from '../../types'
 import type { UseRendererOptions } from '../useRenderer'
-import { useFps, useMemory, useRafFn } from '@vueuse/core'
 import { Raycaster } from 'three'
 import { computed, inject, onUnmounted, provide, readonly, ref, shallowRef } from 'vue'
 import { extend } from '../../core/catalogue'
 import { createRenderLoop } from '../../core/loop'
-import { calculateMemoryUsage } from '../../utils/perf'
 
 import { useCamera } from '../useCamera'
 import { useRenderer } from '../useRenderer'
 import useSizes, { type SizesType } from '../useSizes'
 import { type TresEventManager, useTresEventManager } from '../useTresEventManager'
 import { useTresReady } from '../useTresReady'
+import { setupDevtools } from '../../devtools/setupDevtools'
 
 export interface InternalState {
   priority: Ref<number>
@@ -214,71 +213,7 @@ export function useTresContextProvider({
     ctx.loop.stop()
   })
 
-  // Performance
-  const updateInterval = 100 // Update interval in milliseconds
-  const fps = useFps({ every: updateInterval })
-  const { isSupported, memory } = useMemory({ interval: updateInterval })
-  const maxFrames = 160
-  let lastUpdateTime = performance.now()
-
-  const updatePerformanceData = ({ timestamp }: { timestamp: number }) => {
-    // Update WebGL Memory Usage (Placeholder for actual logic)
-    // perf.memory.value = calculateMemoryUsage(gl)
-    if (ctx.scene.value) {
-      ctx.perf.memory.allocatedMem = calculateMemoryUsage(ctx.scene.value as unknown as TresObject)
-    }
-
-    // Update memory usage
-    if (timestamp - lastUpdateTime >= updateInterval) {
-      lastUpdateTime = timestamp
-
-      // Update FPS
-      ctx.perf.fps.accumulator.push(fps.value as never)
-
-      if (ctx.perf.fps.accumulator.length > maxFrames) {
-        ctx.perf.fps.accumulator.shift()
-      }
-
-      ctx.perf.fps.value = fps.value
-
-      // Update memory
-      if (isSupported.value && memory.value) {
-        ctx.perf.memory.accumulator.push(memory.value.usedJSHeapSize / 1024 / 1024 as never)
-
-        if (ctx.perf.memory.accumulator.length > maxFrames) {
-          ctx.perf.memory.accumulator.shift()
-        }
-
-        ctx.perf.memory.currentMem
-        = ctx.perf.memory.accumulator.reduce((a, b) => a + b, 0) / ctx.perf.memory.accumulator.length
-      }
-    }
-  }
-
-  // Devtools
-  let accumulatedTime = 0
-  const interval = 1 // Interval in milliseconds, e.g., 1000 ms = 1 second
-
-  const { pause } = useRafFn(({ delta }) => {
-    if (!window.__TRES__DEVTOOLS__) { return }
-
-    updatePerformanceData({ timestamp: performance.now() })
-
-    // Accumulate the delta time
-    accumulatedTime += delta
-
-    // Check if the accumulated time is greater than or equal to the interval
-    if (accumulatedTime >= interval) {
-      window.__TRES__DEVTOOLS__.cb(ctx)
-
-      // Reset the accumulated time
-      accumulatedTime = 0
-    }
-  }, { immediate: true })
-
-  onUnmounted(() => {
-    pause()
-  })
+  setupDevtools(ctx)
 
   return ctx
 }

+ 1 - 0
src/devtools/plugin.ts

@@ -112,6 +112,7 @@ const INSPECTOR_ID = 'tres:inspector'
 const state = reactive({
   sceneGraph: null as SceneGraphObject | null,
 })
+
 export function registerTresDevtools(app: DevtoolsApp, tres: TresContext) {
   setupDevtoolsPlugin(
     {

+ 69 - 0
src/devtools/setupDevtools.ts

@@ -0,0 +1,69 @@
+import { useFps, useMemory, useRafFn } from '@vueuse/core'
+import { boundedPush, calculateMemoryUsage } from '../utils/perf'
+import type { TresContext } from '../composables'
+import type { TresObject } from '../types'
+import { onUnmounted } from 'vue'
+
+export function setupDevtools(ctx: TresContext) {
+  if (!ctx) { return }
+
+  // Performance
+  const updateInterval = 100 // Update interval in milliseconds
+  const fps = useFps({ every: updateInterval })
+  const { isSupported, memory } = useMemory({ interval: updateInterval })
+  const maxFrames = 160
+  let lastUpdateTime = performance.now()
+
+  // Devtools
+  let accumulatedTime = 0
+  const interval = 1 // Interval in milliseconds, e.g., 1000 ms = 1 second
+
+  const updatePerformanceData = ({ timestamp }: { timestamp: number }) => {
+    // Update WebGL Memory Usage (Placeholder for actual logic)
+    // perf.memory.value = calculateMemoryUsage(gl)
+    if (ctx.scene.value) {
+      ctx.perf.memory.allocatedMem = calculateMemoryUsage(ctx.scene.value as unknown as TresObject)
+    }
+
+    // Update memory usage
+    if (timestamp - lastUpdateTime >= updateInterval) {
+      lastUpdateTime = timestamp
+
+      // Update FPS
+      boundedPush(ctx.perf.fps.accumulator, fps.value as never, maxFrames)
+
+      ctx.perf.fps.value = fps.value
+
+      // Update memory
+      if (isSupported.value && memory.value?.usedJSHeapSize) {
+        boundedPush(ctx.perf.memory.accumulator, memory.value.usedJSHeapSize / 1024 / 1024 as never, maxFrames)
+
+        if (ctx.perf.memory.accumulator.length > 0) {
+          ctx.perf.memory.currentMem
+        = ctx.perf.memory.accumulator.reduce((a, b) => a + b, 0) / ctx.perf.memory.accumulator.length
+        }
+      }
+    }
+  }
+
+  const { pause } = useRafFn(({ delta }) => {
+    if (!window.__TRES__DEVTOOLS__) { return }
+
+    updatePerformanceData({ timestamp: performance.now() })
+
+    // Accumulate the delta time
+    accumulatedTime += delta
+
+    // Check if the accumulated time is greater than or equal to the interval
+    if (accumulatedTime >= interval) {
+      window.__TRES__DEVTOOLS__.cb(ctx)
+
+      // Reset the accumulated time
+      accumulatedTime = 0
+    }
+  }, { immediate: true })
+
+  onUnmounted(() => {
+    pause()
+  })
+}

+ 5 - 0
src/utils/perf.ts

@@ -21,6 +21,11 @@ export function calculateMemoryUsage(object: TresObject | Scene) {
   return totalMemory // In bytes
 }
 
+export function boundedPush<T>(arr: T[], value: T, max: number) {
+  arr.push(value)
+  if (arr.length > max) { arr.shift() }
+}
+
 export function bytesToKB(bytes: number): string {
   return (bytes / 1024).toFixed(2)
 }