zincjs 3.0.0 → 3.0.1

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.
Files changed (60) hide show
  1. package/README.md +27 -22
  2. package/build/zinc.js +2 -2
  3. package/build/zinc.js.map +1 -1
  4. package/package.json +4 -1
  5. package/src/controls.js +1332 -1241
  6. package/src/geometryCSG.js +111 -115
  7. package/src/glyphsetCSG.js +51 -55
  8. package/src/loaders/GLTFToZincJSLoader.js +31 -33
  9. package/src/loaders/JSONLoader.js +339 -449
  10. package/src/loaders/OBJLoader.js +654 -851
  11. package/src/loaders/STLLoader.js +271 -329
  12. package/src/loaders/niftiReader.js +90 -59
  13. package/src/loaders/primitivesLoader.js +55 -52
  14. package/src/minimap.js +63 -43
  15. package/src/primitives/geometry.js +40 -44
  16. package/src/primitives/glyph.js +16 -19
  17. package/src/primitives/glyphset.js +229 -185
  18. package/src/primitives/label.js +29 -31
  19. package/src/primitives/lines.js +20 -20
  20. package/src/primitives/lines2.js +33 -39
  21. package/src/primitives/lod.js +43 -43
  22. package/src/primitives/marker.js +31 -32
  23. package/src/primitives/markerCluster.js +32 -35
  24. package/src/primitives/pointset.js +86 -83
  25. package/src/primitives/texturePrimitive.js +9 -10
  26. package/src/primitives/textureSlides.js +84 -97
  27. package/src/primitives/textureVolume.js +46 -49
  28. package/src/primitives/tubeLines.js +108 -108
  29. package/src/primitives/zincObject.js +176 -184
  30. package/src/region.js +145 -155
  31. package/src/renderRequests.js +3 -3
  32. package/src/renderer.js +635 -620
  33. package/src/scene.js +479 -419
  34. package/src/sceneExporter.js +22 -17
  35. package/src/sceneLoader.js +542 -296
  36. package/src/shaders/rgbVolumeRender.js +11 -18
  37. package/src/shaders/textureArray.js +5 -12
  38. package/src/shaders/textureSlide.js +10 -17
  39. package/src/shaders/volumeRender.js +11 -18
  40. package/src/shaders/volumeRender_old.js +11 -18
  41. package/src/shaders/volumeTexture.js +7 -14
  42. package/src/textSprite.js +23 -19
  43. package/src/texture/texture.js +14 -15
  44. package/src/texture/textureArray.js +14 -16
  45. package/src/three/InstancedPoints.js +2 -9
  46. package/src/three/Loader.js +334 -315
  47. package/src/three/line/Line.js +165 -215
  48. package/src/three/line/LineSegments.js +40 -55
  49. package/src/three/line/LineSegments2.js +322 -366
  50. package/src/three/line/LineSegmentsGeometry.js +239 -280
  51. package/src/three-js-csg.js +260 -252
  52. package/src/tsl/glyphRenderMaterial.js +12 -3
  53. package/src/tsl/glyphTransform.js +51 -29
  54. package/src/tsl/textureSlides.js +23 -24
  55. package/src/utilities.js +309 -371
  56. package/src/videoHandler.js +76 -83
  57. package/src/workers/geometryCSG.worker.js +33 -36
  58. package/src/workers/geometryCSGInternal.js +39 -44
  59. package/src/zinc.js +4 -7
  60. package/vite.config.js +7 -7
@@ -41,14 +41,14 @@ const SceneLoader = function (sceneIn) {
41
41
  this.progressMap = {};
42
42
  viewLoaded = false;
43
43
  errorDownload = false;
44
- }
44
+ };
45
45
 
46
46
  //Return a function which returns true if the loads requested before
47
47
  //this call have been cancelled.
48
48
  const createStaleCheck = () => {
49
49
  const requestGeneration = generation;
50
50
  return () => requestGeneration !== generation;
51
- }
51
+ };
52
52
  /**
53
53
  * This function returns a three component array, which contains
54
54
  * [totalsize, totalLoaded and errorDownload] of all the downloads happening
@@ -66,71 +66,72 @@ const SceneLoader = function (sceneIn) {
66
66
  totalSize += progress[1];
67
67
  totalLoaded += progress[0];
68
68
 
69
- if (progress[1] == 0)
70
- unknownFound = true;
69
+ if (progress[1] == 0) unknownFound = true;
71
70
  }
72
71
  if (unknownFound) {
73
72
  totalSize = 0;
74
73
  }
75
- return [ totalSize, totalLoaded, errorDownload ];
76
- }
74
+ return [totalSize, totalLoaded, errorDownload];
75
+ };
77
76
 
78
77
  //Stores the current progress of downloads
79
- this.onProgress = id => {
80
- return xhr => {
81
- this.progressMap[id] = [ xhr.loaded, xhr.total ];
78
+ this.onProgress = (id) => {
79
+ return (xhr) => {
80
+ this.progressMap[id] = [xhr.loaded, xhr.total];
82
81
  };
83
- }
82
+ };
84
83
 
85
- this.onError = finishCallback => {
84
+ this.onError = (finishCallback) => {
86
85
  const isStale = createStaleCheck();
87
- return xhr => {
86
+ return (xhr) => {
88
87
  if (isStale()) return;
89
88
  this.toBeDownloaded = this.toBeDownloaded - 1;
90
89
  errorDownload = true;
91
- console.error(`There is an issue with external resource ${xhr?.responseURL ? ": " + xhr?.responseURL: ""}.`);
90
+ console.error(
91
+ `There is an issue with external resource ${xhr?.responseURL ? ': ' + xhr?.responseURL : ''}.`,
92
+ );
92
93
  const payload = {
93
- type: "Error",
94
- xhr
94
+ type: 'Error',
95
+ xhr,
95
96
  };
96
97
  if (finishCallback) {
97
98
  finishCallback(payload);
98
99
  }
99
- }
100
+ };
100
101
  };
101
102
 
102
103
  let loadMultipleViews = (referenceURL, views) => {
103
104
  const defaultView = views.Default;
104
105
  if (views.Inline) {
105
- scene.setupMultipleViews(defaultView, views.Entries);
106
+ scene.setupMultipleViews(defaultView, views.Entries);
106
107
  } else {
107
108
  const promises = [];
108
109
  for (const [key, value] of Object.entries(views.Entries)) {
109
110
  if (referenceURL) {
110
111
  const newURL = createNewURL(value, referenceURL);
111
- promises.push(new Promise((resolve, reject) => {
112
- // Add parameters if we are sent them
113
- fetch(newURL)
114
- .then(response => response.json())
115
- .then(data => resolve({key: key, data: data}))
116
- .catch(data => reject(data));
117
- }));
112
+ promises.push(
113
+ new Promise((resolve, reject) => {
114
+ // Add parameters if we are sent them
115
+ fetch(newURL)
116
+ .then((response) => response.json())
117
+ .then((data) => resolve({ key: key, data: data }))
118
+ .catch((data) => reject(data));
119
+ }),
120
+ );
118
121
  }
119
122
  }
120
- Promise.all(promises)
121
- .then(values => {
123
+ Promise.all(promises).then((values) => {
122
124
  const entries = {};
123
- values.forEach(entry => {
125
+ values.forEach((entry) => {
124
126
  entries[entry.key] = entry.data;
125
127
  });
126
128
  scene.setupMultipleViews(defaultView, entries);
127
129
  let zincCameraControls = scene.getZincCameraControls();
128
- if (zincCameraControls)
129
- zincCameraControls.setCurrentViewport(defaultView);
130
+ if (zincCameraControls) zincCameraControls.setCurrentViewport(defaultView);
130
131
  viewLoaded = true;
131
132
  });
132
133
  }
133
- }
134
+ };
134
135
 
135
136
  /**
136
137
  * Load the viewport from an external location provided by the url.
@@ -149,7 +150,7 @@ const SceneLoader = function (sceneIn) {
149
150
  })
150
151
  .then((viewData) => {
151
152
  if (isStale()) return;
152
- scene.setupMultipleViews("default", { "default" : viewData });
153
+ scene.setupMultipleViews('default', { default: viewData });
153
154
  scene.resetView();
154
155
  viewLoaded = true;
155
156
  --this.toBeDownloaded;
@@ -159,39 +160,60 @@ const SceneLoader = function (sceneIn) {
159
160
  })
160
161
  .catch((error) => {
161
162
  console.error(`Fetch failed for URL: ${requestURL}`, error);
162
- (this.onError(finishCallback))({ responseURL: requestURL });
163
+ this.onError(finishCallback)({ responseURL: requestURL });
163
164
  });
164
- }
165
+ };
165
166
 
166
- /**
167
+ /**
167
168
  * Load a legacy model(s) format with the provided URLs and parameters. This only loads the geometry
168
169
  * without any of the metadata. Therefore, extra parameters should be provided.
169
170
  *
170
171
  * @deprecated
171
172
  */
172
- this.loadModelsURL = (region, urls, colours, opacities, timeEnabled, morphColour, finishCallback) => {
173
+ this.loadModelsURL = (
174
+ region,
175
+ urls,
176
+ colours,
177
+ opacities,
178
+ timeEnabled,
179
+ morphColour,
180
+ finishCallback,
181
+ ) => {
173
182
  const number = urls.length;
174
183
  this.toBeDownloaded += number;
175
184
  for (let i = 0; i < number; i++) {
176
185
  const filename = urls[i];
177
186
  let colour = Zinc.defaultMaterialColor;
178
187
  let opacity = Zinc.defaultOpacity;
179
- if (colours != undefined && colours[i] != undefined)
180
- colour = colours[i] ? true : false;
181
- if (opacities != undefined && opacities[i] != undefined)
182
- opacity = opacities[i];
188
+ if (colours != undefined && colours[i] != undefined) colour = colours[i] ? true : false;
189
+ if (opacities != undefined && opacities[i] != undefined) opacity = opacities[i];
183
190
  let localTimeEnabled = 0;
184
191
  if (timeEnabled != undefined && timeEnabled[i] != undefined)
185
192
  localTimeEnabled = timeEnabled[i] ? true : false;
186
193
  let localMorphColour = false;
187
194
  if (morphColour != undefined && morphColour[i] != undefined)
188
195
  localMorphColour = morphColour[i] ? true : false;
189
- primitivesLoader.load(filename, meshloader(region, colour, opacity, localTimeEnabled, localMorphColour, undefined, undefined,
190
- undefined, undefined, finishCallback), this.onProgress(filename), this.onError(finishCallback));
196
+ primitivesLoader.load(
197
+ filename,
198
+ meshloader(
199
+ region,
200
+ colour,
201
+ opacity,
202
+ localTimeEnabled,
203
+ localMorphColour,
204
+ undefined,
205
+ undefined,
206
+ undefined,
207
+ undefined,
208
+ finishCallback,
209
+ ),
210
+ this.onProgress(filename),
211
+ this.onError(finishCallback),
212
+ );
191
213
  }
192
- }
214
+ };
193
215
 
194
- /**
216
+ /**
195
217
  * Load a legacy file format containing the viewport and its meta file from an external
196
218
  * location provided by the url. Use the new metadata format with
197
219
  * {@link Zinc.SceneLoader.#loadMetadataURL} instead.
@@ -200,44 +222,53 @@ const SceneLoader = function (sceneIn) {
200
222
  * @deprecated
201
223
  */
202
224
  this.loadFromViewURL = (targetRegion, jsonFilePrefix, finishCallback) => {
203
- const requestURL = jsonFilePrefix + "_view.json";
225
+ const requestURL = jsonFilePrefix + '_view.json';
204
226
  const isStale = createStaleCheck();
205
227
  fetch(requestURL)
206
- .then((response) => {
207
- if (!response.ok) {
208
- throw new Error(`HTTP error! status: ${response.status}`);
209
- }
210
- return response.json();
211
- })
212
- .then((viewData) => {
213
- if (isStale()) return;
214
- scene.loadView(viewData);
215
- const urls = [];
216
- const filename_prefix = jsonFilePrefix + "_";
217
- for (let i = 0; i < viewData.numberOfResources; i++) {
218
- const filename = filename_prefix + (i + 1) + ".json";
219
- urls.push(filename);
220
- }
221
- this.loadModelsURL(
222
- targetRegion,
223
- urls,
224
- viewData.colour,
225
- viewData.opacity,
226
- viewData.timeEnabled,
227
- viewData.morphColour,
228
- finishCallback
229
- );
230
- })
231
- .catch((error) => {
232
- console.error(`Failed to load view data from: ${requestURL}`, error);
233
- });
234
- }
228
+ .then((response) => {
229
+ if (!response.ok) {
230
+ throw new Error(`HTTP error! status: ${response.status}`);
231
+ }
232
+ return response.json();
233
+ })
234
+ .then((viewData) => {
235
+ if (isStale()) return;
236
+ scene.loadView(viewData);
237
+ const urls = [];
238
+ const filename_prefix = jsonFilePrefix + '_';
239
+ for (let i = 0; i < viewData.numberOfResources; i++) {
240
+ const filename = filename_prefix + (i + 1) + '.json';
241
+ urls.push(filename);
242
+ }
243
+ this.loadModelsURL(
244
+ targetRegion,
245
+ urls,
246
+ viewData.colour,
247
+ viewData.opacity,
248
+ viewData.timeEnabled,
249
+ viewData.morphColour,
250
+ finishCallback,
251
+ );
252
+ })
253
+ .catch((error) => {
254
+ console.error(`Failed to load view data from: ${requestURL}`, error);
255
+ });
256
+ };
235
257
 
236
258
  //Internal loader for a regular zinc geometry.
237
- const linesloader = (region, localTimeEnabled, localMorphColour, groupName,
238
- anatomicalId, renderOrder, lod, tubeLines, finishCallback) => {
239
- const isStale = createStaleCheck();
240
- return (geometry, materials) => {
259
+ const linesloader = (
260
+ region,
261
+ localTimeEnabled,
262
+ localMorphColour,
263
+ groupName,
264
+ anatomicalId,
265
+ renderOrder,
266
+ lod,
267
+ tubeLines,
268
+ finishCallback,
269
+ ) => {
270
+ const isStale = createStaleCheck();
271
+ return (geometry, materials) => {
241
272
  if (isStale()) {
242
273
  geometry.dispose();
243
274
  return;
@@ -245,7 +276,7 @@ const SceneLoader = function (sceneIn) {
245
276
  const newLines = tubeLines ? new TubeLines() : new Lines();
246
277
  let material = undefined;
247
278
  if (materials && materials[0]) {
248
- material = new THREE.LineBasicMaterial({color:materials[0].color.clone()});
279
+ material = new THREE.LineBasicMaterial({ color: materials[0].color.clone() });
249
280
  if (1.0 > materials[0].opacity) {
250
281
  material.transparent = true;
251
282
  }
@@ -270,10 +301,10 @@ const SceneLoader = function (sceneIn) {
270
301
  }
271
302
  --this.toBeDownloaded;
272
303
  geometry.dispose();
273
- if (finishCallback != undefined && (typeof finishCallback == 'function'))
304
+ if (finishCallback != undefined && typeof finishCallback == 'function')
274
305
  finishCallback(newLines);
275
306
  };
276
- }
307
+ };
277
308
 
278
309
  /**
279
310
  * Load lines into this scene object.
@@ -284,28 +315,57 @@ const SceneLoader = function (sceneIn) {
284
315
  * @param {Function} finishCallback - Callback function which will be called
285
316
  * once the glyphset is succssfully load in.
286
317
  */
287
- this.loadLinesURL = (region, url, timeEnabled, morphColour, groupName, finishCallback, options) => {
288
- let localTimeEnabled = 0;
318
+ this.loadLinesURL = (
319
+ region,
320
+ url,
321
+ timeEnabled,
322
+ morphColour,
323
+ groupName,
324
+ finishCallback,
325
+ options,
326
+ ) => {
327
+ let localTimeEnabled = 0;
289
328
  this.toBeDownloaded += 1;
290
329
  let isInline = options?.isInline ? options.isInline : false;
291
330
  let anatomicalId = options?.anatomicalId ? options.anatomicalId : undefined;
292
- let renderOrder = (options && "renderOrder" in options) ? options.renderOrder : undefined;
293
- if (timeEnabled != undefined)
294
- localTimeEnabled = timeEnabled ? true : false;
295
- let localMorphColour = 0;
296
- if (morphColour != undefined)
297
- localMorphColour = morphColour ? true : false;
331
+ let renderOrder = options && 'renderOrder' in options ? options.renderOrder : undefined;
332
+ if (timeEnabled != undefined) localTimeEnabled = timeEnabled ? true : false;
333
+ let localMorphColour = 0;
334
+ if (morphColour != undefined) localMorphColour = morphColour ? true : false;
298
335
  let tubeLines = options.tubeLines && !localTimeEnabled && !localMorphColour;
299
336
  if (isInline) {
300
- let object = primitivesLoader.parse( url );
301
- (linesloader(region, localTimeEnabled, localMorphColour, groupName, anatomicalId,
302
- renderOrder, options.lod, tubeLines, finishCallback))( object.geometry, object.materials );
337
+ let object = primitivesLoader.parse(url);
338
+ linesloader(
339
+ region,
340
+ localTimeEnabled,
341
+ localMorphColour,
342
+ groupName,
343
+ anatomicalId,
344
+ renderOrder,
345
+ options.lod,
346
+ tubeLines,
347
+ finishCallback,
348
+ )(object.geometry, object.materials);
303
349
  } else {
304
- primitivesLoader.load(url, linesloader(region, localTimeEnabled, localMorphColour, groupName,
305
- anatomicalId, renderOrder, options.lod, tubeLines, finishCallback), this.onProgress(url), this.onError(finishCallback),
306
- options.loaderOptions);
350
+ primitivesLoader.load(
351
+ url,
352
+ linesloader(
353
+ region,
354
+ localTimeEnabled,
355
+ localMorphColour,
356
+ groupName,
357
+ anatomicalId,
358
+ renderOrder,
359
+ options.lod,
360
+ tubeLines,
361
+ finishCallback,
362
+ ),
363
+ this.onProgress(url),
364
+ this.onError(finishCallback),
365
+ options.loaderOptions,
366
+ );
307
367
  }
308
- }
368
+ };
309
369
 
310
370
  const glyphsetloader = (region, glyphurl, groupName, finishCallback, options) => {
311
371
  const isStale = createStaleCheck();
@@ -315,33 +375,32 @@ const SceneLoader = function (sceneIn) {
315
375
  if (typeof glyphsetData === 'string' || glyphsetData instanceof String) {
316
376
  glyphsetData = JSON.parse(data);
317
377
  }
318
- let isInline = (options && options.isInline) ? options.isInline : undefined;
319
- let anatomicalId = (options && options.anatomicalId) ? options.anatomicalId : undefined;
378
+ let isInline = options && options.isInline ? options.isInline : undefined;
379
+ let anatomicalId = options && options.anatomicalId ? options.anatomicalId : undefined;
320
380
  let displayLabels = options?.displayLabels;
321
381
  if (displayLabels === undefined) {
322
382
  displayLabels = true;
323
383
  }
324
- let renderOrder = (options && "renderOrder" in options) ? options.renderOrder : undefined;
384
+ let renderOrder = options && 'renderOrder' in options ? options.renderOrder : undefined;
325
385
  const newGlyphset = new Glyphset();
326
386
  newGlyphset.setDuration(scene.getDuration());
327
387
  newGlyphset.groupName = groupName;
328
388
  let myCallback = () => {
329
389
  if (isStale()) return;
330
390
  --this.toBeDownloaded;
331
- if (finishCallback != undefined && (typeof finishCallback == 'function'))
391
+ if (finishCallback != undefined && typeof finishCallback == 'function')
332
392
  finishCallback(newGlyphset);
333
- }
393
+ };
334
394
  ++this.toBeDownloaded;
335
395
  if (isInline) {
336
396
  newGlyphset.load(glyphsetData, glyphurl, myCallback, isInline, displayLabels);
337
- }
338
- else {
397
+ } else {
339
398
  newGlyphset.load(glyphsetData, glyphurl, myCallback, isInline, displayLabels);
340
399
  }
341
400
  newGlyphset.setAnatomicalId(anatomicalId);
342
401
  newGlyphset.setRenderOrder(renderOrder);
343
402
  region.addZincObject(newGlyphset);
344
- }
403
+ };
345
404
  };
346
405
 
347
406
  //Load a glyphset into this scene.
@@ -357,7 +416,7 @@ const SceneLoader = function (sceneIn) {
357
416
  }
358
417
  }
359
418
  }
360
- (glyphsetloader(region, glyphurl, groupName, finishCallback, options))(glyphsetData);
419
+ glyphsetloader(region, glyphurl, groupName, finishCallback, options)(glyphsetData);
361
420
  }
362
421
  };
363
422
  };
@@ -373,13 +432,17 @@ const SceneLoader = function (sceneIn) {
373
432
  * once the glyphset is succssfully load in.
374
433
  */
375
434
  this.loadGlyphsetURL = (region, metaurl, glyphurl, groupName, finishCallback, options) => {
376
- const isInline = (options && options.isInline) ? options.isInline : false;
435
+ const isInline = options && options.isInline ? options.isInline : false;
377
436
  if (isInline) {
378
- (glyphsetloader(region, glyphurl, groupName, finishCallback, options))(metaurl);
437
+ glyphsetloader(region, glyphurl, groupName, finishCallback, options)(metaurl);
379
438
  } else {
380
- primitivesLoader.load(metaurl, glyphsetloader(region, glyphurl, groupName,
381
- finishCallback, options), this.onProgress(metaurl),
382
- this.onError(finishCallback), options.loaderOptions);
439
+ primitivesLoader.load(
440
+ metaurl,
441
+ glyphsetloader(region, glyphurl, groupName, finishCallback, options),
442
+ this.onProgress(metaurl),
443
+ this.onError(finishCallback),
444
+ options.loaderOptions,
445
+ );
383
446
 
384
447
  /*
385
448
  const xmlhttp = new XMLHttpRequest();
@@ -389,10 +452,18 @@ const SceneLoader = function (sceneIn) {
389
452
  xmlhttp.open("GET", metaurl, true);
390
453
  xmlhttp.send();*/
391
454
  }
392
- }
455
+ };
393
456
 
394
457
  //Internal loader for zinc pointset.
395
- const pointsetloader = (region, localTimeEnabled, localMorphColour, groupName, anatomicalId, renderOrder, finishCallback) => {
458
+ const pointsetloader = (
459
+ region,
460
+ localTimeEnabled,
461
+ localMorphColour,
462
+ groupName,
463
+ anatomicalId,
464
+ renderOrder,
465
+ finishCallback,
466
+ ) => {
396
467
  const isStale = createStaleCheck();
397
468
  return (geometry, materials) => {
398
469
  if (isStale()) {
@@ -400,12 +471,11 @@ const SceneLoader = function (sceneIn) {
400
471
  return;
401
472
  }
402
473
  const newPointset = new Pointset();
403
- let material = new THREE.PointsMaterial(
404
- {
405
- alphaTest: 0.05,
406
- size: 10,
407
- sizeAttenuation: false,
408
- });
474
+ let material = new THREE.PointsMaterial({
475
+ alphaTest: 0.05,
476
+ size: 10,
477
+ sizeAttenuation: false,
478
+ });
409
479
  if (materials && materials[0]) {
410
480
  if (1.0 > materials[0].opacity) {
411
481
  material.transparent = true;
@@ -427,10 +497,10 @@ const SceneLoader = function (sceneIn) {
427
497
  }
428
498
  geometry.dispose();
429
499
  --this.toBeDownloaded;
430
- if (finishCallback != undefined && (typeof finishCallback == 'function'))
500
+ if (finishCallback != undefined && typeof finishCallback == 'function')
431
501
  finishCallback(newPointset);
432
502
  };
433
- }
503
+ };
434
504
 
435
505
  /**
436
506
  * Read a STL file into this scene, the geometry will be presented as
@@ -446,11 +516,25 @@ const SceneLoader = function (sceneIn) {
446
516
  const colour = Zinc.defaultMaterialColor;
447
517
  const opacity = Zinc.defaultOpacity;
448
518
  const loader = new STLLoader();
449
- loader.crossOrigin = "Anonymous";
450
- loader.load(url, meshloader(region, colour, opacity, false,
451
- false, groupName, undefined, undefined, {}, finishCallback),
452
- this.onProgress(url), this.onError(finishCallback));
453
- }
519
+ loader.crossOrigin = 'Anonymous';
520
+ loader.load(
521
+ url,
522
+ meshloader(
523
+ region,
524
+ colour,
525
+ opacity,
526
+ false,
527
+ false,
528
+ groupName,
529
+ undefined,
530
+ undefined,
531
+ {},
532
+ finishCallback,
533
+ ),
534
+ this.onProgress(url),
535
+ this.onError(finishCallback),
536
+ );
537
+ };
454
538
 
455
539
  /**
456
540
  * Read a OBJ file into this scene, the geometry will be presented as
@@ -466,11 +550,25 @@ const SceneLoader = function (sceneIn) {
466
550
  const colour = Zinc.defaultMaterialColor;
467
551
  const opacity = Zinc.defaultOpacity;
468
552
  const loader = new OBJLoader();
469
- loader.crossOrigin = "Anonymous";
470
- loader.load(url, objloader(region, colour, opacity, false,
471
- false, groupName, undefined, undefined, {}, finishCallback),
472
- this.onProgress(url), this.onError(finishCallback));
473
- }
553
+ loader.crossOrigin = 'Anonymous';
554
+ loader.load(
555
+ url,
556
+ objloader(
557
+ region,
558
+ colour,
559
+ opacity,
560
+ false,
561
+ false,
562
+ groupName,
563
+ undefined,
564
+ undefined,
565
+ {},
566
+ finishCallback,
567
+ ),
568
+ this.onProgress(url),
569
+ this.onError(finishCallback),
570
+ );
571
+ };
474
572
 
475
573
  /**
476
574
  * Load a geometry into this scene, this is a subsequent called from
@@ -485,39 +583,84 @@ const SceneLoader = function (sceneIn) {
485
583
  * @param {Function} finishCallback - Callback function which will be called
486
584
  * once the geometry is succssfully loaded in.
487
585
  */
488
- const loadSurfaceURL = (region ,url, timeEnabled, morphColour, groupName, finishCallback, options) => {
586
+ const loadSurfaceURL = (
587
+ region,
588
+ url,
589
+ timeEnabled,
590
+ morphColour,
591
+ groupName,
592
+ finishCallback,
593
+ options,
594
+ ) => {
489
595
  this.toBeDownloaded += 1;
490
596
  const colour = Zinc.defaultMaterialColor;
491
597
  const opacity = Zinc.defaultOpacity;
492
598
  let localTimeEnabled = 0;
493
- let isInline = (options && options.isInline) ? options.isInline : false;
494
- let fileFormat = (options && options.fileFormat) ? options.fileFormat : undefined;
495
- let anatomicalId = (options && options.anatomicalId) ? options.anatomicalId : undefined;
496
- let renderOrder = (options && "renderOrder" in options) ? options.renderOrder : undefined;
497
- if (timeEnabled != undefined)
498
- localTimeEnabled = timeEnabled ? true : false;
599
+ let isInline = options && options.isInline ? options.isInline : false;
600
+ let fileFormat = options && options.fileFormat ? options.fileFormat : undefined;
601
+ let anatomicalId = options && options.anatomicalId ? options.anatomicalId : undefined;
602
+ let renderOrder = options && 'renderOrder' in options ? options.renderOrder : undefined;
603
+ if (timeEnabled != undefined) localTimeEnabled = timeEnabled ? true : false;
499
604
  let localMorphColour = 0;
500
- if (morphColour != undefined)
501
- localMorphColour = morphColour ? true : false;
605
+ if (morphColour != undefined) localMorphColour = morphColour ? true : false;
502
606
  let loader = primitivesLoader;
503
- if (fileFormat == "STL" || fileFormat == "OBJ") {
504
- const typedLoader = fileFormat == "STL" ? meshloader : objloader;
505
- loader = fileFormat == "STL" ? new STLLoader() : new OBJLoader();
506
- loader.crossOrigin = "Anonymous";
507
- loader.load(url, typedLoader(region, colour, opacity, localTimeEnabled,
508
- localMorphColour, groupName, anatomicalId, renderOrder, options ? options : {},
509
- finishCallback), this.onProgress(url), this.onError(finishCallback));
607
+ if (fileFormat == 'STL' || fileFormat == 'OBJ') {
608
+ const typedLoader = fileFormat == 'STL' ? meshloader : objloader;
609
+ loader = fileFormat == 'STL' ? new STLLoader() : new OBJLoader();
610
+ loader.crossOrigin = 'Anonymous';
611
+ loader.load(
612
+ url,
613
+ typedLoader(
614
+ region,
615
+ colour,
616
+ opacity,
617
+ localTimeEnabled,
618
+ localMorphColour,
619
+ groupName,
620
+ anatomicalId,
621
+ renderOrder,
622
+ options ? options : {},
623
+ finishCallback,
624
+ ),
625
+ this.onProgress(url),
626
+ this.onError(finishCallback),
627
+ );
510
628
  return;
511
629
  }
512
630
  if (isInline) {
513
- const object = primitivesLoader.parse( url );
514
- (meshloader(region, colour, opacity, localTimeEnabled,
515
- localMorphColour, groupName, anatomicalId, renderOrder, options, finishCallback))( object.geometry, object.materials );
631
+ const object = primitivesLoader.parse(url);
632
+ meshloader(
633
+ region,
634
+ colour,
635
+ opacity,
636
+ localTimeEnabled,
637
+ localMorphColour,
638
+ groupName,
639
+ anatomicalId,
640
+ renderOrder,
641
+ options,
642
+ finishCallback,
643
+ )(object.geometry, object.materials);
516
644
  } else {
517
- loader.crossOrigin = "Anonymous";
518
- primitivesLoader.load(url, meshloader(region, colour, opacity, localTimeEnabled,
519
- localMorphColour, groupName, anatomicalId, renderOrder, options, finishCallback),
520
- this.onProgress(url), this.onError(finishCallback), options.loaderOptions);
645
+ loader.crossOrigin = 'Anonymous';
646
+ primitivesLoader.load(
647
+ url,
648
+ meshloader(
649
+ region,
650
+ colour,
651
+ opacity,
652
+ localTimeEnabled,
653
+ localMorphColour,
654
+ groupName,
655
+ anatomicalId,
656
+ renderOrder,
657
+ options,
658
+ finishCallback,
659
+ ),
660
+ this.onProgress(url),
661
+ this.onError(finishCallback),
662
+ options.loaderOptions,
663
+ );
521
664
  }
522
665
  };
523
666
 
@@ -525,15 +668,14 @@ const SceneLoader = function (sceneIn) {
525
668
  //allCompletedCallback is called
526
669
  const metaFinishCallback = function (numberOfDownloaded, finishCallback, allCompletedCallback) {
527
670
  let downloadedItem = 0;
528
- return zincObject => {
671
+ return (zincObject) => {
529
672
  downloadedItem = downloadedItem + 1;
530
- if (zincObject && (finishCallback != undefined) && (typeof finishCallback == 'function')) {
673
+ if (zincObject && finishCallback != undefined && typeof finishCallback == 'function') {
531
674
  finishCallback(zincObject);
532
675
  }
533
676
  if (downloadedItem == numberOfDownloaded) {
534
- if (viewLoaded === false)
535
- scene.viewAll();
536
- if (allCompletedCallback != undefined && (typeof allCompletedCallback == 'function')) {
677
+ if (viewLoaded === false) scene.viewAll();
678
+ if (allCompletedCallback != undefined && typeof allCompletedCallback == 'function') {
537
679
  allCompletedCallback();
538
680
  let zincCameraControls = scene.getZincCameraControls();
539
681
  if (zincCameraControls) {
@@ -553,32 +695,57 @@ const SceneLoader = function (sceneIn) {
553
695
  * @param {Function} finishCallback - Callback function which will be called
554
696
  * once the glyphset is succssfully load in.
555
697
  */
556
- this.loadPointsetURL = (region, url, timeEnabled, morphColour, groupName, finishCallback, options) => {
698
+ this.loadPointsetURL = (
699
+ region,
700
+ url,
701
+ timeEnabled,
702
+ morphColour,
703
+ groupName,
704
+ finishCallback,
705
+ options,
706
+ ) => {
557
707
  let localTimeEnabled = 0;
558
708
  this.toBeDownloaded += 1;
559
- if (timeEnabled != undefined)
560
- localTimeEnabled = timeEnabled ? true : false;
709
+ if (timeEnabled != undefined) localTimeEnabled = timeEnabled ? true : false;
561
710
  let localMorphColour = 0;
562
- if (morphColour != undefined)
563
- localMorphColour = morphColour ? true : false;
564
- let isInline = (options && options.isInline) ? options.isInline : false;
565
- let anatomicalId = (options && options.anatomicalId) ? options.anatomicalId : undefined;
566
- let renderOrder = (options && "renderOrder" in options) ? options.renderOrder : undefined;
711
+ if (morphColour != undefined) localMorphColour = morphColour ? true : false;
712
+ let isInline = options && options.isInline ? options.isInline : false;
713
+ let anatomicalId = options && options.anatomicalId ? options.anatomicalId : undefined;
714
+ let renderOrder = options && 'renderOrder' in options ? options.renderOrder : undefined;
567
715
  if (isInline) {
568
- const object = primitivesLoader.parse( url );
569
- (pointsetloader(region, localTimeEnabled, localMorphColour, groupName,
570
- anatomicalId, renderOrder, finishCallback))(object.geometry, object.materials );
716
+ const object = primitivesLoader.parse(url);
717
+ pointsetloader(
718
+ region,
719
+ localTimeEnabled,
720
+ localMorphColour,
721
+ groupName,
722
+ anatomicalId,
723
+ renderOrder,
724
+ finishCallback,
725
+ )(object.geometry, object.materials);
571
726
  } else {
572
- primitivesLoader.load(url, pointsetloader(region, localTimeEnabled, localMorphColour,
573
- groupName, anatomicalId, renderOrder, finishCallback),
574
- this.onProgress(url), this.onError(finishCallback), options.loaderOptions);
727
+ primitivesLoader.load(
728
+ url,
729
+ pointsetloader(
730
+ region,
731
+ localTimeEnabled,
732
+ localMorphColour,
733
+ groupName,
734
+ anatomicalId,
735
+ renderOrder,
736
+ finishCallback,
737
+ ),
738
+ this.onProgress(url),
739
+ this.onError(finishCallback),
740
+ options.loaderOptions,
741
+ );
575
742
  }
576
- }
743
+ };
577
744
 
578
745
  const loadTexture = (region, referenceURL, textureData, groupName, finishCallback, options) => {
579
- let isInline = (options && options.isInline) ? options.isInline : undefined;
580
- let anatomicalId = (options && options.anatomicalId) ? options.anatomicalId : undefined;
581
- let renderOrder = (options && "renderOrder" in options) ? options.renderOrder : undefined;
746
+ let isInline = options && options.isInline ? options.isInline : undefined;
747
+ let anatomicalId = options && options.anatomicalId ? options.anatomicalId : undefined;
748
+ let renderOrder = options && 'renderOrder' in options ? options.renderOrder : undefined;
582
749
  let newTexture = undefined;
583
750
  if (textureData) {
584
751
  if (referenceURL && textureData.images && textureData.images.source) {
@@ -588,7 +755,7 @@ const SceneLoader = function (sceneIn) {
588
755
  textureData.images.source[i] = newURL;
589
756
  }
590
757
  }
591
- if (textureData.type === "slides") {
758
+ if (textureData.type === 'slides') {
592
759
  newTexture = new TextureSlides();
593
760
  }
594
761
  if (newTexture) {
@@ -602,9 +769,9 @@ const SceneLoader = function (sceneIn) {
602
769
  //Add zincObject after it has sort out all the required download
603
770
  region.addZincObject(newTexture);
604
771
  --this.toBeDownloaded;
605
- if (finishCallback != undefined && (typeof finishCallback == 'function'))
772
+ if (finishCallback != undefined && typeof finishCallback == 'function')
606
773
  finishCallback(newTexture);
607
- }
774
+ };
608
775
  ++this.toBeDownloaded;
609
776
  newTexture.load(textureData, myCallback, isInline);
610
777
  newTexture.setAnatomicalId(anatomicalId);
@@ -621,31 +788,31 @@ const SceneLoader = function (sceneIn) {
621
788
  * once the glyphset is succssfully load in.
622
789
  */
623
790
  this.loadTextureURL = (region, url, groupName, finishCallback, options) => {
624
- const isInline = (options && options.isInline) ? options.isInline : false;
791
+ const isInline = options && options.isInline ? options.isInline : false;
625
792
  if (isInline) {
626
793
  loadTexture(region, undefined, url, groupName, finishCallback, options);
627
794
  } else {
628
795
  const requestURL = url;
629
796
  const isStale = createStaleCheck();
630
797
  fetch(requestURL)
631
- .then((response) => {
632
- if (!response.ok) {
633
- throw new Error(`HTTP error! status: ${response.status}`);
634
- }
635
- const referenceURL = response.url || (new URL(requestURL)).href;
636
- return response.json().then((textureData) => ({ textureData, referenceURL }));
637
- })
638
- .then(({textureData, referenceURL}) => {
639
- if (isStale()) return;
640
- loadTexture(region, referenceURL, textureData, groupName, finishCallback, options);
641
- })
642
- .catch((error) => {
643
- console.error(`Fetch failed for texture URL: ${requestURL}`, error);
644
- });
798
+ .then((response) => {
799
+ if (!response.ok) {
800
+ throw new Error(`HTTP error! status: ${response.status}`);
801
+ }
802
+ const referenceURL = response.url || new URL(requestURL).href;
803
+ return response.json().then((textureData) => ({ textureData, referenceURL }));
804
+ })
805
+ .then(({ textureData, referenceURL }) => {
806
+ if (isStale()) return;
807
+ loadTexture(region, referenceURL, textureData, groupName, finishCallback, options);
808
+ })
809
+ .catch((error) => {
810
+ console.error(`Fetch failed for texture URL: ${requestURL}`, error);
811
+ });
645
812
  }
646
- }
813
+ };
647
814
 
648
- /**
815
+ /**
649
816
  * Add a user provided {THREE.Geometry} into the scene as zinc geometry.
650
817
  *
651
818
  * @param {Three.Geometry} geometry - The threejs geometry to be added as {@link Zinc.Geometry}.
@@ -670,13 +837,13 @@ const SceneLoader = function (sceneIn) {
670
837
  materialIn,
671
838
  groupName,
672
839
  renderOrder,
673
- anatomicalId
840
+ anatomicalId,
674
841
  ) => {
675
842
  let options = {};
676
843
  options.colour = colour;
677
844
  options.opacity = opacity;
678
845
  options.localTimeEnabled = localTimeEnabled;
679
- options.localMorphColour = localMorphColour
846
+ options.localMorphColour = localMorphColour;
680
847
  const newGeometry = new Geometry();
681
848
  newGeometry.createMesh(geometryIn, materialIn, options);
682
849
  if (newGeometry.getMorph()) {
@@ -685,7 +852,7 @@ const SceneLoader = function (sceneIn) {
685
852
  newGeometry.setAnatomicalId(anatomicalId);
686
853
  if (region) region.addZincObject(newGeometry);
687
854
  newGeometry.setDuration(scene.getDuration());
688
- if (finishCallback != undefined && (typeof finishCallback == 'function'))
855
+ if (finishCallback != undefined && typeof finishCallback == 'function')
689
856
  finishCallback(newGeometry);
690
857
  if (newGeometry.videoHandler) {
691
858
  scene.setVideoHandler(newGeometry.videoHandler);
@@ -693,7 +860,7 @@ const SceneLoader = function (sceneIn) {
693
860
  return newGeometry;
694
861
  }
695
862
  return undefined;
696
- }
863
+ };
697
864
 
698
865
  //Internal loader for a regular zinc geometry.
699
866
  const meshloader = (
@@ -706,7 +873,7 @@ const SceneLoader = function (sceneIn) {
706
873
  anatomicalId,
707
874
  renderOrder,
708
875
  options,
709
- finishCallback
876
+ finishCallback,
710
877
  ) => {
711
878
  const isStale = createStaleCheck();
712
879
  return (geometry, materials) => {
@@ -718,8 +885,19 @@ const SceneLoader = function (sceneIn) {
718
885
  if (materials && materials[0]) {
719
886
  material = materials[0];
720
887
  }
721
- const zincGeometry = addZincGeometry(region, geometry, colour, opacity,
722
- localTimeEnabled, localMorphColour, undefined, material, groupName, renderOrder, anatomicalId);
888
+ const zincGeometry = addZincGeometry(
889
+ region,
890
+ geometry,
891
+ colour,
892
+ opacity,
893
+ localTimeEnabled,
894
+ localMorphColour,
895
+ undefined,
896
+ material,
897
+ groupName,
898
+ renderOrder,
899
+ anatomicalId,
900
+ );
723
901
  if (options?.lod?.levels) {
724
902
  for (const [key, value] of Object.entries(options.lod.levels)) {
725
903
  zincGeometry.addLOD(primitivesLoader, key, value.URL, value.Index, options.lod.preload);
@@ -727,11 +905,11 @@ const SceneLoader = function (sceneIn) {
727
905
  }
728
906
  --this.toBeDownloaded;
729
907
  geometry.dispose();
730
- if (finishCallback != undefined && (typeof finishCallback == 'function')) {
908
+ if (finishCallback != undefined && typeof finishCallback == 'function') {
731
909
  finishCallback(zincGeometry);
732
910
  }
733
911
  };
734
- }
912
+ };
735
913
 
736
914
  //Internal loader for OBJ files, OBJLoader returns a group and each mesh
737
915
  //in it is added as a separate zinc geometry.
@@ -745,11 +923,21 @@ const SceneLoader = function (sceneIn) {
745
923
  anatomicalId,
746
924
  renderOrder,
747
925
  options,
748
- finishCallback
926
+ finishCallback,
749
927
  ) => {
750
928
  const isStale = createStaleCheck();
751
- const onMeshLoaded = meshloader(region, colour, opacity, localTimeEnabled,
752
- localMorphColour, groupName, anatomicalId, renderOrder, options, finishCallback);
929
+ const onMeshLoaded = meshloader(
930
+ region,
931
+ colour,
932
+ opacity,
933
+ localTimeEnabled,
934
+ localMorphColour,
935
+ groupName,
936
+ anatomicalId,
937
+ renderOrder,
938
+ options,
939
+ finishCallback,
940
+ );
753
941
  return (group) => {
754
942
  const meshes = [];
755
943
  group.traverse((child) => {
@@ -773,16 +961,23 @@ const SceneLoader = function (sceneIn) {
773
961
  this.toBeDownloaded += meshes.length - 1;
774
962
  meshes.forEach((mesh) => onMeshLoaded(mesh.geometry));
775
963
  };
776
- }
964
+ };
777
965
 
778
966
  //Turn ISO 8601 duration string into an array.
779
967
  const parseDuration = (durationString) => {
780
- const regex = /P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/;
781
- const [, years, months, weeks, days, hours, mins, secs] =
782
- durationString.match(regex);
783
- return {years: years,months: months, weeks: weeks, days: days,
784
- hours: hours, mins: mins, secs: secs };
785
- }
968
+ const regex =
969
+ /P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/;
970
+ const [, years, months, weeks, days, hours, mins, secs] = durationString.match(regex);
971
+ return {
972
+ years: years,
973
+ months: months,
974
+ weeks: weeks,
975
+ days: days,
976
+ hours: hours,
977
+ mins: mins,
978
+ secs: secs,
979
+ };
980
+ };
786
981
 
787
982
  //Load settings from metadata item.
788
983
  this.loadSettings = (item) => {
@@ -803,7 +998,7 @@ const SceneLoader = function (sceneIn) {
803
998
  }
804
999
  }
805
1000
  }
806
- }
1001
+ };
807
1002
 
808
1003
  //Function to process each of the graphical metadata item except for view and
809
1004
  //settings.
@@ -814,8 +1009,7 @@ const SceneLoader = function (sceneIn) {
814
1009
  if (item.URL) {
815
1010
  //Convert it into an array
816
1011
  newURL = item.URL;
817
- if (referenceURL)
818
- newURL = createNewURL(newURL, referenceURL);
1012
+ if (referenceURL) newURL = createNewURL(newURL, referenceURL);
819
1013
  } else if (item.Inline) {
820
1014
  newURL = item.Inline.URL;
821
1015
  isInline = true;
@@ -826,13 +1020,13 @@ const SceneLoader = function (sceneIn) {
826
1020
  lod.levels = {};
827
1021
  for (const [key, value] of Object.entries(item.LOD.Levels)) {
828
1022
  lod.levels[key] = {};
829
- lod.levels[key]["URL"] = createNewURL(value.URL, referenceURL);
830
- lod.levels[key]["Index"] = value.Index;
1023
+ lod.levels[key]['URL'] = createNewURL(value.URL, referenceURL);
1024
+ lod.levels[key]['Index'] = value.Index;
831
1025
  }
832
1026
  }
833
1027
  let groupName = item.GroupName;
834
- if (groupName === undefined || groupName === "") {
835
- groupName = "_Unnamed";
1028
+ if (groupName === undefined || groupName === '') {
1029
+ groupName = '_Unnamed';
836
1030
  }
837
1031
 
838
1032
  let options = {
@@ -845,14 +1039,22 @@ const SceneLoader = function (sceneIn) {
845
1039
  compression: item.compression,
846
1040
  tubeLines: item.tubeLines,
847
1041
  lod: lod,
848
- renderOrder: order
1042
+ renderOrder: order,
849
1043
  };
850
1044
 
851
1045
  switch (item.Type) {
852
- case "Surfaces":
853
- loadSurfaceURL(region, newURL, item.MorphVertices, item.MorphColours, groupName, finishCallback, options);
1046
+ case 'Surfaces':
1047
+ loadSurfaceURL(
1048
+ region,
1049
+ newURL,
1050
+ item.MorphVertices,
1051
+ item.MorphColours,
1052
+ groupName,
1053
+ finishCallback,
1054
+ options,
1055
+ );
854
1056
  break;
855
- case "Glyph":
1057
+ case 'Glyph':
856
1058
  let newGeometryURL = undefined;
857
1059
  if (!isInline) {
858
1060
  newGeometryURL = item.GlyphGeometriesURL;
@@ -867,13 +1069,29 @@ const SceneLoader = function (sceneIn) {
867
1069
  options.loaderOptions.isGlyphsets = true;
868
1070
  this.loadGlyphsetURL(region, newURL, newGeometryURL, groupName, finishCallback, options);
869
1071
  break;
870
- case "Points":
871
- this.loadPointsetURL(region, newURL, item.MorphVertices, item.MorphColours, groupName, finishCallback, options);
1072
+ case 'Points':
1073
+ this.loadPointsetURL(
1074
+ region,
1075
+ newURL,
1076
+ item.MorphVertices,
1077
+ item.MorphColours,
1078
+ groupName,
1079
+ finishCallback,
1080
+ options,
1081
+ );
872
1082
  break;
873
- case "Lines":
874
- this.loadLinesURL(region, newURL, item.MorphVertices, item.MorphColours, groupName, finishCallback, options);
1083
+ case 'Lines':
1084
+ this.loadLinesURL(
1085
+ region,
1086
+ newURL,
1087
+ item.MorphVertices,
1088
+ item.MorphColours,
1089
+ groupName,
1090
+ finishCallback,
1091
+ options,
1092
+ );
875
1093
  break;
876
- case "Texture":
1094
+ case 'Texture':
877
1095
  this.loadTextureURL(region, newURL, groupName, finishCallback, options);
878
1096
  break;
879
1097
  default:
@@ -889,24 +1107,21 @@ const SceneLoader = function (sceneIn) {
889
1107
  let isInline = false;
890
1108
  if (item.URL) {
891
1109
  newURL = item.URL;
892
- if (referenceURL)
893
- newURL = createNewURL(item.URL, referenceURL);
1110
+ if (referenceURL) newURL = createNewURL(item.URL, referenceURL);
894
1111
  } else if (item.Inline) {
895
1112
  newURL = item.Inline.URL;
896
1113
  isInline = true;
897
1114
  }
898
1115
  switch (item.Type) {
899
- case "View":
1116
+ case 'View':
900
1117
  if (isInline) {
901
- scene.setupMultipleViews("default", { "default" : newURL});
1118
+ scene.setupMultipleViews('default', { default: newURL });
902
1119
  viewLoaded = true;
903
- if (finishCallback != undefined && (typeof finishCallback == 'function'))
1120
+ if (finishCallback != undefined && typeof finishCallback == 'function')
904
1121
  finishCallback();
905
- }
906
- else
907
- this.loadViewURL(newURL, finishCallback);
1122
+ } else this.loadViewURL(newURL, finishCallback);
908
1123
  break;
909
- case "Settings":
1124
+ case 'Settings':
910
1125
  this.loadSettings(item);
911
1126
  break;
912
1127
  default:
@@ -924,16 +1139,22 @@ const SceneLoader = function (sceneIn) {
924
1139
  */
925
1140
  this.loadGLTF = (region, url, finishCallback, allCompletedCallback, options) => {
926
1141
  const loader = new GLTFToZincJSLoader();
927
- loader.load(scene, region, url, finishCallback, allCompletedCallback, options,
928
- createStaleCheck());
929
- }
1142
+ loader.load(
1143
+ scene,
1144
+ region,
1145
+ url,
1146
+ finishCallback,
1147
+ allCompletedCallback,
1148
+ options,
1149
+ createStaleCheck(),
1150
+ );
1151
+ };
930
1152
 
931
1153
  let loadRegions = (currentRegion, referenceURL, regions, callback) => {
932
1154
  if (regions.Primitives) {
933
- regions.Primitives.forEach(primitive => {
1155
+ regions.Primitives.forEach((primitive) => {
934
1156
  let order = 1;
935
- if (primitive.Order)
936
- order = primitive.Order;
1157
+ if (primitive.Order) order = primitive.Order;
937
1158
  readPrimitivesItem(currentRegion, referenceURL, primitive, order, callback);
938
1159
  });
939
1160
  }
@@ -948,7 +1169,7 @@ const SceneLoader = function (sceneIn) {
948
1169
  }
949
1170
  }
950
1171
  }
951
- }
1172
+ };
952
1173
 
953
1174
  let supplementPrimitivesArray = (array, options) => {
954
1175
  let newArray = array;
@@ -958,7 +1179,7 @@ const SceneLoader = function (sceneIn) {
958
1179
  if (include?.length || exclude?.length) {
959
1180
  if (include) {
960
1181
  newArray = array.filter((item) => {
961
- if (item.Type === "View") {
1182
+ if (item.Type === 'View') {
962
1183
  return true;
963
1184
  }
964
1185
  for (let i = 0; i < include.length; i++) {
@@ -971,7 +1192,7 @@ const SceneLoader = function (sceneIn) {
971
1192
  }
972
1193
  if (exclude) {
973
1194
  newArray = newArray.filter((item) => {
974
- if (item.Type === "View") {
1195
+ if (item.Type === 'View') {
975
1196
  return true;
976
1197
  }
977
1198
  for (let i = 0; i < exclude.length; i++) {
@@ -985,72 +1206,81 @@ const SceneLoader = function (sceneIn) {
985
1206
  }
986
1207
  if (tubeLines) {
987
1208
  newArray.forEach((item) => {
988
- if (item.Type === "Lines") {
1209
+ if (item.Type === 'Lines') {
989
1210
  item.tubeLines = true;
990
1211
  }
991
1212
  });
992
1213
  }
993
1214
  return newArray;
994
- }
1215
+ };
995
1216
 
996
1217
  let supplementMetadataInArray = (metadata, options) => {
997
1218
  if (Array.isArray(metadata)) {
998
1219
  return supplementPrimitivesArray(metadata, options);
999
1220
  }
1000
1221
  return metadata;
1001
- }
1222
+ };
1002
1223
 
1003
1224
  let getNumberOfDownloadsInArray = (array, includeViews) => {
1004
1225
  if (Array.isArray(array)) {
1005
1226
  let count = 0;
1006
1227
  for (let i = 0; i < array.length; i++) {
1007
- if (array[i].Type && (
1008
- (includeViews && array[i].Type === "View") ||
1009
- array[i].Type === "Surfaces" ||
1010
- array[i].Type === "Glyph" ||
1011
- array[i].Type === "Points" ||
1012
- array[i].Type === "Lines" ||
1013
- array[i].Type === "Texture"))
1014
- {
1228
+ if (
1229
+ array[i].Type &&
1230
+ ((includeViews && array[i].Type === 'View') ||
1231
+ array[i].Type === 'Surfaces' ||
1232
+ array[i].Type === 'Glyph' ||
1233
+ array[i].Type === 'Points' ||
1234
+ array[i].Type === 'Lines' ||
1235
+ array[i].Type === 'Texture')
1236
+ ) {
1015
1237
  count++;
1016
1238
  }
1017
1239
  }
1018
1240
  return count;
1019
1241
  }
1020
1242
  return 0;
1021
- }
1243
+ };
1022
1244
 
1023
1245
  let getNumberOfObjectsInRegions = (regionJson) => {
1024
- let counts = regionJson.Primitives ?
1025
- getNumberOfDownloadsInArray(regionJson.Primitives, false) : 0;
1246
+ let counts = regionJson.Primitives
1247
+ ? getNumberOfDownloadsInArray(regionJson.Primitives, false)
1248
+ : 0;
1026
1249
  if (regionJson.Children) {
1027
- Object.values(regionJson.Children).forEach(childRegion => {
1250
+ Object.values(regionJson.Children).forEach((childRegion) => {
1028
1251
  counts += getNumberOfObjectsInRegions(childRegion);
1029
1252
  });
1030
1253
  }
1031
1254
  return counts;
1032
- }
1255
+ };
1033
1256
 
1034
1257
  let getNumberOfObjects = (metadata) => {
1035
1258
  if (Array.isArray(metadata)) {
1036
1259
  return getNumberOfDownloadsInArray(metadata, true);
1037
- } else if ((typeof metadata) === "object" && metadata !== null) {
1038
- if (metadata.Version === "2.0") {
1260
+ } else if (typeof metadata === 'object' && metadata !== null) {
1261
+ if (metadata.Version === '2.0') {
1039
1262
  return getNumberOfObjectsInRegions(metadata.Regions);
1040
1263
  }
1041
1264
  }
1042
- }
1265
+ };
1043
1266
 
1044
1267
  let readVersionOneRegionPath = (region, referenceURL, item, order, callback) => {
1045
1268
  let targetRegion = region;
1046
- if (item.RegionPath && item.RegionPath !== "") {
1269
+ if (item.RegionPath && item.RegionPath !== '') {
1047
1270
  targetRegion = region.findOrCreateChildFromPath(item.RegionPath);
1048
1271
  }
1049
1272
  //Render order is set to i * 2 to account for front and back rendering
1050
1273
  readPrimitivesItem(targetRegion, referenceURL, item, order * 2, callback);
1051
- }
1274
+ };
1052
1275
 
1053
- let loadVersionOne = (targetRegion, metadata, referenceURL, finishCallback, allCompletedCallback, options) => {
1276
+ let loadVersionOne = (
1277
+ targetRegion,
1278
+ metadata,
1279
+ referenceURL,
1280
+ finishCallback,
1281
+ allCompletedCallback,
1282
+ options,
1283
+ ) => {
1054
1284
  const filteredMetada = supplementMetadataInArray(metadata, options);
1055
1285
  let numberOfObjects = getNumberOfObjects(filteredMetada);
1056
1286
  // view file does not receive callback
@@ -1061,30 +1291,33 @@ const SceneLoader = function (sceneIn) {
1061
1291
  for (let i = 0; i < filteredMetada.length; i++) {
1062
1292
  readVersionOneRegionPath(targetRegion, referenceURL, filteredMetada[i], i, callback);
1063
1293
  }
1064
- }
1294
+ };
1065
1295
 
1066
- let loadVersionTwo = (targetRegion, metadata, referenceURL, finishCallback, allCompletedCallback) => {
1296
+ let loadVersionTwo = (
1297
+ targetRegion,
1298
+ metadata,
1299
+ referenceURL,
1300
+ finishCallback,
1301
+ allCompletedCallback,
1302
+ ) => {
1067
1303
  let numberOfObjects = getNumberOfObjects(metadata);
1068
1304
  // view file does not receive callback
1069
1305
  let callback = new metaFinishCallback(numberOfObjects, finishCallback, allCompletedCallback);
1070
- if (metadata.Settings)
1071
- this.loadSettings(metadata.Settings);
1072
- if (metadata.Views)
1073
- loadMultipleViews(referenceURL, metadata.Views, referenceURL);
1074
- if (metadata.Regions)
1075
- loadRegions(targetRegion, referenceURL, metadata.Regions, callback);
1076
- }
1306
+ if (metadata.Settings) this.loadSettings(metadata.Settings);
1307
+ if (metadata.Views) loadMultipleViews(referenceURL, metadata.Views, referenceURL);
1308
+ if (metadata.Regions) loadRegions(targetRegion, referenceURL, metadata.Regions, callback);
1309
+ };
1077
1310
 
1078
1311
  /**
1079
- * Load a metadata file from the provided URL into this scene. Once
1080
- * succssful scene proceeds to read each items into scene for visualisations.
1081
- *
1082
- * @param {String} url - Location of the metadata file
1083
- * @param {Function} finishCallback - Callback function which will be called
1084
- * @param {options} Optional settings, it can be used to ignore some regions/groups
1085
- * in the metadata file. Only supports version 1 at this moment.
1086
- * for each glyphset and geometry that has been written in.
1087
- */
1312
+ * Load a metadata file from the provided URL into this scene. Once
1313
+ * succssful scene proceeds to read each items into scene for visualisations.
1314
+ *
1315
+ * @param {String} url - Location of the metadata file
1316
+ * @param {Function} finishCallback - Callback function which will be called
1317
+ * @param {options} Optional settings, it can be used to ignore some regions/groups
1318
+ * in the metadata file. Only supports version 1 at this moment.
1319
+ * for each glyphset and geometry that has been written in.
1320
+ */
1088
1321
  this.loadMetadataURL = (targetRegion, url, finishCallback, allCompletedCallback, options) => {
1089
1322
  const requestURL = url;
1090
1323
  const isStale = createStaleCheck();
@@ -1093,26 +1326,39 @@ const SceneLoader = function (sceneIn) {
1093
1326
  if (!response.ok) {
1094
1327
  throw new Error(`HTTP error! status: ${response.status}`);
1095
1328
  }
1096
- const referenceURL = response.url || (new URL(requestURL)).href;
1329
+ const referenceURL = response.url || new URL(requestURL).href;
1097
1330
  return response.json().then((metadata) => ({ metadata, referenceURL }));
1098
1331
  })
1099
- .then(({metadata, referenceURL}) => {
1332
+ .then(({ metadata, referenceURL }) => {
1100
1333
  if (isStale()) return;
1101
1334
  scene.resetMetadata();
1102
1335
  scene.resetDuration();
1103
1336
  viewLoaded = false;
1104
1337
  if (Array.isArray(metadata)) {
1105
- loadVersionOne(targetRegion, metadata, referenceURL, finishCallback, allCompletedCallback, options);
1106
- } else if (typeof metadata === "object" && metadata !== null) {
1107
- if (metadata.Version === "2.0") {
1108
- loadVersionTwo(targetRegion, metadata, referenceURL, finishCallback, allCompletedCallback);
1338
+ loadVersionOne(
1339
+ targetRegion,
1340
+ metadata,
1341
+ referenceURL,
1342
+ finishCallback,
1343
+ allCompletedCallback,
1344
+ options,
1345
+ );
1346
+ } else if (typeof metadata === 'object' && metadata !== null) {
1347
+ if (metadata.Version === '2.0') {
1348
+ loadVersionTwo(
1349
+ targetRegion,
1350
+ metadata,
1351
+ referenceURL,
1352
+ finishCallback,
1353
+ allCompletedCallback,
1354
+ );
1109
1355
  }
1110
1356
  }
1111
1357
  })
1112
1358
  .catch((error) => {
1113
1359
  console.error(`Fetch failed for URL: ${requestURL}`, error);
1114
1360
  });
1115
- }
1116
- }
1361
+ };
1362
+ };
1117
1363
 
1118
1364
  export { SceneLoader };