Răsfoiți Sursa

chore: refactor components to sfc (#323)

Alvaro Saburido 1 an în urmă
părinte
comite
4dae415e1f

+ 1 - 1
.vscode/settings.json

@@ -5,7 +5,7 @@
   "editor.formatOnSave": true,
   "editor.defaultFormatter": "esbenp.prettier-vscode",
   "[vue]": {
-    "editor.defaultFormatter": "esbenp.prettier-vscode"
+    "editor.defaultFormatter": "Vue.volar"
   },
   "[javascript]": {
     "editor.defaultFormatter": "esbenp.prettier-vscode"

+ 1 - 1
playground/src/components/DebugUI.vue

@@ -28,7 +28,7 @@ useControls('Box', boxPosition.value)
     <TresPerspectiveCamera :position="[3, 3, 3]" />
     <OrbitControls />
     <Box :position-x="boxPosition[0]">
-      <TresMeshNormalMaterial  />
+      <TresMeshNormalMaterial />
     </Box>
     <TresGridHelper />
     <TresAmbientLight :intensity="1" />

+ 0 - 57
src/components/TresCanvas.ts

@@ -1,57 +0,0 @@
-import { TresScene } from './TresScene'
-import { defineComponent, h } from 'vue'
-import { ColorSpace, ShadowMapType, ToneMapping } from 'three'
-import { CameraType, useTresProvider } from '../composables'
-import { RendererPresetsType } from '../composables/useRenderer/const'
-import { Component } from 'vue'
-
-export interface TresCanvasProps {
-  shadows?: boolean
-  shadowMapType?: ShadowMapType
-  physicallyCorrectLights?: boolean
-  useLegacyLights?: boolean
-  outputColorSpace?: ColorSpace
-  toneMapping?: ToneMapping
-  toneMappingExposure?: number
-  context?: WebGLRenderingContext
-  powerPreference?: 'high-performance' | 'low-power' | 'default'
-  preserveDrawingBuffer?: boolean
-  clearColor?: string
-  windowSize?: boolean
-  preset?: RendererPresetsType
-  disableRender?: boolean
-  camera?: CameraType
-}
-/**
- * Vue component for rendering a Tres component.
- */
-
-export const TresCanvas = defineComponent<TresCanvasProps>({
-  name: 'TresCanvas',
-  props: [
-    'shadows',
-    'shadowMapType',
-    'physicallyCorrectLights',
-    'useLegacyLights',
-    'outputColorSpace',
-    'toneMapping',
-    'toneMappingExposure',
-    'context',
-    'powerPreference',
-    'preserveDrawingBuffer',
-    'clearColor',
-    'windowSize',
-    'preset',
-    'disableRender',
-    'camera',
-  ] as unknown as undefined,
-  setup(props, { slots, expose }) {
-    const tres = useTresProvider()
-
-    expose(tres)
-
-    return () => h(TresScene as Component, props, slots)
-  },
-})
-
-export default TresCanvas

+ 35 - 0
src/components/TresCanvas.vue

@@ -0,0 +1,35 @@
+<script setup lang="ts">
+import TresScene from './TresScene.vue'
+import { CameraType, useTresProvider } from '../composables'
+import { ColorSpace, ShadowMapType, ToneMapping } from 'three'
+import { RendererPresetsType } from '../composables/useRenderer/const'
+
+export type TresCanvasProps = {
+    shadows?: boolean
+    shadowMapType?: ShadowMapType
+    physicallyCorrectLights?: boolean
+    useLegacyLights?: boolean
+    outputColorSpace?: ColorSpace
+    toneMapping?: ToneMapping
+    toneMappingExposure?: number
+    context?: WebGLRenderingContext
+    powerPreference?: 'high-performance' | 'low-power' | 'default'
+    preserveDrawingBuffer?: boolean
+    clearColor?: string
+    windowSize?: boolean
+    preset?: RendererPresetsType
+    disableRender?: boolean
+    camera?: CameraType
+}
+
+defineProps<TresCanvasProps>()
+
+const tres = useTresProvider()
+
+defineExpose(tres)
+</script>
+<template>
+<TresScene v-bind="$props">
+    <slot />
+</TresScene>
+</template>

+ 0 - 213
src/components/TresScene.ts

@@ -1,213 +0,0 @@
-import { App, computed, defineComponent, h, onMounted, onUnmounted, ref, watch, watchEffect } from 'vue'
-import * as THREE from 'three'
-import { ColorSpace, ShadowMapType, ToneMapping } from 'three'
-import { createTres } from '../core/renderer'
-import { TresCamera } from '../types/'
-import {
-  CameraType,
-  TRES_CONTEXT_KEY,
-  useLogger,
-  useCamera,
-  useRenderer,
-  useRenderLoop,
-  useTres,
-  usePointerEventHandler,
-} from '../composables'
-import { extend } from '../core/catalogue'
-import { type RendererPresetsType } from '../composables/useRenderer/const'
-import { OBJECT_3D_USER_DATA_KEYS } from '../keys'
-
-export interface TresSceneProps {
-  shadows?: boolean
-  shadowMapType?: ShadowMapType
-  physicallyCorrectLights?: boolean
-  useLegacyLights?: boolean
-  outputColorSpace?: ColorSpace
-  toneMapping?: ToneMapping
-  toneMappingExposure?: number
-  context?: WebGLRenderingContext
-  powerPreference?: 'high-performance' | 'low-power' | 'default'
-  preserveDrawingBuffer?: boolean
-  clearColor?: string
-  windowSize?: boolean
-  preset?: RendererPresetsType
-  disableRender?: boolean
-  camera?: CameraType
-}
-/**
- * Vue component for rendering a Tres component.
- */
-
-const { logWarning } = useLogger()
-
-export const TresScene = defineComponent<TresSceneProps>({
-  name: 'TresScene',
-  props: [
-    'shadows',
-    'shadowMapType',
-    'physicallyCorrectLights',
-    'useLegacyLights',
-    'outputColorSpace',
-    'toneMapping',
-    'toneMappingExposure',
-    'context',
-    'powerPreference',
-    'preserveDrawingBuffer',
-    'clearColor',
-    'windowSize',
-    'preset',
-    'disableRender',
-    'camera',
-  ] as unknown as undefined,
-  setup(props, { slots, expose }) {
-    if (props.physicallyCorrectLights === true) {
-      logWarning('physicallyCorrectLights is deprecated, useLegacyLights is now false by default')
-    }
-
-    // TODO: refactor this when this component is refactored to SFC (single file component)
-    const isRenderDisabled = computed(() => props.disableRender !== false && props.disableRender !== undefined)
-
-    const container = ref<HTMLElement>()
-    const canvas = ref<HTMLElement>()
-
-    const scene = new THREE.Scene()
-
-    const pointerEventHandler = usePointerEventHandler()
-    const { setState } = useTres()
-
-    scene.userData[OBJECT_3D_USER_DATA_KEYS.REGISTER_AT_POINTER_EVENT_HANDLER] = pointerEventHandler.registerObject
-
-    setState('scene', scene)
-    setState('canvas', canvas)
-    setState('container', container)
-    setState('pointerEventHandler', pointerEventHandler)
-
-    const { onLoop, resume } = useRenderLoop()
-
-    onMounted(() => {
-      initRenderer()
-    })
-
-    onUnmounted(() => {
-      setState('renderer', null)
-    })
-
-    const { activeCamera, pushCamera, clearCameras } = useCamera()
-
-    function setCamera() {
-      const camera = scene.getObjectByProperty('isCamera', true)
-
-      if (!camera) {
-        // eslint-disable-next-line max-len
-        logWarning('No camera found. Creating a default perspective camera. To have full control over a camera, please add one to the scene.')
-        const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
-        camera.position.set(3,3,3)
-        camera.lookAt(0,0,0)
-        pushCamera(camera)
-      } else {
-
-        pushCamera(camera as TresCamera)
-      }
-    }
-
-    function initRenderer() {
-      const { renderer } = useRenderer(props)
-
-      if (props.camera) {
-        pushCamera(props.camera as any)
-      }
-
-      onLoop(() => {
-        if (activeCamera.value && !isRenderDisabled.value) renderer.value?.render(scene, activeCamera.value)
-      })
-    }
-
-    let app: App
-
-    function mountApp() {
-      app = createTres(slots)
-      const tres = useTres()
-      app.provide('useTres', tres)
-      app.provide(TRES_CONTEXT_KEY, tres)
-      app.provide('extend', extend)
-      app.mount(scene as unknown)
-      setCamera()
-    }
-    mountApp()
-
-    expose({
-      scene,
-    })
-
-    function dispose() {
-      scene.children = []
-      app.unmount()
-      app = createTres(slots)
-      app.provide('extend', extend)
-      app.mount(scene as unknown)
-      setCamera()
-      resume()
-    }
-
-    if (import.meta.hot) {
-      import.meta.hot.on('vite:afterUpdate', dispose)
-    }
-
-    watch(
-      () => props.camera,
-      camera => {
-        if (camera) {
-          clearCameras()
-          pushCamera(camera as any)
-        }
-      },
-    )
-
-    return () => {
-      return h(
-        h(
-          'div',
-          {
-            ref: container,
-            'data-scene': scene.uuid,
-            key: scene.uuid,
-            style: {
-              position: 'relative',
-              width: '100%',
-              height: '100%',
-              pointerEvents: 'auto',
-              touchAction: 'none',
-            },
-          },
-          [
-            h(
-              'div',
-              {
-                style: {
-                  width: '100%',
-                  height: '100%',
-                },
-              },
-              [
-                h('canvas', {
-                  ref: canvas,
-                  'data-scene': scene.uuid,
-                  style: {
-                    display: 'block',
-                    width: '100%',
-                    height: '100%',
-                    position: props.windowSize ? 'fixed' : 'absolute',
-                    top: 0,
-                    left: 0,
-                  },
-                }),
-              ],
-            ),
-          ],
-        ),
-      )
-    }
-  },
-})
-
-export default TresScene

+ 161 - 0
src/components/TresScene.vue

@@ -0,0 +1,161 @@
+<script setup lang="ts">
+import { App, onMounted, onUnmounted, ref, watch } from 'vue'
+import { PerspectiveCamera, Scene } from 'three'
+import { ColorSpace, ShadowMapType, ToneMapping } from 'three'
+import { createTres } from '../core/renderer'
+import { TresCamera } from '../types/'
+import {
+  CameraType,
+  TRES_CONTEXT_KEY,
+  useLogger,
+  useCamera,
+  useRenderer,
+  useRenderLoop,
+  useTres,
+  usePointerEventHandler,
+} from '../composables'
+import { extend } from '../core/catalogue'
+import { type RendererPresetsType } from '../composables/useRenderer/const'
+import { OBJECT_3D_USER_DATA_KEYS } from '../keys'
+
+
+export type TresSceneProps = {
+  shadows?: boolean
+  shadowMapType?: ShadowMapType
+  physicallyCorrectLights?: boolean
+  useLegacyLights?: boolean
+  outputColorSpace?: ColorSpace
+  toneMapping?: ToneMapping
+  toneMappingExposure?: number
+  context?: WebGLRenderingContext
+  powerPreference?: 'high-performance' | 'low-power' | 'default'
+  preserveDrawingBuffer?: boolean
+  clearColor?: string
+  windowSize?: boolean
+  preset?: RendererPresetsType
+  disableRender?: boolean
+  camera?: TresCamera
+}
+
+
+const { logWarning } = useLogger()
+
+const props = withDefaults(defineProps<TresSceneProps>(), {
+  physicallyCorrectLights: false,
+})
+
+if (props.physicallyCorrectLights === true) {
+  logWarning('physicallyCorrectLights is deprecated, useLegacyLights is now false by default')
+}
+
+const container = ref<HTMLElement>()
+const canvas = ref<HTMLElement>()
+const scene = new Scene()
+
+const pointerEventHandler = usePointerEventHandler()
+const { setState } = useTres()
+
+scene.userData[OBJECT_3D_USER_DATA_KEYS.REGISTER_AT_POINTER_EVENT_HANDLER] = pointerEventHandler.registerObject
+
+setState('scene', scene)
+setState('canvas', canvas)
+setState('container', container)
+setState('pointerEventHandler', pointerEventHandler)
+
+const { onLoop, resume } = useRenderLoop()
+
+const { activeCamera, pushCamera, clearCameras } = useCamera()
+
+onMounted(() => {
+  initRenderer()
+})
+
+onUnmounted(() => {
+  setState('renderer', null)
+})
+
+
+function setCamera() {
+  const camera = scene.getObjectByProperty('isCamera', true)
+
+  if (!camera) {
+    // eslint-disable-next-line max-len
+    logWarning('No camera found. Creating a default perspective camera. To have full control over a camera, please add one to the scene.')
+    const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
+    camera.position.set(3, 3, 3)
+    camera.lookAt(0, 0, 0)
+    pushCamera(camera)
+  } else {
+    pushCamera(camera as TresCamera)
+  }
+}
+
+function initRenderer() {
+  const { renderer } = useRenderer(props)
+
+  if (props.camera) {
+    pushCamera(props.camera)
+  }
+
+  onLoop(() => {
+    if (activeCamera.value && props.disableRender !== true) renderer.value?.render(scene, activeCamera.value)
+  })
+}
+
+let app: App
+
+const slots = defineSlots<{
+  default(): any
+}>()
+
+function mountApp() {
+  app = createTres(slots)
+  const tres = useTres()
+  app.provide('useTres', tres)
+  app.provide(TRES_CONTEXT_KEY, tres)
+  app.provide('extend', extend)
+  app.mount(scene as unknown)
+  setCamera()
+}
+mountApp()
+
+defineExpose({
+  scene
+})
+
+function dispose() {
+  scene.children = []
+  app.unmount()
+  app = createTres(slots)
+  app.provide('extend', extend)
+  app.mount(scene as unknown)
+  setCamera()
+  resume()
+}
+
+if (import.meta.hot) {
+  import.meta.hot.on('vite:afterUpdate', dispose)
+}
+
+watch(
+  () => props.camera,
+  camera => {
+    if (camera) {
+      clearCameras()
+      pushCamera(camera as any)
+    }
+  },
+)
+
+</script>
+
+<template>
+  <div ref="container" :key="scene.uuid" :data-scene="scene.uuid"
+    style="position: relative; width: 100%; height: 100%; pointerEvents: auto; touchAction: none;">
+    <div style="width: 100%; height: 100%;">
+      <canvas ref="canvas" :data-scene="scene.uuid"
+        :style="{ display: 'block', width: '100%', height: '100%', position: windowSize ? 'fixed' : 'absolute', top: 0, left: 0 }">
+      </canvas>
+    </div>
+  </div>
+</template>

+ 3 - 1
src/components/index.ts

@@ -1 +1,3 @@
-export * from './TresCanvas'
+import TresCanvas from './TresCanvas.vue'
+
+export { TresCanvas }

+ 4 - 3
src/composables/useCamera/index.ts

@@ -1,3 +1,4 @@
+import { TresCamera } from 'src/types'
 import { useTres } from '../useTres'
 import { PerspectiveCamera, OrthographicCamera } from 'three'
 
@@ -80,12 +81,12 @@ export interface OrthographicCameraOptions {
 }
 
 interface UseCameraReturn {
-  activeCamera: Ref<Camera | undefined>
+  activeCamera: Ref<TresCamera | undefined>
   createCamera: (cameraType?: CameraType, options?: PerspectiveCameraOptions | OrthographicCameraOptions) => Camera
   updateCamera: () => void
-  pushCamera: (camera: Camera) => void
+  pushCamera: (camera: TresCamera) => void
   clearCameras: () => void
-  setFirstCamera: (camera: Camera) => void
+  setFirstCamera: (camera: TresCamera) => void
 }
 
 const VERTICAL_FIELD_OF_VIEW = 45

+ 1 - 1
src/index.ts

@@ -1,5 +1,5 @@
 import { App } from 'vue'
-import { TresCanvas } from './components/TresCanvas'
+import TresCanvas from './components/TresCanvas.vue'
 export * from './composables'
 export * from './core/catalogue'
 export * from './components'