浏览代码

feat: wip better typing

alvarosabu 2 月之前
父节点
当前提交
74ab411705

+ 3 - 4
playground/vue/src/pages/advanced/webGPU/index.vue

@@ -1,13 +1,13 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { TresCanvas } from '@tresjs/core'
 import { TresCanvas } from '@tresjs/core'
 import { WebGPURenderer } from 'three/webgpu'
 import { WebGPURenderer } from 'three/webgpu'
-import type { TresContext } from '@tresjs/core'
+import type { TresRendererSetupContext } from '@tresjs/core'
 import { OrbitControls } from '@tresjs/cientos'
 import { OrbitControls } from '@tresjs/cientos'
 import HologramCube from './HologramCube.vue'
 import HologramCube from './HologramCube.vue'
 
 
-const createWebGPURenderer = async (ctx: TresContext) => {
+const createWebGPURenderer = async (ctx: TresRendererSetupContext) => {
   const renderer = new WebGPURenderer({
   const renderer = new WebGPURenderer({
-    canvas: ctx.canvas.value,
+    canvas: toValue(ctx.canvas),
     // WebGPU specific configuration
     // WebGPU specific configuration
     alpha: true,
     alpha: true,
     antialias: true,
     antialias: true,
@@ -24,7 +24,6 @@ const createWebGPURenderer = async (ctx: TresContext) => {
   }, {
   }, {
     immediate: true,
     immediate: true,
   })
   })
-
   return renderer
   return renderer
 }
 }
 </script>
 </script>

+ 6 - 6
src/components/TresCanvas.vue

@@ -3,7 +3,7 @@ import type { App, MaybeRefOrGetter, Ref } from 'vue'
 import type { TresObject, TresScene } from '../types/'
 import type { TresObject, TresScene } from '../types/'
 import { ACESFilmicToneMapping, PCFSoftShadowMap, PerspectiveCamera, Scene } from 'three'
 import { ACESFilmicToneMapping, PCFSoftShadowMap, PerspectiveCamera, Scene } from 'three'
 import * as THREE from 'three'
 import * as THREE from 'three'
-import type { TresContext } from '../composables'
+import type { TresContext, TresRendererSetupContext } from '../composables'
 import { useTresContextProvider } from '../composables'
 import { useTresContextProvider } from '../composables'
 import type { TransformToMaybeRefOrGetter, TresCamera, TresRenderer } from '../types'
 import type { TransformToMaybeRefOrGetter, TresCamera, TresRenderer } from '../types'
 import type { ColorSpace, ShadowMapType, ToneMapping, WebGLRendererParameters } from 'three'
 import type { ColorSpace, ShadowMapType, ToneMapping, WebGLRendererParameters } from 'three'
@@ -69,7 +69,7 @@ const slots = defineSlots<{
   default: () => any
   default: () => any
 }>()
 }>()
 
 
-const canvas = ref<HTMLCanvasElement>()
+const canvasRef = ref<HTMLCanvasElement>()
 
 
 /*
 /*
  `scene` is defined here and not in `useTresContextProvider` because the custom
  `scene` is defined here and not in `useTresContextProvider` because the custom
@@ -130,7 +130,7 @@ const mountCustomRenderer = (context: TresContext, empty = false) => {
 
 
 const dispose = (context: TresContext, force = false) => {
 const dispose = (context: TresContext, force = false) => {
   disposeObject3D(context.scene.value as unknown as TresObject)
   disposeObject3D(context.scene.value as unknown as TresObject)
-  if (force) {
+  if (force && context.renderer.value) {
     context.renderer.value.dispose()
     context.renderer.value.dispose()
     context.renderer.value.renderLists.dispose()
     context.renderer.value.renderLists.dispose()
     context.renderer.value.forceContextLoss()
     context.renderer.value.forceContextLoss()
@@ -155,7 +155,7 @@ const unmountCanvas = () => {
 }
 }
 
 
 onMounted(async () => {
 onMounted(async () => {
-  const existingCanvas = canvas as Ref<HTMLCanvasElement>
+  const existingCanvas = canvasRef.value as Ref<HTMLCanvasElement>
 
 
   context.value = await useTresContextProvider({
   context.value = await useTresContextProvider({
     scene: scene.value as TresScene,
     scene: scene.value as TresScene,
@@ -368,7 +368,7 @@ export interface TresCanvasProps extends /* @vue-ignore */ WebGLRendererProps {
    * Custom WebGL renderer instance
    * Custom WebGL renderer instance
    * Allows using a pre-configured renderer instead of creating a new one
    * Allows using a pre-configured renderer instead of creating a new one
    */
    */
-  renderer?: (ctx: TresContext) => Promise<TresRenderer>
+  renderer?: (ctx: TresRendererSetupContext) => Promise<TresRenderer>
 
 
   /**
   /**
    * Custom camera instance to use as main camera
    * Custom camera instance to use as main camera
@@ -394,7 +394,7 @@ export interface TresCanvasProps extends /* @vue-ignore */ WebGLRendererProps {
 
 
 <template>
 <template>
   <canvas
   <canvas
-    ref="canvas"
+    ref="canvasRef"
     :data-scene="scene.uuid"
     :data-scene="scene.uuid"
     :class="$attrs.class"
     :class="$attrs.class"
     :data-tres="`tresjs ${pkg.version}`"
     :data-tres="`tresjs ${pkg.version}`"

+ 22 - 10
src/composables/useTresContextProvider/index.ts

@@ -1,6 +1,6 @@
 import type { Camera } from 'three'
 import type { Camera } from 'three'
 import { Raycaster, WebGLRenderer } from 'three'
 import { Raycaster, WebGLRenderer } from 'three'
-import type { ComputedRef, DeepReadonly, MaybeRefOrGetter, Ref, ShallowRef } from 'vue'
+import type { ComputedRef, DeepReadonly, MaybeRef, MaybeRefOrGetter, Ref, ShallowRef } from 'vue'
 import type { RendererLoop } from '../../core/loop'
 import type { RendererLoop } from '../../core/loop'
 import type { EmitEventFn, Renderer, TresControl, TresObject, TresScene } from '../../types'
 import type { EmitEventFn, Renderer, TresControl, TresObject, TresScene } from '../../types'
 
 
@@ -52,11 +52,10 @@ export interface PerformanceState {
 export interface TresContext {
 export interface TresContext {
   scene: ShallowRef<TresScene>
   scene: ShallowRef<TresScene>
   sizes: SizesType
   sizes: SizesType
-  extend: (objects: any) => void
   camera: ComputedRef<Camera | undefined>
   camera: ComputedRef<Camera | undefined>
   cameras: DeepReadonly<Ref<Camera[]>>
   cameras: DeepReadonly<Ref<Camera[]>>
   controls: Ref<TresControl | null>
   controls: Ref<TresControl | null>
-  renderer: ShallowRef<Renderer>
+  renderer: ShallowRef<Renderer | null>
   canvas: Ref<HTMLCanvasElement>
   canvas: Ref<HTMLCanvasElement>
   raycaster: ShallowRef<Raycaster>
   raycaster: ShallowRef<Raycaster>
   perf: PerformanceState
   perf: PerformanceState
@@ -85,6 +84,11 @@ export interface TresContext {
   deregisterBlockingObjectAtPointerEventHandler?: (object: TresObject) => void
   deregisterBlockingObjectAtPointerEventHandler?: (object: TresObject) => void
 }
 }
 
 
+export type TresRendererSetupContext = Pick<
+  TresContext,
+  'sizes' | 'scene' | 'camera' | 'renderer' | 'canvas' | 'invalidate' | 'advance'
+>
+
 export async function useTresContextProvider({
 export async function useTresContextProvider({
   scene,
   scene,
   canvas,
   canvas,
@@ -93,7 +97,7 @@ export async function useTresContextProvider({
   emit,
   emit,
 }: {
 }: {
   scene: TresScene
   scene: TresScene
-  canvas: Ref<HTMLCanvasElement>
+  canvas: MaybeRef<HTMLCanvasElement>
   windowSize: MaybeRefOrGetter<boolean>
   windowSize: MaybeRefOrGetter<boolean>
   rendererOptions: TresCanvasProps
   rendererOptions: TresCanvasProps
   emit: EmitEventFn
   emit: EmitEventFn
@@ -138,7 +142,7 @@ export async function useTresContextProvider({
     scene: localScene,
     scene: localScene,
     camera,
     camera,
     cameras: readonly(cameras),
     cameras: readonly(cameras),
-    renderer: shallowRef(null as unknown as Renderer),
+    renderer: shallowRef(null),
     raycaster: shallowRef(new Raycaster()),
     raycaster: shallowRef(new Raycaster()),
     canvas,
     canvas,
     controls: ref(null),
     controls: ref(null),
@@ -167,10 +171,16 @@ export async function useTresContextProvider({
   provide('useTres', ctx)
   provide('useTres', ctx)
 
 
   // Renderer
   // Renderer
-  const renderer = await createRenderer(ctx, rendererOptions)
+  const renderer = await createRenderer({
+    sizes,
+    scene: localScene,
+    camera,
+  }, rendererOptions)
   // Only setup the renderer with Canvas props if it is a WebGLRenderer
   // Only setup the renderer with Canvas props if it is a WebGLRenderer
   if (renderer instanceof WebGLRenderer) {
   if (renderer instanceof WebGLRenderer) {
-    setupWebGLRenderer(renderer, rendererOptions, ctx)
+    setupWebGLRenderer(renderer, rendererOptions, {
+
+    })
   }
   }
   ctx.renderer.value = renderer
   ctx.renderer.value = renderer
 
 
@@ -182,7 +192,7 @@ export async function useTresContextProvider({
   // The loop
   // The loop
 
 
   ctx.loop.register(() => {
   ctx.loop.register(() => {
-    if (camera.value && render.frames.value > 0) {
+    if (ctx.renderer.value && camera.value && render.frames.value > 0) {
       ctx.renderer.value.render(scene, camera.value)
       ctx.renderer.value.render(scene, camera.value)
       emit('render', ctx.renderer.value)
       emit('render', ctx.renderer.value)
     }
     }
@@ -210,8 +220,10 @@ export async function useTresContextProvider({
   })
   })
 
 
   onUnmounted(() => {
   onUnmounted(() => {
-    ctx.renderer.value.dispose()
-    ctx.renderer.value.forceContextLoss()
+    if (ctx.renderer.value) {
+      ctx.renderer.value.dispose()
+      ctx.renderer.value.forceContextLoss()
+    }
     cancelTresReady()
     cancelTresReady()
     ctx.loop.stop()
     ctx.loop.stop()
   })
   })

+ 1 - 0
src/core/catalogue.ts

@@ -2,6 +2,7 @@ import type { Ref } from 'vue'
 import type { TresCatalogue } from '../types'
 import type { TresCatalogue } from '../types'
 import { ref } from 'vue'
 import { ref } from 'vue'
 
 
+// TODO: This should be a composable and not a global ref
 export const catalogue: Ref<TresCatalogue> = ref({})
 export const catalogue: Ref<TresCatalogue> = ref({})
 
 
 export const extend = (objects: any) => Object.assign(catalogue.value, objects)
 export const extend = (objects: any) => Object.assign(catalogue.value, objects)

+ 4 - 3
src/core/createRenderer.ts

@@ -1,8 +1,9 @@
 import { WebGLRenderer } from 'three'
 import { WebGLRenderer } from 'three'
-import * as is from '../utils/is'
 import type { TresContext } from '../composables'
 import type { TresContext } from '../composables'
 import type { TresRenderer } from '../types'
 import type { TresRenderer } from '../types'
 import type { TresCanvasProps } from '../components/TresCanvas.vue'
 import type { TresCanvasProps } from '../components/TresCanvas.vue'
+import { toValue } from 'vue'
+import { isObject } from '../utils/is'
 
 
 export async function createRenderer(ctx: TresContext, options: TresCanvasProps): Promise<TresRenderer> {
 export async function createRenderer(ctx: TresContext, options: TresCanvasProps): Promise<TresRenderer> {
   if (options.renderer) {
   if (options.renderer) {
@@ -14,8 +15,8 @@ export async function createRenderer(ctx: TresContext, options: TresCanvasProps)
   }
   }
 
 
   const rendererConstructorArgs = {
   const rendererConstructorArgs = {
-    ...(is.obj(options) ? options : {}),
-    canvas: ctx.canvas.value,
+    ...(isObject(options) ? options : {}),
+    canvas: toValue(ctx.canvas),
   }
   }
   const renderer = new WebGLRenderer(rendererConstructorArgs)
   const renderer = new WebGLRenderer(rendererConstructorArgs)
 
 

+ 4 - 3
src/core/setupRenderer.ts

@@ -1,10 +1,11 @@
-import type { TresContext } from 'src/composables/useTresContextProvider'
+import type { TresContext, TresPartialContext } from '../composables/useTresContextProvider'
 import type { ColorRepresentation, Object3D, WebGLRenderer } from 'three'
 import type { ColorRepresentation, Object3D, WebGLRenderer } from 'three'
 import { watch } from 'vue'
 import { watch } from 'vue'
 import { useDevicePixelRatio } from '@vueuse/core'
 import { useDevicePixelRatio } from '@vueuse/core'
 import { setPixelRatio } from '../utils'
 import { setPixelRatio } from '../utils'
 
 
 import { Mesh } from 'three'
 import { Mesh } from 'three'
+import type { TresCanvasProps } from '../components/TresCanvas.vue'
 
 
 interface PropertyHandler<T = unknown> {
 interface PropertyHandler<T = unknown> {
   set: (renderer: WebGLRenderer, value: T) => void
   set: (renderer: WebGLRenderer, value: T) => void
@@ -71,8 +72,8 @@ const rendererPropertyHandlers: Record<string, PropertyHandler<ColorRepresentati
 // Modified setup function to handle both types of properties
 // Modified setup function to handle both types of properties
 export function setupWebGLRenderer(
 export function setupWebGLRenderer(
   initialRenderer: WebGLRenderer,
   initialRenderer: WebGLRenderer,
-  options: Record<string, any>,
-  ctx: TresContext,
+  options: TresCanvasProps,
+  ctx: TresPartialContext,
 ) {
 ) {
   const { pixelRatio } = useDevicePixelRatio()
   const { pixelRatio } = useDevicePixelRatio()
   const { invalidate } = ctx
   const { invalidate } = ctx