forked from vue-gl/vue-gl
/
vgl-object3d.js
105 lines (103 loc) · 3.77 KB
/
vgl-object3d.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { Object3D } from 'three';
import { parseVector3, parseEuler, parseQuaternion } from '../parsers';
import {
vector3,
euler,
quaternion,
boolean,
string,
} from '../validators';
/**
* This is the base mixin component for most object components in VueGL,
* corresponding [THREE.Object3D](https://threejs.org/docs/index.html#api/core/Object3D).
* Object3d components inside a object3d component are added
* as children via THREE.Object3D.prototype.add() method.
*
* VglObject3d components inside default slots are added as children.
*/
export default {
props: {
/** The object's local position as a 3D vector. */
position: vector3,
/** The object's local rotation as a euler angle. */
rotation: euler,
/**
* The object's local rotation as a quaternion (specified in x, y, z, w order).
* Do not use in conjunction with the rotation prop, since they both control the same property
* of the underlying THREE.Object3D object.
*/
rotationQuaternion: quaternion,
/** The object's local scale as a 3D vector. */
scale: vector3,
/** Whether the object gets rendered into shadow map. */
castShadow: boolean,
/** Whether the material receives shadows. */
receiveShadow: boolean,
/** Optional name of the object. */
name: string,
/** Whether the object is visible. */
visible: {
type: boolean,
default: true,
},
},
computed: {
inst: () => new Object3D(),
},
inject: {
vglObject3d: { default: {} },
vglNamespace: 'vglNamespace',
},
provide() {
const vm = this;
return { vglObject3d: { get inst() { return vm.inst; } } };
},
created() { this.vglNamespace.update(); },
beforeUpdate() { this.vglNamespace.update(); },
beforeDestroy() {
const { vglNamespace, inst, name } = this;
if (inst.parent) inst.parent.remove(inst);
if (vglNamespace.object3ds[name] === inst) this.$delete(vglNamespace.object3ds, name);
vglNamespace.update();
},
watch: {
inst: {
handler(inst, oldInst) {
if (oldInst && oldInst.parent) oldInst.parent.remove(oldInst);
if (this.vglObject3d.inst) this.vglObject3d.inst.add(inst);
if (this.position) inst.position.copy(parseVector3(this.position));
if (this.rotation) inst.rotation.copy(parseEuler(this.rotation));
if (this.rotationQuaternion) inst.quaternion.copy(parseQuaternion(this.rotationQuaternion));
if (this.scale) inst.scale.copy(parseVector3(this.scale));
Object.assign(inst, {
castShadow: this.castShadow,
receiveShadow: this.receiveShadow,
visible: this.visible,
});
if (this.name !== undefined) {
// eslint-disable-next-line no-param-reassign
inst.name = this.name;
this.$set(this.vglNamespace.object3ds, this.name, inst);
}
},
immediate: true,
},
'vglObject3d.inst': function parentInst(inst) { inst.add(this.inst); },
position(position) { this.inst.position.copy(parseVector3(position)); },
rotation(rotation) { this.inst.rotation.copy(parseEuler(rotation)); },
rotationQuaternion(rotationQuaternion) {
this.inst.quaternion.copy(parseQuaternion(rotationQuaternion));
},
scale(scale) { this.inst.scale.copy(parseVector3(scale)); },
castShadow(castShadow) { this.inst.castShadow = castShadow; },
receiveShadow(receiveShadow) { this.inst.receiveShadow = receiveShadow; },
name(name, oldName) {
const { vglNamespace: { object3ds }, inst } = this;
if (object3ds[oldName] === inst) this.$delete(object3ds, oldName);
this.inst.name = name;
this.$set(object3ds, name, inst);
},
visible(visible) { this.inst.visible = visible; },
},
render(h) { return this.$slots.default ? h('div', this.$slots.default) : undefined; },
};