Tino Koch 2 mēneši atpakaļ
vecāks
revīzija
f1897904f2
2 mainītis faili ar 74 papildinājumiem un 50 dzēšanām
  1. 2 2
      src/components/TresCanvas.vue
  2. 72 48
      src/core/setupRenderer.ts

+ 2 - 2
src/components/TresCanvas.vue

@@ -292,7 +292,7 @@ export interface TresCanvasProps extends /* @vue-ignore */ WebGLRendererProps {
    * Clear color for the canvas
    * Clear color for the canvas
    * Can include alpha value (e.g. '#00808000' for fully transparent teal)
    * Can include alpha value (e.g. '#00808000' for fully transparent teal)
    */
    */
-  clearColor?: MaybeRefOrGetter<string>
+  clearColor?: MaybeRefOrGetter<string> // TODO this should also accept the other parts of ColorRepresentation
 
 
   /**
   /**
    * The opacity of the clear color (0-1)
    * The opacity of the clear color (0-1)
@@ -330,7 +330,7 @@ export interface TresCanvasProps extends /* @vue-ignore */ WebGLRendererProps {
    * @see {@link https://threejs.org/docs/#api/en/constants/Renderer}
    * @see {@link https://threejs.org/docs/#api/en/constants/Renderer}
    * @default PCFSoftShadowMap (Opinionated default by TresJS)
    * @default PCFSoftShadowMap (Opinionated default by TresJS)
    */
    */
-  shadowMapType?: MaybeRefOrGetter<ShadowMapType | number>
+  shadowMapType?: MaybeRefOrGetter<ShadowMapType>
 
 
   /**
   /**
    * Whether to use legacy lights system instead of the new one
    * Whether to use legacy lights system instead of the new one

+ 72 - 48
src/core/setupRenderer.ts

@@ -1,6 +1,6 @@
-import type { ColorRepresentation, Object3D, WebGLRenderer } from 'three'
-import type { UnwrapRef, WatchHandle, WatchOptions } from 'vue'
-import { toValue, watch } from 'vue'
+import type { ColorRepresentation, Object3D, ToneMapping, WebGLRenderer } from 'three'
+import type { MaybeRefOrGetter, UnwrapRef, WatchHandle, WatchOptions } from 'vue'
+import { computed, toValue, watch } from 'vue'
 import { useDevicePixelRatio } from '@vueuse/core'
 import { useDevicePixelRatio } from '@vueuse/core'
 import { setPixelRatio } from '../utils'
 import { setPixelRatio } from '../utils'
 
 
@@ -29,51 +29,14 @@ type NamesOfPropsThatCannotChange = keyof Pick<
   'alpha' |
   'alpha' |
   'renderer'
   'renderer'
 >
 >
+
 type NamesOfPropsThatCanChange = keyof Omit<
 type NamesOfPropsThatCanChange = keyof Omit<
   TresCanvasProps,
   TresCanvasProps,
   NamesOfPropsThatCannotChange
   NamesOfPropsThatCannotChange
 >
 >
 
 
-// const propsToWatch: {
-//   [K in NamesOfPropsThatCanChange]: {
-//     getter: (props: TresCanvasProps) => TresCanvasProps[K] // TODO check if there is a better type than any
-//     setter: (renderer: WebGLRenderer, value: TresCanvasProps[K]) => void
-//     watchOptions: WatchOptions
-//   }
-// } = {
-//   clearAlpha: {
-//     getter: ({ clearAlpha }) => clearAlpha,
-//     setter: (renderer, value) => renderer.setClearAlpha(value),
-//     watchOptions: { immediate: true },
-//   },
-// }
-
 // TODO test by using basic playground
 // TODO test by using basic playground
 
 
-const propsToWatch = {
-  clearAlpha: {
-    getter: ({ clearAlpha }) => clearAlpha,
-    setter: (renderer, value) => {
-      renderer.setClearAlpha(toValue(value))
-    },
-    defaultValue: 1,
-    watchOptions: { immediate: true },
-  },
-  toneMapping: {
-    getter: ({ toneMapping }) => toneMapping,
-    setter: (renderer, value) => renderer.toneMapping = toValue(value),
-    watchOptions: { immediate: true },
-    defaultValue: ACESFilmicToneMapping, // TODO move to common place, this is opinionated
-  },
-} satisfies {
-  [K in NamesOfPropsThatCanChange]: {
-    getter: (props: TresCanvasProps) => TresCanvasProps[K] // TODO check if there is a better type than any
-    setter: (renderer: WebGLRenderer, value: Exclude<UnwrapRef<TresCanvasProps[K]>, undefined>) => void
-    watchOptions: WatchOptions
-    defaultValue: Exclude<UnwrapRef<TresCanvasProps[K]>, undefined>
-  }
-}
-
 // Properties that can be set directly on the renderer
 // Properties that can be set directly on the renderer
 const directProperties: Record<string, DirectProperty> = {
 const directProperties: Record<string, DirectProperty> = {
   toneMapping: {
   toneMapping: {
@@ -156,20 +119,81 @@ export function setupWebGLRenderer( // TODO object format? // TODO name like com
     immediate: true,
     immediate: true,
   })
   })
 
 
-  Object.values(propsToWatch).forEach(({ getter, setter, watchOptions, defaultValue }) => {
+  const createWatcher = <T>({
+    getFromProps,
+    setOnRenderer,
+    immediate,
+    defaultValue,
+  }: {
+    getFromProps: (props: TresCanvasProps) => T | undefined // TODO check if there is a better type than any
+    setOnRenderer: (renderer: WebGLRenderer, value: T) => void
+    immediate?: boolean
+    defaultValue: T
+  }) =>
     watch(
     watch(
-      () => getter(options),
+      () => getFromProps(options),
       (value) => {
       (value) => {
-        if (value === undefined) {
-          setter(initialRenderer, defaultValue)
-        }
-        setter(initialRenderer, value)
+        setOnRenderer(
+          initialRenderer,
+          value === undefined
+            ? defaultValue
+            : value,
+        )
         invalidateIfOnDemandMode()
         invalidateIfOnDemandMode()
       },
       },
-      watchOptions,
+      { immediate },
     )
     )
+
+  const clearColorAndAlpha = computed(() => {
+    const clearColor = toValue(options.clearColor)
+    const clearAlpha = toValue(options.clearAlpha)
+
+    const isClearColorWithAlpha = typeof clearColor === 'string' && clearColor.length === 9 && clearColor.startsWith('#')
+
+    if (isClearColorWithAlpha && clearAlpha !== undefined) {
+      throw new Error('clearColor and clearAlpha cannot both be set')
+    }
+
+    if (isClearColorWithAlpha) {
+      return {
+        alpha: Number.parseInt(clearColor.slice(7, 9), 16) / 255,
+        color: clearColor.slice(0, 7),
+      }
+    }
+
+    return {
+      alpha: clearAlpha,
+      color: clearColor,
+    }
   })
   })
 
 
+  const x: Record<NamesOfPropsThatCanChange, ReturnType<typeof createWatcher>> = {
+    toneMapping: createWatcher<ToneMapping>({
+      getFromProps: ({ toneMapping }) => toValue(toneMapping),
+      setOnRenderer: (renderer, value) => renderer.toneMapping = value,
+      immediate: true,
+      defaultValue: ACESFilmicToneMapping,
+    }),
+    shadows: createWatcher({
+      getFromProps: ({ shadows }) => toValue(shadows),
+      setOnRenderer: (renderer, value) => renderer.shadowMap.enabled = value,
+      immediate: true,
+      defaultValue: false,
+    }),
+    clearColor: createWatcher({
+      getFromProps: () => clearColorAndAlpha.value.color, // TODO name getFromProps doesn't fit anymore
+      setOnRenderer: (renderer, value) => renderer.setClearColor(value),
+      immediate: true,
+      defaultValue: '#000000',
+    }),
+    clearAlpha: createWatcher({
+      getFromProps: () => clearColorAndAlpha.value.alpha,
+      setOnRenderer: (renderer, value) => renderer.setClearAlpha(value),
+      immediate: true,
+      defaultValue: 1,
+    }),
+  }
+
   // Watch properties that need setter methods
   // Watch properties that need setter methods
   Object.entries(rendererPropertyHandlers).forEach(([key, handler]) => {
   Object.entries(rendererPropertyHandlers).forEach(([key, handler]) => {
     watch(
     watch(