zincjs 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -47
- package/build/zinc.frontend.js +1 -1
- package/build/zinc.js +208 -170
- package/build/zinc.js.map +1 -1
- package/package.json +2 -2
- package/src/controls.js +4 -3
- package/src/primitives/geometry.js +34 -1
- package/src/primitives/lines.js +2 -1
- package/src/primitives/pointset.js +2 -1
- package/src/primitives/zincObject.js +3 -72
- package/src/renderer.js +6 -6
- package/src/sceneLoader.js +10 -10
- package/src/utilities.js +192 -144
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zincjs",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "ZincJS (Web-based-Zinc-Visualisation)",
|
|
5
5
|
"main": "build/zinc.js",
|
|
6
6
|
"directories": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"lodash": "^4.17.19",
|
|
61
61
|
"promise-polyfill": "^8.1.3",
|
|
62
62
|
"three": "^0.130.1",
|
|
63
|
-
"three-spritetext": "
|
|
63
|
+
"three-spritetext": "1.6.2",
|
|
64
64
|
"url-loader": "^2.1.0",
|
|
65
65
|
"url-polyfill": "^1.1.7",
|
|
66
66
|
"webworkify-webpack": "^2.1.5"
|
package/src/controls.js
CHANGED
|
@@ -71,6 +71,7 @@ const CameraControls = function ( object, domElement, renderer, scene ) {
|
|
|
71
71
|
this.directionalLight = 0;
|
|
72
72
|
this.scrollRate = 50;
|
|
73
73
|
let duration = 6000;
|
|
74
|
+
let enabled = true;
|
|
74
75
|
let inbuildTime = 0;
|
|
75
76
|
let cameraPath = undefined;
|
|
76
77
|
let numberOfCameraPoint = undefined;
|
|
@@ -740,7 +741,7 @@ const CameraControls = function ( object, domElement, renderer, scene ) {
|
|
|
740
741
|
finishCallback();
|
|
741
742
|
}
|
|
742
743
|
}
|
|
743
|
-
requestURL = resolveURL(path_url);
|
|
744
|
+
const requestURL = resolveURL(path_url);
|
|
744
745
|
xmlhttp.open("GET", requestURL, true);
|
|
745
746
|
xmlhttp.send();
|
|
746
747
|
}
|
|
@@ -1594,7 +1595,7 @@ const CameraAutoTumble = function (tumbleDirectionIn, tumbleRateIn, stopOnCamera
|
|
|
1594
1595
|
/**
|
|
1595
1596
|
* @author mrdoob / http://mrdoob.com/
|
|
1596
1597
|
*/
|
|
1597
|
-
StereoCameraZoomFixed = function () {
|
|
1598
|
+
const StereoCameraZoomFixed = function () {
|
|
1598
1599
|
|
|
1599
1600
|
this.type = 'StereoCamera';
|
|
1600
1601
|
|
|
@@ -1732,7 +1733,7 @@ const StereoEffect = function ( renderer ) {
|
|
|
1732
1733
|
* W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html)
|
|
1733
1734
|
*/
|
|
1734
1735
|
|
|
1735
|
-
ModifiedDeviceOrientationControls = function ( object ) {
|
|
1736
|
+
const ModifiedDeviceOrientationControls = function ( object ) {
|
|
1736
1737
|
|
|
1737
1738
|
const scope = this;
|
|
1738
1739
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const THREE = require('three');
|
|
2
|
+
const toBufferGeometry = require('../utilities').toBufferGeometry;
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Provides an object which stores geometry and provides method which controls its animations.
|
|
@@ -32,7 +33,7 @@ const Geometry = function () {
|
|
|
32
33
|
if (this.geometry && this.morph && (geometryIn != undefined))
|
|
33
34
|
return;
|
|
34
35
|
// First copy the geometry
|
|
35
|
-
let geometry =
|
|
36
|
+
let geometry = toBufferGeometry(geometryIn, options);
|
|
36
37
|
|
|
37
38
|
let isTransparent = false;
|
|
38
39
|
if (1.0 > options.opacity)
|
|
@@ -109,6 +110,37 @@ const Geometry = function () {
|
|
|
109
110
|
}
|
|
110
111
|
geometry.uvsNeedUpdate = true;
|
|
111
112
|
}
|
|
113
|
+
|
|
114
|
+
this.checkAndCreateTransparentMesh = function() {
|
|
115
|
+
if (this.morph.material && this.morph.material.transparent) {
|
|
116
|
+
if (!this.secondaryMesh) {
|
|
117
|
+
let secondaryMaterial = this.morph.material.clone();
|
|
118
|
+
secondaryMaterial.side = THREE.FrontSide;
|
|
119
|
+
this.secondaryMesh = new THREE.Mesh(this.morph.geometry, secondaryMaterial);
|
|
120
|
+
this.secondaryMesh.renderOrder = this.morph.renderOrder + 1;
|
|
121
|
+
this.secondaryMesh.userData = this;
|
|
122
|
+
this.secondaryMesh.name = this.groupName;
|
|
123
|
+
}
|
|
124
|
+
this.morph.material.side = THREE.BackSide;
|
|
125
|
+
this.morph.material.needsUpdate = true;
|
|
126
|
+
this.morph.add(this.secondaryMesh);
|
|
127
|
+
this.animationGroup.add(this.secondaryMesh);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Handle transparent mesh, remove a clone for backside rendering if it is
|
|
133
|
+
* transparent.
|
|
134
|
+
*/
|
|
135
|
+
this.checkAndRemoveTransparentMesh = function() {
|
|
136
|
+
if (this.secondaryMesh) {
|
|
137
|
+
this.morph.remove(this.secondaryMesh);
|
|
138
|
+
this.animationGroup.uncache(this.secondaryMesh);
|
|
139
|
+
this.animationGroup.remove(this.secondaryMesh);
|
|
140
|
+
}
|
|
141
|
+
this.morph.material.side = THREE.DoubleSide;
|
|
142
|
+
}
|
|
143
|
+
|
|
112
144
|
|
|
113
145
|
/**
|
|
114
146
|
* Set wireframe display for this geometry.
|
|
@@ -119,6 +151,7 @@ const Geometry = function () {
|
|
|
119
151
|
this.morph.material.wireframe = wireframe;
|
|
120
152
|
}
|
|
121
153
|
|
|
154
|
+
|
|
122
155
|
}
|
|
123
156
|
|
|
124
157
|
Geometry.prototype = Object.create((require('./zincObject').ZincObject).prototype);
|
package/src/primitives/lines.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const THREE = require('three');
|
|
2
|
+
const toBufferGeometry = require('../utilities').toBufferGeometry;
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Provides an object which stores lines.
|
|
@@ -26,7 +27,7 @@ const Lines = function () {
|
|
|
26
27
|
*/
|
|
27
28
|
this.createLineSegment = (geometryIn, materialIn, options) => {
|
|
28
29
|
if (geometryIn && materialIn) {
|
|
29
|
-
let geometry =
|
|
30
|
+
let geometry = toBufferGeometry(geometryIn, options);
|
|
30
31
|
if (options.localMorphColour && geometry.morphAttributes[ "color" ])
|
|
31
32
|
materialIn.onBeforeCompile = (require("./augmentShader").augmentMorphColor)();
|
|
32
33
|
let line = new (require("../three/line/LineSegments").LineSegments)(geometry, materialIn);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const THREE = require('three');
|
|
2
2
|
const Points = require('../three/Points').Points;
|
|
3
|
+
const toBufferGeometry = require('../utilities').toBufferGeometry;
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Provides an object which stores points and provides method which controls its position.
|
|
@@ -37,7 +38,7 @@ const Pointset = function () {
|
|
|
37
38
|
*/
|
|
38
39
|
this.createMesh = (geometryIn, materialIn, options) => {
|
|
39
40
|
if (geometryIn && materialIn) {
|
|
40
|
-
let geometry =
|
|
41
|
+
let geometry = toBufferGeometry(geometryIn, options);
|
|
41
42
|
const texture = getCircularTexture();
|
|
42
43
|
materialIn.map = texture;
|
|
43
44
|
let point = new Points(geometry, materialIn);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const THREE = require('three');
|
|
2
|
-
const
|
|
3
|
-
|
|
2
|
+
const updateMorphColorAttribute = require("../utilities").updateMorphColorAttribute;
|
|
4
3
|
let uniqueiId = 0;
|
|
5
4
|
|
|
6
5
|
const getUniqueId = function () {
|
|
@@ -93,49 +92,12 @@ ZincObject.prototype.getRegion = function() {
|
|
|
93
92
|
return this.region;
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
/**
|
|
97
|
-
* Convert a {THREE.Geometry} into a {THREE.BufferGeometry}.
|
|
98
|
-
*/
|
|
99
|
-
ZincObject.prototype.toBufferGeometry = function(geometryIn, options) {
|
|
100
|
-
let geometry = undefined;
|
|
101
|
-
if (geometryIn instanceof THREEGeometry) {
|
|
102
|
-
if (options.localTimeEnabled && !geometryIn.morphNormalsReady &&
|
|
103
|
-
(geometryIn.morphNormals == undefined || geometryIn.morphNormals.length == 0))
|
|
104
|
-
geometryIn.computeMorphNormals();
|
|
105
|
-
geometry = geometryIn.toIndexedBufferGeometry();
|
|
106
|
-
if (options.localMorphColour) {
|
|
107
|
-
require("../utilities").copyMorphColorsToIndexedBufferGeometry(geometryIn, geometry);
|
|
108
|
-
}
|
|
109
|
-
} else if (geometryIn instanceof THREE.BufferGeometry) {
|
|
110
|
-
geometry = geometryIn.clone();
|
|
111
|
-
}
|
|
112
|
-
geometry.colorsNeedUpdate = true;
|
|
113
|
-
geometry.computeBoundingBox();
|
|
114
|
-
geometry.computeBoundingSphere();
|
|
115
|
-
if (geometryIn._video)
|
|
116
|
-
geometry._video = geometryIn._video;
|
|
117
|
-
return geometry;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
95
|
/**
|
|
121
96
|
* Handle transparent mesh, create a clone for backside rendering if it is
|
|
122
97
|
* transparent.
|
|
123
98
|
*/
|
|
124
99
|
ZincObject.prototype.checkAndCreateTransparentMesh = function() {
|
|
125
|
-
|
|
126
|
-
if (!this.secondaryMesh) {
|
|
127
|
-
let secondaryMaterial = this.morph.material.clone();
|
|
128
|
-
secondaryMaterial.side = THREE.FrontSide;
|
|
129
|
-
this.secondaryMesh = new THREE.Mesh(this.morph.geometry, secondaryMaterial);
|
|
130
|
-
this.secondaryMesh.renderOrder = this.morph.renderOrder + 1;
|
|
131
|
-
this.secondaryMesh.userData = this;
|
|
132
|
-
this.secondaryMesh.name = this.groupName;
|
|
133
|
-
}
|
|
134
|
-
this.morph.material.side = THREE.BackSide;
|
|
135
|
-
this.morph.material.needsUpdate = true;
|
|
136
|
-
this.morph.add(this.secondaryMesh);
|
|
137
|
-
this.animationGroup.add(this.secondaryMesh);
|
|
138
|
-
}
|
|
100
|
+
return;
|
|
139
101
|
}
|
|
140
102
|
|
|
141
103
|
/**
|
|
@@ -143,12 +105,7 @@ ZincObject.prototype.checkAndCreateTransparentMesh = function() {
|
|
|
143
105
|
* transparent.
|
|
144
106
|
*/
|
|
145
107
|
ZincObject.prototype.checkAndRemoveTransparentMesh = function() {
|
|
146
|
-
|
|
147
|
-
this.morph.remove(this.secondaryMesh);
|
|
148
|
-
this.animationGroup.uncache(this.secondaryMesh);
|
|
149
|
-
this.animationGroup.remove(this.secondaryMesh);
|
|
150
|
-
}
|
|
151
|
-
this.morph.material.side = THREE.DoubleSide;
|
|
108
|
+
return;
|
|
152
109
|
}
|
|
153
110
|
|
|
154
111
|
/**
|
|
@@ -231,32 +188,6 @@ ZincObject.prototype.getCurrentTime = function() {
|
|
|
231
188
|
}
|
|
232
189
|
}
|
|
233
190
|
|
|
234
|
-
const updateMorphColorAttribute = function(targetGeometry, morph) {
|
|
235
|
-
if (morph && targetGeometry && targetGeometry.morphAttributes &&
|
|
236
|
-
targetGeometry.morphAttributes[ "color" ]) {
|
|
237
|
-
const morphColors = targetGeometry.morphAttributes[ "color" ];
|
|
238
|
-
const influences = morph.morphTargetInfluences;
|
|
239
|
-
const length = influences.length;
|
|
240
|
-
targetGeometry.deleteAttribute( 'morphColor0' );
|
|
241
|
-
targetGeometry.deleteAttribute( 'morphColor1' );
|
|
242
|
-
let bound = 0;
|
|
243
|
-
let morphArray = [];
|
|
244
|
-
for (let i = 0; (1 > bound) || (i < length); i++) {
|
|
245
|
-
if (influences[i] > 0) {
|
|
246
|
-
bound++;
|
|
247
|
-
morphArray.push([i, influences[i]]);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
if (morphArray.length == 2) {
|
|
251
|
-
targetGeometry.setAttribute('morphColor0', morphColors[ morphArray[0][0] ] );
|
|
252
|
-
targetGeometry.setAttribute('morphColor1', morphColors[ morphArray[1][0] ] );
|
|
253
|
-
} else if (morphArray.length == 1) {
|
|
254
|
-
targetGeometry.setAttribute('morphColor0', morphColors[ morphArray[0][0] ] );
|
|
255
|
-
targetGeometry.setAttribute('morphColor1', morphColors[ morphArray[0][0] ] );
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
191
|
/**
|
|
261
192
|
* Set the local time of this geometry.
|
|
262
193
|
*
|
package/src/renderer.js
CHANGED
|
@@ -237,7 +237,7 @@ exports.Renderer = function (containerIn) {
|
|
|
237
237
|
if (currentScene) {
|
|
238
238
|
const boundingBox = currentScene.getBoundingBox();
|
|
239
239
|
if (boundingBox) {
|
|
240
|
-
for(i = 0; i < additionalActiveScenes.length; i++) {
|
|
240
|
+
for(let i = 0; i < additionalActiveScenes.length; i++) {
|
|
241
241
|
const boundingBox2 = additionalActiveScenes[i].getBoundingBox();
|
|
242
242
|
if (boundingBox2) {
|
|
243
243
|
boundingBox.union(boundingBox2);
|
|
@@ -470,7 +470,7 @@ exports.Renderer = function (containerIn) {
|
|
|
470
470
|
}
|
|
471
471
|
const delta = clock.getDelta();
|
|
472
472
|
currentScene.renderGeometries(playRate, delta, this.playAnimation);
|
|
473
|
-
for(i = 0; i < additionalActiveScenes.length; i++) {
|
|
473
|
+
for(let i = 0; i < additionalActiveScenes.length; i++) {
|
|
474
474
|
const sceneItem = additionalActiveScenes[i];
|
|
475
475
|
sceneItem.renderGeometries(playRate, delta, this.playAnimation);
|
|
476
476
|
}
|
|
@@ -478,13 +478,13 @@ exports.Renderer = function (containerIn) {
|
|
|
478
478
|
renderer.clearDepth();
|
|
479
479
|
renderer.render( sceneOrtho, cameraOrtho );
|
|
480
480
|
}
|
|
481
|
-
for (key in preRenderCallbackFunctions) {
|
|
481
|
+
for (let key in preRenderCallbackFunctions) {
|
|
482
482
|
if (preRenderCallbackFunctions.hasOwnProperty(key)) {
|
|
483
483
|
preRenderCallbackFunctions[key].call();
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
currentScene.render(renderer);
|
|
487
|
-
for (key in postRenderCallbackFunctions) {
|
|
487
|
+
for (let key in postRenderCallbackFunctions) {
|
|
488
488
|
if (postRenderCallbackFunctions.hasOwnProperty(key)) {
|
|
489
489
|
postRenderCallbackFunctions[key].call();
|
|
490
490
|
}
|
|
@@ -507,7 +507,7 @@ exports.Renderer = function (containerIn) {
|
|
|
507
507
|
if (currentScene === sceneIn) {
|
|
508
508
|
return true;
|
|
509
509
|
} else {
|
|
510
|
-
for(i = 0; i < additionalActiveScenes.length; i++) {
|
|
510
|
+
for(let i = 0; i < additionalActiveScenes.length; i++) {
|
|
511
511
|
const sceneItem = additionalActiveScenes[i];
|
|
512
512
|
if (sceneItem === sceneIn)
|
|
513
513
|
return true;
|
|
@@ -534,7 +534,7 @@ exports.Renderer = function (containerIn) {
|
|
|
534
534
|
* @param {Zinc.Scene} additionalScene - Scene to be removed from rendering.
|
|
535
535
|
*/
|
|
536
536
|
this.removeActiveScene = additionalScene => {
|
|
537
|
-
for(i = 0; i < additionalActiveScenes.length; i++) {
|
|
537
|
+
for(let i = 0; i < additionalActiveScenes.length; i++) {
|
|
538
538
|
const sceneItem = additionalActiveScenes[i];
|
|
539
539
|
if (sceneItem === additionalScene) {
|
|
540
540
|
additionalActiveScenes.splice(i, 1);
|
package/src/sceneLoader.js
CHANGED
|
@@ -29,7 +29,7 @@ const createNewURL = (target, reference) => {
|
|
|
29
29
|
exports.SceneLoader = function (sceneIn) {
|
|
30
30
|
const scene = sceneIn;
|
|
31
31
|
this.toBeDownloaded = 0;
|
|
32
|
-
this.progressMap =
|
|
32
|
+
this.progressMap = {};
|
|
33
33
|
let viewLoaded = false;
|
|
34
34
|
let errorDownload = false;
|
|
35
35
|
const primitivesLoader = new PrimitivesLoader();
|
|
@@ -131,7 +131,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
-
requestURL = resolveURL(url);
|
|
134
|
+
const requestURL = resolveURL(url);
|
|
135
135
|
xmlhttp.open("GET", requestURL, true);
|
|
136
136
|
xmlhttp.send();
|
|
137
137
|
}
|
|
@@ -160,7 +160,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
160
160
|
if (morphColour != undefined && morphColour[i] != undefined)
|
|
161
161
|
localMorphColour = morphColour[i] ? true : false;
|
|
162
162
|
primitivesLoader.load(resolveURL(filename), meshloader(region, colour, opacity, localTimeEnabled, localMorphColour, undefined, undefined,
|
|
163
|
-
undefined, finishCallback), this.onProgress(
|
|
163
|
+
undefined, finishCallback), this.onProgress(filename), this.onError(finishCallback));
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -187,7 +187,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
187
187
|
this.loadModelsURL(targetRegion, urls, viewData.colour, viewData.opacity, viewData.timeEnabled, viewData.morphColour, finishCallback);
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
|
-
requestURL = resolveURL(jsonFilePrefix + "_view.json");
|
|
190
|
+
const requestURL = resolveURL(jsonFilePrefix + "_view.json");
|
|
191
191
|
xmlhttp.open("GET", requestURL, true);
|
|
192
192
|
xmlhttp.send();
|
|
193
193
|
}
|
|
@@ -253,7 +253,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
253
253
|
renderOrder, finishCallback))( object.geometry, object.materials );
|
|
254
254
|
} else {
|
|
255
255
|
primitivesLoader.load(url, linesloader(region, localTimeEnabled, localMorphColour, groupName,
|
|
256
|
-
anatomicalId, renderOrder, finishCallback), this.onProgress(
|
|
256
|
+
anatomicalId, renderOrder, finishCallback), this.onProgress(url), this.onError(finishCallback));
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
@@ -423,7 +423,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
423
423
|
loader = new OBJLoader();
|
|
424
424
|
loader.crossOrigin = "Anonymous";
|
|
425
425
|
loader.load(url, objloader(region, colour, opacity, localTimeEnabled,
|
|
426
|
-
localMorphColour, groupName, anatomicalId, finishCallback), this.onProgress(
|
|
426
|
+
localMorphColour, groupName, anatomicalId, finishCallback), this.onProgress(url), this.onError);
|
|
427
427
|
return;
|
|
428
428
|
}
|
|
429
429
|
}
|
|
@@ -434,7 +434,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
434
434
|
} else {
|
|
435
435
|
loader.crossOrigin = "Anonymous";
|
|
436
436
|
primitivesLoader.load(url, meshloader(region, colour, opacity, localTimeEnabled,
|
|
437
|
-
localMorphColour, groupName, anatomicalId, renderOrder, finishCallback), this.onProgress(
|
|
437
|
+
localMorphColour, groupName, anatomicalId, renderOrder, finishCallback), this.onProgress(url), this.onError(finishCallback));
|
|
438
438
|
}
|
|
439
439
|
};
|
|
440
440
|
|
|
@@ -488,7 +488,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
488
488
|
} else {
|
|
489
489
|
primitivesLoader.load(url, pointsetloader(region, localTimeEnabled, localMorphColour,
|
|
490
490
|
groupName, anatomicalId, renderOrder, finishCallback),
|
|
491
|
-
this.onProgress(
|
|
491
|
+
this.onProgress(url), this.onError(finishCallback));
|
|
492
492
|
}
|
|
493
493
|
}
|
|
494
494
|
|
|
@@ -529,7 +529,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
529
529
|
*
|
|
530
530
|
* @returns {Zinc.Geometry}
|
|
531
531
|
*/
|
|
532
|
-
addZincGeometry = (
|
|
532
|
+
const addZincGeometry = (
|
|
533
533
|
region,
|
|
534
534
|
geometryIn,
|
|
535
535
|
colour,
|
|
@@ -824,7 +824,7 @@ exports.SceneLoader = function (sceneIn) {
|
|
|
824
824
|
*/
|
|
825
825
|
this.loadMetadataURL = (targetRegion, url, finishCallback, allCompletedCallback) => {
|
|
826
826
|
const xmlhttp = new XMLHttpRequest();
|
|
827
|
-
|
|
827
|
+
const requestURL = resolveURL(url);
|
|
828
828
|
xmlhttp.onreadystatechange = () => {
|
|
829
829
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
|
|
830
830
|
scene.resetMetadata();
|