@kitware/vtk.js 29.4.4 → 29.4.6

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.
@@ -93,7 +93,7 @@ export interface vtkRenderWindowInteractor extends vtkObject {
93
93
  *
94
94
  * @default null
95
95
  */
96
- getContainer(): HTMLElement;
96
+ getContainer(): Nullable<HTMLElement>;
97
97
 
98
98
  /**
99
99
  *
@@ -827,6 +827,13 @@ export interface vtkRenderWindowInteractor extends vtkObject {
827
827
  */
828
828
  rotateEvent(args: any): any;
829
829
 
830
+ /**
831
+ * Add an HTMLElement as the new container for the interactor.
832
+ * All events will be bound to this new container.
833
+ * Any old container will be removed along with its listeners.
834
+ */
835
+ setContainer(container: Nullable<HTMLElement>): boolean;
836
+
830
837
  /**
831
838
  * Turn on/off the automatic repositioning of lights as the camera moves.
832
839
  * @param lightFollowCamera
@@ -992,12 +999,15 @@ export interface vtkRenderWindowInteractor extends vtkObject {
992
999
 
993
1000
  /**
994
1001
  *
995
- * @param container
1002
+ * @param container kept for backward compatibility.
1003
+ * @deprecated please use vtkRenderWindowInteractor.setContainer(container: HTMLElement)
1004
+ * which will also bind events.
996
1005
  */
997
1006
  bindEvents(container: any): void;
998
1007
 
999
1008
  /**
1000
1009
  *
1010
+ * @deprecated please use vtkRenderWindowInteractor.setContainer(null) instead.
1001
1011
  */
1002
1012
  unbindEvents(): void;
1003
1013
 
@@ -51,6 +51,11 @@ function vtkRenderWindowInteractor(publicAPI, model) {
51
51
  // Set our className
52
52
  model.classHierarchy.push('vtkRenderWindowInteractor');
53
53
 
54
+ // Capture "parentClass" api for internal use
55
+ const superClass = {
56
+ ...publicAPI
57
+ };
58
+
54
59
  // Initialize list of requesters
55
60
  const animationRequesters = new Set();
56
61
 
@@ -161,8 +166,13 @@ function vtkRenderWindowInteractor(publicAPI, model) {
161
166
  function getDeviceTypeFor(event) {
162
167
  return event.pointerType || '';
163
168
  }
164
- publicAPI.bindEvents = container => {
165
- model.container = container;
169
+ const _bindEvents = () => {
170
+ if (model.container === null) {
171
+ return;
172
+ }
173
+ const {
174
+ container
175
+ } = model;
166
176
  container.addEventListener('contextmenu', preventDefault);
167
177
  container.addEventListener('wheel', publicAPI.handleWheel);
168
178
  container.addEventListener('DOMMouseScroll', publicAPI.handleWheel);
@@ -188,30 +198,53 @@ function vtkRenderWindowInteractor(publicAPI, model) {
188
198
  // disables tap highlight for when cursor is pointer
189
199
  container.style.webkitTapHighlightColor = 'rgba(0,0,0,0)';
190
200
  };
191
- publicAPI.unbindEvents = () => {
201
+
202
+ // For backward compatibility.
203
+ // Necessary for using unbind/bindEvent without calling setContainer.
204
+ publicAPI.bindEvents = container => {
205
+ if (container === null) {
206
+ return;
207
+ }
208
+ const res = superClass.setContainer(container);
209
+ if (res) {
210
+ _bindEvents();
211
+ }
212
+ };
213
+ const _unbindEvents = () => {
214
+ // Clear any previous timeouts and state variables that control mouse / touchpad behavior.
215
+ clearTimeout(model.moveTimeoutID);
216
+ clearTimeout(model.wheelTimeoutID);
217
+ model.moveTimeoutID = 0;
218
+ model.wheelTimeoutID = 0;
219
+ wheelCoefficient = 1.0;
192
220
  const {
193
221
  container
194
222
  } = model;
195
- container.removeEventListener('contextmenu', preventDefault);
196
- container.removeEventListener('wheel', publicAPI.handleWheel);
197
- container.removeEventListener('DOMMouseScroll', publicAPI.handleWheel);
198
- container.removeEventListener('pointerenter', publicAPI.handlePointerEnter);
199
- container.removeEventListener('pointerleave', publicAPI.handlePointerLeave);
200
- container.removeEventListener('pointermove', publicAPI.handlePointerMove, {
201
- passive: false
202
- });
203
- container.removeEventListener('pointerdown', publicAPI.handlePointerDown, {
204
- passive: false
205
- });
206
- container.removeEventListener('pointerup', publicAPI.handlePointerUp);
207
- container.removeEventListener('pointercancel', publicAPI.handlePointerCancel);
223
+ if (container) {
224
+ container.removeEventListener('contextmenu', preventDefault);
225
+ container.removeEventListener('wheel', publicAPI.handleWheel);
226
+ container.removeEventListener('DOMMouseScroll', publicAPI.handleWheel);
227
+ container.removeEventListener('pointerenter', publicAPI.handlePointerEnter);
228
+ container.removeEventListener('pointerleave', publicAPI.handlePointerLeave);
229
+ container.removeEventListener('pointermove', publicAPI.handlePointerMove, {
230
+ passive: false
231
+ });
232
+ container.removeEventListener('pointerdown', publicAPI.handlePointerDown, {
233
+ passive: false
234
+ });
235
+ container.removeEventListener('pointerup', publicAPI.handlePointerUp);
236
+ container.removeEventListener('pointercancel', publicAPI.handlePointerCancel);
237
+ }
208
238
  document.removeEventListener('keypress', publicAPI.handleKeyPress);
209
239
  document.removeEventListener('keydown', publicAPI.handleKeyDown);
210
240
  document.removeEventListener('keyup', publicAPI.handleKeyUp);
211
241
  document.removeEventListener('pointerlockchange', publicAPI.handlePointerLockChange);
212
- model.container = null;
213
242
  pointerCache.clear();
214
243
  };
244
+ publicAPI.unbindEvents = () => {
245
+ _unbindEvents();
246
+ superClass.setContainer(null);
247
+ };
215
248
  publicAPI.handleKeyPress = event => {
216
249
  const data = getKeysFor(event);
217
250
  publicAPI.keyPressEvent(data);
@@ -947,9 +980,16 @@ function vtkRenderWindowInteractor(publicAPI, model) {
947
980
  model._forcedRenderer = !!r;
948
981
  model.currentRenderer = r;
949
982
  };
983
+ publicAPI.setContainer = container => {
984
+ _unbindEvents();
985
+ const res = superClass.setContainer(container ?? null);
986
+ if (res) {
987
+ _bindEvents();
988
+ }
989
+ return res;
990
+ };
950
991
 
951
992
  // Stop animating if the renderWindowInteractor is deleted.
952
- const superDelete = publicAPI.delete;
953
993
  publicAPI.delete = () => {
954
994
  while (animationRequesters.size) {
955
995
  publicAPI.cancelAnimation(animationRequesters.values().next().value);
@@ -958,9 +998,9 @@ function vtkRenderWindowInteractor(publicAPI, model) {
958
998
  document.removeEventListener('visibilitychange', publicAPI.handleVisibilityChange);
959
999
  }
960
1000
  if (model.container) {
961
- publicAPI.unbindEvents();
1001
+ publicAPI.setContainer(null);
962
1002
  }
963
- superDelete();
1003
+ superClass.delete();
964
1004
  };
965
1005
 
966
1006
  // Use the Page Visibility API to detect when we switch away from or back to
@@ -1017,10 +1057,10 @@ function extend(publicAPI, model) {
1017
1057
  handledEvents.forEach(eventName => macro.event(publicAPI, model, eventName));
1018
1058
 
1019
1059
  // Create get-only macros
1020
- macro.get(publicAPI, model, ['initialized', 'container', 'interactorStyle', 'lastFrameTime', 'recentAnimationFrameRate', '_view']);
1060
+ macro.get(publicAPI, model, ['initialized', 'interactorStyle', 'lastFrameTime', 'recentAnimationFrameRate', '_view']);
1021
1061
 
1022
1062
  // Create get-set macros
1023
- macro.setGet(publicAPI, model, ['lightFollowCamera', 'enabled', 'enableRender', 'recognizeGestures', 'desiredUpdateRate', 'stillUpdateRate', 'picker', 'preventDefaultOnPointerDown', 'preventDefaultOnPointerUp', 'mouseScrollDebounceByPass']);
1063
+ macro.setGet(publicAPI, model, ['container', 'lightFollowCamera', 'enabled', 'enableRender', 'recognizeGestures', 'desiredUpdateRate', 'stillUpdateRate', 'picker', 'preventDefaultOnPointerDown', 'preventDefaultOnPointerUp', 'mouseScrollDebounceByPass']);
1024
1064
  macro.moveToProtected(publicAPI, model, ['view']);
1025
1065
 
1026
1066
  // For more macro methods, see "Sources/macros.js"
@@ -1,8 +1,14 @@
1
1
  import { m as macro } from '../../macros2.js';
2
- import { s as subtract, j as cross, d as dot, w as multiplyScalar, k as add } from '../../Common/Core/Math/index.js';
2
+ import { d as dot, s as subtract, j as cross, w as multiplyScalar, k as add } from '../../Common/Core/Math/index.js';
3
3
  import vtkAbstractManipulator from './AbstractManipulator.js';
4
+ import { EPSILON } from '../../Common/Core/Math/Constants.js';
4
5
 
5
6
  function projectDisplayToLine(x, y, lineOrigin, lineDirection, renderer, glRenderWindow) {
7
+ // if the active camera viewPlaneNormal and line direction are parallel, no change is allowed
8
+ const dotProduct = Math.abs(dot(renderer.getActiveCamera().getViewPlaneNormal(), lineDirection));
9
+ if (1 - dotProduct < EPSILON) {
10
+ return [];
11
+ }
6
12
  const near = glRenderWindow.displayToWorld(x, y, 0, renderer);
7
13
  const far = glRenderWindow.displayToWorld(x, y, 1, renderer);
8
14
  const viewDir = [0, 0, 0];
@@ -15,11 +15,13 @@ function vtkPickerManipulator(publicAPI, model) {
15
15
  pokedRenderer
16
16
  } = callData;
17
17
  model.picker.pick([position.x, position.y, 0.0], pokedRenderer);
18
- if (model.picker.getActors().length > 0) {
18
+ if (model.picker.getPickedPositions().length > 0) {
19
19
  model.position = model.picker.getPickedPositions()[0];
20
+ } else {
21
+ model.position = null;
20
22
  }
21
23
  return {
22
- worldCoords: model.position || null
24
+ worldCoords: model.position
23
25
  };
24
26
  };
25
27
  }
@@ -3,8 +3,17 @@ import { vec3 } from 'gl-matrix';
3
3
 
4
4
  function widgetBehavior(publicAPI, model) {
5
5
  model.painting = model._factory.getPainting();
6
- publicAPI.handleLeftButtonPress = () => {
7
- if (!model.activeState || !model.activeState.getActive()) {
6
+ publicAPI.handleLeftButtonPress = callData => {
7
+ const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
8
+ if (!(manipulator && model.activeState && model.activeState.getActive())) {
9
+ model.painting = false;
10
+ return macro.VOID;
11
+ }
12
+ const {
13
+ worldCoords
14
+ } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
15
+ if (!worldCoords?.length) {
16
+ model.painting = false;
8
17
  return macro.VOID;
9
18
  }
10
19
  model.painting = true;
@@ -20,11 +29,12 @@ function widgetBehavior(publicAPI, model) {
20
29
  model.widgetState.clearTrailList();
21
30
  }
22
31
  model.painting = false;
23
- return model.hasFocus ? macro.EVENT_ABORT : macro.VOID;
32
+ return macro.VOID;
24
33
  };
25
34
  publicAPI.handleEvent = callData => {
26
35
  const manipulator = model.activeState?.getManipulator?.() ?? model.manipulator;
27
36
  if (!(manipulator && model.activeState && model.activeState.getActive())) {
37
+ model.painting = false;
28
38
  return macro.VOID;
29
39
  }
30
40
  const normal = model._camera.getDirectionOfProjection();
@@ -37,7 +47,7 @@ function widgetBehavior(publicAPI, model) {
37
47
  const {
38
48
  worldCoords
39
49
  } = manipulator.handleEvent(callData, model._apiSpecificRenderWindow);
40
- if (!worldCoords.length) {
50
+ if (!worldCoords?.length) {
41
51
  return macro.VOID;
42
52
  }
43
53
  model.widgetState.setTrueOrigin(...worldCoords);
@@ -45,6 +55,8 @@ function widgetBehavior(publicAPI, model) {
45
55
  if (model.painting) {
46
56
  const trailCircle = model.widgetState.addTrail();
47
57
  trailCircle.set(model.activeState.get('origin', 'up', 'right', 'direction', 'scale1'));
58
+ } else {
59
+ return macro.VOID;
48
60
  }
49
61
  publicAPI.invokeInteractionEvent();
50
62
  return macro.EVENT_ABORT;
@@ -30,13 +30,13 @@ function widgetBehavior(publicAPI, model) {
30
30
  }
31
31
  const worldCoords = currentWorldCoords(e);
32
32
  if (model.activeState === moveHandle) {
33
- if (!moveHandle.getOrigin()) {
33
+ if (!moveHandle.getOrigin() && worldCoords) {
34
34
  moveHandle.setOrigin(worldCoords);
35
+ model.previousPosition = [...worldCoords];
35
36
  }
36
37
  }
37
38
  model._isDragging = true;
38
39
  model._apiSpecificRenderWindow.setCursor('grabbing');
39
- model.previousPosition = [...currentWorldCoords(e)];
40
40
  publicAPI.invokeStartInteractionEvent();
41
41
  return macro.EVENT_ABORT;
42
42
  };
@@ -63,8 +63,10 @@ function widgetBehavior(publicAPI, model) {
63
63
  }
64
64
  if (!model.activeState) throw Error('no activestate');
65
65
  const worldCoords = currentWorldCoords(e);
66
- model.activeState.setOrigin(worldCoords);
67
- model.previousPosition = worldCoords;
66
+ if (worldCoords) {
67
+ model.activeState.setOrigin(worldCoords);
68
+ model.previousPosition = worldCoords;
69
+ }
68
70
  return macro.VOID;
69
71
  };
70
72
  publicAPI.grabFocus = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitware/vtk.js",
3
- "version": "29.4.4",
3
+ "version": "29.4.6",
4
4
  "description": "Visualization Toolkit for the Web",
5
5
  "keywords": [
6
6
  "3d",