@kitware/vtk.js 28.13.1 → 29.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.
@@ -1,3 +1,10 @@
1
+ ## From 28.x to 29
2
+
3
+ - **getOpenGLRenderWindow**: `getOpenGLRenderWindow` has been renamed to `getApiSpecificRenderWindow` in `vtkFullScreenRenderWindow`, `vtkGenericRenderWindow` and `vtkViewProxy` to support WebGL and WebGPU backend. ([#2816](https://github.com/Kitware/vtk-js/pull/2816))
4
+ - **WidgetManager**: Deprecated APIs have been fully removed. ([#2910](https://github.com/Kitware/vtk-js/pull/2910))
5
+ - **OpenGLRenderWindow**: WebXR API has been moved into a WebXR RenderWindowHelper. ([#2924](https://github.com/Kitware/vtk-js/pull/2924))
6
+ - **DistanceWidget**: Removed from vtk.js in favor of vtkLineWidget ([#2945](https://github.com/Kitware/vtk-js/pull/2945))
7
+
1
8
  ## From 27.x to 28
2
9
 
3
10
  - **vtkManipulator.handleEvent**: Change all `handleEvent` signatures of manipulators. Used to be `handleEvent(callData, glRenderWindow): vec3`, it is now `handleEvent(callData, glRenderWindow): { worldCoords: Nullable<vec3>, worldDirection?: mat3 }`.
@@ -8,6 +8,7 @@ import { vtkSubscription, vtkObject } from './../../interfaces';
8
8
  import vtkRenderer from './../../Rendering/Core/Renderer';
9
9
  import vtkRenderWindow from './../../Rendering/Core/RenderWindow';
10
10
  import vtkOpenGLRenderWindow from './../../Rendering/OpenGL/RenderWindow';
11
+ import vtkWebGPURenderWindow from './../../Rendering/WebGPU/RenderWindow';
11
12
  import { VtkProxy } from './../../macros';
12
13
 
13
14
  export interface vtkViewProxy extends VtkProxy {
@@ -66,7 +67,7 @@ export interface vtkViewProxy extends VtkProxy {
66
67
  getInteractor(): vtkRenderWindowInteractor;
67
68
  getInteractorStyle2D(): vtkInteractorStyle;
68
69
  getInteractorStyle3D(): vtkInteractorStyle;
69
- getOpenGLRenderWindow(): vtkOpenGLRenderWindow;
70
+ getApiSpecificRenderWindow(): vtkOpenGLRenderWindow|vtkWebGPURenderWindow;
70
71
  getOrientationAxesType(): string;
71
72
  getPresetToOrientationAxes(): any;
72
73
  getRenderer(): vtkRenderer;
@@ -148,6 +148,7 @@ export interface vtkRenderWindow extends vtkObject {
148
148
  * Switch the rendering backend between WebGL and WebGPU.
149
149
  * By default, the WebGL backend is used. To switch, to WebGPU call
150
150
  * `renderWindow.setDefaultViewAPI('WebGPU')` before calling `render`.
151
+ * Must be called before `newAPISpecificView()` is called.
151
152
  * @param defaultViewAPI (default: 'WebGL')
152
153
  */
153
154
  setDefaultViewAPI(defaultViewAPI: DEFAULT_VIEW_API): boolean;
@@ -17,6 +17,7 @@ export interface IFullScreenRenderWindowInitialValues {
17
17
  containerStyle?: object;
18
18
  controlPanelStyle?: object;
19
19
  controllerVisibility?: boolean;
20
+ defaultViewAPI?: boolean;
20
21
  listenWindowResize?: boolean;
21
22
  resizeCallback?: any;
22
23
  }
@@ -42,7 +43,9 @@ export interface vtkFullScreenRenderWindow extends vtkObject {
42
43
  delete(): void;
43
44
 
44
45
  /**
45
- *
46
+ * Returns vtkWebGPURenderWindow if ?viewAPI='WebGPU' is in URL, or if
47
+ * vtkFullScreenRenderWindow has been created with "defaultViewAPI: 'WebGPU",
48
+ * otherwise vtkOpenGLRenderWindow is returned.
46
49
  */
47
50
  getApiSpecificRenderWindow(): any; // vtkOpenGLRenderWindow || vtkWebGPURenderWindow
48
51
 
@@ -72,7 +72,7 @@ function vtkFullScreenRenderWindow(publicAPI, model) {
72
72
  model.renderWindow.addRenderer(model.renderer);
73
73
 
74
74
  // apiSpecificRenderWindow
75
- model.apiSpecificRenderWindow = model.renderWindow.newAPISpecificView(userParams.viewAPI);
75
+ model.apiSpecificRenderWindow = model.renderWindow.newAPISpecificView(userParams.viewAPI ?? model.defaultViewAPI);
76
76
  model.apiSpecificRenderWindow.setContainer(model.container);
77
77
  model.renderWindow.addView(model.apiSpecificRenderWindow);
78
78
 
@@ -161,6 +161,7 @@ const DEFAULT_VALUES = {
161
161
  background: [0.32, 0.34, 0.43],
162
162
  containerStyle: null,
163
163
  controlPanelStyle: null,
164
+ // defaultViewAPI: undefined,
164
165
  listenWindowResize: true,
165
166
  resizeCallback: null,
166
167
  controllerVisibility: true
@@ -4,6 +4,7 @@ import vtkRenderer from './../Core/Renderer';
4
4
  import vtkRenderWindow from './../Core/RenderWindow';
5
5
  import vtkRenderWindowInteractor from './../Core/RenderWindowInteractor';
6
6
  import vtkOpenGLRenderWindow from './../OpenGL/RenderWindow';
7
+ import vtkWebGPURenderWindow from './../WebGPU/RenderWindow';
7
8
 
8
9
 
9
10
  /**
@@ -33,9 +34,9 @@ export interface vtkGenericRenderWindow extends vtkObject {
33
34
  getInteractor(): vtkRenderWindowInteractor;
34
35
 
35
36
  /**
36
- *
37
+ * Get the render back-end specific render window.
37
38
  */
38
- getOpenGLRenderWindow(): vtkOpenGLRenderWindow;
39
+ getApiSpecificRenderWindow(): vtkOpenGLRenderWindow|vtkWebGPURenderWindow;
39
40
 
40
41
  /**
41
42
  *
@@ -1,15 +1,17 @@
1
1
  import { m as macro } from '../../macros2.js';
2
- import vtkRenderWindow$1 from '../OpenGL/RenderWindow.js';
3
2
  import vtkRenderer from '../Core/Renderer.js';
4
3
  import vtkRenderWindow from '../Core/RenderWindow.js';
5
4
  import vtkRenderWindowInteractor from '../Core/RenderWindowInteractor.js';
6
5
  import vtkInteractorStyleTrackballCamera from '../../Interaction/Style/InteractorStyleTrackballCamera.js';
6
+ import vtkURLExtract from '../../Common/Core/URLExtract.js';
7
7
  import '../../Common/Core/Points.js';
8
8
  import '../../Common/Core/DataArray.js';
9
9
  import '../../Common/DataModel/PolyData.js';
10
10
  import '../Core/Actor.js';
11
11
  import '../Core/Mapper.js';
12
12
 
13
+ // Process arguments from URL
14
+ const userParams = vtkURLExtract.extractURLParameters();
13
15
  function vtkGenericRenderWindow(publicAPI, model) {
14
16
  // Capture resize trigger method to remove from publicAPI
15
17
  const invokeResize = publicAPI.invokeResize;
@@ -21,13 +23,13 @@ function vtkGenericRenderWindow(publicAPI, model) {
21
23
  model.renderWindow.addRenderer(model.renderer);
22
24
 
23
25
  // OpenGLRenderWindow
24
- model._openGLRenderWindow = vtkRenderWindow$1.newInstance();
25
- model.renderWindow.addView(model._openGLRenderWindow);
26
+ model._apiSpecificRenderWindow = model.renderWindow.newAPISpecificView(userParams.viewAPI ?? model.defaultViewAPI);
27
+ model.renderWindow.addView(model._apiSpecificRenderWindow);
26
28
 
27
29
  // Interactor
28
30
  model.interactor = vtkRenderWindowInteractor.newInstance();
29
31
  model.interactor.setInteractorStyle(vtkInteractorStyleTrackballCamera.newInstance());
30
- model.interactor.setView(model._openGLRenderWindow);
32
+ model.interactor.setView(model._apiSpecificRenderWindow);
31
33
  model.interactor.initialize();
32
34
 
33
35
  // Expose background
@@ -41,7 +43,7 @@ function vtkGenericRenderWindow(publicAPI, model) {
41
43
  if (model.container) {
42
44
  const dims = model.container.getBoundingClientRect();
43
45
  const devicePixelRatio = window.devicePixelRatio || 1;
44
- model._openGLRenderWindow.setSize(Math.floor(dims.width * devicePixelRatio), Math.floor(dims.height * devicePixelRatio));
46
+ model._apiSpecificRenderWindow.setSize(Math.floor(dims.width * devicePixelRatio), Math.floor(dims.height * devicePixelRatio));
45
47
  invokeResize();
46
48
  model.renderWindow.render();
47
49
  }
@@ -55,7 +57,7 @@ function vtkGenericRenderWindow(publicAPI, model) {
55
57
 
56
58
  // Switch container
57
59
  model.container = el;
58
- model._openGLRenderWindow.setContainer(model.container);
60
+ model._apiSpecificRenderWindow.setContainer(model.container);
59
61
 
60
62
  // Bind to new container
61
63
  if (model.container) {
@@ -64,7 +66,7 @@ function vtkGenericRenderWindow(publicAPI, model) {
64
66
  };
65
67
 
66
68
  // Properly release GL context
67
- publicAPI.delete = macro.chain(publicAPI.setContainer, model._openGLRenderWindow.delete, publicAPI.delete);
69
+ publicAPI.delete = macro.chain(publicAPI.setContainer, model._apiSpecificRenderWindow.delete, publicAPI.delete);
68
70
 
69
71
  // Handle size
70
72
  if (model.listenWindowResize) {
@@ -91,8 +93,8 @@ function extend(publicAPI, model) {
91
93
 
92
94
  // Object methods
93
95
  macro.obj(publicAPI, model);
94
- macro.get(publicAPI, model, ['renderWindow', 'renderer', '_openGLRenderWindow', 'interactor', 'container']);
95
- macro.moveToProtected(publicAPI, model, ['openGLRenderWindow']);
96
+ macro.get(publicAPI, model, ['renderWindow', 'renderer', '_apiSpecificRenderWindow', 'interactor', 'container']);
97
+ macro.moveToProtected(publicAPI, model, ['_apiSpecificRenderWindow']);
96
98
  macro.event(publicAPI, model, 'resize');
97
99
 
98
100
  // Object specific methods
@@ -29,10 +29,6 @@ export interface IOpenGLRenderWindowInitialValues {
29
29
  webgl2?: boolean;
30
30
  defaultToWebgl2?: boolean;
31
31
  activeFramebuffer?: any;
32
- xrSession?: any;
33
- xrSessionIsAR?: boolean;
34
- xrReferenceSpace?: any;
35
- xrSupported?: boolean;
36
32
  imageFormat?: 'image/png';
37
33
  useOffScreen?: boolean;
38
34
  useBackgroundImage?: boolean;
@@ -236,36 +232,6 @@ export interface vtkOpenGLRenderWindow extends vtkOpenGLRenderWindowBase {
236
232
  */
237
233
  get3DContext(options: I3DContextOptions): Nullable<WebGLRenderingContext>;
238
234
 
239
- /**
240
- * Request an XR session on the user device with WebXR,
241
- * typically in response to a user request such as a button press.
242
- */
243
- startXR(): void;
244
-
245
- /**
246
- * When an XR session is available, set up the XRWebGLLayer
247
- * and request the first animation frame for the device
248
- */
249
- enterXR(): void,
250
-
251
- /**
252
- * Adjust world-to-physical parameters for different viewing modalities
253
- *
254
- * @param {Number} inputRescaleFactor
255
- * @param {Number} inputTranslateZ
256
- */
257
- resetXRScene(inputRescaleFactor: number, inputTranslateZ: number): void,
258
-
259
- /**
260
- * Request to stop the current XR session
261
- */
262
- stopXR(): void;
263
-
264
- /**
265
- *
266
- */
267
- xrRender(): void;
268
-
269
235
  /**
270
236
  *
271
237
  */
@@ -8,16 +8,12 @@ import vtkTextureUnitManager from './TextureUnitManager.js';
8
8
  import vtkViewNodeFactory from './ViewNodeFactory.js';
9
9
  import vtkRenderPass from '../SceneGraph/RenderPass.js';
10
10
  import vtkRenderWindowViewNode from '../SceneGraph/RenderWindowViewNode.js';
11
- import Constants from './RenderWindow/Constants.js';
12
- import { createContextProxyHandler, GET_UNDERLYING_CONTEXT } from './RenderWindow/ContextProxy.js';
11
+ import { createContextProxyHandler } from './RenderWindow/ContextProxy.js';
13
12
 
14
13
  const {
15
14
  vtkDebugMacro,
16
15
  vtkErrorMacro
17
16
  } = macro;
18
- const {
19
- XrSessionTypes
20
- } = Constants;
21
17
  const SCREENSHOT_PLACEHOLDER = {
22
18
  position: 'absolute',
23
19
  top: 0,
@@ -25,12 +21,6 @@ const SCREENSHOT_PLACEHOLDER = {
25
21
  width: '100%',
26
22
  height: '100%'
27
23
  };
28
- const DEFAULT_RESET_FACTORS = {
29
- rescaleFactor: 0.25,
30
- // isotropic scale factor reduces apparent size of objects
31
- translateZ: -1.5 // default translation initializes object in front of camera
32
- };
33
-
34
24
  function checkRenderTargetSupport(gl, format, type) {
35
25
  // create temporary frame buffer and texture
36
26
  const framebuffer = gl.createFramebuffer();
@@ -227,168 +217,6 @@ function vtkOpenGLRenderWindow(publicAPI, model) {
227
217
  }
228
218
  return new Proxy(result, cachingContextHandler);
229
219
  };
230
-
231
- // Request an XR session on the user device with WebXR,
232
- // typically in response to a user request such as a button press
233
- publicAPI.startXR = xrSessionType => {
234
- if (navigator.xr === undefined) {
235
- throw new Error('WebXR is not available');
236
- }
237
- model.xrSessionType = xrSessionType !== undefined ? xrSessionType : XrSessionTypes.HmdVR;
238
- const isXrSessionAR = [XrSessionTypes.HmdAR, XrSessionTypes.MobileAR].includes(model.xrSessionType);
239
- const sessionType = isXrSessionAR ? 'immersive-ar' : 'immersive-vr';
240
- if (!navigator.xr.isSessionSupported(sessionType)) {
241
- if (isXrSessionAR) {
242
- throw new Error('Device does not support AR session');
243
- } else {
244
- throw new Error('VR display is not available');
245
- }
246
- }
247
- if (model.xrSession === null) {
248
- navigator.xr.requestSession(sessionType).then(publicAPI.enterXR, () => {
249
- throw new Error('Failed to create XR session!');
250
- });
251
- } else {
252
- throw new Error('XR Session already exists!');
253
- }
254
- };
255
-
256
- // When an XR session is available, set up the XRWebGLLayer
257
- // and request the first animation frame for the device
258
- publicAPI.enterXR = async xrSession => {
259
- model.xrSession = xrSession;
260
- model.oldCanvasSize = model.size.slice();
261
- if (model.xrSession !== null) {
262
- const gl = publicAPI.get3DContext();
263
- await gl.makeXRCompatible();
264
- const glLayer = new global.XRWebGLLayer(model.xrSession,
265
- // constructor needs unproxied context
266
- gl[GET_UNDERLYING_CONTEXT]());
267
- publicAPI.setSize(glLayer.framebufferWidth, glLayer.framebufferHeight);
268
- model.xrSession.updateRenderState({
269
- baseLayer: glLayer
270
- });
271
- model.xrSession.requestReferenceSpace('local').then(refSpace => {
272
- model.xrReferenceSpace = refSpace;
273
- });
274
-
275
- // Initialize transparent background for augmented reality session
276
- const isXrSessionAR = [XrSessionTypes.HmdAR, XrSessionTypes.MobileAR].includes(model.xrSessionType);
277
- if (isXrSessionAR) {
278
- const ren = model.renderable.getRenderers()[0];
279
- model.preXrSessionBackground = ren.getBackground();
280
- ren.setBackground([0, 0, 0, 0]);
281
- }
282
- publicAPI.resetXRScene();
283
- model.renderable.getInteractor().switchToXRAnimation();
284
- model.xrSceneFrame = model.xrSession.requestAnimationFrame(publicAPI.xrRender);
285
- } else {
286
- throw new Error('Failed to enter XR with a null xrSession.');
287
- }
288
- };
289
- publicAPI.resetXRScene = function () {
290
- let rescaleFactor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_RESET_FACTORS.rescaleFactor;
291
- let translateZ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_RESET_FACTORS.translateZ;
292
- // Adjust world-to-physical parameters for different modalities
293
-
294
- const ren = model.renderable.getRenderers()[0];
295
- ren.resetCamera();
296
- const camera = ren.getActiveCamera();
297
- let physicalScale = camera.getPhysicalScale();
298
- const physicalTranslation = camera.getPhysicalTranslation();
299
- const rescaledTranslateZ = translateZ * physicalScale;
300
- physicalScale /= rescaleFactor;
301
- physicalTranslation[2] += rescaledTranslateZ;
302
- camera.setPhysicalScale(physicalScale);
303
- camera.setPhysicalTranslation(physicalTranslation);
304
- // Clip at 0.1m, 100.0m in physical space by default
305
- camera.setClippingRange(0.1 * physicalScale, 100.0 * physicalScale);
306
- };
307
- publicAPI.stopXR = async () => {
308
- if (navigator.xr === undefined) {
309
- // WebXR polyfill not available so nothing to do
310
- return;
311
- }
312
- if (model.xrSession !== null) {
313
- model.xrSession.cancelAnimationFrame(model.xrSceneFrame);
314
- model.renderable.getInteractor().returnFromXRAnimation();
315
- const gl = publicAPI.get3DContext();
316
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
317
- await model.xrSession.end().catch(error => {
318
- if (!(error instanceof DOMException)) {
319
- throw error;
320
- }
321
- });
322
- model.xrSession = null;
323
- }
324
- if (model.oldCanvasSize !== undefined) {
325
- publicAPI.setSize(...model.oldCanvasSize);
326
- }
327
-
328
- // Reset to default canvas
329
- const ren = model.renderable.getRenderers()[0];
330
- if (model.preXrSessionBackground != null) {
331
- ren.setBackground(model.preXrSessionBackground);
332
- model.preXrSessionBackground = null;
333
- }
334
- ren.getActiveCamera().setProjectionMatrix(null);
335
- ren.resetCamera();
336
- ren.setViewport(0.0, 0, 1.0, 1.0);
337
- publicAPI.traverseAllPasses();
338
- };
339
- publicAPI.xrRender = async (t, frame) => {
340
- const xrSession = frame.session;
341
- const isXrSessionHMD = [XrSessionTypes.HmdVR, XrSessionTypes.HmdAR].includes(model.xrSessionType);
342
- model.renderable.getInteractor().updateXRGamepads(xrSession, frame, model.xrReferenceSpace);
343
- model.xrSceneFrame = model.xrSession.requestAnimationFrame(publicAPI.xrRender);
344
- const xrPose = frame.getViewerPose(model.xrReferenceSpace);
345
- if (xrPose) {
346
- const gl = publicAPI.get3DContext();
347
- if (model.xrSessionType === XrSessionTypes.MobileAR && model.oldCanvasSize !== undefined) {
348
- gl.canvas.width = model.oldCanvasSize[0];
349
- gl.canvas.height = model.oldCanvasSize[1];
350
- }
351
- const glLayer = xrSession.renderState.baseLayer;
352
- gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
353
- gl.clear(gl.COLOR_BUFFER_BIT);
354
- gl.clear(gl.DEPTH_BUFFER_BIT);
355
- publicAPI.setSize(glLayer.framebufferWidth, glLayer.framebufferHeight);
356
-
357
- // get the first renderer
358
- const ren = model.renderable.getRenderers()[0];
359
-
360
- // Do a render pass for each eye
361
- xrPose.views.forEach((view, index) => {
362
- const viewport = glLayer.getViewport(view);
363
- if (isXrSessionHMD) {
364
- if (view.eye === 'left') {
365
- ren.setViewport(0, 0, 0.5, 1.0);
366
- } else if (view.eye === 'right') {
367
- ren.setViewport(0.5, 0, 1.0, 1.0);
368
- } else {
369
- // No handling for non-eye viewport
370
- return;
371
- }
372
- } else if (model.xrSessionType === XrSessionTypes.LookingGlassVR) {
373
- const startX = viewport.x / glLayer.framebufferWidth;
374
- const startY = viewport.y / glLayer.framebufferHeight;
375
- const endX = (viewport.x + viewport.width) / glLayer.framebufferWidth;
376
- const endY = (viewport.y + viewport.height) / glLayer.framebufferHeight;
377
- ren.setViewport(startX, startY, endX, endY);
378
- } else {
379
- ren.setViewport(0, 0, 1, 1);
380
- }
381
- ren.getActiveCamera().computeViewParametersFromPhysicalMatrix(view.transform.inverse.matrix);
382
- ren.getActiveCamera().setProjectionMatrix(view.projectionMatrix);
383
- publicAPI.traverseAllPasses();
384
- });
385
-
386
- // Reset scissorbox before any subsequent rendering to external displays
387
- // on frame end, such as rendering to a Looking Glass display.
388
- gl.scissor(0, 0, glLayer.framebufferWidth, glLayer.framebufferHeight);
389
- gl.disable(gl.SCISSOR_TEST);
390
- }
391
- };
392
220
  publicAPI.restoreContext = () => {
393
221
  const rp = vtkRenderPass.newInstance();
394
222
  rp.setCurrentOperation('Release');
@@ -855,9 +683,6 @@ const DEFAULT_VALUES = {
855
683
  defaultToWebgl2: true,
856
684
  // attempt webgl2 on by default
857
685
  activeFramebuffer: null,
858
- xrSession: null,
859
- xrReferenceSpace: null,
860
- xrSupported: true,
861
686
  imageFormat: 'image/png',
862
687
  useOffScreen: false,
863
688
  useBackgroundImage: false
@@ -906,7 +731,7 @@ function extend(publicAPI, model) {
906
731
  macro.event(publicAPI, model, 'imageReady');
907
732
 
908
733
  // Build VTK API
909
- macro.get(publicAPI, model, ['shaderCache', 'textureUnitManager', 'webgl2', 'vrDisplay', 'useBackgroundImage', 'xrSupported', 'activeFramebuffer']);
734
+ macro.get(publicAPI, model, ['shaderCache', 'textureUnitManager', 'webgl2', 'useBackgroundImage', 'activeFramebuffer']);
910
735
  macro.setGet(publicAPI, model, ['initialized', 'context', 'canvas', 'renderPasses', 'notifyStartCaptureImage', 'defaultToWebgl2', 'cursor', 'useOffScreen']);
911
736
  macro.setGetArray(publicAPI, model, ['size'], 2);
912
737
  macro.event(publicAPI, model, 'windowResizeEvent');
@@ -175,8 +175,8 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
175
175
 
176
176
  // if we have a ztexture then declare it and use it
177
177
  if (model.zBufferTexture !== null) {
178
- FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Dec', ['uniform sampler2D zBufferTexture;', 'uniform float vpWidth;', 'uniform float vpHeight;']).result;
179
- FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', ['vec4 depthVec = texture2D(zBufferTexture, vec2(gl_FragCoord.x / vpWidth, gl_FragCoord.y/vpHeight));', 'float zdepth = (depthVec.r*256.0 + depthVec.g)/257.0;', 'zdepth = zdepth * 2.0 - 1.0;', 'if (cameraParallel == 0) {', 'zdepth = -2.0 * camFar * camNear / (zdepth*(camFar-camNear)-(camFar+camNear)) - camNear;}', 'else {', 'zdepth = (zdepth + 1.0) * 0.5 * (camFar - camNear);}\n', 'zdepth = -zdepth/rayDir.z;', 'dists.y = min(zdepth,dists.y);']).result;
178
+ FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Dec', ['uniform sampler2D zBufferTexture;', 'uniform float vpZWidth;', 'uniform float vpZHeight;']).result;
179
+ FSSource = vtkShaderProgram.substitute(FSSource, '//VTK::ZBuffer::Impl', ['vec4 depthVec = texture2D(zBufferTexture, vec2(gl_FragCoord.x / vpZWidth, gl_FragCoord.y/vpZHeight));', 'float zdepth = (depthVec.r*256.0 + depthVec.g)/257.0;', 'zdepth = zdepth * 2.0 - 1.0;', 'if (cameraParallel == 0) {', 'zdepth = -2.0 * camFar * camNear / (zdepth*(camFar-camNear)-(camFar+camNear)) - camNear;}', 'else {', 'zdepth = (zdepth + 1.0) * 0.5 * (camFar - camNear);}\n', 'zdepth = -zdepth/rayDir.z;', 'dists.y = min(zdepth,dists.y);']).result;
180
180
  }
181
181
 
182
182
  // Set the BlendMode approach
@@ -362,8 +362,8 @@ function vtkOpenGLVolumeMapper(publicAPI, model) {
362
362
  if (model.zBufferTexture !== null) {
363
363
  program.setUniformi('zBufferTexture', model.zBufferTexture.getTextureUnit());
364
364
  const size = model._useSmallViewport ? [model._smallViewportWidth, model._smallViewportHeight] : model._openGLRenderWindow.getFramebufferSize();
365
- program.setUniformf('vpWidth', size[0]);
366
- program.setUniformf('vpHeight', size[1]);
365
+ program.setUniformf('vpZWidth', size[0]);
366
+ program.setUniformf('vpZHeight', size[1]);
367
367
  }
368
368
  };
369
369
  publicAPI.setCameraShaderParameters = (cellBO, ren, actor) => {
@@ -490,6 +490,17 @@ function vtkWebGPURenderWindow(publicAPI, model) {
490
490
  ret.setWebGPURenderWindow(publicAPI);
491
491
  return ret;
492
492
  };
493
+ const superSetSize = publicAPI.setSize;
494
+ publicAPI.setSize = (width, height) => {
495
+ const modified = superSetSize(width, height);
496
+ if (modified) {
497
+ publicAPI.invokeWindowResizeEvent({
498
+ width,
499
+ height
500
+ });
501
+ }
502
+ return modified;
503
+ };
493
504
  publicAPI.delete = macro.chain(publicAPI.delete, publicAPI.setViewStream);
494
505
  }
495
506
 
@@ -555,6 +566,7 @@ function extend(publicAPI, model) {
555
566
  macro.get(publicAPI, model, ['commandEncoder', 'device', 'presentationFormat', 'useBackgroundImage', 'xrSupported']);
556
567
  macro.setGet(publicAPI, model, ['initialized', 'context', 'canvas', 'device', 'renderPasses', 'notifyStartCaptureImage', 'cursor', 'useOffScreen']);
557
568
  macro.setGetArray(publicAPI, model, ['size'], 2);
569
+ macro.event(publicAPI, model, 'windowResizeEvent');
558
570
 
559
571
  // Object methods
560
572
  vtkWebGPURenderWindow(publicAPI, model);
@@ -1,7 +1,8 @@
1
1
  export declare enum XrSessionTypes {
2
2
  HmdVR = 0,
3
3
  MobileAR = 1,
4
- LookingGlassVR = 2
4
+ LookingGlassVR = 2,
5
+ HmdAR = 3
5
6
  }
6
7
 
7
8
  declare const _default: {
@@ -0,0 +1,90 @@
1
+ import { vtkObject } from './../../interfaces';
2
+ import { Nullable } from './../../types';
3
+ import vtkOpenGLRenderWindow from './../OpenGL/RenderWindow';
4
+
5
+ /**
6
+ *
7
+ */
8
+ export interface IWebXRRenderWindowHelperInitialValues {
9
+ initialized: boolean,
10
+ initCanvasSize?: [number, number],
11
+ initBackground?: [number, number, number, number],
12
+ renderWindow?: Nullable<vtkOpenGLRenderWindow>,
13
+ xrSession?: Nullable<XRSession>,
14
+ xrSessionType: number,
15
+ xrReferenceSpace?: any,
16
+ }
17
+
18
+ export interface vtkWebXRRenderWindowHelper extends vtkObject {
19
+
20
+ /**
21
+ * Initialize the instance.
22
+ */
23
+ initialize(): void;
24
+
25
+ /**
26
+ * Request an XR session on the user device with WebXR,
27
+ * typically in response to a user request such as a button press.
28
+ */
29
+ startXR(xrSessionType: Number): void;
30
+
31
+ /**
32
+ * When an XR session is available, set up the XRWebGLLayer
33
+ * and request the first animation frame for the device
34
+ */
35
+ enterXR(): void;
36
+
37
+ /**
38
+ * Adjust world-to-physical parameters for different viewing modalities
39
+ *
40
+ * @param {Number} inputRescaleFactor
41
+ * @param {Number} inputTranslateZ
42
+ */
43
+ resetXRScene(inputRescaleFactor: number, inputTranslateZ: number): void;
44
+
45
+ /**
46
+ * Request to stop the current XR session
47
+ */
48
+ stopXR(): void;
49
+
50
+ /**
51
+ * Get the underlying render window to drive XR rendering.
52
+ */
53
+ getRenderWindow(): Nullable<vtkOpenGLRenderWindow>;
54
+
55
+ /**
56
+ * Set the underlying render window to drive XR rendering.
57
+ */
58
+ setRenderWindow(renderWindow:Nullable<vtkOpenGLRenderWindow>);
59
+
60
+ /**
61
+ * Get the active WebXR session.
62
+ */
63
+ getXrSession(): Nullable<XRSession>;
64
+ }
65
+
66
+ /**
67
+ * Method used to decorate a given object (publicAPI+model) with vtkWebXRRenderWindowHelper characteristics.
68
+ *
69
+ * @param publicAPI object on which methods will be bounds (public)
70
+ * @param model object on which data structure will be bounds (protected)
71
+ * @param {IWebXRRenderWindowHelperInitialValues} [initialValues] (default: {})
72
+ */
73
+ export function extend(publicAPI: object, model: object, initialValues?: IWebXRRenderWindowHelperInitialValues): void;
74
+
75
+ /**
76
+ * Method used to create a new instance of vtkWebXRRenderWindowHelper.
77
+ * @param {IWebXRRenderWindowHelperInitialValues} [initialValues] for pre-setting some of its content
78
+ */
79
+ export function newInstance(initialValues?: IWebXRRenderWindowHelperInitialValues): vtkWebXRRenderWindowHelper;
80
+
81
+ /**
82
+ * WebXR rendering helper
83
+ *
84
+ * vtkWebXRRenderWindowHelper is designed to wrap a vtkRenderWindow for XR rendering.
85
+ */
86
+ export declare const vtkWebXRRenderWindowHelper: {
87
+ newInstance: typeof newInstance,
88
+ extend: typeof extend,
89
+ };
90
+ export default vtkWebXRRenderWindowHelper;
@@ -0,0 +1,242 @@
1
+ import { m as macro } from '../../macros2.js';
2
+ import Constants from './RenderWindowHelper/Constants.js';
3
+ import { GET_UNDERLYING_CONTEXT } from '../OpenGL/RenderWindow/ContextProxy.js';
4
+
5
+ const {
6
+ XrSessionTypes
7
+ } = Constants;
8
+ const DEFAULT_RESET_FACTORS = {
9
+ rescaleFactor: 0.25,
10
+ // isotropic scale factor reduces apparent size of objects
11
+ translateZ: -1.5 // default translation initializes object in front of camera
12
+ };
13
+
14
+ // ----------------------------------------------------------------------------
15
+ // vtkWebXRRenderWindowHelper methods
16
+ // ----------------------------------------------------------------------------
17
+
18
+ function vtkWebXRRenderWindowHelper(publicAPI, model) {
19
+ // Set our className
20
+ model.classHierarchy.push('vtkWebXRRenderWindowHelper');
21
+ publicAPI.initialize = renderWindow => {
22
+ if (!model.initialized) {
23
+ model.renderWindow = renderWindow;
24
+ model.initialized = true;
25
+ }
26
+ };
27
+ publicAPI.getXrSupported = () => navigator.xr !== undefined;
28
+
29
+ // Request an XR session on the user device with WebXR,
30
+ // typically in response to a user request such as a button press
31
+ publicAPI.startXR = xrSessionType => {
32
+ if (navigator.xr === undefined) {
33
+ throw new Error('WebXR is not available');
34
+ }
35
+ model.xrSessionType = xrSessionType !== undefined ? xrSessionType : XrSessionTypes.HmdVR;
36
+ const isXrSessionAR = [XrSessionTypes.HmdAR, XrSessionTypes.MobileAR].includes(model.xrSessionType);
37
+ const sessionType = isXrSessionAR ? 'immersive-ar' : 'immersive-vr';
38
+ if (!navigator.xr.isSessionSupported(sessionType)) {
39
+ if (isXrSessionAR) {
40
+ throw new Error('Device does not support AR session');
41
+ } else {
42
+ throw new Error('VR display is not available');
43
+ }
44
+ }
45
+ if (model.xrSession === null) {
46
+ navigator.xr.requestSession(sessionType).then(publicAPI.enterXR, () => {
47
+ throw new Error('Failed to create XR session!');
48
+ });
49
+ } else {
50
+ throw new Error('XR Session already exists!');
51
+ }
52
+ };
53
+
54
+ // When an XR session is available, set up the XRWebGLLayer
55
+ // and request the first animation frame for the device
56
+ publicAPI.enterXR = async xrSession => {
57
+ model.xrSession = xrSession;
58
+ model.initCanvasSize = model.renderWindow.getSize();
59
+ if (model.xrSession !== null) {
60
+ const gl = model.renderWindow.get3DContext();
61
+ await gl.makeXRCompatible();
62
+
63
+ // XRWebGLLayer definition is deferred to here to give any WebXR polyfill
64
+ // an opportunity to override this definition.
65
+ const {
66
+ XRWebGLLayer
67
+ } = window;
68
+ const glLayer = new XRWebGLLayer(model.xrSession,
69
+ // constructor needs unproxied context
70
+ gl[GET_UNDERLYING_CONTEXT]());
71
+ model.renderWindow.setSize(glLayer.framebufferWidth, glLayer.framebufferHeight);
72
+ model.xrSession.updateRenderState({
73
+ baseLayer: glLayer
74
+ });
75
+ model.xrSession.requestReferenceSpace('local').then(refSpace => {
76
+ model.xrReferenceSpace = refSpace;
77
+ });
78
+
79
+ // Initialize transparent background for augmented reality session
80
+ const isXrSessionAR = [XrSessionTypes.HmdAR, XrSessionTypes.MobileAR].includes(model.xrSessionType);
81
+ if (isXrSessionAR) {
82
+ const ren = model.renderWindow.getRenderable().getRenderers()[0];
83
+ model.initBackground = ren.getBackground();
84
+ ren.setBackground([0, 0, 0, 0]);
85
+ }
86
+ publicAPI.resetXRScene();
87
+ model.renderWindow.getRenderable().getInteractor().switchToXRAnimation();
88
+ model.xrSceneFrame = model.xrSession.requestAnimationFrame(model.xrRender);
89
+ publicAPI.modified();
90
+ } else {
91
+ throw new Error('Failed to enter XR with a null xrSession.');
92
+ }
93
+ };
94
+ publicAPI.resetXRScene = function () {
95
+ let rescaleFactor = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_RESET_FACTORS.rescaleFactor;
96
+ let translateZ = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_RESET_FACTORS.translateZ;
97
+ // Adjust world-to-physical parameters for different modalities
98
+
99
+ const ren = model.renderWindow.getRenderable().getRenderers()[0];
100
+ ren.resetCamera();
101
+ const camera = ren.getActiveCamera();
102
+ let physicalScale = camera.getPhysicalScale();
103
+ const physicalTranslation = camera.getPhysicalTranslation();
104
+ const rescaledTranslateZ = translateZ * physicalScale;
105
+ physicalScale /= rescaleFactor;
106
+ physicalTranslation[2] += rescaledTranslateZ;
107
+ camera.setPhysicalScale(physicalScale);
108
+ camera.setPhysicalTranslation(physicalTranslation);
109
+ // Clip at 0.1m, 100.0m in physical space by default
110
+ camera.setClippingRange(0.1 * physicalScale, 100.0 * physicalScale);
111
+ };
112
+ publicAPI.stopXR = async () => {
113
+ if (navigator.xr === undefined) {
114
+ // WebXR polyfill not available so nothing to do
115
+ return;
116
+ }
117
+ if (model.xrSession !== null) {
118
+ model.xrSession.cancelAnimationFrame(model.xrSceneFrame);
119
+ model.renderWindow.getRenderable().getInteractor().returnFromXRAnimation();
120
+ const gl = model.renderWindow.get3DContext();
121
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
122
+ await model.xrSession.end().catch(error => {
123
+ if (!(error instanceof DOMException)) {
124
+ throw error;
125
+ }
126
+ });
127
+ model.xrSession = null;
128
+ }
129
+ if (model.initCanvasSize !== null) {
130
+ model.renderWindow.setSize(...model.initCanvasSize);
131
+ }
132
+
133
+ // Reset to default canvas
134
+ const ren = model.renderWindow.getRenderable().getRenderers()[0];
135
+ if (model.initBackground != null) {
136
+ ren.setBackground(model.initBackground);
137
+ model.initBackground = null;
138
+ }
139
+ ren.getActiveCamera().setProjectionMatrix(null);
140
+ ren.resetCamera();
141
+ ren.setViewport(0.0, 0, 1.0, 1.0);
142
+ model.renderWindow.traverseAllPasses();
143
+ publicAPI.modified();
144
+ };
145
+ model.xrRender = async (t, frame) => {
146
+ const xrSession = frame.session;
147
+ const isXrSessionHMD = [XrSessionTypes.HmdVR, XrSessionTypes.HmdAR].includes(model.xrSessionType);
148
+ model.renderWindow.getRenderable().getInteractor().updateXRGamepads(xrSession, frame, model.xrReferenceSpace);
149
+ model.xrSceneFrame = model.xrSession.requestAnimationFrame(model.xrRender);
150
+ const xrPose = frame.getViewerPose(model.xrReferenceSpace);
151
+ if (xrPose) {
152
+ const gl = model.renderWindow.get3DContext();
153
+ if (model.xrSessionType === XrSessionTypes.MobileAR && model.initCanvasSize !== null) {
154
+ gl.canvas.width = model.initCanvasSize[0];
155
+ gl.canvas.height = model.initCanvasSize[1];
156
+ }
157
+ const glLayer = xrSession.renderState.baseLayer;
158
+ gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
159
+ gl.clear(gl.COLOR_BUFFER_BIT);
160
+ gl.clear(gl.DEPTH_BUFFER_BIT);
161
+ model.renderWindow.setSize(glLayer.framebufferWidth, glLayer.framebufferHeight);
162
+
163
+ // get the first renderer
164
+ const ren = model.renderWindow.getRenderable().getRenderers()[0];
165
+
166
+ // Do a render pass for each eye
167
+ xrPose.views.forEach((view, index) => {
168
+ const viewport = glLayer.getViewport(view);
169
+ if (isXrSessionHMD) {
170
+ if (view.eye === 'left') {
171
+ ren.setViewport(0, 0, 0.5, 1.0);
172
+ } else if (view.eye === 'right') {
173
+ ren.setViewport(0.5, 0, 1.0, 1.0);
174
+ } else {
175
+ // No handling for non-eye viewport
176
+ return;
177
+ }
178
+ } else if (model.xrSessionType === XrSessionTypes.LookingGlassVR) {
179
+ const startX = viewport.x / glLayer.framebufferWidth;
180
+ const startY = viewport.y / glLayer.framebufferHeight;
181
+ const endX = (viewport.x + viewport.width) / glLayer.framebufferWidth;
182
+ const endY = (viewport.y + viewport.height) / glLayer.framebufferHeight;
183
+ ren.setViewport(startX, startY, endX, endY);
184
+ } else {
185
+ ren.setViewport(0, 0, 1, 1);
186
+ }
187
+ ren.getActiveCamera().computeViewParametersFromPhysicalMatrix(view.transform.inverse.matrix);
188
+ ren.getActiveCamera().setProjectionMatrix(view.projectionMatrix);
189
+ model.renderWindow.traverseAllPasses();
190
+ });
191
+
192
+ // Reset scissorbox before any subsequent rendering to external displays
193
+ // on frame end, such as rendering to a Looking Glass display.
194
+ gl.scissor(0, 0, glLayer.framebufferWidth, glLayer.framebufferHeight);
195
+ gl.disable(gl.SCISSOR_TEST);
196
+ }
197
+ };
198
+ publicAPI.delete = macro.chain(publicAPI.delete);
199
+ }
200
+
201
+ // ----------------------------------------------------------------------------
202
+ // Object factory
203
+ // ----------------------------------------------------------------------------
204
+
205
+ const DEFAULT_VALUES = {
206
+ initialized: false,
207
+ initCanvasSize: null,
208
+ initBackground: null,
209
+ renderWindow: null,
210
+ xrSession: null,
211
+ xrSessionType: 0,
212
+ xrReferenceSpace: null
213
+ };
214
+
215
+ // ----------------------------------------------------------------------------
216
+
217
+ function extend(publicAPI, model) {
218
+ let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
219
+ Object.assign(model, DEFAULT_VALUES, initialValues);
220
+
221
+ // Build VTK API
222
+ macro.obj(publicAPI, model);
223
+ macro.event(publicAPI, model, 'event');
224
+ macro.get(publicAPI, model, ['xrSession']);
225
+ macro.setGet(publicAPI, model, ['renderWindow']);
226
+
227
+ // Object methods
228
+ vtkWebXRRenderWindowHelper(publicAPI, model);
229
+ }
230
+
231
+ // ----------------------------------------------------------------------------
232
+
233
+ const newInstance = macro.newInstance(extend, 'vtkWebXRRenderWindowHelper');
234
+
235
+ // ----------------------------------------------------------------------------
236
+
237
+ var index = {
238
+ newInstance,
239
+ extend
240
+ };
241
+
242
+ export { index as default, extend, newInstance };
@@ -99,16 +99,6 @@ export interface vtkWidgetManager extends vtkObject {
99
99
  */
100
100
  getPickingEnabled(): boolean;
101
101
 
102
- /**
103
- * @deprecated
104
- */
105
- getUseSvgLayer(): boolean;
106
-
107
- /**
108
- * @deprecated
109
- */
110
- setUseSvgLayer(use: boolean): boolean;
111
-
112
102
  /**
113
103
  * Enable the picking.
114
104
  */
@@ -165,16 +155,6 @@ export interface vtkWidgetManager extends vtkObject {
165
155
  */
166
156
  getSelectedDataForXY(x: number, y: number): Promise<ISelectedData>;
167
157
 
168
- /**
169
- * @deprecated
170
- */
171
- updateSelectionFromXY(x: number, y: number): void;
172
-
173
- /**
174
- * @deprecated
175
- */
176
- updateSelectionFromMouseEvent(event: MouseEvent): void;
177
-
178
158
  /**
179
159
  * The all currently selected data.
180
160
  */
@@ -197,10 +177,6 @@ export interface IWidgetManagerInitialValues {
197
177
  captureOn?: CaptureOn;
198
178
  viewType?: ViewTypes;
199
179
  pickingEnabled?: boolean;
200
- /**
201
- * @deprecated
202
- */
203
- useSvgLayer?: boolean;
204
180
  }
205
181
 
206
182
  /**
@@ -10,8 +10,7 @@ const {
10
10
  CaptureOn
11
11
  } = WidgetManagerConst;
12
12
  const {
13
- vtkErrorMacro,
14
- vtkWarningMacro
13
+ vtkErrorMacro
15
14
  } = macro;
16
15
  let viewIdCount = 1;
17
16
 
@@ -203,15 +202,16 @@ function vtkWidgetManager(publicAPI, model) {
203
202
  }
204
203
  async function captureBuffers(x1, y1, x2, y2) {
205
204
  if (model._captureInProgress) {
205
+ await model._captureInProgress;
206
206
  return;
207
207
  }
208
- model._captureInProgress = true;
209
208
  renderPickingBuffer();
210
209
  model._capturedBuffers = null;
211
- model._capturedBuffers = await model._selector.getSourceDataAsync(model._renderer, x1, y1, x2, y2);
210
+ model._captureInProgress = model._selector.getSourceDataAsync(model._renderer, x1, y1, x2, y2);
211
+ model._capturedBuffers = await model._captureInProgress;
212
+ model._captureInProgress = null;
212
213
  model.previousSelectedData = null;
213
214
  renderFrontBuffer();
214
- model._captureInProgress = false;
215
215
  }
216
216
  publicAPI.enablePicking = () => {
217
217
  model.pickingEnabled = true;
@@ -343,30 +343,6 @@ function vtkWidgetManager(publicAPI, model) {
343
343
  }
344
344
  return publicAPI.getSelectedData();
345
345
  };
346
- publicAPI.updateSelectionFromXY = (x, y) => {
347
- vtkWarningMacro('updateSelectionFromXY is deprecated, please use getSelectedDataForXY');
348
- if (model.pickingEnabled) {
349
- // Then pick regular representations.
350
- if (model.captureOn === CaptureOn.MOUSE_MOVE) {
351
- captureBuffers(x, y, x, y);
352
- }
353
- }
354
- };
355
- publicAPI.updateSelectionFromMouseEvent = event => {
356
- vtkWarningMacro('updateSelectionFromMouseEvent is deprecated, please use getSelectedDataForXY');
357
- const {
358
- pageX,
359
- pageY
360
- } = event;
361
- const {
362
- top,
363
- left,
364
- height
365
- } = model._apiSpecificRenderWindow.getCanvas().getBoundingClientRect();
366
- const x = pageX - left;
367
- const y = height - (pageY - top);
368
- publicAPI.updateSelectionFromXY(x, y);
369
- };
370
346
  publicAPI.getSelectedData = () => {
371
347
  if (!model.selections || !model.selections.length) {
372
348
  model.previousSelectedData = null;
@@ -1,5 +1,4 @@
1
1
  import vtkAngleWidget from './Widgets3D/AngleWidget.js';
2
- import vtkDistanceWidget from './Widgets3D/DistanceWidget.js';
3
2
  import vtkEllipseWidget from './Widgets3D/EllipseWidget.js';
4
3
  import vtkImageCroppingWidget from './Widgets3D/ImageCroppingWidget.js';
5
4
  import vtkImplicitPlaneWidget from './Widgets3D/ImplicitPlaneWidget.js';
@@ -16,7 +15,6 @@ import vtkSplineWidget from './Widgets3D/SplineWidget.js';
16
15
 
17
16
  var Widgets3D = {
18
17
  vtkAngleWidget,
19
- vtkDistanceWidget,
20
18
  vtkEllipseWidget,
21
19
  vtkImageCroppingWidget,
22
20
  vtkImplicitPlaneWidget,
package/index.d.ts CHANGED
@@ -205,11 +205,12 @@
205
205
  /// <reference path="./Rendering/Misc/TextureLODsDownloader.d.ts" />
206
206
  /// <reference path="./Rendering/OpenGL/HardwareSelector/Constants.d.ts" />
207
207
  /// <reference path="./Rendering/OpenGL/HardwareSelector.d.ts" />
208
- /// <reference path="./Rendering/OpenGL/RenderWindow/Constants.d.ts" />
209
208
  /// <reference path="./Rendering/OpenGL/RenderWindow.d.ts" />
210
209
  /// <reference path="./Rendering/SceneGraph/RenderPass.d.ts" />
211
210
  /// <reference path="./Rendering/SceneGraph/ViewNode.d.ts" />
212
211
  /// <reference path="./Rendering/SceneGraph/ViewNodeFactory.d.ts" />
212
+ /// <reference path="./Rendering/WebXR/RenderWindowHelper/Constants.d.ts" />
213
+ /// <reference path="./Rendering/WebXR/RenderWindowHelper.d.ts" />
213
214
  /// <reference path="./Widgets/Core/AbstractWidget.d.ts" />
214
215
  /// <reference path="./Widgets/Core/AbstractWidgetFactory.d.ts" />
215
216
  /// <reference path="./Widgets/Core/StateBuilder.d.ts" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "28.13.1",
3
+ "version": "29.0.0",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",
@@ -31,6 +31,7 @@
31
31
  "module": "./index.js",
32
32
  "dependencies": {
33
33
  "@babel/runtime": "7.22.11",
34
+ "@types/webxr": "^0.5.5",
34
35
  "commander": "9.2.0",
35
36
  "d3-scale": "4.0.2",
36
37
  "fast-deep-equal": "^3.1.3",
@@ -1,133 +0,0 @@
1
- import { m as macro } from '../../../macros2.js';
2
-
3
- const MAX_POINTS = 2;
4
- function widgetBehavior(publicAPI, model) {
5
- model.classHierarchy.push('vtkDistanceWidgetProp');
6
- model._isDragging = false;
7
-
8
- // --------------------------------------------------------------------------
9
- // Display 2D
10
- // --------------------------------------------------------------------------
11
-
12
- publicAPI.setDisplayCallback = callback => model.representations[0].setDisplayCallback(callback);
13
-
14
- // --------------------------------------------------------------------------
15
- // Interactor events
16
- // --------------------------------------------------------------------------
17
-
18
- function ignoreKey(e) {
19
- return e.altKey || e.controlKey || e.shiftKey;
20
- }
21
-
22
- // --------------------------------------------------------------------------
23
- // Left press: Select handle to drag
24
- // --------------------------------------------------------------------------
25
-
26
- publicAPI.handleLeftButtonPress = e => {
27
- if (!model.activeState || !model.activeState.getActive() || !model.pickable || ignoreKey(e)) {
28
- return macro.VOID;
29
- }
30
- const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
31
- if (model.activeState === model.widgetState.getMoveHandle() && model.widgetState.getHandleList().length < MAX_POINTS && manipulator) {
32
- const {
33
- worldCoords
34
- } = manipulator.handleEvent(e, model._apiSpecificRenderWindow);
35
- // Commit handle to location
36
- const moveHandle = model.widgetState.getMoveHandle();
37
- moveHandle.setOrigin(...worldCoords);
38
- const newHandle = model.widgetState.addHandle();
39
- newHandle.setOrigin(...moveHandle.getOrigin());
40
- newHandle.setColor(moveHandle.getColor());
41
- newHandle.setScale1(moveHandle.getScale1());
42
- newHandle.setManipulator(manipulator);
43
- } else if (model.dragable) {
44
- model._isDragging = true;
45
- model._apiSpecificRenderWindow.setCursor('grabbing');
46
- model._interactor.requestAnimation(publicAPI);
47
- }
48
- publicAPI.invokeStartInteractionEvent();
49
- return macro.EVENT_ABORT;
50
- };
51
-
52
- // --------------------------------------------------------------------------
53
- // Mouse move: Drag selected handle / Handle follow the mouse
54
- // --------------------------------------------------------------------------
55
-
56
- publicAPI.handleMouseMove = callData => {
57
- const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
58
- if (manipulator && model.pickable && model.dragable && model.activeState && model.activeState.getActive() && !ignoreKey(callData)) {
59
- const {
60
- worldCoords
61
- } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
62
- if (worldCoords.length && (model.activeState === model.widgetState.getMoveHandle() || model._isDragging) && model.activeState.setOrigin // e.g. the line is pickable but not draggable
63
- ) {
64
- model.activeState.setOrigin(worldCoords);
65
- publicAPI.invokeInteractionEvent();
66
- return macro.EVENT_ABORT;
67
- }
68
- }
69
- return macro.VOID;
70
- };
71
-
72
- // --------------------------------------------------------------------------
73
- // Left release: Finish drag / Create new handle
74
- // --------------------------------------------------------------------------
75
-
76
- publicAPI.handleLeftButtonRelease = () => {
77
- if (!model.activeState || !model.activeState.getActive() || !model.pickable) {
78
- return macro.VOID;
79
- }
80
- if (model.hasFocus && model.widgetState.getHandleList().length === MAX_POINTS) {
81
- publicAPI.loseFocus();
82
- return macro.VOID;
83
- }
84
- if (model._isDragging) {
85
- model._apiSpecificRenderWindow.setCursor('pointer');
86
- model.widgetState.deactivate();
87
- model._interactor.cancelAnimation(publicAPI);
88
- model._isDragging = false;
89
- } else if (model.activeState !== model.widgetState.getMoveHandle()) {
90
- model.widgetState.deactivate();
91
- }
92
- if (model.hasFocus && !model.activeState || model.activeState && !model.activeState.getActive()) {
93
- model._widgetManager.enablePicking();
94
- model._interactor.render();
95
- }
96
- publicAPI.invokeEndInteractionEvent();
97
- return macro.EVENT_ABORT;
98
- };
99
-
100
- // --------------------------------------------------------------------------
101
- // Focus API - modeHandle follow mouse when widget has focus
102
- // --------------------------------------------------------------------------
103
-
104
- publicAPI.grabFocus = () => {
105
- if (!model.hasFocus && model.widgetState.getHandleList().length < MAX_POINTS) {
106
- model.activeState = model.widgetState.getMoveHandle();
107
- model.activeState.activate();
108
- model.activeState.setVisible(true);
109
- model._interactor.requestAnimation(publicAPI);
110
- publicAPI.invokeStartInteractionEvent();
111
- }
112
- model.hasFocus = true;
113
- };
114
-
115
- // --------------------------------------------------------------------------
116
-
117
- publicAPI.loseFocus = () => {
118
- if (model.hasFocus) {
119
- model._interactor.cancelAnimation(publicAPI);
120
- publicAPI.invokeEndInteractionEvent();
121
- }
122
- model.widgetState.deactivate();
123
- model.widgetState.getMoveHandle().deactivate();
124
- model.widgetState.getMoveHandle().setVisible(false);
125
- model.widgetState.getMoveHandle().setOrigin(null);
126
- model.activeState = null;
127
- model.hasFocus = false;
128
- model._widgetManager.enablePicking();
129
- model._interactor.render();
130
- };
131
- }
132
-
133
- export { widgetBehavior as default };
@@ -1,22 +0,0 @@
1
- import vtkStateBuilder from '../../Core/StateBuilder.js';
2
-
3
- function generateState() {
4
- return vtkStateBuilder.createBuilder().addStateFromMixin({
5
- labels: ['moveHandle'],
6
- mixins: ['origin', 'color', 'scale1', 'visible', 'manipulator'],
7
- name: 'moveHandle',
8
- initialValues: {
9
- scale1: 30,
10
- visible: false
11
- }
12
- }).addDynamicMixinState({
13
- labels: ['handles'],
14
- mixins: ['origin', 'color', 'scale1', 'visible', 'manipulator'],
15
- name: 'handle',
16
- initialValues: {
17
- scale1: 30
18
- }
19
- }).build();
20
- }
21
-
22
- export { generateState as default };
@@ -1,109 +0,0 @@
1
- import { m as macro } from '../../macros2.js';
2
- import vtkAbstractWidgetFactory from '../Core/AbstractWidgetFactory.js';
3
- import vtkPlanePointManipulator from '../Manipulators/PlaneManipulator.js';
4
- import vtkPolyLineRepresentation from '../Representations/PolyLineRepresentation.js';
5
- import vtkSphereHandleRepresentation from '../Representations/SphereHandleRepresentation.js';
6
- import { e as distance2BetweenPoints } from '../../Common/Core/Math/index.js';
7
- import widgetBehavior from './DistanceWidget/behavior.js';
8
- import generateState from './DistanceWidget/state.js';
9
- import { ViewTypes } from '../Core/WidgetManager/Constants.js';
10
-
11
- // ----------------------------------------------------------------------------
12
- // Factory
13
- // ----------------------------------------------------------------------------
14
-
15
- function vtkDistanceWidget(publicAPI, model) {
16
- model.classHierarchy.push('vtkDistanceWidget');
17
- const superClass = {
18
- ...publicAPI
19
- };
20
-
21
- // --- Widget Requirement ---------------------------------------------------
22
-
23
- model.methodsToLink = ['activeScaleFactor', 'activeColor', 'useActiveColor', 'glyphResolution', 'defaultScale', 'scaleInPixels'];
24
- publicAPI.getRepresentationsForViewType = viewType => {
25
- switch (viewType) {
26
- case ViewTypes.DEFAULT:
27
- case ViewTypes.GEOMETRY:
28
- case ViewTypes.SLICE:
29
- case ViewTypes.VOLUME:
30
- default:
31
- return [{
32
- builder: vtkSphereHandleRepresentation,
33
- labels: ['handles']
34
- }, {
35
- builder: vtkSphereHandleRepresentation,
36
- labels: ['moveHandle']
37
- }, {
38
- builder: vtkPolyLineRepresentation,
39
- labels: ['handles', 'moveHandle']
40
- }];
41
- }
42
- };
43
-
44
- // --- Public methods -------------------------------------------------------
45
-
46
- publicAPI.getDistance = () => {
47
- const handles = model.widgetState.getHandleList();
48
- if (handles.length !== 2) {
49
- return 0;
50
- }
51
- if (!handles[0].getOrigin() || !handles[1].getOrigin()) {
52
- return 0;
53
- }
54
- return Math.sqrt(distance2BetweenPoints(handles[0].getOrigin(), handles[1].getOrigin()));
55
- };
56
- publicAPI.setManipulator = manipulator => {
57
- superClass.setManipulator(manipulator);
58
- model.widgetState.getMoveHandle().setManipulator(manipulator);
59
- model.widgetState.getHandleList().forEach(handle => {
60
- handle.setManipulator(manipulator);
61
- });
62
- };
63
-
64
- // --------------------------------------------------------------------------
65
- // initialization
66
- // --------------------------------------------------------------------------
67
-
68
- model.widgetState.onBoundsChange(bounds => {
69
- const center = [(bounds[0] + bounds[1]) * 0.5, (bounds[2] + bounds[3]) * 0.5, (bounds[4] + bounds[5]) * 0.5];
70
- model.widgetState.getMoveHandle().setOrigin(center);
71
- });
72
-
73
- // Default manipulator
74
- publicAPI.setManipulator(model.manipulator || vtkPlanePointManipulator.newInstance({
75
- useCameraNormal: true
76
- }));
77
- }
78
-
79
- // ----------------------------------------------------------------------------
80
-
81
- const defaultValues = initialValues => ({
82
- // manipulator: null,
83
- behavior: widgetBehavior,
84
- widgetState: generateState(),
85
- ...initialValues
86
- });
87
-
88
- // ----------------------------------------------------------------------------
89
-
90
- function extend(publicAPI, model) {
91
- let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
92
- Object.assign(model, defaultValues(initialValues));
93
- vtkAbstractWidgetFactory.extend(publicAPI, model, initialValues);
94
- macro.setGet(publicAPI, model, ['manipulator']);
95
- vtkDistanceWidget(publicAPI, model);
96
- }
97
-
98
- // ----------------------------------------------------------------------------
99
-
100
- const newInstance = macro.newInstance(extend, 'vtkDistanceWidget');
101
-
102
- // ----------------------------------------------------------------------------
103
-
104
- var vtkDistanceWidget$1 = {
105
- newInstance,
106
- extend
107
- };
108
-
109
- export { vtkDistanceWidget$1 as default, extend, newInstance };