@abi-software/scaffoldvuer 1.21.1-beta.2 → 2.0.0

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 (45) hide show
  1. package/README.md +31 -12
  2. package/dist/index.html +9 -6
  3. package/dist/scaffoldvuer.js +14095 -13154
  4. package/dist/scaffoldvuer.umd.cjs +48 -48
  5. package/dist/style.css +1 -1
  6. package/eslint.config.js +37 -9
  7. package/package.json +10 -3
  8. package/public/index.html +9 -6
  9. package/src/App.vue +312 -279
  10. package/src/ScaffoldVuer-wc.js +4 -4
  11. package/src/app/DropZone.vue +11 -27
  12. package/src/app/ModelsInformation.js +22 -19
  13. package/src/app/ModelsTable.vue +42 -65
  14. package/src/app/TextureDemos.js +38 -64
  15. package/src/assets/_variables.scss +12 -10
  16. package/src/components/GlyphsControls.vue +3 -23
  17. package/src/components/LinesControls.vue +27 -66
  18. package/src/components/OpacityControls.vue +22 -26
  19. package/src/components/PointsControls.vue +20 -71
  20. package/src/components/PrimitiveControls.vue +35 -49
  21. package/src/components/ScaffoldOverlay.vue +63 -63
  22. package/src/components/ScaffoldTooltip.vue +36 -49
  23. package/src/components/ScaffoldTreeControls.vue +81 -129
  24. package/src/components/ScaffoldVuer.vue +509 -498
  25. package/src/components/TextureSlidesControls.vue +22 -64
  26. package/src/components/TransformationControls.vue +15 -42
  27. package/src/components/index.js +2 -2
  28. package/src/main.js +16 -18
  29. package/src/scripts/Annotation.js +3 -3
  30. package/src/scripts/BaseModule.js +26 -30
  31. package/src/scripts/EventNotifier.js +30 -36
  32. package/src/scripts/GraphicsHighlight.js +43 -50
  33. package/src/scripts/LocalFilesHelper.js +27 -26
  34. package/src/scripts/MappedNerves.js +2139 -697
  35. package/src/scripts/MappedOrgans.js +24 -25
  36. package/src/scripts/OrgansRenderer.js +445 -425
  37. package/src/scripts/RendererModule.js +133 -122
  38. package/src/scripts/Search.js +135 -151
  39. package/src/scripts/Utilities.js +129 -127
  40. package/src/scripts/WebGL.js +57 -91
  41. package/src/scripts/niftiHelper.js +3 -3
  42. package/src/store/index.js +7 -7
  43. package/vite.config.js +51 -50
  44. package/vite.static-build.js +7 -7
  45. package/vuese-generator.js +48 -56
@@ -1,22 +1,22 @@
1
- import { Label, THREE } from 'zincjs';
1
+ import { THREE } from 'zincjs';
2
2
 
3
- // This will be the config for nerves selection and highlight
4
- export const NERVE_CONFIG = {
5
- SELECTED_COLOUR: '#00ff00',
6
- HIGHLIGHTED_COLOUR: '#ff0000',
7
- DEFAULT_RADIUS: 1,
8
- DEFAULT_RADIAL_SEGMENTS: 8,
9
- ZOOM_RADIUS: 5,
10
- ZOOM_RADIAL_SEGMENTS: 12,
11
- }
3
+ // This will be the config for nerves selection and highlight
4
+ export const NERVE_CONFIG = {
5
+ SELECTED_COLOUR: '#00ff00',
6
+ HIGHLIGHTED_COLOUR: '#ff0000',
7
+ DEFAULT_RADIUS: 1,
8
+ DEFAULT_RADIAL_SEGMENTS: 8,
9
+ ZOOM_RADIUS: 5,
10
+ ZOOM_RADIAL_SEGMENTS: 12,
11
+ };
12
12
 
13
13
  export const createListFromPrimitives = (primitives, list) => {
14
14
  if (primitives) {
15
- let id = "";
16
- primitives.forEach(primitive => {
15
+ let id = '';
16
+ primitives.forEach((primitive) => {
17
17
  id = primitive.uuid;
18
18
  if (primitive.region) {
19
- id = primitive.region.uuid + "/" + id;
19
+ id = primitive.region.uuid + '/' + id;
20
20
  }
21
21
  if (primitive && primitive.getVisibility()) {
22
22
  list.push(id);
@@ -24,14 +24,14 @@ export const createListFromPrimitives = (primitives, list) => {
24
24
  });
25
25
  }
26
26
  return list;
27
- }
27
+ };
28
28
 
29
29
  const getDistance = (point1, point2) => {
30
30
  const dist0 = point1[0] - point2[0];
31
31
  const dist1 = point1[1] - point2[1];
32
32
  const dist2 = point1[2] - point2[2];
33
33
  return Math.sqrt(dist0 * dist0 + dist1 * dist1 + dist2 * dist2);
34
- }
34
+ };
35
35
 
36
36
  export const getEditablePoint = (eventIdentifiers) => {
37
37
  //const zincObjects = event.zincObjects;
@@ -42,13 +42,13 @@ export const getEditablePoint = (eventIdentifiers) => {
42
42
  if (info && info.index > -1) {
43
43
  const v = zincObject.getVerticesByIndex(info.index);
44
44
  if (v) {
45
- return { zincObject, index: info.index, point: v};
45
+ return { zincObject, index: info.index, point: v };
46
46
  }
47
47
  }
48
48
  }
49
49
  }
50
50
  return undefined;
51
- }
51
+ };
52
52
 
53
53
  export const getDeletableObjects = (eventIdentifiers) => {
54
54
  const zincObject = eventIdentifiers[0].data?.zincObject;
@@ -58,7 +58,7 @@ export const getDeletableObjects = (eventIdentifiers) => {
58
58
  }
59
59
  }
60
60
  return undefined;
61
- }
61
+ };
62
62
 
63
63
  export const getEditableLines = (eventIdentifiers) => {
64
64
  const zincObject = eventIdentifiers[0].data?.zincObject;
@@ -72,16 +72,26 @@ export const getEditableLines = (eventIdentifiers) => {
72
72
  const dist0 = getDistance(v[0], [p.x, p.y, p.z]);
73
73
  const dist1 = getDistance(v[1], [p.x, p.y, p.z]);
74
74
  if (dist0 > dist1) {
75
- return { zincObject, faceIndex: info.faceIndex, vertexIndex: info.faceIndex * 2 + 1, point: v[0]};
75
+ return {
76
+ zincObject,
77
+ faceIndex: info.faceIndex,
78
+ vertexIndex: info.faceIndex * 2 + 1,
79
+ point: v[0],
80
+ };
76
81
  } else {
77
- return { zincObject, faceIndex: info.faceIndex, vertexIndex: info.faceIndex * 2, point: v[1]};
82
+ return {
83
+ zincObject,
84
+ faceIndex: info.faceIndex,
85
+ vertexIndex: info.faceIndex * 2,
86
+ point: v[1],
87
+ };
78
88
  }
79
89
  }
80
90
  }
81
91
  }
82
92
  }
83
93
  return undefined;
84
- }
94
+ };
85
95
 
86
96
  export const getClickedObjects = (event) => {
87
97
  const zincObjects = event.zincObjects;
@@ -90,7 +100,7 @@ export const getClickedObjects = (event) => {
90
100
  return zincObject;
91
101
  }
92
102
  return undefined;
93
- }
103
+ };
94
104
 
95
105
  export const movePoint = (zincObject, index, diff) => {
96
106
  if (zincObject?.isEditable && zincObject?.isPointset) {
@@ -113,7 +123,7 @@ export const movePoint = (zincObject, index, diff) => {
113
123
  }
114
124
  }
115
125
  return false;
116
- }
126
+ };
117
127
 
118
128
  export const getLineDistance = (zincObject, faceIndex) => {
119
129
  if (zincObject?.isEditable && zincObject?.isLines2) {
@@ -125,7 +135,7 @@ export const getLineDistance = (zincObject, faceIndex) => {
125
135
  }
126
136
  }
127
137
  return 0;
128
- }
138
+ };
129
139
 
130
140
  //Move or extend a line
131
141
  export const moveAndExtendLine = (zincObject, faceIndex, unit, extendOnly) => {
@@ -136,7 +146,7 @@ export const moveAndExtendLine = (zincObject, faceIndex, unit, extendOnly) => {
136
146
  let d = [v[1][0] - v[0][0], v[1][1] - v[0][1], v[1][2] - v[0][2]];
137
147
  const mag = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
138
148
  for (let i = 0; i < 3; i++) {
139
- d[i] = d[i] / mag * unit;
149
+ d[i] = (d[i] / mag) * unit;
140
150
  if (!extendOnly) {
141
151
  v[0][i] = v[0][i] + d[i];
142
152
  v[1][i] = v[1][i] + d[i];
@@ -151,30 +161,26 @@ export const moveAndExtendLine = (zincObject, faceIndex, unit, extendOnly) => {
151
161
  }
152
162
  }
153
163
  return false;
154
- }
164
+ };
155
165
 
156
166
  export const updateBoundingBox = (geometry, scene) => {
157
167
  const box = scene.getBoundingBox();
158
168
  const dim = new THREE.Vector3().subVectors(box.max, box.min);
159
169
  const boxGeo = new THREE.BoxGeometry(dim.x, dim.y, dim.z);
160
- dim.addVectors(box.min, box.max).multiplyScalar( 0.5 );
161
- const positions = boxGeo.getAttribute("position");
170
+ dim.addVectors(box.min, box.max).multiplyScalar(0.5);
171
+ const positions = boxGeo.getAttribute('position');
162
172
  const count = positions.count;
163
173
  const vertices = [];
164
174
  for (let i = 0; i < count; i++) {
165
- vertices[i] = [
166
- positions.array[i * 3],
167
- positions.array[i * 3 + 1],
168
- positions.array[i * 3 + 2]
169
- ];
175
+ vertices[i] = [positions.array[i * 3], positions.array[i * 3 + 1], positions.array[i * 3 + 2]];
170
176
  }
171
- geometry.editVertices(vertices , 0);
177
+ geometry.editVertices(vertices, 0);
172
178
  geometry.setPosition(dim.x, dim.y, dim.z);
173
179
  boxGeo.dispose();
174
- }
180
+ };
175
181
 
176
182
  export const extractAllFullPaths = (item, list) => {
177
- let nodeName = "";
183
+ let nodeName = '';
178
184
  if (item.isRegion) {
179
185
  nodeName = `__r${item.regionPath}`;
180
186
  }
@@ -182,37 +188,35 @@ export const extractAllFullPaths = (item, list) => {
182
188
  nodeName = `${item.regionPath}/${item.label}`;
183
189
  }
184
190
  list.push(nodeName);
185
- if (item.children)
186
- item.children.forEach(child => extractAllFullPaths(child, list));
187
- }
191
+ if (item.children) item.children.forEach((child) => extractAllFullPaths(child, list));
192
+ };
188
193
 
189
194
  export const findObjectsWithNames = (rootRegion, names, regionPath, transverse) => {
190
195
  let targetRegion = rootRegion;
191
196
  const targetObjects = [];
192
- if (regionPath)
193
- targetRegion = rootRegion.findChildFromPath(regionPath);
197
+ if (regionPath) targetRegion = rootRegion.findChildFromPath(regionPath);
194
198
  if (targetRegion) {
195
199
  const isArray = Array.isArray(names);
196
200
  let array = names;
197
201
  if (!isArray) {
198
202
  array = [array];
199
203
  }
200
- array.forEach(name => {
204
+ array.forEach((name) => {
201
205
  const temp = targetRegion.findObjectsWithGroupName(name, transverse);
202
206
  targetObjects.push(...temp);
203
207
  });
204
208
  }
205
209
  return targetObjects;
206
- }
210
+ };
207
211
 
208
212
  export const getAllObjects = (scene) => {
209
213
  let objects = scene.getRootRegion().getAllObjects(true);
210
214
  let id = 1;
211
- return objects.map(object => Object.assign(object, { id: id++ })); // Add id to each object
212
- }
215
+ return objects.map((object) => Object.assign(object, { id: id++ })); // Add id to each object
216
+ };
213
217
 
214
218
  const findObjectWithUUID = (objects, uuid, remove) => {
215
- const index = objects.findIndex(obj => obj.uuid === uuid);
219
+ const index = objects.findIndex((obj) => obj.uuid === uuid);
216
220
  let object = undefined;
217
221
  if (index > -1) {
218
222
  object = objects[index];
@@ -221,7 +225,7 @@ const findObjectWithUUID = (objects, uuid, remove) => {
221
225
  }
222
226
  }
223
227
  return object;
224
- }
228
+ };
225
229
 
226
230
  export const convertUUIDsToFullPaths = (rootRegion, IDs) => {
227
231
  const results = [];
@@ -234,8 +238,8 @@ export const convertUUIDsToFullPaths = (rootRegion, IDs) => {
234
238
  let primitive = undefined;
235
239
  let regionID = undefined;
236
240
 
237
- IDs.forEach(id => {
238
- const uuids = id.split("/");
241
+ IDs.forEach((id) => {
242
+ const uuids = id.split('/');
239
243
  regionID = uuids[0];
240
244
  region = findObjectWithUUID(allRegions, regionID, false);
241
245
  if (region) {
@@ -257,28 +261,26 @@ export const convertUUIDsToFullPaths = (rootRegion, IDs) => {
257
261
  });
258
262
  }
259
263
  return results;
260
- }
264
+ };
261
265
 
262
266
  export const createUnqiuesFromObjects = (zincObjects) => {
263
267
  if (zincObjects) {
264
268
  const expanded = [];
265
- zincObjects.forEach(obj => {
269
+ zincObjects.forEach((obj) => {
266
270
  if (obj.isZincObject) {
267
271
  expanded.push(obj);
268
272
  } else if (obj.isRegion) {
269
273
  expanded.push(...obj.getAllObjects(true));
270
274
  }
271
275
  });
272
- const uniq = Object.values(
273
- expanded.reduce((acc, obj) => ({ ...acc, [obj.uuid]: obj }), {})
274
- );
276
+ const uniq = Object.values(expanded.reduce((acc, obj) => ({ ...acc, [obj.uuid]: obj }), {}));
275
277
  return uniq;
276
278
  }
277
279
  return [];
278
- }
280
+ };
279
281
 
280
282
  export const getObjectsFromAnnotations = (scene, annotations) => {
281
- const returned = {label: "Multiple selections", regionPath: "", objects: []};
283
+ const returned = { label: 'Multiple selections', regionPath: '', objects: [] };
282
284
  if (annotations && scene) {
283
285
  const rpList = {};
284
286
  const rootRegion = scene.getRootRegion();
@@ -286,12 +288,12 @@ export const getObjectsFromAnnotations = (scene, annotations) => {
286
288
  returned.regionPath = annotations[0].data.region;
287
289
  returned.label = annotations[0].data.group;
288
290
  }
289
- annotations.forEach(annotation => {
291
+ annotations.forEach((annotation) => {
290
292
  if (!annotation.data.region.includes(returned.regionPath)) {
291
- returned.regionPath = "";
293
+ returned.regionPath = '';
292
294
  }
293
295
  if (returned.label !== annotation.data.group) {
294
- returned.label = "Multiple selections";
296
+ returned.label = 'Multiple selections';
295
297
  }
296
298
  const region = rootRegion.findChildFromPath(annotation.data.region);
297
299
  if (!rpList[region.uuid]) {
@@ -302,7 +304,7 @@ export const getObjectsFromAnnotations = (scene, annotations) => {
302
304
  });
303
305
  }
304
306
  return returned;
305
- }
307
+ };
306
308
 
307
309
  const getCoordinatesForAnnotationFeature = (zincObject) => {
308
310
  const mesh = zincObject.getMorph();
@@ -311,11 +313,7 @@ const getCoordinatesForAnnotationFeature = (zincObject) => {
311
313
  if (zincObject.isPointset) {
312
314
  const positionArray = mesh.pointPositions;
313
315
  for (let i = 0; i < zincObject.drawRange; i++) {
314
- coords.push([
315
- positionArray[vIndex++],
316
- positionArray[vIndex++],
317
- positionArray[vIndex++],
318
- ]);
316
+ coords.push([positionArray[vIndex++], positionArray[vIndex++], positionArray[vIndex++]]);
319
317
  }
320
318
  return coords;
321
319
  }
@@ -323,86 +321,102 @@ const getCoordinatesForAnnotationFeature = (zincObject) => {
323
321
  if (zincObject.isLines2) {
324
322
  attr = 'instanceStart';
325
323
  }
326
- const position = mesh.geometry.getAttribute( attr );
324
+ const position = mesh.geometry.getAttribute(attr);
327
325
  for (let i = 0; i < zincObject.drawRange; i++) {
328
- coords.push([
329
- position.array[vIndex++],
330
- position.array[vIndex++],
331
- position.array[vIndex++],
332
- ]);
326
+ coords.push([position.array[vIndex++], position.array[vIndex++], position.array[vIndex++]]);
333
327
  }
334
328
  return coords;
335
- }
329
+ };
336
330
 
337
- export const createNewAnnotationsWithFeatures = (zincObject, region, group, scaffoldUrl, comment) => {
338
- let type = undefined;
331
+ export const createNewAnnotationsWithFeatures = (
332
+ zincObject,
333
+ region,
334
+ group,
335
+ scaffoldUrl,
336
+ comment,
337
+ ) => {
338
+ let type;
339
339
  if (zincObject.isPointset) {
340
- type = "MultiPoint";
340
+ type = 'MultiPoint';
341
341
  } else if (zincObject.isLines2) {
342
- type = "MultiLineString";
342
+ type = 'MultiLineString';
343
343
  } else {
344
- type = "Feature";
344
+ type = 'Feature';
345
345
  }
346
- const drawn = type === "Feature" ? false : true;
347
- const label = type === "Feature" ? "Feature annotation" : "Drawn annotation";
346
+ const drawn = type === 'Feature' ? false : true;
347
+ const label = type === 'Feature' ? 'Feature annotation' : 'Drawn annotation';
348
348
  if (type) {
349
349
  const coords = getCoordinatesForAnnotationFeature(zincObject);
350
350
  //Check if region ends with a slash
351
- let fullName = region.slice(-1) === "/" ? region : region + "/";
351
+ let fullName = region.slice(-1) === '/' ? region : region + '/';
352
352
  fullName = fullName + group;
353
353
  const featureID = fullName;
354
354
  const userAnnotation = {
355
355
  resource: scaffoldUrl,
356
356
  item: {
357
- "id": featureID,
357
+ id: featureID,
358
358
  },
359
359
  body: {
360
360
  evidence: [],
361
361
  comment: comment,
362
362
  },
363
363
  feature: {
364
- "id": featureID,
365
- "properties": {
366
- "drawn": drawn,
367
- "label": label
364
+ id: featureID,
365
+ properties: {
366
+ drawn: drawn,
367
+ label: label,
368
+ },
369
+ geometry: {
370
+ coordinates: coords,
371
+ type: type,
368
372
  },
369
- "geometry": {
370
- "coordinates": coords,
371
- "type": type
372
- }
373
373
  },
374
- }
375
- if (comment === "Deleted") {
374
+ };
375
+ if (comment === 'Deleted') {
376
376
  userAnnotation.feature = undefined;
377
377
  }
378
378
 
379
379
  return userAnnotation;
380
380
  }
381
- }
381
+ };
382
382
 
383
383
  /*
384
384
  * Add/Update drawn annotations to the server.
385
385
  */
386
- export const addUserAnnotationWithFeature = (service, userToken, zincObject,
387
- region, group, scaffoldUrl, action) => {
388
- const annotation = createNewAnnotationsWithFeatures(zincObject, region, group, scaffoldUrl, action);
386
+ export const addUserAnnotationWithFeature = (
387
+ service,
388
+ userToken,
389
+ zincObject,
390
+ region,
391
+ group,
392
+ scaffoldUrl,
393
+ action,
394
+ ) => {
395
+ const annotation = createNewAnnotationsWithFeatures(
396
+ zincObject,
397
+ region,
398
+ group,
399
+ scaffoldUrl,
400
+ action,
401
+ );
389
402
  if (annotation) {
390
403
  if (service && service.currentUser) {
391
- annotation.creator = {...service.currentUser};
404
+ annotation.creator = { ...service.currentUser };
392
405
  if (!annotation.creator.orcid) annotation.creator.orcid = '0000-0000-0000-0000';
393
- service.addAnnotation(userToken, annotation)
394
- .then((response) => {
395
- if (!response.annotationId) {
406
+ service
407
+ .addAnnotation(userToken, annotation)
408
+ .then((response) => {
409
+ if (!response.annotationId) {
410
+ console.log('There is a problem with the submission, please try again later');
411
+ }
412
+ })
413
+ .catch(() => {
396
414
  console.log('There is a problem with the submission, please try again later');
397
- }
398
- })
399
- .catch(() => {
400
- console.log('There is a problem with the submission, please try again later');
401
- })
415
+ });
402
416
  }
403
417
  return annotation;
404
418
  }
405
- }
419
+ };
406
420
 
407
421
  /*
408
422
  * Get the drawn annotation stored on the annotation server
@@ -410,12 +424,12 @@ export const addUserAnnotationWithFeature = (service, userToken, zincObject,
410
424
  export const getDrawnAnnotations = async (service, userToken, scaffoldUrl) => {
411
425
  const resource = scaffoldUrl;
412
426
  return await service.drawnFeatures(userToken, resource);
413
- }
427
+ };
414
428
 
415
429
  /*
416
430
  * Convert features store in annotation server into primitives
417
431
  */
418
- export const annotationFeaturesToPrimitives = (scene, features) => {
432
+ export const annotationFeaturesToPrimitives = (scene, features) => {
419
433
  if (scene) {
420
434
  features.forEach((feature) => {
421
435
  const geometry = feature.geometry;
@@ -424,36 +438,24 @@ export const annotationFeaturesToPrimitives = (scene, features) => {
424
438
  const region = regionGroup.substring(0, last);
425
439
  const group = regionGroup.substring(last + 1);
426
440
  let object = undefined;
427
- if (geometry.type === "MultiPoint") {
428
- object = scene.createPoints(
429
- region,
430
- group,
431
- geometry.coordinates,
432
- group,
433
- 0x0022ee,
434
- );
435
- } else if (geometry.type === "MultiLineString") {
436
- object = scene.createLines(
437
- region,
438
- group,
439
- geometry.coordinates,
440
- 0x00ee22,
441
- );
441
+ if (geometry.type === 'MultiPoint') {
442
+ object = scene.createPoints(region, group, geometry.coordinates, group, 0x0022ee);
443
+ } else if (geometry.type === 'MultiLineString') {
444
+ object = scene.createLines(region, group, geometry.coordinates, 0x00ee22);
442
445
  }
443
446
  if (object) object.zincObject.isEditable = true;
444
447
  });
445
448
  }
446
- }
449
+ };
447
450
 
448
- export const objectsToZincObjects = function(objects) {
451
+ export const objectsToZincObjects = function (objects) {
449
452
  const zincObjects = [];
450
453
  for (let i = 0; i < objects.length; i++) {
451
454
  let zincObject = objects[i].userData;
452
455
  if (zincObject) {
453
456
  if (zincObject.isGlyph || zincObject.isGlyphset) {
454
457
  let glyphset = zincObject;
455
- if (zincObject.isGlyph)
456
- glyphset = zincObject.getGlyphset();
458
+ if (zincObject.isGlyph) glyphset = zincObject.getGlyphset();
457
459
  zincObjects.push(glyphset);
458
460
  } else {
459
461
  zincObjects.push(zincObject);
@@ -461,4 +463,4 @@ export const objectsToZincObjects = function(objects) {
461
463
  }
462
464
  }
463
465
  return zincObjects;
464
- }
466
+ };
@@ -1,96 +1,62 @@
1
1
  /**
2
- * @author alteredq / http://alteredqualia.com/
3
- * @author mr.doob / http://mrdoob.com/
2
+ * Checks whether the browser can run the ZincJS renderer. ZincJS uses
3
+ * THREE.WebGPURenderer, which renders with WebGPU when it is available and
4
+ * falls back to WebGL 2 otherwise. WebGL 1 is not supported.
4
5
  */
5
6
 
6
- const WEBGL = {
7
-
8
- isWebGLAvailable: function () {
9
-
10
- try {
11
-
12
- var canvas = document.createElement( 'canvas' );
13
- return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) );
14
-
15
- } catch ( e ) {
16
-
17
- return false;
18
-
19
- }
20
-
21
- },
22
-
23
- isWebGL2Available: function () {
24
-
25
- try {
26
-
27
- var canvas = document.createElement( 'canvas' );
28
- return !! ( window.WebGL2RenderingContext && canvas.getContext( 'webgl2' ) );
29
-
30
- } catch ( e ) {
31
-
32
- return false;
33
-
34
- }
35
-
36
- },
37
-
38
- getWebGLErrorMessage: function () {
39
-
40
- return this.getErrorMessage( 1 );
41
-
42
- },
43
-
44
- getWebGL2ErrorMessage: function () {
45
-
46
- return this.getErrorMessage( 2 );
47
-
48
- },
49
-
50
- getErrorMessage: function ( version ) {
51
-
52
- var names = {
53
- 1: 'WebGL',
54
- 2: 'WebGL 2'
55
- };
56
-
57
- var contexts = {
58
- 1: window.WebGLRenderingContext,
59
- 2: window.WebGL2RenderingContext
60
- };
61
-
62
- var message = 'This module requires <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#008">$1</a> support but your $0 does not seem to support it.';
63
-
64
- var element = document.createElement( 'div' );
65
- element.id = 'webglmessage';
66
- element.style.fontFamily = 'monospace';
67
- element.style.fontSize = '20px';
68
- element.style.fontWeight = 'normal';
69
- element.style.textAlign = 'center';
70
- element.style.background = '#fff';
71
- element.style.color = '#000';
72
- element.style.padding = '1.5em';
73
- element.style.width = '400px';
74
- element.style.margin = '5em auto 0';
75
-
76
- if ( contexts[ version ] ) {
77
-
78
- message = message.replace( '$0', 'graphics card' );
79
-
80
- } else {
81
-
82
- message = message.replace( '$0', 'browser' );
83
-
84
- }
85
-
86
- message = message.replace( '$1', names[ version ] );
87
-
88
- element.innerHTML = message;
89
-
90
- return element;
91
-
92
- }
93
-
7
+ const GPU_SUPPORT = {
8
+ isWebGPUAvailable: async function () {
9
+ try {
10
+ if (typeof navigator === 'undefined' || !navigator.gpu) return false;
11
+ //navigator.gpu can exist without a usable adapter, e.g. on a blocklisted GPU.
12
+ const adapter = await navigator.gpu.requestAdapter();
13
+ return !!adapter;
14
+ } catch (_e) {
15
+ return false;
16
+ }
17
+ },
18
+
19
+ isWebGL2Available: function () {
20
+ try {
21
+ const canvas = document.createElement('canvas');
22
+ return !!(window.WebGL2RenderingContext && canvas.getContext('webgl2'));
23
+ } catch (_e) {
24
+ return false;
25
+ }
26
+ },
27
+
28
+ isRendererSupported: async function () {
29
+ return (await this.isWebGPUAvailable()) || this.isWebGL2Available();
30
+ },
31
+
32
+ getErrorMessage: function () {
33
+ let message =
34
+ 'This module requires <a href="https://caniuse.com/webgpu" style="color:#008">WebGPU</a> or ' +
35
+ '<a href="https://caniuse.com/webgl2" style="color:#008">WebGL 2</a> support but your $0 does not seem to support either.';
36
+
37
+ const element = document.createElement('div');
38
+ element.id = 'webglmessage';
39
+ element.style.fontFamily = 'monospace';
40
+ element.style.fontSize = '20px';
41
+ element.style.fontWeight = 'normal';
42
+ element.style.textAlign = 'center';
43
+ element.style.background = '#fff';
44
+ element.style.color = '#000';
45
+ element.style.padding = '1.5em';
46
+ element.style.width = '400px';
47
+ element.style.margin = '5em auto 0';
48
+
49
+ //The browser knows the APIs but could not create a context: blame the graphics card.
50
+ if ((typeof navigator !== 'undefined' && navigator.gpu) || window.WebGL2RenderingContext) {
51
+ message = message.replace('$0', 'graphics card');
52
+ } else {
53
+ message = message.replace('$0', 'browser');
54
+ }
55
+
56
+ element.innerHTML = message;
57
+
58
+ return element;
59
+ },
94
60
  };
95
61
 
96
- export { WEBGL as default };
62
+ export { GPU_SUPPORT as default };
@@ -1,9 +1,9 @@
1
1
  //import * as nifti from 'nifti-reader-js';
2
- import { createPrimitivesFromNIFTI } from "zincjs";
2
+ import { createPrimitivesFromNIFTI } from 'zincjs';
3
3
 
4
4
  const readNIFTIFromSource = async (url, useHeaderInfo, maskURL, settings, options) => {
5
5
  const images = await createPrimitivesFromNIFTI(url, useHeaderInfo, maskURL, settings, options);
6
6
  return images;
7
- }
7
+ };
8
8
 
9
- export { readNIFTIFromSource }
9
+ export { readNIFTIFromSource };