/
THREEObject3DMixin.js
167 lines (137 loc) · 5.49 KB
/
THREEObject3DMixin.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import * as THREE from 'three';
import assign from 'object-assign';
import THREEContainerMixin from './THREEContainerMixin';
import warning from 'fbjs/lib/warning';
//
// The container methods are use by both the THREEScene composite component
// and by THREEObject3D components, so container/child stuff is in a separate
// mixin (THREEContainerMixin) and here gets merged into the typical THREE
// node methods for applying and updating props
//
var THREEObject3DMixin = assign({}, THREEContainerMixin, {
construct: function(element) {
this._currentElement = element;
this._THREEObject3D = null;
this._nativeParent = null;
this._nativeContainerInfo = null;
},
getPublicInstance: function() {
return this._THREEObject3D;
},
createTHREEObject: function() {
return new THREE.Object3D();
},
applyTHREEObject3DProps: function(oldProps, props) {
this.applyTHREEObject3DPropsToObject(this._THREEObject3D, oldProps, props);
},
applyTHREEObject3DPropsToObject: function(THREEObject3D, oldProps, props) {
// if a matrix transformation is defined, it will handle position,
// rotation, and scaling
if (typeof props.matrix !== 'undefined') {
THREEObject3D.matrix.copy(props.matrix);
// prevent the matrix from being over-written on render
// (see https://threejs.org/docs/manual/introduction/Matrix-transformations.html)
THREEObject3D.matrixAutoUpdate = false;
warning(typeof props.position === 'undefined', "The `position` property "+
"of 3D objects is ignored when the `matrix` property is specified");
warning(typeof props.rotation === 'undefined', "The `rotation` property "+
"of 3D objects is ignored when the `matrix` property is specified");
warning(typeof props.quaternion === 'undefined', "The `quaternion` property "+
"of 3D objects is ignored when the `matrix` property is specified");
warning(typeof props.scale === 'undefined', "The `scale` property "+
"of 3D objects is ignored when the `matrix` property is specified");
} else {
if (typeof props.position !== 'undefined') {
THREEObject3D.position.copy(props.position);
} else {
THREEObject3D.position.set(0,0,0);
}
// rotation be specified using either Euler angles or a quaternion
if (typeof props.rotation !== 'undefined') {
THREEObject3D.rotation.copy(props.rotation);
} else if (typeof props.quaternion !== 'undefined') {
THREEObject3D.quaternion.copy(props.quaternion);
} else {
THREEObject3D.quaternion.set(0,0,0,1); // no rotation
}
// scale supports a single number or a Vector3
if (typeof props.scale === "number") {
THREEObject3D.scale.set(props.scale, props.scale, props.scale);
} else if (props.scale instanceof THREE.Vector3) {
// copy over scale values
THREEObject3D.scale.copy(props.scale);
} else {
THREEObject3D.scale.set(1,1,1);
}
}
if (typeof props.visible !== 'undefined') {
THREEObject3D.visible = props.visible;
} else {
THREEObject3D.visible = true;
}
if (typeof props.up !== 'undefined') {
THREEObject3D.up.copy(props.up);
}
if (typeof props.lookat !== 'undefined') {
THREEObject3D.lookAt(props.lookat);
}
if (typeof props.name !== 'undefined') {
THREEObject3D.name = props.name;
}
if (typeof props.castShadow !== 'undefined') {
THREEObject3D.castShadow = props.castShadow;
}
if (typeof props.receiveShadow !== 'undefined') {
THREEObject3D.receiveShadow = props.receiveShadow;
}
if (typeof props.fog !== 'undefined') {
THREEObject3D.fog = props.fog;
}
},
transferTHREEObject3DPropsByName: function(oldProps, newProps, propnames) {
var THREEObject3D = this._THREEObject3D;
propnames.forEach(function(propname) {
if (typeof newProps[propname] !== 'undefined') {
THREEObject3D[propname] = newProps[propname];
}
});
},
applySpecificTHREEProps: function(/*oldProps, newProps*/) {
// the default props are applied in applyTHREEObject3DProps.
// to create a new object type, mixin your own version of this method
},
mountComponent: function(transaction, nativeParent, nativeContainerInfo, context) {
var props = this._currentElement.props;
this._nativeParent = nativeParent;
this._nativeContainerInfo = nativeContainerInfo;
/* jshint unused: vars */
this._THREEObject3D = this.createTHREEObject(arguments);
this._THREEObject3D.userData = this;
this.applyTHREEObject3DProps({}, props);
this.applySpecificTHREEProps({}, props);
this.mountAndAddChildren(props.children, transaction, context);
return this._THREEObject3D;
},
receiveComponent: function(nextElement, transaction, context) {
var oldProps = this._currentElement.props;
var props = nextElement.props;
this.applyTHREEObject3DProps(oldProps, props);
this.applySpecificTHREEProps(oldProps, props);
this.updateChildren(props.children, transaction, context);
this._currentElement = nextElement;
},
unmountComponent: function() {
this.unmountChildren();
},
/*eslint no-unused-vars: [2, { "args": "none" }]*/
mountComponentIntoNode: function(rootID, container) {
throw new Error(
'You cannot render an THREE Object3D standalone. ' +
'You need to wrap it in a THREEScene.'
);
},
getNativeNode: function() {
return this._THREEObject3D;
}
});
export default THREEObject3DMixin;