123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- <script setup lang="ts">
- 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, onUnmounted } from 'vue'
- import { pick, hasSetter } from '../utils'
- import { useCientos } from './useCientos'
- const props = withDefaults(
- defineProps<{
- object: Object3D
- mode?: string
- enabled?: boolean
- axis?: 'X' | 'Y' | 'Z' | 'XY' | 'YZ' | 'XZ' | 'XYZ'
- translationSnap?: number
- rotationSnap?: number
- scaleSnap?: number
- space?: 'local' | 'world'
- size?: number
- showX?: boolean
- showY?: boolean
- showZ?: boolean
- }>(),
- {
- enabled: true,
- },
- )
- const emit = defineEmits(['dragging', 'change', 'mouseDown', 'mouseUp', 'objectChange'])
- let controls: ShallowRef<TransformControlsImp | undefined> = shallowRef()
- const { state } = useCientos()
- const transformProps = computed(() =>
- pick(props, [
- 'enabled',
- 'axis',
- 'mode',
- 'translationSnap',
- 'rotationSnap',
- 'scaleSnap',
- 'space',
- 'size',
- 'showX',
- 'showY',
- 'showZ',
- ]),
- )
- 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(
- () => props.object,
- () => {
- if (state.camera?.value && state.renderer && state.scene && props.object) {
- controls.value = new TransformControlsImp(state.camera.value, unref(state.renderer).domElement)
- controls.value.attach(unref(props.object))
- state.scene.add(unref(controls) as TransformControlsImp)
- addEventListeners(unref(controls) as TransformControlsImp)
- }
- },
- {
- deep: true,
- },
- )
- watch(
- [transformProps, controls],
- // TODO: properly type this
- ([value, controlsValue]: [any, any]) => {
- if (value && controlsValue) {
- for (const key in value) {
- if (!hasSetter(controlsValue, key)) {
- controlsValue[key] = value[key]
- } else {
- const methodName = `set${key[0].toUpperCase()}${key.slice(1)}`
- if (typeof controlsValue[methodName] === 'function' && value[key] !== undefined) {
- ;(controlsValue[methodName] as (param: any) => void)(value[key])
- }
- }
- }
- }
- },
- {
- 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 />
- </template>
|