Browse Source

feat(cientos): add events and controls default support on dragging

Alvaro 2 years ago
parent
commit
f03f8e8159

+ 12 - 46
packages/cientos/src/core/OrbitControls.vue

@@ -1,7 +1,8 @@
 <script lang="ts" setup>
+import { useTres } from '@tresjs/core'
 import { Camera, Vector3, WebGLRenderer } from 'three'
 import { OrbitControls } from 'three-stdlib'
-import { inject, ref, type Ref } from 'vue'
+import { inject, ref, watch, type Ref } from 'vue'
 
 import { useCientos } from './useCientos'
 
@@ -18,12 +19,22 @@ const props = withDefaults(
   },
 )
 
+const { setState } = useTres()
+
 const controls = ref(null)
 const camera = inject<Ref<Camera>>('camera')
 const renderer = inject<Ref<WebGLRenderer>>('renderer')
 
 const { extend } = useCientos()
 extend({ OrbitControls })
+
+watch(controls, value => {
+  if (value && props.makeDefault) {
+    setState('controls', value)
+  } else {
+    setState('controls', null)
+  }
+})
 </script>
 
 <template>
@@ -34,48 +45,3 @@ extend({ OrbitControls })
     :enabling-dampling="enableDamping"
   />
 </template>
-
-<!-- <script setup lang="ts">
-import { useRenderLoop } from '@tresjs/core'
-import { Camera, Vector3, WebGLRenderer } from 'three'
-import { OrbitControls as OrbitControlsImp } from 'three-stdlib'
-import { inject, type Ref, unref, watch } from 'vue'
-
-const props = withDefaults(
-  defineProps<{
-    makeDefault?: boolean
-    camera?: Camera
-    domElement?: HTMLElement
-    target?: Ref<Vector3>
-  }>(),
-  {
-    makeDefault: false,
-  },
-)
-let controls: OrbitControlsImp
-
-const camera = inject<Ref<Camera>>('camera')
-const renderer = inject<Ref<WebGLRenderer>>('renderer')
-watch(
-  [camera, renderer],
-  () => {
-    if (camera?.value && renderer?.value) {
-      if (controls) controls.reset()
-      controls = new OrbitControlsImp(camera.value, unref(renderer).domElement)
-      controls.enableDamping = true
-
-      const { onLoop } = useRenderLoop()
-
-      onLoop(() => {
-        if (controls.enabled) {
-          controls.update()
-        }
-      })
-    }
-  },
-  {
-    deep: true,
-  },
-)
-</script>
- -->

+ 51 - 18
packages/cientos/src/core/TransformControls.vue

@@ -1,7 +1,8 @@
 <script setup lang="ts">
-import { Camera, Object3D, Scene, WebGLRenderer } from 'three'
+import { useTres } from '@tresjs/core'
+import { Camera, Object3D, Scene, WebGLRenderer, type Event } from 'three'
 import { TransformControls as TransformControlsImp } from 'three-stdlib'
-import { inject, computed, type Ref, unref, watch, shallowRef, ShallowRef } from 'vue'
+import { inject, computed, type Ref, unref, watch, shallowRef, ShallowRef, onUnmounted } from 'vue'
 import { pick } from '../utils'
 
 const props = withDefaults(
@@ -24,27 +25,48 @@ const props = withDefaults(
   },
 )
 
-let controls: ShallowRef<TransformControlsImp | undefined> = shallowRef()
+const emit = defineEmits(['dragging', 'change', 'mouseDown', 'mouseUp', 'objectChange'])
 
-const transformOnlyProps = [
-  'enabled',
-  'axis',
-  'mode',
-  'translationSnap',
-  'rotationSnap',
-  'scaleSnap',
-  'space',
-  'size',
-  'showX',
-  'showY',
-  'showZ',
-]
+let controls: ShallowRef<TransformControlsImp | undefined> = shallowRef()
 
 const camera = inject<Ref<Camera>>('camera')
 const renderer = inject<Ref<WebGLRenderer>>('renderer')
 const scene = inject<Ref<Scene>>('local-scene')
 
-const transformProps = computed(() => pick(props, transformOnlyProps))
+const transformProps = computed(() =>
+  pick(props, [
+    'enabled',
+    'axis',
+    'mode',
+    'translationSnap',
+    'rotationSnap',
+    'scaleSnap',
+    'space',
+    'size',
+    'showX',
+    'showY',
+    'showZ',
+  ]),
+)
+const { state } = useTres()
+
+const onChange = () => emit('change', controls.value)
+const onMouseDown = () => emit('mouseDown', controls.value)
+const onMouseUp = () => emit('mouseUp', controls.value)
+const onObjectChange = () => emit('objectChange', controls.value)
+
+const onDragingChange = (e: Event) => {
+  if (state.controls) state.controls.enabled = !e.value
+  emit('dragging', e.value)
+}
+
+function addEventListeners(controls: TransformControlsImp) {
+  controls.addEventListener('dragging-changed', onDragingChange)
+  controls.addEventListener('change', onChange)
+  controls.addEventListener('mouseDown', onMouseDown)
+  controls.addEventListener('mouseUp', onMouseUp)
+  controls.addEventListener('objectChange', onObjectChange)
+}
 
 watch(
   [camera, renderer],
@@ -54,6 +76,8 @@ watch(
 
       controls.value.attach(unref(props.object))
       scene.value.add(unref(controls) as TransformControlsImp)
+
+      addEventListeners(unref(controls) as TransformControlsImp)
     }
   },
   {
@@ -65,7 +89,6 @@ watch(
   [transformProps, controls],
   // TODO: properly type this
   ([value, controlsValue]: [any, any]) => {
-    console.log([value, controlsValue])
     if (value && controlsValue) {
       for (const key in value) {
         const methodName = `set${key[0].toUpperCase()}${key.slice(1)}`
@@ -80,6 +103,16 @@ watch(
     immediate: true,
   },
 )
+
+onUnmounted(() => {
+  if (controls.value) {
+    controls.value.removeEventListener('dragging-changed', onDragingChange)
+    controls.value.removeEventListener('change', onChange)
+    controls.value.removeEventListener('mouseDown', onMouseDown)
+    controls.value.removeEventListener('mouseUp', onMouseUp)
+    controls.value.removeEventListener('objectChange', onObjectChange)
+  }
+})
 </script>
 <template>
   <slot />

+ 2 - 2
packages/cientos/src/core/useCientos.ts

@@ -2,8 +2,8 @@ import { useCatalogue } from '@tresjs/core'
 import { getCurrentInstance } from 'vue'
 
 export function useCientos() {
-  const { appContext } = getCurrentInstance()
-  const { catalogue, extend } = useCatalogue(appContext.app)
+  const appContext = getCurrentInstance()?.appContext
+  const { catalogue, extend } = useCatalogue(appContext?.app)
 
   return {
     catalogue,

+ 7 - 8
packages/cientos/src/utils/index.ts

@@ -1,11 +1,10 @@
-export function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
-  const result: Partial<T> = {}
-
-  for (const key of keys) {
-    if (key in obj) {
-      result[key] = obj[key]
+// Update the function signature to explicitly specify the type of the props parameter
+export function pick<T extends object, K extends keyof T>(obj: T, props: K[]): Pick<T, K> {
+  const pickedProperties = {} as Pick<T, K>
+  for (const prop of props) {
+    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
+      pickedProperties[prop] = obj[prop]
     }
   }
-
-  return result as Pick<T, K>
+  return pickedProperties
 }

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

@@ -1,14 +1,16 @@
 <script setup lang="ts">
 /* import { Color } from 'three' */
+import { ref } from 'vue'
 import { useTweakPane, OrbitControls, TransformControls } from '../../cientos/src'
 /* import TestSphere from '/@/components/TestSphere.vue' */
-import Text3D from '/@/components/Text3D.vue'
+/* import Text3D from '/@/components/Text3D.vue' */
 /* import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
 import { useTres, useCatalogue } from '/@/core' */
 
 /* const { extend } = useCatalogue() */
 
 /* extend({ OrbitControls }) */
+const cubeRef = ref(null)
 
 useTweakPane()
 
@@ -25,12 +27,17 @@ useTweakPane()
       physically-correct-lights
     >
       <TresPerspectiveCamera :position="[5, 5, 5]" :fov="45" :near="0.1" :far="1000" :look-at="[-8, 3, -3]" />
-      <OrbitControls />
+      <OrbitControls make-default />
       <TresScene>
         <TresAmbientLight :intensity="0.5" />
+        <TransformControls :object="cubeRef" />
+        <TresMesh ref="cubeRef">
+          <TresBoxGeometry :args="[1, 1, 1]" />
+          <TresMeshNormalMaterial />
+        </TresMesh>
         <!--  <TresOrbitControls v-if="state.renderer" :args="[state.camera, state.renderer?.domElement]" /> -->
-        <Text3D />
-        <!--   <TestSphere /> -->
+        <!-- <Text3D /> -->
+        <!--  <TestSphere /> -->
         <TresAxesHelper :args="[1]" :visible="false" />
         <TresDirectionalLight :position="[0, 2, 4]" :intensity="2" cast-shadow />
       </TresScene>