1
0
mirror of https://github.com/troisjs/trois.git synced 2024-11-24 04:12:02 +08:00

improve inject/provide types

This commit is contained in:
Kevin Levron 2021-04-24 21:45:57 +02:00
parent 9c41f1db6d
commit cc87e699bd
27 changed files with 229 additions and 150 deletions

View File

@ -1,11 +1,12 @@
import Stats from 'stats.js'
import { RendererInjectionKey } from '../../core/Renderer'
export default {
props: {
noSetup: { type: Boolean, default: false },
},
emits: ['created'],
inject: ['renderer'],
inject: { renderer: RendererInjectionKey },
setup({ noSetup }) {
const stats = new Stats()
if (!noSetup) {

View File

@ -1,9 +1,13 @@
import { defineComponent } from 'vue'
import useCannon from './useCannon.js'
// import { bindProp } from '../../tools';
import { RendererInjectionKey } from '../../core/Renderer'
import { SceneInjectionKey } from '../../core/Scene'
export default defineComponent({
inject: ['renderer', 'scene'],
inject: {
renderer: RendererInjectionKey,
scene: SceneInjectionKey,
},
props: {
gravity: { type: Object, default: () => ({ x: 0, y: 0, z: -9.82 }) },
broadphase: { type: String },

View File

@ -1,21 +1,22 @@
import { defineComponent, inject } from 'vue'
import { RendererInterface } from './Renderer'
import { defineComponent } from 'vue'
// import { Camera } from 'three'
// import { RendererInjectionKey, RendererInterface } from './Renderer'
// import Object3D from './Object3D'
// export interface CameraSetupInterface {
// renderer?: RendererInterface
// camera: Camera
// }
export default defineComponent({
// TODO: eventually extend Object3D
// extends: Object3D,
// don't work with typescript, bug ?
// but works in sub components (injection, not typescript)
inject: ['renderer'],
// inject: { renderer: RendererInjectionKey as symbol },
setup() {
// this works with typescript in sub component
// but setup is not called
const renderer = inject('renderer') as RendererInterface
return { renderer }
},
// setup(): CameraSetupInterface {
// return {}
// },
render() {
return this.$slots.default ? this.$slots.default() : []

View File

@ -1,11 +1,12 @@
import { Object3D, Scene } from 'three'
import { ComponentPublicInstance, defineComponent, inject, PropType, watch } from 'vue'
import { ComponentPublicInstance, defineComponent, PropType, watch } from 'vue'
import { bindProp } from '../tools'
import { RendererInterface } from './Renderer'
import { RendererInjectionKey, RendererInterface } from './Renderer'
import { SceneInjectionKey } from './Scene'
export interface Object3DSetupInterface {
renderer: RendererInterface
scene: Scene
renderer?: RendererInterface
scene?: Scene
o3d?: Object3D
parent?: ComponentPublicInstance
}
@ -17,11 +18,11 @@ export interface Object3DInterface extends Object3DSetupInterface {
remove(o: Object3D): void
}
export function object3DSetup(): Object3DSetupInterface {
const renderer = inject('renderer') as RendererInterface
const scene = inject('scene') as Scene
return { scene, renderer }
}
// export function object3DSetup(): Object3DSetupInterface {
// const renderer = inject(RendererInjectionKey)
// const scene = inject(SceneInjectionKey)
// return { scene, renderer }
// }
export interface Vector2PropInterface {
x?: number
@ -38,7 +39,11 @@ export interface EulerPropInterface extends Vector3PropInterface {
export default defineComponent({
name: 'Object3D',
inject: ['renderer', 'scene'],
// inject for sub components
inject: {
renderer: RendererInjectionKey as symbol,
scene: SceneInjectionKey as symbol,
},
emits: ['created', 'ready'],
props: {
position: { type: Object as PropType<Vector3PropInterface>, default: () => ({ x: 0, y: 0, z: 0 }) },
@ -48,10 +53,17 @@ export default defineComponent({
autoRemove: { type: Boolean, default: true },
userData: { type: Object, default: () => ({}) },
},
setup() {
return object3DSetup()
setup(): Object3DSetupInterface {
// return object3DSetup()
return {}
},
computed: {
created() {
if (!this.renderer) {
console.error('Missing parent Renderer')
}
if (!this.scene) {
console.error('Missing parent Scene')
}
},
unmounted() {
if (this.autoRemove) this.removeFromParent()
@ -67,7 +79,6 @@ export default defineComponent({
bindProp(this, 'scale', o3d)
bindProp(this, 'userData', o3d.userData)
// TODO : fix lookat.x
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 })

View File

@ -1,8 +1,9 @@
import { defineComponent, PropType, watch } from 'vue'
import { defineComponent, inject, PropType, watch } from 'vue'
import { OrthographicCamera } from 'three'
import { bindProp } from '../tools'
import Camera from './Camera'
import { Vector3PropInterface } from './Object3D'
import { RendererInjectionKey } from './Renderer'
export default defineComponent({
extends: Camera,
@ -18,7 +19,14 @@ export default defineComponent({
position: { type: Object as PropType<Vector3PropInterface>, default: () => ({ x: 0, y: 0, z: 0 }) },
},
setup(props) {
const renderer = inject(RendererInjectionKey)
if (!renderer) {
console.error('Renderer not found')
return
}
const camera = new OrthographicCamera(props.left, props.right, props.top, props.bottom, props.near, props.far)
renderer.camera = camera
bindProp(props, 'position', camera)
@ -32,10 +40,7 @@ export default defineComponent({
})
})
return { camera }
},
created() {
this.renderer.camera = this.camera
return { renderer, camera }
},
__hmrId: 'OrthographicCamera',
})

View File

@ -1,8 +1,9 @@
import { defineComponent, PropType, watch } from 'vue'
import { defineComponent, inject, PropType, watch } from 'vue'
import { PerspectiveCamera } from 'three'
import { bindProp } from '../tools'
import Camera from './Camera'
import { Vector3PropInterface } from './Object3D'
import { RendererInjectionKey } from './Renderer'
export default defineComponent({
extends: Camera,
@ -16,7 +17,14 @@ export default defineComponent({
lookAt: { type: Object as PropType<Vector3PropInterface>, default: null },
},
setup(props) {
const renderer = inject(RendererInjectionKey)
if (!renderer) {
console.error('Renderer not found')
return
}
const camera = new PerspectiveCamera(props.fov, props.aspect, props.near, props.far)
renderer.camera = camera
bindProp(props, 'position', camera)
@ -33,10 +41,7 @@ export default defineComponent({
})
})
return { camera }
},
created() {
this.renderer.camera = this.camera
return { renderer, camera }
},
__hmrId: 'PerspectiveCamera',
})

View File

@ -1,13 +1,13 @@
import { Object3D } from 'three'
import { defineComponent, inject, PropType } from 'vue'
import usePointer, { IntersectObject, PointerInterface, PointerIntersectCallbackType } from './usePointer'
import { RendererInterface } from './Renderer'
import { RendererInjectionKey, RendererInterface } from './Renderer'
// eslint-disable-next-line @typescript-eslint/no-empty-function
const emptyCallBack: PointerIntersectCallbackType = () => {}
interface RaycasterSetupInterface {
renderer: RendererInterface
renderer?: RendererInterface
pointer?: PointerInterface
}
@ -22,16 +22,22 @@ export default defineComponent({
intersectMode: { type: String, default: 'move' },
},
setup(): RaycasterSetupInterface {
const renderer = inject('renderer') as RendererInterface
const renderer = inject(RendererInjectionKey)
return { renderer }
},
mounted() {
if (!this.renderer) {
console.error('Renderer not found')
return
}
const renderer = this.renderer
this.renderer.onMounted(() => {
if (!this.renderer.camera) return
if (!renderer.camera) return
this.pointer = usePointer({
camera: this.renderer.camera,
domElement: this.renderer.canvas,
camera: renderer.camera,
domElement: renderer.canvas,
intersectObjects: this.getIntersectObjects(),
onIntersectEnter: this.onPointerEnter,
onIntersectOver: this.onPointerOver,
@ -42,19 +48,19 @@ export default defineComponent({
this.pointer.addListeners()
if (this.intersectMode === 'frame') {
this.renderer.onBeforeRender(this.pointer.intersect)
renderer.onBeforeRender(this.pointer.intersect)
}
})
},
unmounted() {
if (this.pointer) {
this.pointer.removeListeners()
this.renderer.offBeforeRender(this.pointer.intersect)
this.renderer?.offBeforeRender(this.pointer.intersect)
}
},
methods: {
getIntersectObjects() {
if (this.renderer.scene) {
if (this.renderer && this.renderer.scene) {
const children = this.renderer.scene.children.filter((c: Object3D) => ['Mesh', 'InstancedMesh'].includes(c.type))
return children as IntersectObject[]
}

View File

@ -1,7 +1,7 @@
/* eslint-disable no-use-before-define */
import { Camera, Scene, WebGLRenderer } from 'three'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { defineComponent, PropType } from 'vue'
import { defineComponent, InjectionKey, PropType } from 'vue'
import useThree, { SizeInterface, ThreeConfigInterface, ThreeInterface } from './useThree'
type CallbackType<T> = (event: T) => void
@ -86,6 +86,8 @@ export interface RendererInterface extends RendererSetupInterface {
removeListener<T extends keyof EventCallbackMap>(t: T, cb: EventCallbackMap[T]): void
}
export const RendererInjectionKey: InjectionKey<RendererInterface> = Symbol('Renderer')
export default defineComponent({
name: 'Renderer',
props: {
@ -162,7 +164,7 @@ export default defineComponent({
},
provide() {
return {
renderer: this,
[RendererInjectionKey as symbol]: this,
}
},
mounted() {

View File

@ -1,33 +1,43 @@
import { defineComponent, inject, watch } from 'vue'
import { Scene, Color, Object3D } from 'three'
import { RendererInterface } from './Renderer'
import { defineComponent, inject, InjectionKey, provide, watch } from 'vue'
import { Scene, Color, Object3D, Texture } from 'three'
import { RendererInjectionKey } from './Renderer'
export const SceneInjectionKey: InjectionKey<Scene> = Symbol('Scene')
export default defineComponent({
name: 'Scene',
props: {
// id: String,
background: [String, Number],
background: [String, Number, Object],
},
setup(props) {
const renderer = inject('renderer') as RendererInterface
const renderer = inject(RendererInjectionKey)
const scene = new Scene()
if (props.background) {
scene.background = new Color(props.background)
if (!renderer) {
console.error('Renderer not found')
return
}
watch(() => props.background, (value) => { if (scene.background instanceof Color && value) scene.background.set(value) })
return { renderer, scene }
},
provide() {
return {
scene: this.scene,
renderer.scene = scene
provide(SceneInjectionKey, scene)
const setBackground = (value: any): void => {
if (!value) return
if (typeof value === 'string' || typeof value === 'number') {
if (scene.background instanceof Color) scene.background.set(value)
else scene.background = new Color(value)
} else if (value instanceof Texture) {
scene.background = value
}
}
},
created() {
this.renderer.scene = this.scene
},
methods: {
add(o: Object3D) { this.scene.add(o) },
remove(o: Object3D) { this.scene.remove(o) },
setBackground(props.background)
watch(() => props.background, setBackground)
const add = (o: Object3D): void => { scene.add(o) }
const remove = (o: Object3D): void => { scene.remove(o) }
return { add, remove }
},
render() {
return this.$slots.default ? this.$slots.default() : []

View File

@ -12,6 +12,8 @@ export default defineComponent({
extends: EffectPass,
props,
created() {
if (!this.renderer) return
if (!this.renderer.scene) {
console.error('Missing Scene')
return

View File

@ -1,10 +1,10 @@
import { defineComponent, inject } from 'vue'
import { defineComponent, inject, InjectionKey } from 'vue'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { Pass } from 'three/examples/jsm/postprocessing/Pass'
import { RendererInterface } from '../core/Renderer'
import { RendererInjectionKey, RendererInterface } from '../core/Renderer'
interface EffectComposerSetupInterface {
renderer: RendererInterface
renderer?: RendererInterface
composer?: EffectComposer
}
@ -13,34 +13,38 @@ export interface EffectComposerInterface extends EffectComposerSetupInterface {
removePass(pass: Pass): void
}
export const ComposerInjectionKey: InjectionKey<EffectComposerInterface> = Symbol('Composer')
export default defineComponent({
setup(): EffectComposerSetupInterface {
const renderer = inject('renderer') as RendererInterface
return {
renderer,
}
const renderer = inject(RendererInjectionKey)
return { renderer }
},
provide() {
return {
composer: this,
[ComposerInjectionKey as symbol]: this,
}
},
created() {
if (!this.renderer) {
console.error('Renderer not found')
return
}
const renderer = this.renderer
const composer = new EffectComposer(this.renderer.renderer)
this.composer = composer
this.renderer.composer = composer
// this.renderer.onInit(() => {
this.renderer.addListener('init', () => {
this.renderer.renderer.autoClear = false
renderer.addListener('init', () => {
renderer.renderer.autoClear = false
this.resize()
// this.renderer.onResize(this.resize)
this.renderer.addListener('resize', this.resize)
renderer.addListener('resize', this.resize)
})
},
unmounted() {
// this.renderer.offResize(this.resize)
this.renderer.removeListener('resize', this.resize)
this.renderer?.removeListener('resize', this.resize)
},
methods: {
addPass(pass: Pass) {
@ -50,7 +54,9 @@ export default defineComponent({
this.composer?.removePass(pass)
},
resize() {
this.composer?.setSize(this.renderer.size.width, this.renderer.size.height)
if (this.composer && this.renderer) {
this.composer.setSize(this.renderer.size.width, this.renderer.size.height)
}
},
},
render() {

View File

@ -1,37 +1,42 @@
import { Pass } from 'three/examples/jsm/postprocessing/Pass'
import { defineComponent, inject } from 'vue'
import { RendererInterface } from '../core/Renderer'
import { EffectComposerInterface } from './EffectComposer'
import { defineComponent } from 'vue'
import { RendererInjectionKey, RendererInterface } from '../core/Renderer'
import { ComposerInjectionKey, EffectComposerInterface } from './EffectComposer'
export interface EffectSetupInterface {
renderer: RendererInterface
composer: EffectComposerInterface
renderer?: RendererInterface
composer?: EffectComposerInterface
pass?: Pass
}
export default defineComponent({
inject: ['renderer', 'composer'],
// inject for sub components
inject: {
renderer: RendererInjectionKey as symbol,
composer: ComposerInjectionKey as symbol,
},
emits: ['ready'],
setup(): EffectSetupInterface {
const renderer = inject('renderer') as RendererInterface
const composer = inject('composer') as EffectComposerInterface
return { renderer, composer }
return {}
},
created() {
if (!this.composer) {
console.error('Missing parent EffectComposer')
}
if (!this.renderer) {
console.error('Missing parent Renderer')
}
},
unmounted() {
if (this.pass) {
this.composer.removePass(this.pass);
this.composer?.removePass(this.pass);
(this.pass as any).dispose?.()
}
},
methods: {
initEffectPass(pass: Pass) {
this.pass = pass
this.composer.addPass(pass)
this.composer?.addPass(pass)
this.$emit('ready', pass)
},
},

View File

@ -10,12 +10,12 @@ export default defineComponent({
const pass = new ShaderPass(FXAAShader)
// resize will be first called in renderer init
this.renderer.addListener('resize', this.resize)
this.renderer?.addListener('resize', this.resize)
this.initEffectPass(pass)
},
unmounted() {
this.renderer.removeListener('resize', this.resize)
this.renderer?.removeListener('resize', this.resize)
},
methods: {
resize({ size }: { size: SizeInterface }) {

View File

@ -15,6 +15,8 @@ export default defineComponent({
extends: EffectPass,
props,
created() {
if (!this.renderer) return
const pass = new HalftonePass(this.renderer.size.width, this.renderer.size.height, {})
Object.keys(props).forEach(p => {

View File

@ -5,6 +5,8 @@ import EffectPass from './EffectPass'
export default defineComponent({
extends: EffectPass,
created() {
if (!this.renderer) return
if (!this.renderer.scene) {
console.error('Missing Scene')
return

View File

@ -5,6 +5,8 @@ import EffectPass from './EffectPass'
export default defineComponent({
extends: EffectPass,
created() {
if (!this.renderer) return
const pass = new SMAAPass(this.renderer.size.width, this.renderer.size.height)
this.initEffectPass(pass)
},

View File

@ -11,6 +11,8 @@ export default defineComponent({
},
},
created() {
if (!this.renderer) return
if (!this.renderer.scene) {
console.error('Missing Scene')
return

View File

@ -26,6 +26,8 @@ export default defineComponent({
return { uniforms1: {}, uniforms2: {} }
},
created() {
if (!this.composer) return
this.pass1 = new ShaderPass(TiltShift)
this.pass2 = new ShaderPass(TiltShift)
@ -57,7 +59,7 @@ export default defineComponent({
this.composer.addPass(this.pass2)
},
unmounted() {
if (this.pass2) this.composer.removePass(this.pass2)
if (this.composer && this.pass2) this.composer.removePass(this.pass2)
},
methods: {
updateFocusLine() {

View File

@ -13,6 +13,8 @@ export default defineComponent({
extends: EffectPass,
props,
created() {
if (!this.renderer) return
const size = new Vector2(this.renderer.size.width, this.renderer.size.height)
const pass = new UnrealBloomPass(size, this.strength, this.radius, this.threshold)

View File

@ -1,18 +1,18 @@
import { BufferGeometry } from 'three'
import { defineComponent, inject, watch } from 'vue'
import { MeshInterface } from '../meshes/Mesh'
import { MeshInjectionKey, MeshInterface } from '../meshes/Mesh'
export interface GeometryInterface {
geometry?: BufferGeometry
export interface GeometrySetupInterface {
mesh?: MeshInterface
watchProps: string[]
geometry?: BufferGeometry
watchProps?: string[]
}
function defaultSetup(): GeometryInterface {
const mesh = inject('mesh') as MeshInterface
const watchProps: string[] = []
return { mesh, watchProps }
}
// function defaultSetup(): GeometryInterface {
// const mesh = inject('mesh') as MeshInterface
// const watchProps: string[] = []
// return { mesh, watchProps }
// }
const Geometry = defineComponent({
props: {
@ -20,8 +20,12 @@ const Geometry = defineComponent({
rotateY: Number,
rotateZ: Number,
},
setup() {
return defaultSetup()
// inject for sub components
inject: {
mesh: MeshInjectionKey as symbol,
},
setup(): GeometrySetupInterface {
return {}
},
created() {
if (!this.mesh) {
@ -29,37 +33,31 @@ const Geometry = defineComponent({
return
}
Object.entries(this.$props).forEach(e => this.watchProps.push(e[0]))
this.createGeometry()
this.rotateGeometry()
if (this.geometry) this.mesh.setGeometry(this.geometry)
this.addWatchers()
Object.keys(this.$props).forEach(prop => {
// @ts-ignore
watch(() => this[prop], this.refreshGeometry)
})
},
unmounted() {
this.geometry?.dispose()
},
methods: {
createGeometry() {},
addWatchers() {
this.watchProps.forEach(prop => {
// @ts-ignore
watch(() => this[prop], () => {
this.refreshGeometry()
})
})
},
rotateGeometry() {
if (this.rotateX) this.geometry?.rotateX(this.rotateX)
if (this.rotateY) this.geometry?.rotateY(this.rotateY)
if (this.rotateZ) this.geometry?.rotateZ(this.rotateZ)
if (!this.geometry) return
if (this.rotateX) this.geometry.rotateX(this.rotateX)
if (this.rotateY) this.geometry.rotateY(this.rotateY)
if (this.rotateZ) this.geometry.rotateZ(this.rotateZ)
},
refreshGeometry() {
const oldGeo = this.geometry
this.createGeometry()
this.rotateGeometry()
if (this.geometry) this.mesh?.setGeometry(this.geometry)
if (this.geometry && this.mesh) this.mesh.setGeometry(this.geometry)
oldGeo?.dispose()
},
},
@ -74,8 +72,8 @@ export function geometryComponent(name, props, createGeometry) {
name,
extends: Geometry,
props,
setup() {
return defaultSetup()
setup(): GeometrySetupInterface {
return {}
},
methods: {
createGeometry() {

View File

@ -1,6 +1,6 @@
import { defineComponent, watch } from 'vue'
import { defineComponent, InjectionKey, watch } from 'vue'
import { FrontSide, Material, Texture } from 'three'
import { MeshInterface } from '../meshes/Mesh'
import { MeshInjectionKey, MeshInterface } from '../meshes/Mesh'
export interface MaterialSetupInterface {
mesh?: MeshInterface
@ -13,8 +13,13 @@ export interface MaterialInterface extends MaterialSetupInterface {
setTexture(texture: Texture | null, key: string): void
}
export const MaterialInjectionKey: InjectionKey<MaterialInterface> = Symbol('Material')
export default defineComponent({
inject: ['mesh'],
// inject for sub components
inject: {
mesh: MeshInjectionKey as symbol,
},
props: {
color: { type: [String, Number], default: '#ffffff' },
depthTest: { type: Boolean, default: true },
@ -30,7 +35,7 @@ export default defineComponent({
},
provide() {
return {
material: this,
[MaterialInjectionKey as symbol]: this,
}
},
created() {

View File

@ -1,7 +1,7 @@
import { defineComponent, PropType, watch } from 'vue'
import { ClampToEdgeWrapping, LinearFilter, LinearMipmapLinearFilter, RGBAFormat, ShaderMaterial, Texture, TextureLoader, UVMapping } from 'three'
import { ClampToEdgeWrapping, LinearFilter, LinearMipmapLinearFilter, ShaderMaterial, Texture, TextureLoader, UVMapping } from 'three'
import { bindProp } from '../tools'
import { MaterialInterface } from './Material'
import { MaterialInjectionKey, MaterialInterface } from './Material'
export interface TexureInterface {
material?: MaterialInterface
@ -9,7 +9,9 @@ export interface TexureInterface {
}
export default defineComponent({
inject: ['material'],
inject: {
material: MaterialInjectionKey as symbol,
},
props: {
name: { type: String, default: 'map' },
uniform: String,
@ -53,7 +55,7 @@ export default defineComponent({
if (this.texture && this.material) {
this.material.setTexture(this.texture, this.name)
if (this.material.material instanceof ShaderMaterial && this.uniform) {
// this.material.uniforms[this.uniform] = { value: this.texture }
(this.material as any).uniforms[this.uniform] = { value: this.texture }
}
}
},

View File

@ -1,7 +1,6 @@
import { defineComponent, watch } from 'vue'
import { DoubleSide, MeshBasicMaterial, PlaneGeometry, Texture, TextureLoader } from 'three'
import Mesh, { MeshSetupInterface } from './Mesh'
import { object3DSetup } from '../core/Object3D'
interface ImageSetupInterface extends MeshSetupInterface {
material?: MeshBasicMaterial
@ -20,9 +19,11 @@ export default defineComponent({
keepSize: Boolean,
},
setup(): ImageSetupInterface {
return object3DSetup()
return {}
},
created() {
if (!this.renderer) return
this.geometry = new PlaneGeometry(1, 1, this.widthSegments, this.heightSegments)
this.material = new MeshBasicMaterial({ side: DoubleSide, map: this.loadTexture() })
@ -37,7 +38,7 @@ export default defineComponent({
if (this.keepSize) this.renderer.onResize(this.resize)
},
unmounted() {
this.renderer.offResize(this.resize)
this.renderer?.offResize(this.resize)
},
methods: {
loadTexture() {
@ -56,7 +57,7 @@ export default defineComponent({
this.$emit('loaded', texture)
},
resize() {
if (!this.texture) return
if (!this.renderer || !this.texture) return
const screen = this.renderer.size
const iW = this.texture.image.width
const iH = this.texture.image.height

View File

@ -10,6 +10,8 @@ export default defineComponent({
},
methods: {
initMesh() {
if (!this.renderer) return
if (!this.geometry || !this.material) {
console.error('Missing geometry and/or material')
return false

View File

@ -1,6 +1,6 @@
import { ComponentPropsOptions, defineComponent, watch } from 'vue'
import { ComponentPropsOptions, defineComponent, InjectionKey, watch } from 'vue'
import { BufferGeometry, Material, Mesh as TMesh } from 'three'
import Object3D, { object3DSetup, Object3DSetupInterface } from '../core/Object3D'
import Object3D, { Object3DSetupInterface } from '../core/Object3D'
import { bindProp } from '../tools'
export const pointerProps = {
@ -25,6 +25,8 @@ export interface MeshInterface extends MeshSetupInterface {
setMaterial(m: Material): void
}
export const MeshInjectionKey: InjectionKey<MeshInterface> = Symbol('Mesh')
const Mesh = defineComponent({
name: 'Mesh',
extends: Object3D,
@ -34,11 +36,11 @@ const Mesh = defineComponent({
...pointerProps,
},
setup(): MeshSetupInterface {
return object3DSetup()
return {}
},
provide() {
return {
mesh: this,
[MeshInjectionKey as symbol]: this,
}
},
mounted() {
@ -60,7 +62,7 @@ const Mesh = defineComponent({
this.onPointerDown ||
this.onPointerUp ||
this.onClick) {
this.renderer.three.addIntersectObject(mesh)
if (this.renderer) this.renderer.three.addIntersectObject(mesh)
}
this.mesh = mesh
@ -92,7 +94,7 @@ const Mesh = defineComponent({
},
unmounted() {
if (this.mesh) {
this.renderer.three?.removeIntersectObject(this.mesh)
if (this.renderer) this.renderer.three.removeIntersectObject(this.mesh)
}
// for predefined mesh (geometry/material are not unmounted)
if (this.geometry) this.geometry.dispose()
@ -110,7 +112,7 @@ export function meshComponent(name, props, createGeometry) {
extends: Mesh,
props,
setup(): MeshSetupInterface {
return object3DSetup()
return {}
},
created() {
this.createGeometry()

View File

@ -1,6 +1,6 @@
import { defineComponent } from 'vue'
import { Sprite, SpriteMaterial, Texture, TextureLoader } from 'three'
import Object3D, { object3DSetup, Object3DSetupInterface } from '../core/Object3D'
import Object3D, { Object3DSetupInterface } from '../core/Object3D'
interface SpriteSetupInterface extends Object3DSetupInterface {
texture?: Texture
@ -15,7 +15,7 @@ export default defineComponent({
src: { type: String, required: true },
},
setup(): SpriteSetupInterface {
return object3DSetup()
return {}
},
created() {
this.texture = new TextureLoader().load(this.src, this.onLoaded)

View File

@ -1,7 +1,6 @@
import { defineComponent, watch } from 'vue'
import { Font, FontLoader, TextGeometry } from 'three'
import Mesh, { MeshSetupInterface } from './Mesh'
import { object3DSetup } from '../core/Object3D'
interface TextSetupInterface extends MeshSetupInterface {
geometry?: TextGeometry
@ -27,7 +26,7 @@ export default defineComponent({
extends: Mesh,
props,
setup(): TextSetupInterface {
return object3DSetup()
return {}
},
created() {
if (!this.fontSrc) {