@vertexvis/viewer 0.10.2-canary.7 → 0.11.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 (139) hide show
  1. package/dist/cjs/{browser.esm-ae55f058.js → browser.esm-17419694.js} +25 -25
  2. package/dist/cjs/{bundle.esm-c457ad4d.js → bundle.esm-b79513ef.js} +231 -207
  3. package/dist/cjs/{constants-4277684a.js → constants-1d65ed39.js} +1 -1
  4. package/dist/cjs/{cursors-b93b43ef.js → cursors-8aaf500f.js} +1 -1
  5. package/dist/cjs/{dom-cdb50ebc.js → dom-40804039.js} +1 -1
  6. package/dist/cjs/index.cjs.js +8 -7
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/cjs/{markup-3dac4cef.js → markup-e84a143f.js} +11 -2
  9. package/dist/cjs/{measurement-b494bf55.js → measurement-4579193b.js} +2 -2
  10. package/dist/cjs/{orientation-42cc9e8d.js → orientation-09d0f3ef.js} +14 -7
  11. package/dist/cjs/{png-decoder-2add73dd.js → png-decoder-97ea96ba.js} +3 -3
  12. package/dist/cjs/{scene-23a0a330.js → scene-4397373a.js} +28524 -2446
  13. package/dist/cjs/{utils-6933381f.js → utils-414e6cfe.js} +2 -2
  14. package/dist/cjs/utils-440f0f7d.js +61 -0
  15. package/dist/cjs/vertex-scene-tree.cjs.entry.js +6 -5
  16. package/dist/cjs/vertex-viewer-dom-element_3.cjs.entry.js +4 -4
  17. package/dist/cjs/{vertex-viewer-markup-arrow_2.cjs.entry.js → vertex-viewer-markup-arrow_3.cjs.entry.js} +267 -4
  18. package/dist/cjs/vertex-viewer-markup-tool.cjs.entry.js +43 -9
  19. package/dist/cjs/vertex-viewer-markup.cjs.entry.js +25 -5
  20. package/dist/cjs/vertex-viewer-measurement-distance_2.cjs.entry.js +8 -8
  21. package/dist/cjs/vertex-viewer-measurement-tool.cjs.entry.js +5 -5
  22. package/dist/cjs/vertex-viewer-measurements.cjs.entry.js +5 -5
  23. package/dist/cjs/vertex-viewer-view-cube.cjs.entry.js +3 -3
  24. package/dist/cjs/vertex-viewer.cjs.entry.js +141 -48
  25. package/dist/cjs/viewer.cjs.js +1 -1
  26. package/dist/cjs/{viewport-e69f8223.js → viewport-fc405a48.js} +31 -7
  27. package/dist/collection/collection-manifest.json +1 -0
  28. package/dist/collection/components/scene-tree/scene-tree.js +3 -2
  29. package/dist/collection/components/viewer/viewer.js +28 -3
  30. package/dist/collection/components/viewer-markup/utils.js +65 -1
  31. package/dist/collection/components/viewer-markup/viewer-markup.js +72 -16
  32. package/dist/collection/components/viewer-markup-circle/utils.js +2 -55
  33. package/dist/collection/components/viewer-markup-circle/viewer-markup-circle.js +4 -4
  34. package/dist/collection/components/viewer-markup-freeform.tsx/utils.js +10 -0
  35. package/dist/collection/components/viewer-markup-freeform.tsx/viewer-markup-freeform.css +157 -0
  36. package/dist/collection/components/viewer-markup-freeform.tsx/viewer-markup-freeform.js +413 -0
  37. package/dist/collection/components/viewer-markup-tool/viewer-markup-tool.js +63 -9
  38. package/dist/collection/components/viewer-measurement-distance/viewer-measurement-distance-components.js +1 -1
  39. package/dist/collection/components/viewer-measurement-distance/viewer-measurement-distance.js +2 -2
  40. package/dist/collection/lib/cursors.js +1 -1
  41. package/dist/collection/lib/interactions/baseInteractionHandler.js +5 -4
  42. package/dist/collection/lib/interactions/flyToPartKeyInteraction.js +1 -1
  43. package/dist/collection/lib/interactions/interactionApi.js +101 -22
  44. package/dist/collection/lib/interactions/mouseInteractions.js +17 -15
  45. package/dist/collection/lib/interactions/multiTouchInteractionHandler.js +2 -2
  46. package/dist/collection/lib/mappers.js +4 -3
  47. package/dist/collection/lib/scenes/camera.js +8 -2
  48. package/dist/collection/lib/scenes/operations.js +1 -1
  49. package/dist/collection/lib/scenes/scene.js +5 -2
  50. package/dist/collection/lib/types/frame.js +8 -2
  51. package/dist/collection/lib/types/markup.js +9 -1
  52. package/dist/collection/lib/types/stencilBuffer.js +2 -2
  53. package/dist/collection/lib/types/viewport.js +32 -8
  54. package/dist/collection/testing/fixtures.js +2 -1
  55. package/dist/esm/{browser.esm-7dbdf78a.js → browser.esm-e4fb17dc.js} +25 -25
  56. package/dist/esm/{bundle.esm-590d2273.js → bundle.esm-d891316f.js} +232 -208
  57. package/dist/esm/{constants-083f6b2c.js → constants-037e417f.js} +1 -1
  58. package/dist/esm/{cursors-39294365.js → cursors-00835249.js} +1 -1
  59. package/dist/esm/{dom-43682375.js → dom-d0877f90.js} +1 -1
  60. package/dist/esm/index.js +7 -7
  61. package/dist/esm/index.mjs +7 -7
  62. package/dist/esm/loader.js +1 -1
  63. package/dist/esm/loader.mjs +1 -1
  64. package/dist/esm/{markup-3ce3dccd.js → markup-9b29aa94.js} +11 -3
  65. package/dist/esm/{measurement-78bd27fc.js → measurement-8430d5d6.js} +2 -2
  66. package/dist/esm/{orientation-c3e2af18.js → orientation-bb34b652.js} +14 -7
  67. package/dist/esm/{png-decoder-dfb97536.js → png-decoder-c4745070.js} +3 -3
  68. package/dist/esm/{scene-30ac6229.js → scene-72760305.js} +28532 -2454
  69. package/dist/esm/utils-5fe43b8a.js +52 -0
  70. package/dist/esm/{utils-b857bd7c.js → utils-f8e0baf7.js} +2 -2
  71. package/dist/esm/vertex-scene-tree.entry.js +6 -5
  72. package/dist/esm/vertex-viewer-dom-element_3.entry.js +4 -4
  73. package/dist/esm/{vertex-viewer-markup-arrow_2.entry.js → vertex-viewer-markup-arrow_3.entry.js} +267 -5
  74. package/dist/esm/vertex-viewer-markup-tool.entry.js +43 -9
  75. package/dist/esm/vertex-viewer-markup.entry.js +25 -5
  76. package/dist/esm/vertex-viewer-measurement-distance_2.entry.js +8 -8
  77. package/dist/esm/vertex-viewer-measurement-tool.entry.js +5 -5
  78. package/dist/esm/vertex-viewer-measurements.entry.js +5 -5
  79. package/dist/esm/vertex-viewer-view-cube.entry.js +3 -3
  80. package/dist/esm/vertex-viewer.entry.js +141 -48
  81. package/dist/esm/viewer.js +1 -1
  82. package/dist/esm/{viewport-8fea0743.js → viewport-d6f5cd7b.js} +31 -7
  83. package/dist/types/components/viewer/viewer.d.ts +4 -0
  84. package/dist/types/components/viewer-markup/utils.d.ts +8 -0
  85. package/dist/types/components/viewer-markup/viewer-markup.d.ts +13 -6
  86. package/dist/types/components/viewer-markup-circle/utils.d.ts +1 -4
  87. package/dist/types/components/viewer-markup-freeform.tsx/utils.d.ts +3 -0
  88. package/dist/types/components/viewer-markup-freeform.tsx/viewer-markup-freeform.d.ts +116 -0
  89. package/dist/types/components/viewer-markup-tool/viewer-markup-tool.d.ts +13 -1
  90. package/dist/types/components.d.ts +107 -10
  91. package/dist/types/lib/interactions/interactionApi.d.ts +22 -6
  92. package/dist/types/lib/interactions/mouseInteractions.d.ts +7 -6
  93. package/dist/types/lib/scenes/camera.d.ts +5 -1
  94. package/dist/types/lib/scenes/scene.d.ts +1 -1
  95. package/dist/types/lib/types/frame.d.ts +4 -1
  96. package/dist/types/lib/types/markup.d.ts +12 -1
  97. package/dist/types/lib/types/viewport.d.ts +17 -0
  98. package/dist/viewer/index.esm.js +1 -1
  99. package/dist/viewer/p-012fb54f.js +4 -0
  100. package/dist/viewer/{p-3dc15d99.entry.js → p-117324c0.entry.js} +1 -1
  101. package/dist/viewer/{p-1ee75110.entry.js → p-1c772ec1.entry.js} +1 -1
  102. package/dist/viewer/p-1f8a238b.js +4 -0
  103. package/dist/viewer/p-21e8510d.js +4 -0
  104. package/dist/viewer/{p-e3105f9a.entry.js → p-3c2aff67.entry.js} +1 -1
  105. package/dist/viewer/p-5389e9d4.js +4 -0
  106. package/dist/viewer/p-59d075d4.js +17 -0
  107. package/dist/viewer/{p-5b078339.js → p-62c6f482.js} +1 -1
  108. package/dist/viewer/p-640cb5f8.js +18 -0
  109. package/dist/viewer/p-68aaf1f8.entry.js +4 -0
  110. package/dist/viewer/{p-05b2444e.js → p-75682963.js} +1 -1
  111. package/dist/viewer/{p-4183c421.entry.js → p-79c45c02.entry.js} +1 -1
  112. package/dist/viewer/p-835e158e.js +4 -0
  113. package/dist/viewer/p-8c255868.entry.js +4 -0
  114. package/dist/viewer/{p-f4a492e1.js → p-9faabd97.js} +1 -1
  115. package/dist/viewer/p-b122ee39.js +4 -0
  116. package/dist/viewer/p-b36b3d1a.js +4 -0
  117. package/dist/viewer/{p-7c71db57.entry.js → p-bc9e6919.entry.js} +1 -1
  118. package/dist/viewer/{p-f090a3f3.entry.js → p-c818c80e.entry.js} +1 -1
  119. package/dist/viewer/{p-e96bc9a2.js → p-d42a482c.js} +1 -1
  120. package/dist/viewer/p-f43e8cc2.entry.js +4 -0
  121. package/dist/viewer/p-f75436be.entry.js +4 -0
  122. package/dist/viewer/viewer.esm.js +1 -1
  123. package/package.json +18 -16
  124. package/readme.md +6 -6
  125. package/dist/cjs/utils-96f244e1.js +0 -104
  126. package/dist/esm/utils-a550c58f.js +0 -96
  127. package/dist/viewer/p-11bdd2c4.js +0 -4
  128. package/dist/viewer/p-14182324.entry.js +0 -4
  129. package/dist/viewer/p-2768474e.js +0 -4
  130. package/dist/viewer/p-2e11803d.js +0 -4
  131. package/dist/viewer/p-6d4ab5fc.js +0 -17
  132. package/dist/viewer/p-964642c6.js +0 -4
  133. package/dist/viewer/p-9e856d0a.entry.js +0 -4
  134. package/dist/viewer/p-a717d9ff.js +0 -4
  135. package/dist/viewer/p-a9434d8e.entry.js +0 -4
  136. package/dist/viewer/p-af806858.js +0 -4
  137. package/dist/viewer/p-b5c350a7.js +0 -4
  138. package/dist/viewer/p-d912dd24.js +0 -18
  139. package/dist/viewer/p-f6d75616.entry.js +0 -4
@@ -2,15 +2,15 @@
2
2
  * Copyright (c) 2021 Vertex Software LLC. All rights reserved.
3
3
  */
4
4
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-8d7400a7.js';
5
- import { a as getElementBackgroundColor, g as getElementBoundingClientRect, p as parseConfig } from './utils-b857bd7c.js';
6
- import { v as vector3, i as angle, p as point, e as boundingBox, h as plane, r as ray, l as matrix2, f as dimensions } from './bundle.esm-590d2273.js';
5
+ import { a as getElementBackgroundColor, g as getElementBoundingClientRect, p as parseConfig } from './utils-f8e0baf7.js';
6
+ import { v as vector3, k as angle, p as point, h as plane, r as ray, e as boundingBox, l as matrix2, f as dimensions } from './bundle.esm-d891316f.js';
7
7
  import { c as classnames } from './index-455380d0.js';
8
- import { u as uri, E as EventDispatcher, o as objects, b as async } from './browser.esm-7dbdf78a.js';
9
- import { I as InvalidCredentialsError, t as toProtoDuration, b as ImageLoadError, p as protoToDate, d as StreamApi, W as WebSocketClientImpl, v as vertexvis, e as defaultSelectionMaterial, f as fromUrn, V as ViewerInitializationError, C as CustomError, g as WebsocketConnectionError, h as currentDateAsProtoTimestamp, a as SynchronizedClock, i as InteractionHandlerError, j as ComponentInitializationError, k as IllegalStateError, m as fromHex, S as Scene } from './scene-30ac6229.js';
10
- import { S as StencilBufferManager, m as mapWorldOrientationOrThrow, d as mapFrameOrThrow } from './orientation-c3e2af18.js';
11
- import { V as Viewport } from './viewport-8fea0743.js';
12
- import { g as getMouseClientPosition, c as cssCursor } from './dom-43682375.js';
13
- import { C as CursorManager } from './cursors-39294365.js';
8
+ import { u as uri, E as EventDispatcher, o as objects, b as async } from './browser.esm-e4fb17dc.js';
9
+ import { I as InvalidCredentialsError, t as toProtoDuration, b as ImageLoadError, p as protoToDate, d as StreamApi, W as WebSocketClientImpl, v as vertexvis, e as defaultSelectionMaterial, f as fromUrn, V as ViewerInitializationError, C as CustomError, g as WebsocketConnectionError, h as currentDateAsProtoTimestamp, a as SynchronizedClock, i as InteractionHandlerError, j as ComponentInitializationError, k as IllegalStateError, m as fromHex, S as Scene } from './scene-72760305.js';
10
+ import { S as StencilBufferManager, m as mapWorldOrientationOrThrow, d as mapFrameOrThrow } from './orientation-bb34b652.js';
11
+ import { V as Viewport } from './viewport-d6f5cd7b.js';
12
+ import { g as getMouseClientPosition, c as cssCursor } from './dom-d0877f90.js';
13
+ import { C as CursorManager } from './cursors-00835249.js';
14
14
  import './_commonjsHelpers-9943807e.js';
15
15
 
16
16
  function isPromise(obj) {
@@ -659,13 +659,18 @@ class InteractionApi {
659
659
  var _a;
660
660
  if (this.isInteracting()) {
661
661
  const scene = this.getScene();
662
+ const viewport = this.getViewport();
663
+ const frame = this.getFrame();
664
+ const depthBuffer = await (frame === null || frame === void 0 ? void 0 : frame.depthBuffer());
662
665
  this.currentCamera =
663
- this.currentCamera != null
666
+ this.currentCamera != null && viewport != null && frame != null
664
667
  ? t({
665
668
  camera: this.currentCamera,
666
- viewport: scene.viewport(),
669
+ viewport,
667
670
  scale: scene.scale(),
668
671
  boundingBox: scene.boundingBox(),
672
+ frame,
673
+ depthBuffer,
669
674
  })
670
675
  : undefined;
671
676
  await ((_a = this.currentCamera) === null || _a === void 0 ? void 0 : _a.render());
@@ -690,6 +695,52 @@ class InteractionApi {
690
695
  return camera;
691
696
  });
692
697
  }
698
+ /**
699
+ * Moves the camera's position and look at to the given screen coordinate.
700
+ *
701
+ * If the screen coordinate intersects with an object, the camera will track
702
+ * the hit point so the mouse position is always under the mouse.
703
+ *
704
+ * If the screen coordinate doesn't intersect with an object, then ???.
705
+ *
706
+ * @param screenPt A point in screen coordinates.
707
+ */
708
+ async panCameraToScreenPoint(screenPt) {
709
+ return this.transformCamera(({ camera, frame, viewport, depthBuffer }) => {
710
+ // Capture the starting state of the pan.
711
+ if (this.panData == null) {
712
+ const startingCamera = camera.toFrameCamera();
713
+ const direction = startingCamera.direction;
714
+ const ray$1 = viewport.transformPointToRay(screenPt, frame.image, startingCamera);
715
+ const fallbackPlane = plane.fromNormalAndCoplanarPoint(direction, camera.lookAt);
716
+ const fallback = ray.intersectPlane(ray$1, fallbackPlane);
717
+ if (fallback == null) {
718
+ console.warn('Cannot determine fallback for pan. Ray does not intersect plane.');
719
+ return camera;
720
+ }
721
+ // Create a plane for the hit point that will be used to determine the
722
+ // delta of future mouse movements to the original hit point. Fallback
723
+ // to a plane placed at the look at point, in case there's no hit.
724
+ const hitPt = depthBuffer != null
725
+ ? this.getWorldPoint(screenPt, depthBuffer, fallback)
726
+ : fallback;
727
+ const hitPlane = plane.fromNormalAndCoplanarPoint(direction, hitPt);
728
+ this.panData = { hitPt, hitPlane, startingCamera };
729
+ }
730
+ if (this.panData != null) {
731
+ const { hitPt, hitPlane, startingCamera } = this.panData;
732
+ // Use a ray that originates at the screen and intersects with the hit
733
+ // plane to determine the move distance.
734
+ const ray$1 = viewport.transformPointToRay(screenPt, frame.image, startingCamera);
735
+ const movePt = ray.intersectPlane(ray$1, hitPlane);
736
+ if (movePt != null) {
737
+ const delta = vector3.subtract(hitPt, movePt);
738
+ return camera.update(startingCamera).moveBy(delta);
739
+ }
740
+ }
741
+ return camera;
742
+ });
743
+ }
693
744
  /**
694
745
  * Performs a pan operation of the scene's camera, and requests a new image
695
746
  * for the updated scene.
@@ -697,7 +748,7 @@ class InteractionApi {
697
748
  * @param delta A position delta `{x, y}` in the 2D coordinate space of the
698
749
  * viewer.
699
750
  */
700
- async panCamera(delta) {
751
+ async panCameraByDelta(delta) {
701
752
  return this.transformCamera(({ camera, viewport }) => {
702
753
  const vv = camera.viewVector();
703
754
  const u = vector3.normalize(camera.up);
@@ -737,14 +788,12 @@ class InteractionApi {
737
788
  });
738
789
  }
739
790
  async rotateCameraAtPoint(delta, point) {
740
- const frame = this.getFrame();
741
- const depthBuffer = await (frame === null || frame === void 0 ? void 0 : frame.depthBuffer());
742
- return this.transformCamera(({ camera, viewport, boundingBox: boundingBox$1 }) => {
791
+ return this.transformCamera(({ camera, viewport, boundingBox: boundingBox$1, depthBuffer }) => {
743
792
  if (this.worldRotationPoint == null) {
744
793
  const worldCenter = boundingBox.center(boundingBox$1);
745
794
  this.worldRotationPoint =
746
795
  depthBuffer != null
747
- ? this.getWorldRotationPoint(point, depthBuffer, worldCenter)
796
+ ? this.getWorldPoint(point, depthBuffer, worldCenter)
748
797
  : camera.lookAt;
749
798
  }
750
799
  const upVector = vector3.normalize(camera.up);
@@ -762,8 +811,8 @@ class InteractionApi {
762
811
  const angle = Math.abs(epsilonX) + Math.abs(epsilonY);
763
812
  const updated = camera.rotateAroundAxisAtPoint(angle, this.worldRotationPoint, rotationAxis);
764
813
  return updated.update({
765
- // Scale the lookAt point to the same length as the distance to the center
766
- // of the bounding box to maintain zoom and pan behavior.
814
+ // Scale the lookAt point to the same length as the distance to the
815
+ // center of the bounding box to maintain zoom and pan behavior.
767
816
  lookAt: vector3.add(vector3.scale(camera.distanceToBoundingBoxCenter() /
768
817
  vector3.magnitude(updated.viewVector()), updated.viewVector()), updated.position),
769
818
  });
@@ -776,21 +825,49 @@ class InteractionApi {
776
825
  * @param delta The distance to zoom. Positive values zoom in and negative
777
826
  * values zoom out.
778
827
  */
779
- async zoomCamera(delta, ray$1) {
828
+ async zoomCamera(delta) {
780
829
  return this.transformCamera(({ camera, viewport }) => {
781
830
  const vv = camera.viewVector();
782
831
  const v = vector3.normalize(vv);
783
- const vvPlane = plane.create({
784
- normal: v,
785
- });
786
- const pt = ray$1 != null ? ray.intersectPlane(ray$1, vvPlane) : undefined;
787
- const zv = pt != null ? vector3.subtract(pt, camera.position) : vv;
788
- const direction = vector3.normalize(zv);
789
- const distance = vector3.magnitude(zv);
832
+ const distance = vector3.magnitude(vv);
790
833
  const epsilon = (3 * distance * delta) / viewport.height;
791
- const position = vector3.add(camera.position, vector3.scale(epsilon, direction));
792
- const lookAt = plane.projectPoint(vvPlane, position);
793
- return camera.update({ position, lookAt });
834
+ const position = vector3.add(camera.position, vector3.scale(epsilon, v));
835
+ const newCamera = camera.update({ position });
836
+ return newCamera;
837
+ });
838
+ }
839
+ async zoomCameraToPoint(point, delta) {
840
+ return this.transformCamera(({ camera, viewport, frame, depthBuffer }) => {
841
+ const cam = frame.scene.camera;
842
+ const dir = cam.direction;
843
+ const frameCam = camera.toFrameCamera();
844
+ const ray$1 = viewport.transformPointToRay(point, frame.image, frameCam);
845
+ if (this.zoomData == null) {
846
+ const fallbackPlane = plane.fromNormalAndCoplanarPoint(dir, cam.lookAt);
847
+ const fallbackPt = ray.intersectPlane(ray$1, fallbackPlane);
848
+ if (fallbackPt == null) {
849
+ console.warn('Cannot determine fallback point for zoom. Ray does not intersect plane.');
850
+ return camera;
851
+ }
852
+ const hitPt = depthBuffer != null
853
+ ? this.getWorldPoint(point, depthBuffer, fallbackPt)
854
+ : fallbackPt;
855
+ const hitPlane = plane.fromNormalAndCoplanarPoint(dir, hitPt);
856
+ this.zoomData = { hitPt, hitPlane };
857
+ }
858
+ if (this.zoomData != null) {
859
+ const { hitPt, hitPlane } = this.zoomData;
860
+ const distance = vector3.distance(camera.position, hitPt);
861
+ const epsilon = (6 * distance * delta) / viewport.height;
862
+ const position = ray.at(ray$1, epsilon);
863
+ const lookAt = plane.projectPoint(hitPlane, position);
864
+ const newCamera = camera.update({ position, lookAt });
865
+ const newDistance = vector3.distance(position, lookAt);
866
+ if (newDistance >= newCamera.near) {
867
+ return newCamera;
868
+ }
869
+ }
870
+ return camera;
794
871
  });
795
872
  }
796
873
  /**
@@ -800,6 +877,8 @@ class InteractionApi {
800
877
  if (this.isInteracting()) {
801
878
  this.currentCamera = undefined;
802
879
  this.worldRotationPoint = undefined;
880
+ this.panData = undefined;
881
+ this.zoomData = undefined;
803
882
  this.resetLastAngle();
804
883
  this.interactionFinishedEmitter.emit();
805
884
  await this.stream.endInteraction();
@@ -847,7 +926,7 @@ class InteractionApi {
847
926
  isCoarseInputDevice(isTouch) {
848
927
  return isTouch || window.matchMedia('(pointer: coarse)').matches;
849
928
  }
850
- getWorldRotationPoint(point, depthBuffer, fallbackPoint) {
929
+ getWorldPoint(point, depthBuffer, fallbackPoint) {
851
930
  const viewport = this.getViewport();
852
931
  const framePt = viewport.transformPointToFrame(point, depthBuffer);
853
932
  const hasDepth = depthBuffer.isDepthAtFarPlane(framePt);
@@ -1009,7 +1088,9 @@ class BaseInteractionHandler {
1009
1088
  else if (event.buttons === 2) {
1010
1089
  this.draggingInteraction = this.panInteraction;
1011
1090
  }
1012
- if (this.draggingInteraction != null && this.interactionApi != null) {
1091
+ if (this.draggingInteraction != null &&
1092
+ this.interactionApi != null &&
1093
+ this.element != null) {
1013
1094
  // Ensure any scroll wheel interactions have been ended prior to beginning
1014
1095
  // another interaction to prevent the interaction from being ended early.
1015
1096
  this.zoomInteraction.endDrag(event, this.interactionApi);
@@ -1043,12 +1124,11 @@ class BaseInteractionHandler {
1043
1124
  const delta = -this.wheelDeltaToPixels(event.deltaY, event.deltaMode) / 10;
1044
1125
  const rect = this.element.getBoundingClientRect();
1045
1126
  const point = getMouseClientPosition(event, rect);
1046
- const ray = this.interactionApi.getRayFromPoint(point);
1047
1127
  SCROLL_WHEEL_DELTA_PERCENTAGES.forEach((percentage, index) => {
1048
1128
  window.setTimeout(() => {
1049
1129
  if (this.interactionApi != null) {
1050
1130
  const zoomDelta = delta * percentage;
1051
- this.zoomInteraction.zoomOnRay(zoomDelta, ray, this.interactionApi);
1131
+ this.zoomInteraction.zoomToPoint(point, zoomDelta, this.interactionApi);
1052
1132
  }
1053
1133
  }, index * 2);
1054
1134
  });
@@ -1181,32 +1261,34 @@ class ZoomInteraction extends MouseInteraction {
1181
1261
  }
1182
1262
  beginDrag(event, canvasPosition, api, element) {
1183
1263
  if (this.currentPosition == null) {
1184
- this.currentPosition = point.create(event.screenX, event.screenY);
1185
- const rect = element === null || element === void 0 ? void 0 : element.getBoundingClientRect();
1264
+ this.currentPosition = point.create(event.clientX, event.clientY);
1265
+ const rect = element.getBoundingClientRect();
1186
1266
  const point$1 = getMouseClientPosition(event, rect);
1187
- this.startRay = api.getRayFromPoint(point$1);
1267
+ this.startPt = point$1;
1188
1268
  api.beginInteraction();
1189
1269
  }
1190
1270
  }
1191
1271
  drag(event, api) {
1192
1272
  if (this.currentPosition != null) {
1193
- const position = point.create(event.screenX, event.screenY);
1273
+ const position = point.create(event.clientX, event.clientY);
1194
1274
  const delta = point.subtract(position, this.currentPosition);
1195
- api.zoomCamera(delta.y, this.startRay);
1196
- this.currentPosition = position;
1275
+ if (this.startPt != null) {
1276
+ api.zoomCameraToPoint(this.startPt, delta.y);
1277
+ this.currentPosition = position;
1278
+ }
1197
1279
  }
1198
1280
  }
1199
1281
  endDrag(event, api) {
1200
1282
  super.endDrag(event, api);
1201
1283
  this.stopInteractionTimer();
1202
1284
  this.didTransformBegin = false;
1203
- this.startRay = undefined;
1285
+ this.startPt = undefined;
1204
1286
  }
1205
1287
  zoom(delta, api) {
1206
1288
  this.operateWithTimer(api, () => api.zoomCamera(delta));
1207
1289
  }
1208
- zoomOnRay(delta, ray, api) {
1209
- this.operateWithTimer(api, () => api.zoomCamera(delta, ray));
1290
+ zoomToPoint(pt, delta, api) {
1291
+ this.operateWithTimer(api, () => api.zoomCameraToPoint(pt, delta));
1210
1292
  }
1211
1293
  beginInteraction(api) {
1212
1294
  this.didTransformBegin = true;
@@ -1245,17 +1327,17 @@ class PanInteraction extends MouseInteraction {
1245
1327
  super(...arguments);
1246
1328
  this.type = 'pan';
1247
1329
  }
1248
- beginDrag(event, canvasPosition, api) {
1330
+ beginDrag(event, canvasPosition, api, element) {
1249
1331
  if (this.currentPosition == null) {
1250
1332
  this.currentPosition = point.create(event.screenX, event.screenY);
1333
+ this.canvasRect = element.getBoundingClientRect();
1251
1334
  api.beginInteraction();
1252
1335
  }
1253
1336
  }
1254
1337
  drag(event, api) {
1255
- if (this.currentPosition != null) {
1256
- const position = point.create(event.screenX, event.screenY);
1257
- const delta = point.subtract(position, this.currentPosition);
1258
- api.panCamera(delta);
1338
+ if (this.currentPosition != null && this.canvasRect != null) {
1339
+ const position = getMouseClientPosition(event, this.canvasRect);
1340
+ api.panCameraToScreenPoint(position);
1259
1341
  this.currentPosition = position;
1260
1342
  }
1261
1343
  }
@@ -1307,7 +1389,7 @@ class MultiTouchInteractionHandler {
1307
1389
  const angle$1 = angle.toDegrees(Math.atan2(matrix2.determinant(previousToCurrent), matrix2.dot(previousToCurrent)));
1308
1390
  (_a = this.interactionApi) === null || _a === void 0 ? void 0 : _a.beginInteraction();
1309
1391
  (_b = this.interactionApi) === null || _b === void 0 ? void 0 : _b.zoomCamera(zoom);
1310
- (_c = this.interactionApi) === null || _c === void 0 ? void 0 : _c.panCamera(delta);
1392
+ (_c = this.interactionApi) === null || _c === void 0 ? void 0 : _c.panCameraByDelta(delta);
1311
1393
  (_d = this.interactionApi) === null || _d === void 0 ? void 0 : _d.twistCamera(angle$1);
1312
1394
  }
1313
1395
  this.currentPosition1 = point1;
@@ -2060,6 +2142,7 @@ const Viewer = class {
2060
2142
  this.tokenExpired = createEvent(this, "tokenExpired", 7);
2061
2143
  this.connectionChange = createEvent(this, "connectionChange", 7);
2062
2144
  this.sceneReady = createEvent(this, "sceneReady", 7);
2145
+ this.sceneChanged = createEvent(this, "sceneChanged", 7);
2063
2146
  this.interactionStarted = createEvent(this, "interactionStarted", 7);
2064
2147
  this.interactionFinished = createEvent(this, "interactionFinished", 7);
2065
2148
  this.sessionidchange = createEvent(this, "sessionidchange", 7);
@@ -2461,6 +2544,12 @@ const Viewer = class {
2461
2544
  this.urn = undefined;
2462
2545
  this.stateMap.streamWorldOrientation = undefined;
2463
2546
  }
2547
+ if (this.canvasElement != null) {
2548
+ const context = this.canvasElement.getContext('2d');
2549
+ if (context != null) {
2550
+ context.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
2551
+ }
2552
+ }
2464
2553
  }
2465
2554
  /**
2466
2555
  * Returns an object that is used to perform operations on the `Scene` that's
@@ -2523,7 +2612,8 @@ const Viewer = class {
2523
2612
  this.streamId = streamId.hex;
2524
2613
  }
2525
2614
  // Need to parse world orientation.
2526
- this.stateMap.streamWorldOrientation = mapWorldOrientationOrThrow(worldOrientation);
2615
+ this.stateMap.streamWorldOrientation =
2616
+ mapWorldOrientationOrThrow(worldOrientation);
2527
2617
  console.debug(`Stream connected [stream-id=${this.streamId}, scene-view-id=${this.sceneViewId}]`);
2528
2618
  await this.waitNextDrawnFrame(15 * 1000);
2529
2619
  this.sceneReady.emit();
@@ -2684,6 +2774,9 @@ const Viewer = class {
2684
2774
  viewport: Viewport.fromDimensions(this.getCanvasDimensions() || dimensions.create(0, 0)),
2685
2775
  };
2686
2776
  this.frameReceived.emit(this.frame);
2777
+ if (this.frame.scene.hasChanged) {
2778
+ this.sceneChanged.emit();
2779
+ }
2687
2780
  const drawnFrame = await this.canvasRenderer(data);
2688
2781
  this.dispatchFrameDrawn(drawnFrame);
2689
2782
  }
@@ -66,5 +66,5 @@ const patchDynamicImport = (base, orgScriptElm) => {
66
66
  };
67
67
 
68
68
  patchBrowser().then(options => {
69
- return bootstrapLazy([["vertex-viewer-default-toolbar",[[1,"vertex-viewer-default-toolbar",{"viewer":[16],"placement":[1],"direction":[1],"animationsDisabled":[4,"animations-disabled"],"animationMs":[2,"animation-ms"]}]]],["vertex-scene-tree",[[1,"vertex-scene-tree",{"overScanCount":[2,"over-scan-count"],"viewerSelector":[1,"viewer-selector"],"viewer":[1040],"rowData":[16],"config":[16],"configEnv":[1,"config-env"],"controller":[1040],"metadataKeys":[16],"isComputingRowHeight":[32],"rows":[32],"totalRows":[32],"scrollTop":[32],"computedRowHeight":[32],"stateMap":[32],"connectionErrorDetails":[32],"invalidateRows":[64],"scrollToIndex":[64],"scrollToItem":[64],"expandAll":[64],"collapseAll":[64],"expandItem":[64],"collapseItem":[64],"toggleExpandItem":[64],"toggleItemVisibility":[64],"hideItem":[64],"showItem":[64],"selectItem":[64],"deselectItem":[64],"getRowAtIndex":[64],"getRowForEvent":[64],"getRowAtClientY":[64],"filterItems":[64],"fetchMetadataKeys":[64]},[[0,"search","handleSearch"]]]]],["vertex-viewer-measurement-tool",[[1,"vertex-viewer-measurement-tool",{"distanceTemplateId":[1,"distance-template-id"],"tool":[1],"units":[1],"fractionalDigits":[2,"fractional-digits"],"disabled":[4],"viewer":[16],"isMeasuring":[1540,"is-measuring"],"snapDistance":[2,"snap-distance"],"stateMap":[32]}]]],["vertex-viewer-view-cube",[[1,"vertex-viewer-view-cube",{"xPositiveLabel":[1,"x-positive-label"],"xNegativeLabel":[1,"x-negative-label"],"yPositiveLabel":[1,"y-positive-label"],"yNegativeLabel":[1,"y-negative-label"],"zPositiveLabel":[1,"z-positive-label"],"zNegativeLabel":[1,"z-negative-label"],"standardViewsOff":[4,"standard-views-off"],"animationDuration":[2,"animation-duration"],"triadOff":[4,"triad-off"],"worldOrientation":[1040],"camera":[1040],"viewer":[16],"boxLength":[32],"triadPosition":[32]}]]],["vertex-viewer-markup",[[1,"vertex-viewer-markup",{"arrowTemplateId":[1,"arrow-template-id"],"circleTemplateId":[1,"circle-template-id"],"tool":[1],"disabled":[4],"viewer":[16],"selectedMarkupId":[1025,"selected-markup-id"],"addMarkup":[64],"removeMarkup":[64],"getMarkupElements":[64],"getMarkupElement":[64]},[[0,"markupEnd","handleMarkupEnd"],[0,"markupEditCancel","handleMarkupEditCancel"],[1,"pointerdown","handleMarkupPointerDown"]]]]],["vertex-viewer-markup-tool",[[1,"vertex-viewer-markup-tool",{"arrowTemplateId":[1,"arrow-template-id"],"circleTemplateId":[1,"circle-template-id"],"tool":[1],"disabled":[4],"viewer":[16],"stateMap":[32]}]]],["vertex-viewer-measurements",[[1,"vertex-viewer-measurements",{"distanceTemplateId":[1,"distance-template-id"],"tool":[1],"units":[1],"fractionalDigits":[2,"fractional-digits"],"disabled":[4],"viewer":[16],"selectedMeasurementId":[1025,"selected-measurement-id"],"snapDistance":[2,"snap-distance"],"addMeasurement":[64],"removeMeasurement":[64],"getMeasurementElement":[64],"getMeasurementElements":[64]},[[0,"measureEnd","handleMeasureEnd"],[1,"pointerdown","handleMeasurementPointerDown"]]]]],["vertex-scene-tree-row",[[1,"vertex-scene-tree-row",{"node":[16],"tree":[16],"interactionsDisabled":[4,"interactions-disabled"],"recurseParentSelectionDisabled":[4,"recurse-parent-selection-disabled"]}]]],["vertex-scene-tree-toolbar-group",[[1,"vertex-scene-tree-toolbar-group"]]],["vertex-viewer",[[1,"vertex-viewer",{"src":[1],"clientId":[1,"client-id"],"sessionId":[1,"session-id"],"config":[1],"configEnv":[1,"config-env"],"resolvedConfig":[1040],"cameraControls":[4,"camera-controls"],"keyboardControls":[4,"keyboard-controls"],"rotateAroundTapPoint":[4,"rotate-around-tap-point"],"depthBuffers":[1,"depth-buffers"],"experimentalGhostingOpacity":[2,"experimental-ghosting-opacity"],"featureLines":[16],"selectionMaterial":[1,"selection-material"],"frame":[1040],"streamAttributes":[1040],"stream":[1040],"stencilBuffer":[1040],"dimensions":[32],"hostDimensions":[32],"errorMessage":[32],"cursor":[32],"stateMap":[32],"registerCommand":[64],"dispatchFrameDrawn":[64],"registerInteractionHandler":[64],"registerTapKeyInteraction":[64],"getInteractionTarget":[64],"addCursor":[64],"getInteractionHandlers":[64],"getBaseInteractionHandler":[64],"getJwt":[64],"load":[64],"unload":[64],"scene":[64],"isSceneReady":[64],"handleWebSocketClose":[64]},[[0,"tap","handleTapEvent"]]]]],["vertex-scene-tree-search_2",[[1,"vertex-scene-tree-search",{"debounce":[2],"disabled":[4],"placeholder":[1],"value":[1025],"focused":[32],"setFocus":[64]}],[1,"vertex-scene-tree-toolbar"]]],["vertex-viewer-button_3",[[1,"vertex-viewer-toolbar",{"placement":[1],"direction":[1]}],[1,"vertex-viewer-button"],[1,"vertex-viewer-toolbar-group",{"direction":[1]}]]],["vertex-viewer-dom-element_3",[[1,"vertex-viewer-dom-element",{"position":[1040],"positionJson":[1,"position"],"rotation":[1040],"rotationJson":[1,"rotation"],"quaternion":[1040],"quaternionJson":[1,"quaternion"],"scale":[1040],"scaleJson":[1,"scale"],"matrix":[1040],"occlusionOff":[4,"occlusion-off"],"occluded":[516],"billboardOff":[4,"billboard-off"],"interactionsOff":[516,"interactions-off"]}],[1,"vertex-viewer-dom-group",{"position":[1040],"positionJson":[1,"position"],"rotation":[1040],"rotationJson":[1,"rotation"],"quaternion":[1040],"quaternionJson":[1,"quaternion"],"scale":[1040],"scaleJson":[1,"scale"],"matrix":[1040]}],[1,"vertex-viewer-dom-renderer",{"drawMode":[1,"draw-mode"],"viewer":[16],"camera":[1040],"depthBuffer":[1040],"viewport":[32],"invalidateFrameCounter":[32]},[[0,"propertyChange","handlePropertyChange"]]]]],["vertex-viewer-icon",[[1,"vertex-viewer-icon",{"name":[1],"size":[1]}]]],["vertex-viewer-layer",[[1,"vertex-viewer-layer",{"stretchOff":[516,"stretch-off"]}]]],["vertex-viewer-markup-arrow_2",[[1,"vertex-viewer-markup-arrow",{"start":[1040],"startJson":[1,"start"],"end":[1040],"endJson":[1,"end"],"mode":[513],"viewer":[16],"elementBounds":[32],"editAnchor":[32],"dispose":[64]}],[1,"vertex-viewer-markup-circle",{"bounds":[1040],"boundsJson":[1,"bounds"],"mode":[513],"viewer":[16],"elementBounds":[32],"startPosition":[32],"editAnchor":[32],"resizeBounds":[32],"dispose":[64]}]]],["vertex-viewer-measurement-distance_2",[[1,"vertex-viewer-measurement-distance",{"start":[1040],"startJson":[1,"start"],"end":[1040],"endJson":[1,"end"],"distance":[1026],"snapDistance":[2,"snap-distance"],"units":[1],"fractionalDigits":[2,"fractional-digits"],"labelFormatter":[16],"anchorLabelOffset":[2,"anchor-label-offset"],"lineCapLength":[2,"line-cap-length"],"mode":[513],"interactingAnchor":[1537,"interacting-anchor"],"invalid":[1540],"camera":[16],"depthBuffer":[16],"viewer":[16],"line":[32],"viewport":[32],"elementBounds":[32],"interactionCount":[32],"internalCamera":[32],"internalDepthBuffer":[32],"invalidateStateCounter":[32],"interactiveStartPoint":[32],"interactiveEndPoint":[32],"stateMap":[32],"computeElementMetrics":[64]}],[1,"vertex-viewer-measurement-line",{"start":[16],"end":[16],"capLength":[2,"cap-length"],"pointerEvents":[1,"pointer-events"]}]]]], options);
69
+ return bootstrapLazy([["vertex-viewer-default-toolbar",[[1,"vertex-viewer-default-toolbar",{"viewer":[16],"placement":[1],"direction":[1],"animationsDisabled":[4,"animations-disabled"],"animationMs":[2,"animation-ms"]}]]],["vertex-scene-tree",[[1,"vertex-scene-tree",{"overScanCount":[2,"over-scan-count"],"viewerSelector":[1,"viewer-selector"],"viewer":[1040],"rowData":[16],"config":[16],"configEnv":[1,"config-env"],"controller":[1040],"metadataKeys":[16],"isComputingRowHeight":[32],"rows":[32],"totalRows":[32],"scrollTop":[32],"computedRowHeight":[32],"stateMap":[32],"connectionErrorDetails":[32],"invalidateRows":[64],"scrollToIndex":[64],"scrollToItem":[64],"expandAll":[64],"collapseAll":[64],"expandItem":[64],"collapseItem":[64],"toggleExpandItem":[64],"toggleItemVisibility":[64],"hideItem":[64],"showItem":[64],"selectItem":[64],"deselectItem":[64],"getRowAtIndex":[64],"getRowForEvent":[64],"getRowAtClientY":[64],"filterItems":[64],"fetchMetadataKeys":[64]},[[0,"search","handleSearch"]]]]],["vertex-viewer-markup",[[1,"vertex-viewer-markup",{"arrowTemplateId":[1,"arrow-template-id"],"circleTemplateId":[1,"circle-template-id"],"freeformTemplateId":[1,"freeform-template-id"],"tool":[1],"disabled":[4],"viewer":[16],"selectedMarkupId":[1025,"selected-markup-id"],"addMarkup":[64],"removeMarkup":[64],"getMarkupElements":[64],"getMarkupElement":[64]},[[0,"markupEnd","handleMarkupEnd"],[0,"markupEditCancel","handleMarkupEditCancel"],[1,"pointerdown","handleMarkupPointerDown"]]]]],["vertex-viewer-markup-tool",[[1,"vertex-viewer-markup-tool",{"arrowTemplateId":[1,"arrow-template-id"],"circleTemplateId":[1,"circle-template-id"],"freeformTemplateId":[1,"freeform-template-id"],"tool":[1],"disabled":[4],"viewer":[16],"stateMap":[32]}]]],["vertex-viewer-measurement-tool",[[1,"vertex-viewer-measurement-tool",{"distanceTemplateId":[1,"distance-template-id"],"tool":[1],"units":[1],"fractionalDigits":[2,"fractional-digits"],"disabled":[4],"viewer":[16],"isMeasuring":[1540,"is-measuring"],"snapDistance":[2,"snap-distance"],"stateMap":[32]}]]],["vertex-viewer-view-cube",[[1,"vertex-viewer-view-cube",{"xPositiveLabel":[1,"x-positive-label"],"xNegativeLabel":[1,"x-negative-label"],"yPositiveLabel":[1,"y-positive-label"],"yNegativeLabel":[1,"y-negative-label"],"zPositiveLabel":[1,"z-positive-label"],"zNegativeLabel":[1,"z-negative-label"],"standardViewsOff":[4,"standard-views-off"],"animationDuration":[2,"animation-duration"],"triadOff":[4,"triad-off"],"worldOrientation":[1040],"camera":[1040],"viewer":[16],"boxLength":[32],"triadPosition":[32]}]]],["vertex-viewer-measurements",[[1,"vertex-viewer-measurements",{"distanceTemplateId":[1,"distance-template-id"],"tool":[1],"units":[1],"fractionalDigits":[2,"fractional-digits"],"disabled":[4],"viewer":[16],"selectedMeasurementId":[1025,"selected-measurement-id"],"snapDistance":[2,"snap-distance"],"addMeasurement":[64],"removeMeasurement":[64],"getMeasurementElement":[64],"getMeasurementElements":[64]},[[0,"measureEnd","handleMeasureEnd"],[1,"pointerdown","handleMeasurementPointerDown"]]]]],["vertex-scene-tree-row",[[1,"vertex-scene-tree-row",{"node":[16],"tree":[16],"interactionsDisabled":[4,"interactions-disabled"],"recurseParentSelectionDisabled":[4,"recurse-parent-selection-disabled"]}]]],["vertex-scene-tree-toolbar-group",[[1,"vertex-scene-tree-toolbar-group"]]],["vertex-viewer",[[1,"vertex-viewer",{"src":[1],"clientId":[1,"client-id"],"sessionId":[1,"session-id"],"config":[1],"configEnv":[1,"config-env"],"resolvedConfig":[1040],"cameraControls":[4,"camera-controls"],"keyboardControls":[4,"keyboard-controls"],"rotateAroundTapPoint":[4,"rotate-around-tap-point"],"depthBuffers":[1,"depth-buffers"],"experimentalGhostingOpacity":[2,"experimental-ghosting-opacity"],"featureLines":[16],"selectionMaterial":[1,"selection-material"],"frame":[1040],"streamAttributes":[1040],"stream":[1040],"stencilBuffer":[1040],"dimensions":[32],"hostDimensions":[32],"errorMessage":[32],"cursor":[32],"stateMap":[32],"registerCommand":[64],"dispatchFrameDrawn":[64],"registerInteractionHandler":[64],"registerTapKeyInteraction":[64],"getInteractionTarget":[64],"addCursor":[64],"getInteractionHandlers":[64],"getBaseInteractionHandler":[64],"getJwt":[64],"load":[64],"unload":[64],"scene":[64],"isSceneReady":[64],"handleWebSocketClose":[64]},[[0,"tap","handleTapEvent"]]]]],["vertex-scene-tree-search_2",[[1,"vertex-scene-tree-search",{"debounce":[2],"disabled":[4],"placeholder":[1],"value":[1025],"focused":[32],"setFocus":[64]}],[1,"vertex-scene-tree-toolbar"]]],["vertex-viewer-button_3",[[1,"vertex-viewer-toolbar",{"placement":[1],"direction":[1]}],[1,"vertex-viewer-button"],[1,"vertex-viewer-toolbar-group",{"direction":[1]}]]],["vertex-viewer-dom-element_3",[[1,"vertex-viewer-dom-element",{"position":[1040],"positionJson":[1,"position"],"rotation":[1040],"rotationJson":[1,"rotation"],"quaternion":[1040],"quaternionJson":[1,"quaternion"],"scale":[1040],"scaleJson":[1,"scale"],"matrix":[1040],"occlusionOff":[4,"occlusion-off"],"occluded":[516],"billboardOff":[4,"billboard-off"],"interactionsOff":[516,"interactions-off"]}],[1,"vertex-viewer-dom-group",{"position":[1040],"positionJson":[1,"position"],"rotation":[1040],"rotationJson":[1,"rotation"],"quaternion":[1040],"quaternionJson":[1,"quaternion"],"scale":[1040],"scaleJson":[1,"scale"],"matrix":[1040]}],[1,"vertex-viewer-dom-renderer",{"drawMode":[1,"draw-mode"],"viewer":[16],"camera":[1040],"depthBuffer":[1040],"viewport":[32],"invalidateFrameCounter":[32]},[[0,"propertyChange","handlePropertyChange"]]]]],["vertex-viewer-icon",[[1,"vertex-viewer-icon",{"name":[1],"size":[1]}]]],["vertex-viewer-layer",[[1,"vertex-viewer-layer",{"stretchOff":[516,"stretch-off"]}]]],["vertex-viewer-measurement-distance_2",[[1,"vertex-viewer-measurement-distance",{"start":[1040],"startJson":[1,"start"],"end":[1040],"endJson":[1,"end"],"distance":[1026],"snapDistance":[2,"snap-distance"],"units":[1],"fractionalDigits":[2,"fractional-digits"],"labelFormatter":[16],"anchorLabelOffset":[2,"anchor-label-offset"],"lineCapLength":[2,"line-cap-length"],"mode":[513],"interactingAnchor":[1537,"interacting-anchor"],"invalid":[1540],"camera":[16],"depthBuffer":[16],"viewer":[16],"line":[32],"viewport":[32],"elementBounds":[32],"interactionCount":[32],"internalCamera":[32],"internalDepthBuffer":[32],"invalidateStateCounter":[32],"interactiveStartPoint":[32],"interactiveEndPoint":[32],"stateMap":[32],"computeElementMetrics":[64]}],[1,"vertex-viewer-measurement-line",{"start":[16],"end":[16],"capLength":[2,"cap-length"],"pointerEvents":[1,"pointer-events"]}]]],["vertex-viewer-markup-arrow_3",[[1,"vertex-viewer-markup-arrow",{"start":[1040],"startJson":[1,"start"],"end":[1040],"endJson":[1,"end"],"mode":[513],"viewer":[16],"elementBounds":[32],"editAnchor":[32],"dispose":[64]}],[1,"vertex-viewer-markup-circle",{"bounds":[1040],"boundsJson":[1,"bounds"],"mode":[513],"viewer":[16],"elementBounds":[32],"startPosition":[32],"editAnchor":[32],"resizeBounds":[32],"dispose":[64]}],[1,"vertex-viewer-markup-freeform",{"points":[1040],"pointsJson":[1,"points"],"bounds":[1040],"boundsJson":[1,"bounds"],"mode":[513],"viewer":[16],"elementBounds":[32],"resizeStartPosition":[32],"editAnchor":[32],"resizeBounds":[32],"resizePoints":[32],"screenPoints":[32],"dispose":[64]}]]]], options);
70
70
  });
@@ -1,7 +1,7 @@
1
1
  /**!
2
2
  * Copyright (c) 2021 Vertex Software LLC. All rights reserved.
3
3
  */
4
- import { f as dimensions, v as vector3, h as plane, p as point, m as matrix4, i as angle, r as ray, g as rectangle } from './bundle.esm-590d2273.js';
4
+ import { f as dimensions, v as vector3, h as plane, p as point, r as ray, g as rectangle } from './bundle.esm-d891316f.js';
5
5
 
6
6
  /**
7
7
  * A `Viewport` represents the drawing area in the viewer.
@@ -102,12 +102,36 @@ class Viewport {
102
102
  * @returns
103
103
  */
104
104
  transformPointToRay(pt, image, camera) {
105
- const { position, lookAt, up, aspectRatio, fovY } = camera;
106
- const framePt = this.transformPointToFrame(pt, image);
107
- const m = matrix4.position(matrix4.makeLookAt(position, lookAt, up), matrix4.makeIdentity());
108
- const normal = vector3.normalize(vector3.create((framePt.x / image.frameDimensions.width - 0.5) * aspectRatio, -(framePt.y / image.frameDimensions.height) + 0.5, -0.5 / Math.tan(angle.toRadians(fovY / 2.0))));
109
- const direction = vector3.normalize(vector3.transformMatrix(normal, m));
110
- return ray.create({ origin: position, direction });
105
+ const ndc = this.transformScreenPointToNdc(pt, image);
106
+ const origin = vector3.fromMatrixPosition(camera.worldMatrix);
107
+ const world = vector3.transformNdcToWorldSpace(vector3.create(ndc.x, ndc.y, 0.5), camera.worldMatrix, camera.projectionMatrixInverse);
108
+ const direction = vector3.normalize(vector3.subtract(world, origin));
109
+ return ray.create({ origin, direction });
110
+ }
111
+ /**
112
+ * Maps a screen point to normalized device coordinates (NDC). A screen point
113
+ * at 0,0 represents the top-left of the viewport.
114
+ *
115
+ * @param screenPt A screen point.
116
+ */
117
+ transformScreenPointToNdc(screenPt, image) {
118
+ const framePt = this.transformPointToFrame(screenPt, image);
119
+ return point.create((framePt.x / image.frameDimensions.width) * 2 - 1, -(framePt.y / image.frameDimensions.height) * 2 + 1);
120
+ }
121
+ /**
122
+ * Maps a point in screen space to a world point that is coplanar with the
123
+ * camera's near plane.
124
+ *
125
+ * @param screenPt The screen point to transform.
126
+ * @param image An image of frame.
127
+ * @param camera The camera used to map a 2D point to 3D point.
128
+ * @returns A point on the screen in world space.
129
+ */
130
+ transformPointToScreenWorld(screenPt, image, camera) {
131
+ const { direction, near } = camera;
132
+ const ray$1 = this.transformPointToRay(screenPt, image, camera);
133
+ const screen = plane.create({ normal: direction, constant: near });
134
+ return ray.intersectPlane(ray$1, screen);
111
135
  }
112
136
  /**
113
137
  * Computes a rectangle that is scaled correctly to be drawn within the
@@ -173,6 +173,10 @@ export declare class Viewer {
173
173
  * Emits an event when the scene is ready to be interacted with.
174
174
  */
175
175
  sceneReady: EventEmitter<void>;
176
+ /**
177
+ * Emits an event when a frame is received with a different scene attribute.
178
+ */
179
+ sceneChanged: EventEmitter<void>;
176
180
  /**
177
181
  * Emits an event when the user has started an interaction.
178
182
  */
@@ -22,6 +22,7 @@ export declare function toScreenScaleFactor(dimensions: Dimensions.Dimensions):
22
22
  */
23
23
  export declare function toRelativeScaleFactor(dimensions: Dimensions.Dimensions): number;
24
24
  export declare function translatePointToScreen(pt: Point.Point, canvasDimensions: Dimensions.Dimensions): Point.Point;
25
+ export declare function translatePointToBounds(pt: Point.Point, rect: Rectangle.Rectangle, canvasDimensions: Dimensions.Dimensions): Point.Point;
25
26
  export declare function translateDimensionsToScreen(dimensions: Dimensions.Dimensions, canvasDimensions: Dimensions.Dimensions): Dimensions.Dimensions;
26
27
  /**
27
28
  * Translates a rectangle in relative units, to a rectangle in screen units.
@@ -34,3 +35,10 @@ export declare function translateRectToScreen(rect: Rectangle.Rectangle, canvasD
34
35
  * Translates a point in screen units, to a point in relative units.
35
36
  */
36
37
  export declare function translatePointToRelative(pt: Point.Point, canvasDimensions: Dimensions.Dimensions): Point.Point;
38
+ /**
39
+ * Translates a set of points in relative `original` units to
40
+ * points in relative `bounds` units.
41
+ */
42
+ export declare function translatePointsToBounds(points: Point.Point[], original: Rectangle.Rectangle, bounds: Rectangle.Rectangle): Point.Point[];
43
+ export declare function createRectangle(initialPoint: Point.Point, currentPoint: Point.Point, maintainAspectRatio: boolean): Rectangle.Rectangle;
44
+ export declare function transformRectangle(bounds: Rectangle.Rectangle, start: Point.Point, current: Point.Point, anchor: BoundingBox2dAnchorPosition, maintainAspectRatio?: boolean): Rectangle.Rectangle;
@@ -14,6 +14,12 @@ export declare class ViewerMarkup {
14
14
  * `<vertex-viewer-markup-circle>`.
15
15
  */
16
16
  circleTemplateId?: string;
17
+ /**
18
+ * An HTML template that describes the HTML to use for new freeform
19
+ * markup. It's expected that the template contains a
20
+ * `<vertex-viewer-markup-freeform>`.
21
+ */
22
+ freeformTemplateId?: string;
17
23
  /**
18
24
  * The type of markup to perform.
19
25
  */
@@ -36,12 +42,12 @@ export declare class ViewerMarkup {
36
42
  * Dispatched when a new markup is added, either through user interaction
37
43
  * or programmatically.
38
44
  */
39
- markupAdded: EventEmitter<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement>;
45
+ markupAdded: EventEmitter<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | HTMLVertexViewerMarkupFreeformElement>;
40
46
  /**
41
47
  * Dispatched when a markup is removed, either through user
42
48
  * interaction or programmatically.
43
49
  */
44
- markupRemoved: EventEmitter<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement>;
50
+ markupRemoved: EventEmitter<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | HTMLVertexViewerMarkupFreeformElement>;
45
51
  private hostEl;
46
52
  /**
47
53
  * Adds a new markup as a child to this component. A new markup
@@ -54,7 +60,7 @@ export declare class ViewerMarkup {
54
60
  * @see {@link ViewerMarkups.arrowTemplateId}
55
61
  * @see {@link ViewerMarkups.circleTemplateId}
56
62
  */
57
- addMarkup(markup: Markup): Promise<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement>;
63
+ addMarkup(markup: Markup): Promise<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | HTMLVertexViewerMarkupFreeformElement>;
58
64
  /**
59
65
  * Removes a markup with the given ID, and returns the HTML element
60
66
  * associated to the markup. Returns `undefined` if no markup is
@@ -63,14 +69,14 @@ export declare class ViewerMarkup {
63
69
  * @param id The ID of the markup to remove.
64
70
  * @returns The markup element, or undefined.
65
71
  */
66
- removeMarkup(id: string): Promise<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | undefined>;
72
+ removeMarkup(id: string): Promise<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | HTMLVertexViewerMarkupFreeformElement | undefined>;
67
73
  /**
68
74
  * Returns a list of markup elements that are children of this component.
69
75
  *
70
76
  * @returns A list of all markups.
71
77
  * @see {@link ViewerMarkup.getMarkupElement}
72
78
  */
73
- getMarkupElements(): Promise<Array<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement>>;
79
+ getMarkupElements(): Promise<Array<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | HTMLVertexViewerMarkupFreeformElement>>;
74
80
  /**
75
81
  * Returns the markup element associated to the given ID.
76
82
  *
@@ -78,7 +84,7 @@ export declare class ViewerMarkup {
78
84
  * @returns A markup element, or `undefined`.
79
85
  * @see {@link ViewerMarkup.getMarkupElements}
80
86
  */
81
- getMarkupElement(id: string): Promise<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | undefined>;
87
+ getMarkupElement(id: string): Promise<HTMLVertexViewerMarkupArrowElement | HTMLVertexViewerMarkupCircleElement | HTMLVertexViewerMarkupFreeformElement | undefined>;
82
88
  /**
83
89
  * @ignore
84
90
  */
@@ -126,6 +132,7 @@ export declare class ViewerMarkup {
126
132
  private appendMarkupElement;
127
133
  private createArrowMarkupElement;
128
134
  private createCircleMarkupElement;
135
+ private createFreeformMarkupElement;
129
136
  private updatePropsOnMarkups;
130
137
  private updatePropsOnMarkup;
131
138
  private updatePropsOnMarkupTool;
@@ -1,6 +1,3 @@
1
- import { Point, Rectangle } from '@vertexvis/geometry';
2
- import { BoundingBox2dAnchorPosition } from '../viewer-markup/utils';
1
+ import { Rectangle } from '@vertexvis/geometry';
3
2
  export declare function isVertexViewerCircleMarkup(el: unknown): el is HTMLVertexViewerMarkupCircleElement;
4
3
  export declare function parseBounds(value: string | Rectangle.Rectangle | undefined): Rectangle.Rectangle | undefined;
5
- export declare function createCircle(initialPoint: Point.Point, currentPoint: Point.Point, maintainAspectRatio: boolean): Rectangle.Rectangle;
6
- export declare function transformCircle(bounds: Rectangle.Rectangle, start: Point.Point, current: Point.Point, anchor: BoundingBox2dAnchorPosition, maintainAspectRatio?: boolean): Rectangle.Rectangle;
@@ -0,0 +1,3 @@
1
+ import { Point } from '@vertexvis/geometry';
2
+ export declare function parsePoints(value: string | Point.Point[] | undefined): Point.Point[] | undefined;
3
+ export declare function isVertexViewerFreeformMarkup(el: unknown): el is HTMLVertexViewerMarkupFreeformElement;