Bläddra i källkod

fix: useCamera issue due to deps tracking

check Cameras component in playground plz
enpitsulin 2 år sedan
förälder
incheckning
6d39f0c729

+ 21 - 37
src/components/TresCanvas.vue

@@ -7,7 +7,7 @@ import {
     type ShadowMapType,
     type ToneMapping,
 } from 'three'
-import { Fragment, computed, defineComponent, h, onMounted, provide, ref, shallowRef, watch } from 'vue'
+import { Fragment, computed, defineComponent, h, provide, ref, shallowRef, watch } from 'vue'
 import { useTresContextProvider } from '../composables'
 import { render } from '../core/renderer'
 
@@ -77,7 +77,6 @@ const context = useTresContextProvider({
 
 usePointerEventHandler({ scene: scene.value, contextParts: context })
 
-
 const internalFnComponent = defineComponent({
     setup() {
         provide('useTres', context);
@@ -88,27 +87,30 @@ const internalFnComponent = defineComponent({
 const renderScene = () => {
     const container = scene.value as unknown as TresObject
     render(h(internalFnComponent), container)
+    triggerRef(scene)
 }
 
-
-
-onMounted(() => {
-
-    const { addCamera, removeCamera } = context
-
+watch(canvas, canvas => {
+    if (!canvas) return
     renderScene()
+    if (!context.camera.value && !props.camera) {
+        logWarning(
+            'No camera found. Creating a default perspective camera. ' +
+            'To have full control over a camera, please add one to the scene.',
+        )
+        addDefaultCamera()
+    }
+})
 
-    watch(() => props.camera, (newCamera, oldCamera) => {
-        if (newCamera)
-            addCamera(newCamera)
-        else if (oldCamera) {
-            oldCamera.removeFromParent()
-            removeCamera(oldCamera)
-        }
-    }, {
-        immediate: true
-    })
-
+watch(() => props.camera, (newCamera, oldCamera) => {
+    if (newCamera)
+        context.addCamera(newCamera, true)
+    else if (oldCamera) {
+        oldCamera.removeFromParent()
+        context.removeCamera(oldCamera)
+    }
+}, {
+    immediate: true
 })
 
 const addDefaultCamera = () => {
@@ -123,24 +125,6 @@ const addDefaultCamera = () => {
     }
 }
 
-const unwatch = watch(canvas, val => {
-    if (!val) return
-    triggerRef(scene)
-    unwatch?.()
-})
-
-watch(scene, () => {
-    if (!context.camera.value) {
-        logWarning(
-            'No camera found. Creating a default perspective camera. ' +
-            'To have full control over a camera, please add one to the scene.',
-        )
-        addDefaultCamera()
-    }
-})
-
-
-
 if (import.meta.hot)
     import.meta.hot.on('vite:afterUpdate', () => {
         renderScene()

+ 11 - 15
src/composables/useCamera/index.ts

@@ -1,43 +1,39 @@
 import { Camera, OrthographicCamera, PerspectiveCamera } from 'three'
-import { computed, triggerRef, watch, watchEffect } from 'vue'
+import { computed, ref, triggerRef, watchEffect } from 'vue'
 
 import type { TresContext } from '../useTresContextProvider'
 
 
 export const useCamera = ({ sizes, scene }: Pick<TresContext, 'sizes' | 'scene'>) => {
   const cameras = computed<Camera[]>(() => scene.value.children.filter((i): i is Camera => (i as any).isCamera))
+  const activeCameraUuid = ref(cameras.value?.[0]?.uuid ?? "")
   const camera = computed<Camera | undefined>(
-    () => cameras.value[0],
+    () => cameras.value.find(c => c.uuid === activeCameraUuid.value) ?? cameras.value.at(0),
   )
-  // don't known why need manually trigger here
-  const unwatch = watch(camera, () => {
-    triggerRef(cameras)
-    unwatch?.()
-  }, { deep: true })
 
   const addCamera = (newCamera: Camera, active = false) => {
     if (cameras.value.some(({ uuid }) => uuid === newCamera.uuid))
       return
 
+    scene.value.add(newCamera)
+    triggerRef(scene)
     if (active)
       setCameraActive(newCamera)
-    else
-      cameras.value.push(newCamera)
   }
 
   const removeCamera = (camera: Camera) => {
     scene.value.remove(camera)
+    triggerRef(scene)
   }
 
   const setCameraActive = (cameraOrUuid: string | Camera) => {
-    const camera = cameraOrUuid instanceof Camera ?
-      cameraOrUuid :
-      cameras.value.find((camera: Camera) => camera.uuid === cameraOrUuid)
+    const cameraUuid = cameraOrUuid instanceof Camera ?
+      cameraOrUuid.uuid :
+      cameraOrUuid
 
-    if (!camera) return
+    if (!cameraUuid) return
 
-    const otherCameras = cameras.value.filter(({ uuid }) => uuid !== camera.uuid)
-    scene.value.add(...otherCameras)
+    activeCameraUuid.value = cameraUuid
   }
 
   watchEffect(() => {

+ 1 - 1
src/composables/useTresContextProvider/index.ts

@@ -15,7 +15,7 @@ export type TresContext = {
   raycaster: ShallowRef<Raycaster>
   controls: Ref<(EventDispatcher & { enabled: boolean }) | null>
   extend: (objects: any) => void
-  addCamera: (camera: Camera) => void;
+  addCamera: (camera: Camera, active?: boolean) => void;
   removeCamera: (camera: Camera) => void
   setCameraActive: (cameraOrUuid: Camera | string) => void;