diff --git a/src/core/Object3D.js b/src/core/Object3D.js index 4b20eb3..02b7ec2 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -4,14 +4,13 @@ import { bindProp } from '../tools.js'; export default { inject: ['three', 'scene', 'rendererComponent'], props: { - position: Object, - rotation: Object, - scale: Object, + position: { type: Object, default: { x: 0, y: 0, z: 0 } }, + rotation: { type: Object, default: { x: 0, y: 0, z: 0 } }, + scale: { type: Object, default: { x: 1, y: 1, z: 1 } }, lookAt: { type: Object, default: null }, }, // can't use setup because it will not be used in sub components // setup() {}, - created() {}, unmounted() { if (this.$parent.remove) this.$parent.remove(this.o3d); }, @@ -19,10 +18,11 @@ export default { initObject3D(o3d) { this.o3d = o3d; - bindProp(this, 'position', this.o3d.position); - bindProp(this, 'rotation', this.o3d.rotation); - bindProp(this, 'scale', this.o3d.scale); + bindProp(this, 'position', this.o3d); + bindProp(this, 'rotation', this.o3d); + bindProp(this, 'scale', this.o3d); + // fix lookat.x if (this.lookAt) this.o3d.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z); watch(() => this.lookAt, (v) => { this.o3d.lookAt(v.x, v.y, v.z); }, { deep: true }); diff --git a/src/core/OrthographicCamera.js b/src/core/OrthographicCamera.js index 7f7006a..a22370c 100644 --- a/src/core/OrthographicCamera.js +++ b/src/core/OrthographicCamera.js @@ -1,4 +1,4 @@ -import { OrthographicCamera, Vector3 } from 'three'; +import { OrthographicCamera } from 'three'; import { watch } from 'vue'; import { bindProp } from '../tools.js'; @@ -12,11 +12,11 @@ export default { near: { type: Number, default: 0.1 }, far: { type: Number, default: 2000 }, zoom: { type: Number, default: 1 }, - position: { type: [Object, Vector3], default: { x: 0, y: 0, z: 0 } }, + position: { type: Object, default: { x: 0, y: 0, z: 0 } }, }, created() { this.camera = new OrthographicCamera(this.left, this.right, this.top, this.bottom, this.near, this.far); - bindProp(this, 'position', this.camera.position); + bindProp(this, 'position', this.camera); ['left', 'right', 'top', 'bottom', 'near', 'far', 'zoom'].forEach(p => { watch(() => this[p], () => { diff --git a/src/core/PerspectiveCamera.js b/src/core/PerspectiveCamera.js index e77272c..515612b 100644 --- a/src/core/PerspectiveCamera.js +++ b/src/core/PerspectiveCamera.js @@ -9,12 +9,12 @@ export default { far: { type: Number, default: 2000 }, fov: { type: Number, default: 50 }, near: { type: Number, default: 0.1 }, - position: { type: [Object, Vector3], default: { x: 0, y: 0, z: 0 } }, - lookAt: { type: [Object, Vector3], default: null }, + position: { type: Object, default: { x: 0, y: 0, z: 0 } }, + lookAt: { type: Object, default: null }, }, created() { this.camera = new PerspectiveCamera(this.fov, this.aspect, this.near, this.far); - bindProp(this, 'position', this.camera.position); + bindProp(this, 'position', this.camera); if (this.lookAt) this.camera.lookAt(this.lookAt.x, this.lookAt.y, this.lookAt.z); watch(() => this.lookAt, (v) => { this.camera.lookAt(v.x, v.y, v.z); }, { deep: true }); diff --git a/src/effects/TiltShiftPass.js b/src/effects/TiltShiftPass.js index d636281..7046969 100644 --- a/src/effects/TiltShiftPass.js +++ b/src/effects/TiltShiftPass.js @@ -3,7 +3,7 @@ import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'; import { watch } from 'vue'; import EffectPass from './EffectPass.js'; import TiltShift from '../shaders/TiltShift.js'; -import { bindPropValue } from '../tools.js'; +import { bindProp } from '../tools.js'; export default { extends: EffectPass, @@ -28,8 +28,8 @@ export default { uniforms1.end = uniforms.end; uniforms1.texSize = uniforms.texSize; - bindPropValue(this, 'blurRadius', uniforms.blurRadius); - bindPropValue(this, 'gradientRadius', uniforms.gradientRadius); + bindProp(this, 'blurRadius', uniforms.blurRadius, 'value'); + bindProp(this, 'gradientRadius', uniforms.gradientRadius, 'value'); this.updateFocusLine(); ['start', 'end'].forEach(p => { diff --git a/src/effects/ZoomBlurPass.js b/src/effects/ZoomBlurPass.js index e7c2022..b492af5 100644 --- a/src/effects/ZoomBlurPass.js +++ b/src/effects/ZoomBlurPass.js @@ -1,7 +1,7 @@ import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'; import EffectPass from './EffectPass.js'; import ZoomBlur from '../shaders/ZoomBlur.js'; -import { bindProp, bindPropValue } from '../tools.js'; +import { bindProp } from '../tools.js'; export default { extends: EffectPass, @@ -14,8 +14,8 @@ export default { this.passes.push(this.pass); const uniforms = this.uniforms = this.pass.uniforms; - bindProp(this, 'center', uniforms.center.value); - bindPropValue(this, 'strength', uniforms.strength); + bindProp(this, 'center', uniforms.center, 'value'); + bindProp(this, 'strength', uniforms.strength, 'value'); }, __hmrId: 'ZoomBlurPass', }; diff --git a/src/lights/Light.js b/src/lights/Light.js index f8faed5..a9e0827 100644 --- a/src/lights/Light.js +++ b/src/lights/Light.js @@ -19,7 +19,7 @@ export default { methods: { initLight() { if (this.light.target) { - bindProp(this, 'target', this.light.target.position); + bindProp(this, 'target', this.light.target, 'position'); } if (this.light.shadow) { diff --git a/src/materials/StandardMaterial.js b/src/materials/StandardMaterial.js index 3f42f15..562a1da 100644 --- a/src/materials/StandardMaterial.js +++ b/src/materials/StandardMaterial.js @@ -1,7 +1,6 @@ -import { MeshStandardMaterial, Vector2 } from 'three'; +import { MeshStandardMaterial } from 'three'; import { watch } from 'vue'; -import { propsValues } from '../tools.js'; -import { bindProp } from '../tools.js'; +import { bindProp, propsValues } from '../tools.js'; import Material from './Material'; const props = { @@ -14,7 +13,7 @@ const props = { envMapIntensity: { type: Number, default: 1 }, lightMapIntensity: { type: Number, default: 1 }, metalness: { type: Number, default: 0 }, - normalScale: { type: Object, default: () => new Vector2(1, 1) }, + normalScale: { type: Object, default: { x: 1, y: 1 } }, roughness: { type: Number, default: 1 }, refractionRatio: { type: Number, default: 0.98 }, wireframe: Boolean, @@ -39,7 +38,7 @@ export default { } }); }); - bindProp(this, 'normalScale', this.material.normalScale); + bindProp(this, 'normalScale', this.material); }, }, __hmrId: 'StandardMaterial', diff --git a/src/meshes/Gem.js b/src/meshes/Gem.js index c578a05..71f90f1 100644 --- a/src/meshes/Gem.js +++ b/src/meshes/Gem.js @@ -32,7 +32,7 @@ export default { initGem() { const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); - bindProp(this, 'position', this.cubeCamera.position); + bindProp(this, 'position', this.cubeCamera); this.$parent.add(this.cubeCamera); this.material.side = FrontSide; @@ -54,9 +54,9 @@ export default { this.meshBack = new TMesh(this.geometry, this.materialBack); - bindProp(this, 'position', this.meshBack.position); - bindProp(this, 'rotation', this.meshBack.rotation); - bindProp(this, 'scale', this.meshBack.scale); + bindProp(this, 'position', this.meshBack); + bindProp(this, 'rotation', this.meshBack); + bindProp(this, 'scale', this.meshBack); this.$parent.add(this.meshBack); }, updateCubeRT() { diff --git a/src/meshes/RefractionMesh.js b/src/meshes/RefractionMesh.js index 9d69e8c..431a5f4 100644 --- a/src/meshes/RefractionMesh.js +++ b/src/meshes/RefractionMesh.js @@ -30,7 +30,7 @@ export default { initMirrorMesh() { const cubeRT = new WebGLCubeRenderTarget(this.cubeRTSize, { mapping: CubeRefractionMapping, format: RGBFormat, generateMipmaps: true, minFilter: LinearMipmapLinearFilter }); this.cubeCamera = new CubeCamera(this.cubeCameraNear, this.cubeCameraFar, cubeRT); - bindProp(this, 'position', this.cubeCamera.position); + bindProp(this, 'position', this.cubeCamera); this.$parent.add(this.cubeCamera); this.material.envMap = cubeRT.texture; diff --git a/src/tools.js b/src/tools.js index c4c25b6..428b97a 100644 --- a/src/tools.js +++ b/src/tools.js @@ -8,19 +8,16 @@ export function setFromProp(o, prop) { } }; -export function bindProp(comp, prop, object) { - const ref = toRef(comp, prop); - setFromProp(object, ref.value); - watch(ref, () => { - setFromProp(object, ref.value); - }, { deep: true }); -}; - -export function bindPropValue(src, srcProp, dst, dstProp = 'value') { - dst[dstProp] = src[srcProp]; - watch(() => src[srcProp], (value) => { - dst[dstProp] = value; - }); +export function bindProp(src, srcProp, dst, dstProp) { + if (!dstProp) dstProp = srcProp; + const ref = toRef(src, srcProp); + if (ref.value instanceof Object) { + setFromProp(dst[dstProp], ref.value); + watch(ref, (value) => { setFromProp(dst[dstProp], value); }, { deep: true }); + } else { + if (ref.value) dst[dstProp] = src[srcProp]; + watch(ref, (value) => { dst[dstProp] = value; }); + } }; export function propsValues(props, exclude) {