Browse Source

feat(core): extend reactive catalog

Alvaro 2 years ago
parent
commit
a6bc3f9e6e

+ 7 - 3
packages/tres/src/App.vue

@@ -1,12 +1,16 @@
 <script setup lang="ts">
+import { useCatalogue } from '/@/core'
 import { Color } from 'three'
 import { useTweakPane, OrbitControls } from '../../cientos/src'
 import TestSphere from '/@/components/TestSphere.vue'
+import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry'
 
 const colorTeal = new Color('teal')
 useTweakPane()
 
-const meshPosition = [0, 1, 0]
+const { extend } = useCatalogue()
+
+extend({ TextGeometry: TextGeometry })
 </script>
 <template>
   <Suspense>
@@ -14,8 +18,8 @@ const meshPosition = [0, 1, 0]
       <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
       <TresScene>
         <OrbitControls />
-        <TresMesh :position="meshPosition" :scale="1">
-          <TresSphereGeometry />
+        <TresMesh>
+          <TresTextGeometry :args="['Awiwi']" :position="[-8, 3, -3]" :scale="0.5" />
           <TresMeshToonMaterial :color="colorTeal" />
         </TresMesh>
         <TestSphere />

+ 19 - 6
packages/tres/src/core/useCatalogue/index.ts

@@ -1,14 +1,27 @@
+import { useInstanceCreator } from '/@/core'
+import { App, ref, Component, Ref } from 'vue'
 import * as THREE from 'three'
+import { TresCatalogue } from '/@/types'
 
-let catalogue: {
-  [key: string]: any
-} = { ...THREE }
+const catalogue: Ref<TresCatalogue> = ref({ ...THREE })
 
-delete catalogue.Scene
+delete catalogue.value.Scene
+
+let localApp: App
+
+export function useCatalogue(app?: App, prefix = 'Tres') {
+  if (!localApp && app) {
+    localApp = app
+  }
+  const { createComponentInstances } = useInstanceCreator(prefix)
 
-export function useCatalogue() {
   const extend = (objects: any) => {
-    catalogue = Object.assign(catalogue, objects)
+    catalogue.value = Object.assign(catalogue.value, objects)
+    const components = createComponentInstances(ref(objects))
+
+    components.forEach(([key, cmp]) => {
+      localApp.component(key as string, cmp as Component)
+    })
   }
 
   return {

+ 15 - 15
packages/tres/src/core/useInstanceCreator/index.ts

@@ -1,8 +1,8 @@
 import { OrthographicCamera } from 'three'
 /* eslint-disable new-cap */
 /* eslint-disable @typescript-eslint/no-empty-function */
-import { Object3D, PerspectiveCamera } from 'three'
-import { defineComponent } from 'vue'
+import { PerspectiveCamera } from 'three'
+import { defineComponent, Ref } from 'vue'
 import { isArray, isDefined, isFunction } from '@alvarosabu/utils'
 import { normalizeVectorFlexibleParam } from '/@/utils/normalize'
 import { useCamera, useScene } from '/@/core/'
@@ -61,17 +61,17 @@ export function useInstanceCreator(prefix: string) {
     })
   }
 
-  function createInstanceFromVNode(vnode: TresVNode, catalogue: TresCatalogue): TresInstance {
+  function createInstanceFromVNode(vnode: TresVNode, catalogue: Ref<TresCatalogue>): TresInstance {
     const vNodeType = ((vnode.type as TresVNodeType).name as string).replace(prefix, '')
 
     // check if args prop is defined on the vnode
     let internalInstance
     if (vnode?.props?.args) {
       // if args prop is defined, create new instance of catalogue[vNodeType] with the provided arguments
-      internalInstance = new catalogue[vNodeType](...vnode.props.args)
+      internalInstance = new catalogue.value[vNodeType](...vnode.props.args)
     } else {
       // if args prop is not defined, create a new instance of catalogue[vNodeType] without arguments
-      internalInstance = new catalogue[vNodeType]()
+      internalInstance = new catalogue.value[vNodeType]()
     }
 
     // check if props is defined on the vnode
@@ -84,7 +84,7 @@ export function useInstanceCreator(prefix: string) {
   }
 
   function createInstance(
-    catalogue: Record<string, any>,
+    catalogue: Ref<TresCatalogue>,
     threeObj: any,
     attrs: TresAttributes,
     slots: Record<string, any>,
@@ -109,20 +109,14 @@ export function useInstanceCreator(prefix: string) {
     }
   }
 
-  function createComponentInstances(catalogue: Record<string, any>) {
-    return Object.entries(catalogue)
+  function createComponentInstances(catalogue: Ref<TresCatalogue>) {
+    return Object.entries(catalogue.value)
       .filter(([_key, value]) => (value as { prototype: any })?.prototype?.constructor?.toString().includes('class'))
       .map(([key, threeObj]) => {
         const name = `${prefix}${key}`
         const cmp = defineComponent({
           name,
           setup(props, { slots, attrs, ...ctx }) {
-            logMessage(name, {
-              props,
-              slots,
-              attrs,
-              ctx,
-            })
             const { scene } = useScene()
             const { pushCamera } = useCamera()
 
@@ -139,7 +133,13 @@ export function useInstanceCreator(prefix: string) {
             }
 
             ctx.expose(instance)
-
+            logMessage(name, {
+              props,
+              slots,
+              attrs,
+              ctx,
+              scene,
+            })
             return () => {}
           },
         })

+ 10 - 3
packages/tres/src/index.ts

@@ -1,4 +1,4 @@
-import { App, Component } from 'vue'
+import { App, Component, watchEffect } from 'vue'
 import { TresCanvas } from '/@/core/useRenderer/component'
 import { Scene } from '/@/core/useScene/component'
 import { useCatalogue, useInstanceCreator } from '/@/core'
@@ -19,12 +19,19 @@ const plugin: TresPlugin = {
     const prefix = options?.prefix || 'Tres'
     app.component(`${prefix}Canvas`, TresCanvas)
     app.component(`${prefix}Scene`, Scene)
-    const { catalogue } = useCatalogue()
+    const { catalogue } = useCatalogue(app, prefix)
     const { createComponentInstances } = useInstanceCreator(prefix)
-    const components = createComponentInstances(options?.extends ? { ...catalogue, ...options.extends } : catalogue)
+    const components = createComponentInstances(catalogue)
+    /*  const components = createComponentInstances(
+      options?.extends ? { ...catalogue, ...options.extends } : catalogue,
+    ) */
     components.forEach(([key, cmp]) => {
       app.component(key as string, cmp as Component)
     })
+
+    watchEffect(() => {
+      console.log({ catalogue })
+    })
   },
 }