Przeglądaj źródła

feat(core): cleaning up a little bit

alvarosabu 2 lat temu
rodzic
commit
8bdd825d64

+ 16 - 11
packages/tres/src/App.vue

@@ -2,37 +2,39 @@
 import { ref, watchEffect } from 'vue'
 import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
 import TresCanvas from './components/TresCanvas'
-import AkuAku from './demos/AkuAku.vue'
 import { useRenderLoop, useTres } from '/@/composables'
+import { extend } from './core/catalogue'
 // import TheEvents from '/@/components/TheEvents.vue'
 const gl = {
   antialias: true,
   alpha: true,
+  shadows: true,
   clearColor: '#82DBC5',
 }
 
 const { state } = useTres()
-let controls = null
+
+extend({ OrbitControls })
 
 const { onLoop } = useRenderLoop()
 
 watchEffect(() => {
   if (state.camera && state.renderer) {
-    controls = new OrbitControls(state.camera, state.renderer.domElement)
+    /*  controls = new OrbitControls(state.camera, state.renderer.domElement)
     controls.enableDamping = true
     controls.dampingFactor = 0.05
     controls.screenSpacePanning = false
     controls.minDistance = 1
     controls.maxDistance = 500
-    controls.maxPolarAngle = Math.PI / 2
+    controls.maxPolarAngle = Math.PI / 2 */
   }
 })
 
-onLoop(() => {
+/* onLoop(() => {
   if (controls) {
     controls.update()
   }
-})
+}) */
 
 const gridVisible = ref(false)
 function click(e) {
@@ -45,17 +47,20 @@ function enter(e) {
 </script>
 
 <template>
-  <button @click="click">{{ gridVisible }}</button>
-  <p v-if="gridVisible">Soc invisible</p>
   <TresCanvas v-bind="gl">
     <TresPerspectiveCamera :args="[75, 1, 0.1, 1000]" :position="[0, 2, 7]"></TresPerspectiveCamera>
+    <TresOrbitControls v-if="state.camera" :args="[state.camera, state.renderer.domElement]" />
     <TresAmbientLight :color="0xffffff" :intensity="0.75" />
-    <TresDirectionalLight :color="0xffffff" :intensity="2" :position="[-2, 2, 0]" />
-    <TresMesh :position="[0, 1, 0]" @click="click" @pointer-enter="enter">
+    <TresDirectionalLight :color="0xffffff" :intensity="2" :position="[-2, 2, 0]" cast-shadow />
+    <TresMesh :position="[0, 3, 0]" @click="click" @pointer-enter="enter" cast-shadow>
       <TresSphereGeometry :args="[1, 32, 16]"></TresSphereGeometry>
       <TresMeshToonMaterial color="teal"></TresMeshToonMaterial>
     </TresMesh>
-    <TresGridHelper v-if="gridVisible" :args="[4, 4]"></TresGridHelper>
+    <TresMesh :position="[0, 0, 0]" receive-shadow :rotation-x="-Math.PI / 2">
+      <TresPlaneGeometry :args="[12, 12, 100, 100]"></TresPlaneGeometry>
+      <TresMeshToonMaterial color="gray"></TresMeshToonMaterial>
+    </TresMesh>
+    <TresGridHelper :args="[4, 4]"></TresGridHelper>
   </TresCanvas>
 </template>
 

+ 5 - 21
packages/tres/src/components/TresCanvas.ts

@@ -1,10 +1,9 @@
-import { defineComponent, h, PropType, ref, watch, watchEffect, compile } from 'vue'
-/* eslint-disable vue/one-component-per-file */
+import { defineComponent, h, PropType, ref, watch } from 'vue'
 import * as THREE from 'three'
-import { ShadowMapType, TextureEncoding, ToneMapping, Scene } from 'three'
+import { ShadowMapType, TextureEncoding, ToneMapping } from 'three'
 import { createTres } from '/@/core/renderer'
 import { useCamera, useRenderer, useRenderLoop, useRaycaster } from '/@/composables'
-import TestRenderer from './TestRenderer.vue'
+import { TresObject } from '../types'
 
 export const TresCanvas = defineComponent({
   name: 'TresCanvas',
@@ -53,22 +52,11 @@ export const TresCanvas = defineComponent({
       })
 
       const app = createTres(slots)
-      app.mount(scene)
+      app.mount(scene as unknown as TresObject)
 
-      watchEffect(() => {
-        if (slots) {
-          console.log('slots', slots)
-        }
-      })
-
-      console.log({
-        app,
-        scene,
-        TestRenderer,
-      })
+      console.log({ scene, renderer })
       expose({
         scene,
-        /*  app, */
       })
     })
 
@@ -78,13 +66,10 @@ export const TresCanvas = defineComponent({
           'div',
           {
             ref: container,
-            'data-v-app': true,
-            id: 'container',
             style: {
               position: 'relative',
               width: '100%',
               height: '100%',
-
               pointerEvents: 'auto',
               touchAction: 'none',
             },
@@ -110,7 +95,6 @@ export const TresCanvas = defineComponent({
                     left: 0,
                   },
                 }),
-                /* ...(slots.default ? slots?.default() : [] || []), */
               ],
             ),
           ],

+ 27 - 99
packages/tres/src/core/nodeOps.ts

@@ -1,32 +1,10 @@
-import { useCamera, useRaycaster, useRenderLoop } from '/@/composables'
+import { Mesh } from 'three'
+import { useCamera, useRaycaster, useRenderLoop, useLogger } from '/@/composables'
 import { RendererOptions } from 'vue'
-import { useLogger } from '/@/composables'
 import { catalogue } from './catalogue'
-import { Mesh } from 'three'
 import { useEventListener } from '@vueuse/core'
 import { TresEvent, TresObject } from '../types'
-
-const HTML_TAGS =
-  'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
-  'header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' +
-  'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
-  'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' +
-  'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
-  'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
-  'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
-  'option,output,progress,select,textarea,details,dialog,menu,' +
-  'summary,template,blockquote,iframe,tfoot'
-
-export const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS)
-
-export function makeMap(str: string, expectsLowerCase?: boolean): (key: string) => boolean {
-  const map: Record<string, boolean> = Object.create(null)
-  const list: Array<string> = str.split(',')
-  for (let i = 0; i < list.length; i++) {
-    map[list[i]] = true
-  }
-  return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val]
-}
+import { isHTMLTag, kebabToCamel } from '../utils'
 
 const { logWarning } = useLogger()
 
@@ -43,33 +21,17 @@ function noop(fn: string): any {
   fn
 }
 
-const doc = (typeof document !== 'undefined' ? document : null) as Document
-export const svgNS = 'http://www.w3.org/2000/svg'
-
-const templateContainer = doc && /*#__PURE__*/ doc.createElement('template')
+let scene: TresObject | null = null
 
-let scene = null
-
-export const nodeOps: RendererOptions<any, any> = {
-  createElement(tag, isSVG, anchor, props) {
-    // Vue core
-    /* const el = isSVG ? doc.createElementNS(svgNS, tag) : doc.createElement(tag, anchor ? { anchor } : undefined)
-
-    if (tag === 'select' && props && props.multiple != null) {
-      ;(el as HTMLSelectElement).setAttribute('multiple', props.multiple)
-    }
-
-    return el */
-    // Tres
+export const nodeOps: RendererOptions<TresObject, TresObject> = {
+  createElement(tag, _isSVG, _anchor, props) {
     if (tag === 'template') return null
     if (isHTMLTag(tag)) return null
     let instance
 
-    if (props === null) {
-      props = {}
-    }
+    if (props === null) props = {}
 
-    if (props?.arg) {
+    if (props?.args) {
       instance = new catalogue[tag.replace('Tres', '')](...props.args)
     } else {
       instance = new catalogue[tag.replace('Tres', '')]()
@@ -103,7 +65,7 @@ export const nodeOps: RendererOptions<any, any> = {
   },
   insert(child, parent, anchor) {
     if (scene === null && parent.isScene) scene = parent
-    if (parent === null) parent = scene
+    if (parent === null) parent = scene as TresObject
     //vue core
     /*  parent.insertBefore(child, anchor || null) */
     if (parent?.isObject3D && child?.isObject3D) {
@@ -157,48 +119,30 @@ export const nodeOps: RendererOptions<any, any> = {
     }
   },
   remove(node) {
-    // Vue Core
+    if (!node) return
     const parent = node.parentNode
     if (parent) {
       parent.removeChild(node)
     }
-    /* if (!node) return
-    const parent = node.parent
-    if (parent) {
-      if (parent.isObject3D && node.isObject3D) {
-        parent.remove(node)
-      } else if (typeof node.attach === 'string') {
-        parent[node.attach] = node.__previousAttach
-        delete node.__previousAttach
-        node.parent = null
-      }
-    }
-
-    node.dispose?.()
-    node.traverse?.(node => {
-      ;(node as TresObject).dispose?.()
-    }) */
   },
-  patchProp(node, prop, prevValue, nextValue) {
+  patchProp(node, prop, _prevValue, nextValue) {
     if (node) {
       let root = node
       let key = prop
-      let target = root?.[key]
+      let target = root?.[kebabToCamel(key)]
+
       // Traverse pierced props (e.g. foo-bar=value => foo.bar = value)
-      /* if (key.includes('-')) {
+      if (key.includes('-') && !Object.keys(root).includes(kebabToCamel(key))) {
         const chain = key.split('-')
         target = chain.reduce((acc, key) => acc[key], root)
         key = chain.pop() as string
-  
+
         if (!target?.set) root = chain.reduce((acc, key) => acc[key], root)
-      } */
-      const value = nextValue
-      /*   try {
-        const num = parseFloat(value)
-        value = isNaN(num) ? value : num
-      } catch (_) {} */
+      }
+      let value = nextValue
+      if (value === '') value = true
       // Set prop, prefer atomic methods if applicable
-      if (!target?.set) root[key] = value
+      if (!target?.set) root[kebabToCamel(key)] = value
       else if (target.constructor === value.constructor && target?.copy) target?.copy(value)
       else if (Array.isArray(value)) target.set(...value)
       else if (!target.isColor && target.setScalar) target.setScalar(value)
@@ -207,36 +151,20 @@ export const nodeOps: RendererOptions<any, any> = {
   },
 
   parentNode(node) {
-    // Vue core
-    return node.parentNode as Element | null
-    /*  return node?.parent || null */
+    return node?.parent || null
   },
-  createText: text => doc.createTextNode(text),
+  createText: () => noop('createText'),
 
-  createComment: text => doc.createComment(text),
+  createComment: () => noop('createComment'),
 
-  setText: (node, text) => {
-    node.nodeValue = text
-  },
+  setText: () => noop('setText'),
 
-  setElementText: (el, text) => {
-    el.textContent = text
-  },
-  nextSibling: node => node.nextSibling,
+  setElementText: () => noop('setElementText'),
+  nextSibling: () => noop('nextSibling'),
 
-  querySelector: selector => doc.querySelector(selector),
+  querySelector: () => noop('querySelector'),
 
-  setScopeId(el, id) {
-    /* el.setAttribute(id, '') */
-  },
+  setScopeId: () => noop('setScopeId'),
   cloneNode: () => noop('cloneNode'),
   insertStaticContent: () => noop('insertStaticContent'),
-
-  /* nextSibling(node) {
-    if (node?.parent?.children) {
-      const index = node.parent.children.indexOf(node)
-      if (index !== -1) return node.parent.children[index + 1]
-    }
-    return null
-  }, */
 }

+ 3 - 30
packages/tres/src/core/renderer.ts

@@ -1,43 +1,16 @@
-import { isString } from '@vueuse/core'
 import * as THREE from 'three'
 
-import { createRenderer } from 'vue'
+import { createRenderer, Slots } from 'vue'
 import { extend } from './catalogue'
 import { nodeOps } from './nodeOps'
 
-function normalizeContainer(container: Element | ShadowRoot | string): Element | null {
-  if (isString(container)) {
-    const res = document.querySelector(container)
-    /*  if (__DEV__ && !res) {
-      console.warn(`Failed to mount app: mount target selector "${container}" returned null.`)
-    } */
-    return res
-  }
-  /* if (__DEV__ && window.ShadowRoot && container instanceof window.ShadowRoot && container.mode === 'closed') {
-    console.warn(`mounting on a ShadowRoot with \`{mode: "closed"}\` may lead to unpredictable bugs`)
-  } */
-  return container as any
-}
-
 export const { createApp } = createRenderer(nodeOps)
 
-export const createTres = slots => {
+export const createTres = (slots: Slots) => {
   const app = createApp(internalFnComponent)
   function internalFnComponent() {
-    return slots.default()
+    return slots && slots.default ? slots.default() : []
   }
-
-  const { mount } = app
-  app.mount = containerOrSelector => {
-    const container = normalizeContainer(containerOrSelector)
-    if (!container) return
-    if (container instanceof Element) {
-      container.removeAttribute('v-cloak')
-      container.setAttribute('data-v-app', '')
-    }
-    mount(container, false, false)
-  }
-
   return app
 }
 

+ 26 - 0
packages/tres/src/utils/index.ts

@@ -12,3 +12,29 @@ export const merge = (target: any, source: any) => {
   Object.assign(target || {}, source)
   return target
 }
+
+const HTML_TAGS =
+  'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
+  'header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' +
+  'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
+  'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' +
+  'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
+  'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
+  'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
+  'option,output,progress,select,textarea,details,dialog,menu,' +
+  'summary,template,blockquote,iframe,tfoot'
+
+export const isHTMLTag = /*#__PURE__*/ makeMap(HTML_TAGS)
+
+export function kebabToCamel(str: string) {
+  return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase())
+}
+
+export function makeMap(str: string, expectsLowerCase?: boolean): (key: string) => boolean {
+  const map: Record<string, boolean> = Object.create(null)
+  const list: Array<string> = str.split(',')
+  for (let i = 0; i < list.length; i++) {
+    map[list[i]] = true
+  }
+  return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val]
+}