zincjs 2.4.1-beta.3 → 2.4.1-beta.4
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/README.md +80 -74
- package/build/zinc.js +2 -2
- package/build/zinc.js.map +1 -1
- package/package.json +1 -1
- package/src/loaders/GLTFToZincJSLoader.js +4 -1
- package/src/loaders/JSONLoader.js +2 -2
- package/src/loaders/primitivesLoader.js +1 -1
- package/src/primitives/glyphset.js +8 -0
- package/src/primitives/lod.js +7 -0
- package/src/primitives/texturePrimitive.js +12 -0
- package/src/primitives/textureSlides.js +5 -0
- package/src/primitives/zincObject.js +4 -0
- package/src/region.js +7 -2
- package/src/scene.js +1 -1
- package/src/sceneLoader.js +58 -1
- package/src/texture/texture.js +10 -0
- package/src/texture/textureArray.js +9 -0
package/package.json
CHANGED
|
@@ -123,13 +123,16 @@ const GLTFToZincJSLoader = function () {
|
|
|
123
123
|
* @param {String} url - URL to the GLTF file
|
|
124
124
|
* @param {Function} finishCallback - Callback function which will be called
|
|
125
125
|
* once the glyphset is succssfully load in.
|
|
126
|
+
* @param {Function} isCancelled - Optional function returning true if this
|
|
127
|
+
* load has been cancelled, the loaded content will be discarded.
|
|
126
128
|
*/
|
|
127
|
-
this.load = (scene, region, url, finishCallback, allCompletedCallback, options) => {
|
|
129
|
+
this.load = (scene, region, url, finishCallback, allCompletedCallback, options, isCancelled) => {
|
|
128
130
|
const path = url.substring(0, url.lastIndexOf("/") + 1);
|
|
129
131
|
const filename = url.substring(url.lastIndexOf("/") + 1, url.length);
|
|
130
132
|
const loader = new GLTFLoader().setPath(path);
|
|
131
133
|
|
|
132
134
|
loader.load( filename, function ( gltf ) {
|
|
135
|
+
if (isCancelled && isCancelled()) return;
|
|
133
136
|
console.log(gltf)
|
|
134
137
|
_this.parseGLTFObjects(gltf.scene, region, 0, finishCallback);
|
|
135
138
|
_this.setCamera(scene);
|
|
@@ -302,7 +302,7 @@ Object.assign( JSONLoader.prototype, {
|
|
|
302
302
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
const attribute = new
|
|
305
|
+
const attribute = new BufferAttribute( array, 3 );
|
|
306
306
|
attribute.name = json.morphTargets[ i ].name;
|
|
307
307
|
morphPositions.push( attribute );
|
|
308
308
|
|
|
@@ -321,7 +321,7 @@ Object.assign( JSONLoader.prototype, {
|
|
|
321
321
|
const srcNormals = json.morphNormals[ i ].normals;
|
|
322
322
|
const array = Float32Array.from( srcNormals );
|
|
323
323
|
|
|
324
|
-
const attribute = new
|
|
324
|
+
const attribute = new BufferAttribute( array, 3 );
|
|
325
325
|
attribute.name = morphPositions[ i ].name;
|
|
326
326
|
morphNormals[ i ] = attribute;
|
|
327
327
|
|
|
@@ -124,7 +124,7 @@ const IndexedSourcesHandler = function(urlIn, crossOrigin, onDownloadedCallback)
|
|
|
124
124
|
if (data) {
|
|
125
125
|
processItemDownloaded(item);
|
|
126
126
|
} else {
|
|
127
|
-
processItemError(
|
|
127
|
+
processItemError(item);
|
|
128
128
|
}
|
|
129
129
|
} else if (downloading) {
|
|
130
130
|
//quene it up
|
|
@@ -22,6 +22,8 @@ const Glyphset = function () {
|
|
|
22
22
|
let axis2s = undefined;
|
|
23
23
|
let axis3s = undefined;
|
|
24
24
|
let positions = undefined;
|
|
25
|
+
//Glyph geometry loaded after dispose is discarded
|
|
26
|
+
let disposed = false;
|
|
25
27
|
let scales = undefined;
|
|
26
28
|
let colors = undefined;
|
|
27
29
|
let labels = undefined;
|
|
@@ -149,6 +151,7 @@ const Glyphset = function () {
|
|
|
149
151
|
* geometry is loaded.
|
|
150
152
|
*/
|
|
151
153
|
this.load = (glyphsetData, glyphURL, finishCallback, isInline, displayLabels) => {
|
|
154
|
+
disposed = false;
|
|
152
155
|
axis1s = glyphsetData.axis1;
|
|
153
156
|
axis2s = glyphsetData.axis2;
|
|
154
157
|
axis3s = glyphsetData.axis3;
|
|
@@ -856,6 +859,10 @@ const Glyphset = function () {
|
|
|
856
859
|
|
|
857
860
|
var meshloader = (finishCallback, displayLabels) => {
|
|
858
861
|
return (geometry, materials) => {
|
|
862
|
+
if (disposed) {
|
|
863
|
+
geometry.dispose();
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
859
866
|
this.geometry.copy(geometry);
|
|
860
867
|
this.geometry.computeBoundingSphere();
|
|
861
868
|
this.geometry.computeBoundingBox();
|
|
@@ -1063,6 +1070,7 @@ const Glyphset = function () {
|
|
|
1063
1070
|
* Clear this glyphset and its list of glyphs which will release them from the memory.
|
|
1064
1071
|
*/
|
|
1065
1072
|
this.dispose = () => {
|
|
1073
|
+
disposed = true;
|
|
1066
1074
|
for (let i = glyphList.length - 1; i >= 0; i--) {
|
|
1067
1075
|
glyphList[i].dispose();
|
|
1068
1076
|
}
|
package/src/primitives/lod.js
CHANGED
|
@@ -26,6 +26,8 @@ const LOD = function (parent) {
|
|
|
26
26
|
this._loader = undefined;
|
|
27
27
|
//The owning Zinc Object
|
|
28
28
|
this._parent = parent;
|
|
29
|
+
//Levels loaded after dispose are discarded
|
|
30
|
+
this._disposed = false;
|
|
29
31
|
|
|
30
32
|
/*
|
|
31
33
|
* Add a level of LOD at the specified distance
|
|
@@ -182,6 +184,7 @@ const LOD = function (parent) {
|
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
this.dispose = () => {
|
|
187
|
+
this._disposed = true;
|
|
185
188
|
this.levels.forEach((level) => {
|
|
186
189
|
if (level.morph && level.morph.geometry) {
|
|
187
190
|
level.morph.geometry.dispose();
|
|
@@ -212,6 +215,10 @@ const LOD = function (parent) {
|
|
|
212
215
|
*/
|
|
213
216
|
this.lodLoader = function (distance) {
|
|
214
217
|
return (geometryIn) => {
|
|
218
|
+
if (this._disposed) {
|
|
219
|
+
geometryIn.dispose();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
215
222
|
const material = this._material;
|
|
216
223
|
const options = {
|
|
217
224
|
localTimeEnabled: this._parent.timeEnabled,
|
|
@@ -70,4 +70,16 @@ const TexturePrimitive = function (textureIn) {
|
|
|
70
70
|
|
|
71
71
|
TexturePrimitive.prototype = Object.create(ZincObject.prototype);
|
|
72
72
|
TexturePrimitive.prototype.constructor = TexturePrimitive;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Free the textures and the other allocated memory.
|
|
76
|
+
*/
|
|
77
|
+
TexturePrimitive.prototype.dispose = function() {
|
|
78
|
+
const textures = new Set(this.textureList);
|
|
79
|
+
if (this.texture) textures.add(this.texture);
|
|
80
|
+
textures.forEach(texture => texture.dispose());
|
|
81
|
+
this.texture = undefined;
|
|
82
|
+
this.textureList = [];
|
|
83
|
+
ZincObject.prototype.dispose.call(this);
|
|
84
|
+
}
|
|
73
85
|
export { TexturePrimitive };
|
|
@@ -277,6 +277,11 @@ const TextureSlides = function (textureIn) {
|
|
|
277
277
|
if (slide.material)
|
|
278
278
|
slide.material.dispose();
|
|
279
279
|
});
|
|
280
|
+
if (maskTexture) {
|
|
281
|
+
maskTexture.dispose();
|
|
282
|
+
maskTexture = undefined;
|
|
283
|
+
maskEnabled = false;
|
|
284
|
+
}
|
|
280
285
|
TexturePrimitive.prototype.dispose.call(this);
|
|
281
286
|
this.boundingBoxUpdateRequired = true;
|
|
282
287
|
}
|
|
@@ -565,6 +565,10 @@ ZincObject.prototype.getBoundingBox = function() {
|
|
|
565
565
|
ZincObject.prototype.dispose = function() {
|
|
566
566
|
//multilayyers
|
|
567
567
|
this._lod.dispose();
|
|
568
|
+
if (this.marker) {
|
|
569
|
+
this.marker.dispose();
|
|
570
|
+
this.marker = undefined;
|
|
571
|
+
}
|
|
568
572
|
this.animationGroup = undefined;
|
|
569
573
|
this.mixer = undefined;
|
|
570
574
|
this.morph = undefined;
|
package/src/region.js
CHANGED
|
@@ -445,13 +445,18 @@ let Region = function (parentIn, sceneIn) {
|
|
|
445
445
|
*/
|
|
446
446
|
this.clear = transverse => {
|
|
447
447
|
if (transverse) {
|
|
448
|
-
children.forEach(childRegion =>
|
|
448
|
+
children.forEach(childRegion => {
|
|
449
|
+
childRegion.clear(transverse);
|
|
450
|
+
group.remove(childRegion.getGroup());
|
|
451
|
+
});
|
|
449
452
|
}
|
|
450
453
|
zincObjects.forEach(zincObject => {
|
|
451
454
|
group.remove(zincObject.getGroup());
|
|
452
455
|
zincObject.dispose();
|
|
453
456
|
});
|
|
454
|
-
|
|
457
|
+
if (transverse) {
|
|
458
|
+
children = [];
|
|
459
|
+
}
|
|
455
460
|
zincObjects = [];
|
|
456
461
|
}
|
|
457
462
|
|
package/src/scene.js
CHANGED
|
@@ -1025,7 +1025,7 @@ const Scene = function (containerIn, rendererIn) {
|
|
|
1025
1025
|
rootRegion.clear(true);
|
|
1026
1026
|
this.clearZincObjectAddedCallbacks();
|
|
1027
1027
|
this.clearZincObjectRemovedCallbacks();
|
|
1028
|
-
sceneLoader.
|
|
1028
|
+
sceneLoader.cancelPendingLoads();
|
|
1029
1029
|
if (zincCameraControls) {
|
|
1030
1030
|
zincCameraControls.calculateMaxAllowedDistance(this);
|
|
1031
1031
|
}
|
package/src/sceneLoader.js
CHANGED
|
@@ -27,7 +27,30 @@ const SceneLoader = function (sceneIn) {
|
|
|
27
27
|
this.progressMap = {};
|
|
28
28
|
let viewLoaded = false;
|
|
29
29
|
let errorDownload = false;
|
|
30
|
+
//Incremented when pending loads are cancelled, loads requested
|
|
31
|
+
//before the increment are discarded once they complete.
|
|
32
|
+
let generation = 0;
|
|
30
33
|
const primitivesLoader = new PrimitivesLoader();
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Cancel all pending downloads, objects from the cancelled downloads
|
|
37
|
+
* will be discarded instead of being added into the scene once they
|
|
38
|
+
* arrive.
|
|
39
|
+
*/
|
|
40
|
+
this.cancelPendingLoads = () => {
|
|
41
|
+
generation++;
|
|
42
|
+
this.toBeDownloaded = 0;
|
|
43
|
+
this.progressMap = {};
|
|
44
|
+
viewLoaded = false;
|
|
45
|
+
errorDownload = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//Return a function which returns true if the loads requested before
|
|
49
|
+
//this call have been cancelled.
|
|
50
|
+
const createStaleCheck = () => {
|
|
51
|
+
const requestGeneration = generation;
|
|
52
|
+
return () => requestGeneration !== generation;
|
|
53
|
+
}
|
|
31
54
|
/**
|
|
32
55
|
* This function returns a three component array, which contains
|
|
33
56
|
* [totalsize, totalLoaded and errorDownload] of all the downloads happening
|
|
@@ -62,7 +85,9 @@ const SceneLoader = function (sceneIn) {
|
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
this.onError = finishCallback => {
|
|
88
|
+
const isStale = createStaleCheck();
|
|
65
89
|
return xhr => {
|
|
90
|
+
if (isStale()) return;
|
|
66
91
|
this.toBeDownloaded = this.toBeDownloaded - 1;
|
|
67
92
|
errorDownload = true;
|
|
68
93
|
console.error(`There is an issue with external resource ${xhr?.responseURL ? ": " + xhr?.responseURL: ""}.`);
|
|
@@ -116,6 +141,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
116
141
|
this.loadViewURL = (url, finishCallback) => {
|
|
117
142
|
this.toBeDownloaded += 1;
|
|
118
143
|
const requestURL = url;
|
|
144
|
+
const isStale = createStaleCheck();
|
|
119
145
|
fetch(requestURL)
|
|
120
146
|
.then((response) => {
|
|
121
147
|
if (!response.ok) {
|
|
@@ -124,6 +150,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
124
150
|
return response.json();
|
|
125
151
|
})
|
|
126
152
|
.then((viewData) => {
|
|
153
|
+
if (isStale()) return;
|
|
127
154
|
scene.setupMultipleViews("default", { "default" : viewData });
|
|
128
155
|
scene.resetView();
|
|
129
156
|
viewLoaded = true;
|
|
@@ -176,6 +203,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
176
203
|
*/
|
|
177
204
|
this.loadFromViewURL = (targetRegion, jsonFilePrefix, finishCallback) => {
|
|
178
205
|
const requestURL = jsonFilePrefix + "_view.json";
|
|
206
|
+
const isStale = createStaleCheck();
|
|
179
207
|
fetch(requestURL)
|
|
180
208
|
.then((response) => {
|
|
181
209
|
if (!response.ok) {
|
|
@@ -184,6 +212,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
184
212
|
return response.json();
|
|
185
213
|
})
|
|
186
214
|
.then((viewData) => {
|
|
215
|
+
if (isStale()) return;
|
|
187
216
|
scene.loadView(viewData);
|
|
188
217
|
const urls = [];
|
|
189
218
|
const filename_prefix = jsonFilePrefix + "_";
|
|
@@ -209,7 +238,12 @@ const SceneLoader = function (sceneIn) {
|
|
|
209
238
|
//Internal loader for a regular zinc geometry.
|
|
210
239
|
const linesloader = (region, localTimeEnabled, localMorphColour, groupName,
|
|
211
240
|
anatomicalId, renderOrder, lod, tubeLines, finishCallback) => {
|
|
241
|
+
const isStale = createStaleCheck();
|
|
212
242
|
return (geometry, materials) => {
|
|
243
|
+
if (isStale()) {
|
|
244
|
+
geometry.dispose();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
213
247
|
const newLines = tubeLines ? new TubeLines() : new Lines();
|
|
214
248
|
let material = undefined;
|
|
215
249
|
if (materials && materials[0]) {
|
|
@@ -276,7 +310,9 @@ const SceneLoader = function (sceneIn) {
|
|
|
276
310
|
}
|
|
277
311
|
|
|
278
312
|
const glyphsetloader = (region, glyphurl, groupName, finishCallback, options) => {
|
|
313
|
+
const isStale = createStaleCheck();
|
|
279
314
|
return (data) => {
|
|
315
|
+
if (isStale()) return;
|
|
280
316
|
let glyphsetData = data;
|
|
281
317
|
if (typeof glyphsetData === 'string' || glyphsetData instanceof String) {
|
|
282
318
|
glyphsetData = JSON.parse(data);
|
|
@@ -292,6 +328,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
292
328
|
newGlyphset.setDuration(scene.getDuration());
|
|
293
329
|
newGlyphset.groupName = groupName;
|
|
294
330
|
let myCallback = () => {
|
|
331
|
+
if (isStale()) return;
|
|
295
332
|
--this.toBeDownloaded;
|
|
296
333
|
if (finishCallback != undefined && (typeof finishCallback == 'function'))
|
|
297
334
|
finishCallback(newGlyphset);
|
|
@@ -358,7 +395,12 @@ const SceneLoader = function (sceneIn) {
|
|
|
358
395
|
|
|
359
396
|
//Internal loader for zinc pointset.
|
|
360
397
|
const pointsetloader = (region, localTimeEnabled, localMorphColour, groupName, anatomicalId, renderOrder, finishCallback) => {
|
|
398
|
+
const isStale = createStaleCheck();
|
|
361
399
|
return (geometry, materials) => {
|
|
400
|
+
if (isStale()) {
|
|
401
|
+
geometry.dispose();
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
362
404
|
const newPointset = new Pointset();
|
|
363
405
|
let material = new THREE.PointsMaterial(
|
|
364
406
|
{
|
|
@@ -554,7 +596,12 @@ const SceneLoader = function (sceneIn) {
|
|
|
554
596
|
}
|
|
555
597
|
if (newTexture) {
|
|
556
598
|
newTexture.groupName = groupName;
|
|
599
|
+
const isStale = createStaleCheck();
|
|
557
600
|
let myCallback = () => {
|
|
601
|
+
if (isStale()) {
|
|
602
|
+
newTexture.dispose();
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
558
605
|
//Add zincObject after it has sort out all the required download
|
|
559
606
|
region.addZincObject(newTexture);
|
|
560
607
|
--this.toBeDownloaded;
|
|
@@ -582,6 +629,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
582
629
|
loadTexture(region, undefined, url, groupName, finishCallback, options);
|
|
583
630
|
} else {
|
|
584
631
|
const requestURL = url;
|
|
632
|
+
const isStale = createStaleCheck();
|
|
585
633
|
fetch(requestURL)
|
|
586
634
|
.then((response) => {
|
|
587
635
|
if (!response.ok) {
|
|
@@ -591,6 +639,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
591
639
|
return response.json().then((textureData) => ({ textureData, referenceURL }));
|
|
592
640
|
})
|
|
593
641
|
.then(({textureData, referenceURL}) => {
|
|
642
|
+
if (isStale()) return;
|
|
594
643
|
loadTexture(region, referenceURL, textureData, groupName, finishCallback, options);
|
|
595
644
|
})
|
|
596
645
|
.catch((error) => {
|
|
@@ -662,7 +711,12 @@ const SceneLoader = function (sceneIn) {
|
|
|
662
711
|
options,
|
|
663
712
|
finishCallback
|
|
664
713
|
) => {
|
|
714
|
+
const isStale = createStaleCheck();
|
|
665
715
|
return (geometry, materials) => {
|
|
716
|
+
if (isStale()) {
|
|
717
|
+
geometry.dispose();
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
666
720
|
let material = undefined;
|
|
667
721
|
if (materials && materials[0]) {
|
|
668
722
|
material = materials[0];
|
|
@@ -831,7 +885,8 @@ const SceneLoader = function (sceneIn) {
|
|
|
831
885
|
*/
|
|
832
886
|
this.loadGLTF = (region, url, finishCallback, allCompletedCallback, options) => {
|
|
833
887
|
const loader = new GLTFToZincJSLoader();
|
|
834
|
-
loader.load(scene, region, url, finishCallback, allCompletedCallback, options
|
|
888
|
+
loader.load(scene, region, url, finishCallback, allCompletedCallback, options,
|
|
889
|
+
createStaleCheck());
|
|
835
890
|
}
|
|
836
891
|
|
|
837
892
|
let loadRegions = (currentRegion, referenceURL, regions, callback) => {
|
|
@@ -993,6 +1048,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
993
1048
|
*/
|
|
994
1049
|
this.loadMetadataURL = (targetRegion, url, finishCallback, allCompletedCallback, options) => {
|
|
995
1050
|
const requestURL = url;
|
|
1051
|
+
const isStale = createStaleCheck();
|
|
996
1052
|
fetch(requestURL)
|
|
997
1053
|
.then((response) => {
|
|
998
1054
|
if (!response.ok) {
|
|
@@ -1002,6 +1058,7 @@ const SceneLoader = function (sceneIn) {
|
|
|
1002
1058
|
return response.json().then((metadata) => ({ metadata, referenceURL }));
|
|
1003
1059
|
})
|
|
1004
1060
|
.then(({metadata, referenceURL}) => {
|
|
1061
|
+
if (isStale()) return;
|
|
1005
1062
|
scene.resetMetadata();
|
|
1006
1063
|
scene.resetDuration();
|
|
1007
1064
|
viewLoaded = false;
|
package/src/texture/texture.js
CHANGED
|
@@ -70,6 +70,16 @@ Texture.prototype.loadFromImages = async function (srcArrays) {
|
|
|
70
70
|
return
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Free the memory allocated for this texture.
|
|
75
|
+
*/
|
|
76
|
+
Texture.prototype.dispose = function () {
|
|
77
|
+
if (this.impl) {
|
|
78
|
+
this.impl.dispose();
|
|
79
|
+
this.impl = undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
/**
|
|
74
84
|
* Return true if the texture is ready for consumption.
|
|
75
85
|
*
|
|
@@ -121,4 +121,13 @@ const TextureArray = function () {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
TextureArray.prototype = Object.create(Texture.prototype);
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Free the memory allocated for this texture array.
|
|
127
|
+
*/
|
|
128
|
+
TextureArray.prototype.dispose = function () {
|
|
129
|
+
Texture.prototype.dispose.call(this);
|
|
130
|
+
this.imageData = undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
124
133
|
export { TextureArray };
|