2021-04-21 07:10:48 +08:00
|
|
|
import { Object3D, Scene } from 'three'
|
2021-04-24 05:29:56 +08:00
|
|
|
import { ComponentPublicInstance, defineComponent, inject, PropType, watch } from 'vue'
|
2021-04-16 07:56:52 +08:00
|
|
|
import { bindProp } from '../tools'
|
2021-04-21 07:10:48 +08:00
|
|
|
import { RendererInterface } from './Renderer'
|
2021-04-16 07:56:52 +08:00
|
|
|
|
2021-04-21 22:04:20 +08:00
|
|
|
export interface Object3DSetupInterface {
|
|
|
|
renderer: RendererInterface
|
2021-04-21 07:10:48 +08:00
|
|
|
scene: Scene
|
2021-04-19 04:27:53 +08:00
|
|
|
o3d?: Object3D
|
|
|
|
parent?: ComponentPublicInstance
|
|
|
|
}
|
|
|
|
|
2021-04-20 23:50:06 +08:00
|
|
|
export interface Object3DInterface extends Object3DSetupInterface {
|
|
|
|
addToParent(o?: Object3D): boolean
|
|
|
|
removeFromParent(o?: Object3D): boolean
|
|
|
|
add(o: Object3D): void
|
|
|
|
remove(o: Object3D): void
|
|
|
|
}
|
|
|
|
|
2021-04-21 22:04:20 +08:00
|
|
|
export function object3DSetup(): Object3DSetupInterface {
|
|
|
|
const renderer = inject('renderer') as RendererInterface
|
|
|
|
const scene = inject('scene') as Scene
|
2021-04-22 03:35:43 +08:00
|
|
|
return { scene, renderer }
|
2021-04-21 22:04:20 +08:00
|
|
|
}
|
|
|
|
|
2021-04-24 05:29:56 +08:00
|
|
|
export interface Vector2PropInterface {
|
|
|
|
x?: number
|
|
|
|
y?: number
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Vector3PropInterface extends Vector2PropInterface {
|
|
|
|
z?: number
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface EulerPropInterface extends Vector3PropInterface {
|
|
|
|
order?: 'XYZ' | 'YZX' | 'ZXY' | 'XZY' | 'YXZ' | 'ZYX'
|
|
|
|
}
|
|
|
|
|
2021-04-16 07:56:52 +08:00
|
|
|
export default defineComponent({
|
|
|
|
name: 'Object3D',
|
2021-04-22 03:35:43 +08:00
|
|
|
inject: ['renderer', 'scene'],
|
2021-04-16 07:56:52 +08:00
|
|
|
emits: ['created', 'ready'],
|
|
|
|
props: {
|
2021-04-24 05:29:56 +08:00
|
|
|
position: { type: Object as PropType<Vector3PropInterface>, default: () => ({ x: 0, y: 0, z: 0 }) },
|
|
|
|
rotation: { type: Object as PropType<EulerPropInterface>, default: () => ({ x: 0, y: 0, z: 0 }) },
|
|
|
|
scale: { type: Object as PropType<Vector3PropInterface>, default: () => ({ x: 1, y: 1, z: 1, order: 'XYZ' }) },
|
|
|
|
lookAt: { type: Object as PropType<Vector3PropInterface>, default: null },
|
2021-04-16 07:56:52 +08:00
|
|
|
autoRemove: { type: Boolean, default: true },
|
|
|
|
userData: { type: Object, default: () => ({}) },
|
|
|
|
},
|
2021-04-21 22:04:20 +08:00
|
|
|
setup() {
|
|
|
|
return object3DSetup()
|
2021-04-19 04:27:53 +08:00
|
|
|
},
|
2021-04-24 05:29:56 +08:00
|
|
|
computed: {
|
|
|
|
},
|
2021-04-16 07:56:52 +08:00
|
|
|
unmounted() {
|
|
|
|
if (this.autoRemove) this.removeFromParent()
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
initObject3D(o3d: Object3D) {
|
|
|
|
this.o3d = o3d
|
|
|
|
|
2021-04-19 04:27:53 +08:00
|
|
|
this.$emit('created', o3d)
|
|
|
|
|
|
|
|
bindProp(this, 'position', o3d)
|
|
|
|
bindProp(this, 'rotation', o3d)
|
|
|
|
bindProp(this, 'scale', o3d)
|
2021-04-19 07:28:09 +08:00
|
|
|
bindProp(this, 'userData', o3d.userData)
|
2021-04-16 07:56:52 +08:00
|
|
|
|
|
|
|
// TODO : fix lookat.x
|
2021-04-24 05:29:56 +08:00
|
|
|
if (this.lookAt) o3d.lookAt(this.lookAt.x ?? 0, this.lookAt.y, this.lookAt.z)
|
|
|
|
watch(() => this.lookAt, (v) => { o3d.lookAt(v.x ?? 0, v.y, v.z) }, { deep: true })
|
2021-04-16 07:56:52 +08:00
|
|
|
|
2021-04-19 04:27:53 +08:00
|
|
|
this.parent = this.getParent()
|
2021-04-16 07:56:52 +08:00
|
|
|
if (this.addToParent()) this.$emit('ready', this)
|
|
|
|
else console.error('Missing parent (Scene, Group...)')
|
|
|
|
},
|
2021-04-19 04:27:53 +08:00
|
|
|
getParent(): undefined | ComponentPublicInstance {
|
2021-04-16 07:56:52 +08:00
|
|
|
let parent = this.$parent
|
|
|
|
while (parent) {
|
2021-04-19 04:27:53 +08:00
|
|
|
if ((parent as any).add) return parent
|
2021-04-16 07:56:52 +08:00
|
|
|
parent = parent.$parent
|
|
|
|
}
|
2021-04-19 04:27:53 +08:00
|
|
|
return undefined
|
2021-04-16 07:56:52 +08:00
|
|
|
},
|
2021-04-19 04:27:53 +08:00
|
|
|
addToParent(o?: Object3D) {
|
2021-04-16 07:56:52 +08:00
|
|
|
const o3d = o || this.o3d
|
2021-04-19 04:27:53 +08:00
|
|
|
if (this.parent) {
|
|
|
|
(this.parent as any).add(o3d)
|
2021-04-16 07:56:52 +08:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
2021-04-19 04:27:53 +08:00
|
|
|
removeFromParent(o?: Object3D) {
|
2021-04-16 07:56:52 +08:00
|
|
|
const o3d = o || this.o3d
|
2021-04-19 04:27:53 +08:00
|
|
|
if (this.parent) {
|
|
|
|
(this.parent as any).remove(o3d)
|
2021-04-16 07:56:52 +08:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
2021-04-19 04:27:53 +08:00
|
|
|
add(o: Object3D) { this.o3d?.add(o) },
|
|
|
|
remove(o: Object3D) { this.o3d?.remove(o) },
|
2021-04-16 07:56:52 +08:00
|
|
|
},
|
|
|
|
render() {
|
|
|
|
return this.$slots.default ? this.$slots.default() : []
|
|
|
|
},
|
|
|
|
__hmrId: 'Object3D',
|
|
|
|
})
|