@inweb/viewer-three 25.10.0 → 25.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.
@@ -1,9 +1,7 @@
1
- import { Box3, Vector3, Sphere, Vector2, Raycaster, MeshBasicMaterial, LoadingManager, LoaderUtils, MOUSE, TOUCH, EventDispatcher, Clock, Quaternion, Object3D, Euler, Matrix4, LineBasicMaterial, CylinderGeometry, BoxGeometry, BufferGeometry, Float32BufferAttribute, Mesh, OctahedronGeometry, Line, SphereGeometry, TorusGeometry, PlaneGeometry, DoubleSide, Plane, AmbientLight, DirectionalLight, Color, PMREMGenerator, OrthographicCamera, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, Vector4, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
1
+ import { Vector2, Raycaster, MeshBasicMaterial, Box3, Vector3, Sphere, LoadingManager, LoaderUtils, EventDispatcher, MOUSE, TOUCH, Quaternion, Spherical, Clock, Object3D, Euler, Matrix4, LineBasicMaterial, CylinderGeometry, BoxGeometry, BufferGeometry, Float32BufferAttribute, Mesh, OctahedronGeometry, Line, SphereGeometry, TorusGeometry, PlaneGeometry, DoubleSide, Plane, AmbientLight, DirectionalLight, Color, PMREMGenerator, OrthographicCamera, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, Vector4, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
2
2
 
3
3
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
4
4
 
5
- import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
6
-
7
5
  import { RoomEnvironment } from "three/examples/jsm/environments/RoomEnvironment.js";
8
6
 
9
7
  class Commands {
@@ -105,7 +103,8 @@ function defaultOptions() {
105
103
  reverseZoomWheel: false,
106
104
  enableZoomWheel: true,
107
105
  enableGestures: true,
108
- geometryType: "vsfx"
106
+ geometryType: "vsfx",
107
+ rulerUnit: "Default"
109
108
  };
110
109
  }
111
110
 
@@ -365,6 +364,13 @@ class Options {
365
364
  this._data.geometryType = value;
366
365
  this.change();
367
366
  }
367
+ get rulerUnit() {
368
+ return this._data.rulerUnit;
369
+ }
370
+ set rulerUnit(value) {
371
+ this._data.rulerUnit = value;
372
+ this.change();
373
+ }
368
374
  }
369
375
 
370
376
  const CanvasEvents = [ "click", "contextmenu", "dblclick", "mousedown", "mouseleave", "mousemove", "mouseup", "pointercancel", "pointerdown", "pointerleave", "pointermove", "pointerup", "touchcancel", "touchend", "touchmove", "touchstart", "wheel" ];
@@ -390,6 +396,101 @@ commands("ThreeJS").registerCommand("clearMarkup", (viewer => console.warn("clea
390
396
 
391
397
  commands("ThreeJS").registerCommandAlias("clearMarkup", "clearOverlay");
392
398
 
399
+ class SelectionComponent {
400
+ constructor(viewer) {
401
+ this.onPointerDown = event => {
402
+ if (!event.isPrimary || event.button !== 0) return;
403
+ this.getMousePosition(event, this.downPosition);
404
+ };
405
+ this.onPointerUp = event => {
406
+ if (!event.isPrimary) return;
407
+ const upPosition = this.getMousePosition(event, new Vector2);
408
+ if (this.downPosition.distanceTo(upPosition) !== 0) return;
409
+ const intersects = this.getPointerIntersects(upPosition);
410
+ this.clearSelection();
411
+ if (intersects.length > 0) this.select(intersects[0].object);
412
+ this.viewer.update();
413
+ this.viewer.emitEvent({
414
+ type: "select",
415
+ data: undefined,
416
+ handles: this.viewer.getSelected()
417
+ });
418
+ };
419
+ this.onDoubleClick = event => {
420
+ if (event.button !== 0) return;
421
+ this.viewer.executeCommand("zoomToSelected");
422
+ };
423
+ this.optionsChange = () => {
424
+ const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
425
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
426
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
427
+ this.viewer.update();
428
+ };
429
+ this.viewer = viewer;
430
+ this.raycaster = new Raycaster;
431
+ this.downPosition = new Vector2;
432
+ const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
433
+ this.facesMaterial = new MeshBasicMaterial;
434
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
435
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
436
+ this.facesMaterial.transparent = true;
437
+ this.viewer.addEventListener("pointerdown", this.onPointerDown);
438
+ this.viewer.addEventListener("pointerup", this.onPointerUp);
439
+ this.viewer.addEventListener("dblclick", this.onDoubleClick);
440
+ this.viewer.addEventListener("optionschange", this.optionsChange);
441
+ }
442
+ dispose() {
443
+ this.facesMaterial.dispose();
444
+ this.viewer.removeEventListener("pointerdown", this.onPointerDown);
445
+ this.viewer.removeEventListener("pointerup", this.onPointerUp);
446
+ this.viewer.removeEventListener("dblclick", this.onDoubleClick);
447
+ this.viewer.removeEventListener("optionschange", this.optionsChange);
448
+ }
449
+ getMousePosition(event, position) {
450
+ const rect = this.viewer.canvas.getBoundingClientRect();
451
+ position.setX((event.clientX - rect.left) / rect.width);
452
+ position.setY((event.clientY - rect.top) / rect.height);
453
+ return position;
454
+ }
455
+ getPointerIntersects(position) {
456
+ const mouse = new Vector2(position.x * 2 - 1, -(position.y * 2) + 1);
457
+ this.raycaster.setFromCamera(mouse, this.viewer.camera);
458
+ const objects = [];
459
+ this.viewer.scene.traverseVisible((child => objects.push(child)));
460
+ return this.raycaster.intersectObjects(objects, false);
461
+ }
462
+ select(object) {
463
+ if (object.isSelected) return;
464
+ object.isSelected = true;
465
+ object.originalMaterial = object.material;
466
+ object.material = this.facesMaterial;
467
+ this.viewer.selected.push(object);
468
+ }
469
+ clearSelection() {
470
+ this.viewer.selected.forEach((object => {
471
+ object.isSelected = false;
472
+ object.material = object.originalMaterial;
473
+ }));
474
+ this.viewer.selected.length = 0;
475
+ }
476
+ }
477
+
478
+ function clearSelected(viewer) {
479
+ const selection = new SelectionComponent(viewer);
480
+ selection.clearSelection();
481
+ selection.dispose();
482
+ viewer.update();
483
+ viewer.emitEvent({
484
+ type: "select",
485
+ data: undefined,
486
+ handles: []
487
+ });
488
+ }
489
+
490
+ commands("ThreeJS").registerCommand("clearSelected", clearSelected);
491
+
492
+ commands("ThreeJS").registerCommandAlias("clearSelected", "unselect");
493
+
393
494
  function clearSlices(viewer) {
394
495
  viewer.renderer.clippingPlanes = [];
395
496
  viewer.update();
@@ -444,7 +545,7 @@ function explodeScene(scene, scale = 0) {
444
545
  function explode(viewer, index = 0) {
445
546
  viewer.models.forEach((gltf => explodeScene(gltf.scene, index)));
446
547
  viewer.update();
447
- viewer.emit({
548
+ viewer.emitEvent({
448
549
  type: "explode",
449
550
  data: index
450
551
  });
@@ -550,95 +651,16 @@ function getSelected(viewer) {
550
651
 
551
652
  commands("ThreeJS").registerCommand("getSelected", getSelected);
552
653
 
553
- class SelectionComponent {
554
- constructor(viewer) {
555
- this.onPointerDown = event => {
556
- if (!event.isPrimary || event.button !== 0) return;
557
- this.getMousePosition(event, this.downPosition);
558
- };
559
- this.onPointerUp = event => {
560
- if (!event.isPrimary) return;
561
- const upPosition = this.getMousePosition(event, new Vector2);
562
- if (this.downPosition.distanceTo(upPosition) !== 0) return;
563
- const intersects = this.getPointerIntersects(upPosition);
564
- this.clearSelection();
565
- if (intersects.length > 0) this.select(intersects[0].object);
566
- this.viewer.update();
567
- this.viewer.emitEvent({
568
- type: "select",
569
- data: undefined,
570
- handles: this.viewer.getSelected()
571
- });
572
- };
573
- this.onDoubleClick = event => {
574
- if (event.button !== 0) return;
575
- this.viewer.executeCommand("zoomToSelected");
576
- };
577
- this.optionsChange = () => {
578
- const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
579
- this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
580
- this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
581
- this.viewer.update();
582
- };
583
- this.viewer = viewer;
584
- this.raycaster = new Raycaster;
585
- this.downPosition = new Vector2;
586
- const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
587
- this.facesMaterial = new MeshBasicMaterial;
588
- this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
589
- this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
590
- this.facesMaterial.transparent = true;
591
- this.viewer.addEventListener("pointerdown", this.onPointerDown);
592
- this.viewer.addEventListener("pointerup", this.onPointerUp);
593
- this.viewer.addEventListener("dblclick", this.onDoubleClick);
594
- this.viewer.addEventListener("optionschange", this.optionsChange);
595
- }
596
- dispose() {
597
- this.facesMaterial.dispose();
598
- this.viewer.removeEventListener("pointerdown", this.onPointerDown);
599
- this.viewer.removeEventListener("pointerup", this.onPointerUp);
600
- this.viewer.removeEventListener("dblclick", this.onDoubleClick);
601
- this.viewer.removeEventListener("optionschange", this.optionsChange);
602
- }
603
- getMousePosition(event, position) {
604
- const rect = this.viewer.canvas.getBoundingClientRect();
605
- position.setX((event.clientX - rect.left) / rect.width);
606
- position.setY((event.clientY - rect.top) / rect.height);
607
- return position;
608
- }
609
- getPointerIntersects(position) {
610
- const mouse = new Vector2(position.x * 2 - 1, -(position.y * 2) + 1);
611
- this.raycaster.setFromCamera(mouse, this.viewer.camera);
612
- const objects = [];
613
- this.viewer.scene.traverseVisible((child => objects.push(child)));
614
- return this.raycaster.intersectObjects(objects, false);
615
- }
616
- select(object) {
617
- if (object.isSelected) return;
618
- object.isSelected = true;
619
- object.originalMaterial = object.material;
620
- object.material = this.facesMaterial;
621
- this.viewer.selected.push(object);
622
- }
623
- clearSelection() {
624
- this.viewer.selected.forEach((object => {
625
- object.isSelected = false;
626
- object.material = object.originalMaterial;
627
- }));
628
- this.viewer.selected.length = 0;
629
- }
630
- }
631
-
632
654
  function hideSelected(viewer) {
633
655
  viewer.selected.forEach((object => object.visible = false));
634
656
  const selection = new SelectionComponent(viewer);
635
657
  selection.clearSelection();
636
658
  selection.dispose();
637
659
  viewer.update();
638
- viewer.emit({
660
+ viewer.emitEvent({
639
661
  type: "hide"
640
662
  });
641
- viewer.emit({
663
+ viewer.emitEvent({
642
664
  type: "select",
643
665
  data: undefined,
644
666
  handles: []
@@ -659,7 +681,7 @@ function isolateSelected(viewer) {
659
681
  }
660
682
  isolateObject(viewer.scene, 0);
661
683
  viewer.update();
662
- viewer.emit({
684
+ viewer.emitEvent({
663
685
  type: "isolate"
664
686
  });
665
687
  }
@@ -680,7 +702,7 @@ function resetView(viewer) {
680
702
  viewer.executeCommand("clearSlices");
681
703
  viewer.executeCommand("clearOverlay");
682
704
  viewer.executeCommand("setMarkupColor");
683
- viewer.executeCommand("unselect");
705
+ viewer.executeCommand("clearSelected");
684
706
  viewer.executeCommand("showAll");
685
707
  viewer.executeCommand("explode", 0);
686
708
  viewer.executeCommand("zoomToExtents", true);
@@ -722,7 +744,7 @@ function setSelected(viewer, handles = []) {
722
744
  objects.forEach((object => selection.select(object)));
723
745
  selection.dispose();
724
746
  viewer.update();
725
- viewer.emit({
747
+ viewer.emitEvent({
726
748
  type: "select",
727
749
  data: undefined,
728
750
  handles: handles
@@ -734,27 +756,13 @@ commands("ThreeJS").registerCommand("setSelected", setSelected);
734
756
  function showAll(viewer) {
735
757
  viewer.scene.traverse((object => object.visible = true));
736
758
  viewer.update();
737
- viewer.emit({
759
+ viewer.emitEvent({
738
760
  type: "showall"
739
761
  });
740
762
  }
741
763
 
742
764
  commands("ThreeJS").registerCommand("showAll", showAll);
743
765
 
744
- function unselect(viewer) {
745
- const selection = new SelectionComponent(viewer);
746
- selection.clearSelection();
747
- selection.dispose();
748
- viewer.update();
749
- viewer.emit({
750
- type: "select",
751
- data: undefined,
752
- handles: []
753
- });
754
- }
755
-
756
- commands("ThreeJS").registerCommand("unselect", unselect);
757
-
758
766
  function zoomToExtents(viewer) {
759
767
  if (viewer.extents.isEmpty()) return;
760
768
  const center = viewer.extents.getCenter(new Vector3);
@@ -891,6 +899,695 @@ class EventEmitter2 {
891
899
  }
892
900
  }
893
901
 
902
+ const _changeEvent$2 = {
903
+ type: "change"
904
+ };
905
+
906
+ const _startEvent = {
907
+ type: "start"
908
+ };
909
+
910
+ const _endEvent = {
911
+ type: "end"
912
+ };
913
+
914
+ const STATE = {
915
+ NONE: -1,
916
+ ROTATE: 0,
917
+ DOLLY: 1,
918
+ PAN: 2,
919
+ TOUCH_ROTATE: 3,
920
+ TOUCH_PAN: 4,
921
+ TOUCH_DOLLY_PAN: 5,
922
+ TOUCH_DOLLY_ROTATE: 6
923
+ };
924
+
925
+ class OrbitControls extends EventDispatcher {
926
+ constructor(object, domElement) {
927
+ super();
928
+ this.object = object;
929
+ this.domElement = domElement;
930
+ this.domElement.style.touchAction = "none";
931
+ this.enabled = true;
932
+ this.target = new Vector3;
933
+ this.minDistance = 0;
934
+ this.maxDistance = Infinity;
935
+ this.minZoom = 0;
936
+ this.maxZoom = Infinity;
937
+ this.minPolarAngle = 0;
938
+ this.maxPolarAngle = Math.PI;
939
+ this.minAzimuthAngle = -Infinity;
940
+ this.maxAzimuthAngle = Infinity;
941
+ this.enableDamping = false;
942
+ this.dampingFactor = .05;
943
+ this.enableZoom = true;
944
+ this.zoomSpeed = 1;
945
+ this.enableRotate = true;
946
+ this.rotateSpeed = 1;
947
+ this.enablePan = true;
948
+ this.panSpeed = 1;
949
+ this.screenSpacePanning = true;
950
+ this.keyPanSpeed = 7;
951
+ this.autoRotate = false;
952
+ this.autoRotateSpeed = 2;
953
+ this.keys = {
954
+ LEFT: "ArrowLeft",
955
+ UP: "ArrowUp",
956
+ RIGHT: "ArrowRight",
957
+ BOTTOM: "ArrowDown"
958
+ };
959
+ this.mouseButtons = {
960
+ LEFT: MOUSE.ROTATE,
961
+ MIDDLE: MOUSE.DOLLY,
962
+ RIGHT: MOUSE.PAN
963
+ };
964
+ this.touches = {
965
+ ONE: TOUCH.ROTATE,
966
+ TWO: TOUCH.DOLLY_PAN
967
+ };
968
+ this.target0 = this.target.clone();
969
+ this.position0 = this.object.position.clone();
970
+ this.zoom0 = this.object.zoom;
971
+ this._domElementKeyEvents = null;
972
+ this.getPolarAngle = function() {
973
+ return spherical.phi;
974
+ };
975
+ this.getAzimuthalAngle = function() {
976
+ return spherical.theta;
977
+ };
978
+ this.getDistance = function() {
979
+ return this.object.position.distanceTo(this.target);
980
+ };
981
+ this.listenToKeyEvents = function(domElement) {
982
+ domElement.addEventListener("keydown", onKeyDown);
983
+ this._domElementKeyEvents = domElement;
984
+ };
985
+ this.stopListenToKeyEvents = function() {
986
+ this._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
987
+ this._domElementKeyEvents = null;
988
+ };
989
+ this.saveState = function() {
990
+ scope.target0.copy(scope.target);
991
+ scope.position0.copy(scope.object.position);
992
+ scope.zoom0 = scope.object.zoom;
993
+ };
994
+ this.reset = function() {
995
+ scope.target.copy(scope.target0);
996
+ scope.object.position.copy(scope.position0);
997
+ scope.object.zoom = scope.zoom0;
998
+ scope.object.updateProjectionMatrix();
999
+ scope.dispatchEvent(_changeEvent$2);
1000
+ scope.update();
1001
+ scope.state = STATE.NONE;
1002
+ };
1003
+ this.update = function() {
1004
+ const offset = new Vector3;
1005
+ const quat = (new Quaternion).setFromUnitVectors(object.up, new Vector3(0, 1, 0));
1006
+ const quatInverse = quat.clone().invert();
1007
+ const lastPosition = new Vector3;
1008
+ const lastQuaternion = new Quaternion;
1009
+ const lastTargetPosition = new Vector3;
1010
+ const twoPI = 2 * Math.PI;
1011
+ return function update() {
1012
+ const position = scope.object.position;
1013
+ offset.copy(position).sub(scope.target);
1014
+ offset.applyQuaternion(quat);
1015
+ spherical.setFromVector3(offset);
1016
+ if (scope.autoRotate && scope.state === STATE.NONE) {
1017
+ rotateLeft(getAutoRotationAngle());
1018
+ }
1019
+ if (scope.enableDamping) {
1020
+ spherical.theta += sphericalDelta.theta * scope.dampingFactor;
1021
+ spherical.phi += sphericalDelta.phi * scope.dampingFactor;
1022
+ } else {
1023
+ spherical.theta += sphericalDelta.theta;
1024
+ spherical.phi += sphericalDelta.phi;
1025
+ }
1026
+ let min = scope.minAzimuthAngle;
1027
+ let max = scope.maxAzimuthAngle;
1028
+ if (isFinite(min) && isFinite(max)) {
1029
+ if (min < -Math.PI) min += twoPI; else if (min > Math.PI) min -= twoPI;
1030
+ if (max < -Math.PI) max += twoPI; else if (max > Math.PI) max -= twoPI;
1031
+ if (min <= max) {
1032
+ spherical.theta = Math.max(min, Math.min(max, spherical.theta));
1033
+ } else {
1034
+ spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
1035
+ }
1036
+ }
1037
+ spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
1038
+ spherical.makeSafe();
1039
+ spherical.radius *= scope.scale;
1040
+ spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
1041
+ if (scope.enableDamping === true) {
1042
+ scope.target.addScaledVector(scope.panOffset, scope.dampingFactor);
1043
+ } else {
1044
+ scope.target.add(scope.panOffset);
1045
+ }
1046
+ offset.setFromSpherical(spherical);
1047
+ offset.applyQuaternion(quatInverse);
1048
+ position.copy(scope.target).add(offset);
1049
+ scope.object.lookAt(scope.target);
1050
+ if (scope.enableDamping === true) {
1051
+ sphericalDelta.theta *= 1 - scope.dampingFactor;
1052
+ sphericalDelta.phi *= 1 - scope.dampingFactor;
1053
+ scope.panOffset.multiplyScalar(1 - scope.dampingFactor);
1054
+ } else {
1055
+ sphericalDelta.set(0, 0, 0);
1056
+ scope.panOffset.set(0, 0, 0);
1057
+ }
1058
+ scope.scale = 1;
1059
+ if (scope.zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS || lastTargetPosition.distanceToSquared(scope.target) > 0) {
1060
+ scope.dispatchEvent(_changeEvent$2);
1061
+ lastPosition.copy(scope.object.position);
1062
+ lastQuaternion.copy(scope.object.quaternion);
1063
+ lastTargetPosition.copy(scope.target);
1064
+ scope.zoomChanged = false;
1065
+ return true;
1066
+ }
1067
+ return false;
1068
+ };
1069
+ }();
1070
+ this.dispose = function() {
1071
+ scope.domElement.removeEventListener("contextmenu", onContextMenu);
1072
+ scope.domElement.removeEventListener("pointerdown", onPointerDown);
1073
+ scope.domElement.removeEventListener("pointercancel", onPointerUp);
1074
+ scope.domElement.removeEventListener("wheel", onMouseWheel);
1075
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
1076
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
1077
+ if (scope._domElementKeyEvents !== null) {
1078
+ scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
1079
+ scope._domElementKeyEvents = null;
1080
+ }
1081
+ };
1082
+ const scope = this;
1083
+ scope.state = STATE.NONE;
1084
+ const EPS = 1e-6;
1085
+ const spherical = new Spherical;
1086
+ const sphericalDelta = new Spherical;
1087
+ scope.scale = 1;
1088
+ scope.panOffset = new Vector3;
1089
+ scope.zoomChanged = false;
1090
+ scope.rotateStart = new Vector2;
1091
+ scope.rotateEnd = new Vector2;
1092
+ scope.rotateDelta = new Vector2;
1093
+ scope.panStart = new Vector2;
1094
+ scope.panEnd = new Vector2;
1095
+ scope.panDelta = new Vector2;
1096
+ scope.dollyStart = new Vector2;
1097
+ scope.dollyEnd = new Vector2;
1098
+ scope.dollyDelta = new Vector2;
1099
+ scope.dollyScale = 0;
1100
+ scope.pointers = [];
1101
+ scope.pointerPositions = {};
1102
+ function getAutoRotationAngle() {
1103
+ return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
1104
+ }
1105
+ function getZoomScale() {
1106
+ return Math.pow(.95, scope.zoomSpeed);
1107
+ }
1108
+ function rotateLeft(angle) {
1109
+ sphericalDelta.theta -= angle;
1110
+ }
1111
+ function rotateUp(angle) {
1112
+ sphericalDelta.phi -= angle;
1113
+ }
1114
+ const panLeft = function() {
1115
+ const v = new Vector3;
1116
+ return function panLeft(distance, objectMatrix) {
1117
+ v.setFromMatrixColumn(objectMatrix, 0);
1118
+ v.multiplyScalar(-distance);
1119
+ scope.panOffset.add(v);
1120
+ };
1121
+ }();
1122
+ const panUp = function() {
1123
+ const v = new Vector3;
1124
+ return function panUp(distance, objectMatrix) {
1125
+ if (scope.screenSpacePanning === true) {
1126
+ v.setFromMatrixColumn(objectMatrix, 1);
1127
+ } else {
1128
+ v.setFromMatrixColumn(objectMatrix, 0);
1129
+ v.crossVectors(scope.object.up, v);
1130
+ }
1131
+ v.multiplyScalar(distance);
1132
+ scope.panOffset.add(v);
1133
+ };
1134
+ }();
1135
+ const pan = function() {
1136
+ const offset = new Vector3;
1137
+ return function pan(deltaX, deltaY) {
1138
+ const element = scope.domElement;
1139
+ if (scope.object.isPerspectiveCamera) {
1140
+ const position = scope.object.position;
1141
+ offset.copy(position).sub(scope.target);
1142
+ let targetDistance = offset.length();
1143
+ targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
1144
+ panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
1145
+ panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
1146
+ } else if (scope.object.isOrthographicCamera) {
1147
+ panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
1148
+ panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
1149
+ } else {
1150
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
1151
+ scope.enablePan = false;
1152
+ }
1153
+ };
1154
+ }();
1155
+ function dollyOut(dollyScale) {
1156
+ if (scope.object.isPerspectiveCamera) {
1157
+ scope.scale /= dollyScale;
1158
+ } else if (scope.object.isOrthographicCamera) {
1159
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
1160
+ scope.object.updateProjectionMatrix();
1161
+ scope.zoomChanged = true;
1162
+ } else {
1163
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
1164
+ scope.enableZoom = false;
1165
+ }
1166
+ }
1167
+ function dollyIn(dollyScale) {
1168
+ if (scope.object.isPerspectiveCamera) {
1169
+ scope.scale *= dollyScale;
1170
+ } else if (scope.object.isOrthographicCamera) {
1171
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
1172
+ scope.object.updateProjectionMatrix();
1173
+ scope.zoomChanged = true;
1174
+ } else {
1175
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
1176
+ scope.enableZoom = false;
1177
+ }
1178
+ }
1179
+ function handleMouseDownRotate(event) {
1180
+ scope.rotateStart.set(event.clientX, event.clientY);
1181
+ }
1182
+ function handleMouseDownDolly(event) {
1183
+ scope.dollyStart.set(event.clientX, event.clientY);
1184
+ }
1185
+ function handleMouseDownPan(event) {
1186
+ scope.panStart.set(event.clientX, event.clientY);
1187
+ }
1188
+ function handleMouseMoveRotate(event) {
1189
+ scope.rotateEnd.set(event.clientX, event.clientY);
1190
+ scope.rotateDelta.subVectors(scope.rotateEnd, scope.rotateStart).multiplyScalar(scope.rotateSpeed);
1191
+ const element = scope.domElement;
1192
+ rotateLeft(2 * Math.PI * scope.rotateDelta.x / element.clientHeight);
1193
+ rotateUp(2 * Math.PI * scope.rotateDelta.y / element.clientHeight);
1194
+ scope.rotateStart.copy(scope.rotateEnd);
1195
+ scope.update();
1196
+ }
1197
+ function handleMouseMoveDolly(event) {
1198
+ scope.dollyEnd.set(event.clientX, event.clientY);
1199
+ scope.dollyDelta.subVectors(scope.dollyEnd, scope.dollyStart);
1200
+ if (scope.dollyDelta.y < 0) {
1201
+ scope.dollyScale = 1 / getZoomScale();
1202
+ dollyOut(getZoomScale());
1203
+ } else if (scope.dollyDelta.y > 0) {
1204
+ scope.dollyScale = getZoomScale();
1205
+ dollyIn(getZoomScale());
1206
+ }
1207
+ scope.dollyStart.copy(scope.dollyEnd);
1208
+ scope.update();
1209
+ }
1210
+ function handleMouseMovePan(event) {
1211
+ scope.panEnd.set(event.clientX, event.clientY);
1212
+ scope.panDelta.subVectors(scope.panEnd, scope.panStart).multiplyScalar(scope.panSpeed);
1213
+ pan(scope.panDelta.x, scope.panDelta.y);
1214
+ scope.panStart.copy(scope.panEnd);
1215
+ scope.update();
1216
+ }
1217
+ function handleMouseWheel(event) {
1218
+ scope.dollyEnd.set(scope.domElement.clientWidth / 2, scope.domElement.clientHeight / 2);
1219
+ scope.dollyDelta.set(event.deltaX, event.deltaY);
1220
+ if (event.deltaY < 0) {
1221
+ scope.dollyScale = 1 / getZoomScale();
1222
+ dollyIn(getZoomScale());
1223
+ } else if (event.deltaY > 0) {
1224
+ scope.dollyScale = getZoomScale();
1225
+ dollyOut(getZoomScale());
1226
+ }
1227
+ scope.dollyStart.copy(scope.dollyEnd);
1228
+ scope.update();
1229
+ if (event.deltaY !== 0) {
1230
+ scope.state = STATE.DOLLY;
1231
+ scope.dispatchEvent(_changeEvent$2);
1232
+ scope.state = STATE.NONE;
1233
+ }
1234
+ }
1235
+ function handleKeyDown(event) {
1236
+ let needsUpdate = false;
1237
+ switch (event.code) {
1238
+ case scope.keys.UP:
1239
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
1240
+ rotateUp(2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
1241
+ } else {
1242
+ pan(0, scope.keyPanSpeed);
1243
+ }
1244
+ needsUpdate = true;
1245
+ break;
1246
+
1247
+ case scope.keys.BOTTOM:
1248
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
1249
+ rotateUp(-2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
1250
+ } else {
1251
+ pan(0, -scope.keyPanSpeed);
1252
+ }
1253
+ needsUpdate = true;
1254
+ break;
1255
+
1256
+ case scope.keys.LEFT:
1257
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
1258
+ rotateLeft(2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
1259
+ } else {
1260
+ pan(scope.keyPanSpeed, 0);
1261
+ }
1262
+ needsUpdate = true;
1263
+ break;
1264
+
1265
+ case scope.keys.RIGHT:
1266
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
1267
+ rotateLeft(-2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight);
1268
+ } else {
1269
+ pan(-scope.keyPanSpeed, 0);
1270
+ }
1271
+ needsUpdate = true;
1272
+ break;
1273
+ }
1274
+ if (needsUpdate) {
1275
+ event.preventDefault();
1276
+ scope.update();
1277
+ }
1278
+ }
1279
+ function handleTouchStartRotate() {
1280
+ if (scope.pointers.length === 1) {
1281
+ scope.rotateStart.set(scope.pointers[0].pageX, scope.pointers[0].pageY);
1282
+ } else {
1283
+ const x = .5 * (scope.pointers[0].pageX + scope.pointers[1].pageX);
1284
+ const y = .5 * (scope.pointers[0].pageY + scope.pointers[1].pageY);
1285
+ scope.rotateStart.set(x, y);
1286
+ }
1287
+ }
1288
+ function handleTouchStartPan() {
1289
+ if (scope.pointers.length === 1) {
1290
+ scope.panStart.set(scope.pointers[0].pageX, scope.pointers[0].pageY);
1291
+ } else {
1292
+ const x = .5 * (scope.pointers[0].pageX + scope.pointers[1].pageX);
1293
+ const y = .5 * (scope.pointers[0].pageY + scope.pointers[1].pageY);
1294
+ scope.panStart.set(x, y);
1295
+ }
1296
+ }
1297
+ function handleTouchStartDolly() {
1298
+ const dx = scope.pointers[0].pageX - scope.pointers[1].pageX;
1299
+ const dy = scope.pointers[0].pageY - scope.pointers[1].pageY;
1300
+ const distance = Math.sqrt(dx * dx + dy * dy);
1301
+ scope.dollyStart.set(0, distance);
1302
+ }
1303
+ function handleTouchStartDollyPan() {
1304
+ if (scope.enableZoom) handleTouchStartDolly();
1305
+ if (scope.enablePan) handleTouchStartPan();
1306
+ }
1307
+ function handleTouchStartDollyRotate() {
1308
+ if (scope.enableZoom) handleTouchStartDolly();
1309
+ if (scope.enableRotate) handleTouchStartRotate();
1310
+ }
1311
+ function handleTouchMoveRotate(event) {
1312
+ if (scope.pointers.length == 1) {
1313
+ scope.rotateEnd.set(event.pageX, event.pageY);
1314
+ } else {
1315
+ const position = getSecondPointerPosition(event);
1316
+ const x = .5 * (event.pageX + position.x);
1317
+ const y = .5 * (event.pageY + position.y);
1318
+ scope.rotateEnd.set(x, y);
1319
+ }
1320
+ scope.rotateDelta.subVectors(scope.rotateEnd, scope.rotateStart).multiplyScalar(scope.rotateSpeed);
1321
+ const element = scope.domElement;
1322
+ rotateLeft(2 * Math.PI * scope.rotateDelta.x / element.clientHeight);
1323
+ rotateUp(2 * Math.PI * scope.rotateDelta.y / element.clientHeight);
1324
+ scope.rotateStart.copy(scope.rotateEnd);
1325
+ }
1326
+ function handleTouchMovePan(event) {
1327
+ if (scope.pointers.length === 1) {
1328
+ scope.panEnd.set(event.pageX, event.pageY);
1329
+ } else {
1330
+ const position = getSecondPointerPosition(event);
1331
+ const x = .5 * (event.pageX + position.x);
1332
+ const y = .5 * (event.pageY + position.y);
1333
+ scope.panEnd.set(x, y);
1334
+ }
1335
+ scope.panDelta.subVectors(scope.panEnd, scope.panStart).multiplyScalar(scope.panSpeed);
1336
+ pan(scope.panDelta.x, scope.panDelta.y);
1337
+ scope.panStart.copy(scope.panEnd);
1338
+ }
1339
+ function handleTouchMoveDolly(event) {
1340
+ const position = getSecondPointerPosition(event);
1341
+ const dx = event.pageX - position.x;
1342
+ const dy = event.pageY - position.y;
1343
+ const distance = Math.sqrt(dx * dx + dy * dy);
1344
+ scope.dollyEnd.set(0, distance);
1345
+ scope.dollyDelta.set(0, Math.pow(scope.dollyEnd.y / scope.dollyStart.y, scope.zoomSpeed));
1346
+ dollyOut(scope.dollyDelta.y);
1347
+ scope.dollyStart.copy(scope.dollyEnd);
1348
+ }
1349
+ function handleTouchMoveDollyPan(event) {
1350
+ if (scope.enableZoom) handleTouchMoveDolly(event);
1351
+ if (scope.enablePan) handleTouchMovePan(event);
1352
+ }
1353
+ function handleTouchMoveDollyRotate(event) {
1354
+ if (scope.enableZoom) handleTouchMoveDolly(event);
1355
+ if (scope.enableRotate) handleTouchMoveRotate(event);
1356
+ }
1357
+ function onPointerDown(event) {
1358
+ if (scope.enabled === false) return;
1359
+ if (scope.pointers.length === 0) {
1360
+ scope.domElement.setPointerCapture(event.pointerId);
1361
+ scope.domElement.addEventListener("pointermove", onPointerMove);
1362
+ scope.domElement.addEventListener("pointerup", onPointerUp);
1363
+ }
1364
+ addPointer(event);
1365
+ if (event.pointerType === "touch") {
1366
+ onTouchStart(event);
1367
+ } else {
1368
+ onMouseDown(event);
1369
+ }
1370
+ }
1371
+ function onPointerMove(event) {
1372
+ if (scope.enabled === false) return;
1373
+ if (event.pointerType === "touch") {
1374
+ onTouchMove(event);
1375
+ } else {
1376
+ onMouseMove(event);
1377
+ }
1378
+ }
1379
+ function onPointerUp(event) {
1380
+ removePointer(event);
1381
+ if (scope.pointers.length === 0) {
1382
+ scope.domElement.releasePointerCapture(event.pointerId);
1383
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
1384
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
1385
+ }
1386
+ scope.dispatchEvent(_endEvent);
1387
+ scope.state = STATE.NONE;
1388
+ }
1389
+ function onMouseDown(event) {
1390
+ let mouseAction;
1391
+ switch (event.button) {
1392
+ case 0:
1393
+ mouseAction = scope.mouseButtons.LEFT;
1394
+ break;
1395
+
1396
+ case 1:
1397
+ mouseAction = scope.mouseButtons.MIDDLE;
1398
+ break;
1399
+
1400
+ case 2:
1401
+ mouseAction = scope.mouseButtons.RIGHT;
1402
+ break;
1403
+
1404
+ default:
1405
+ mouseAction = -1;
1406
+ }
1407
+ switch (mouseAction) {
1408
+ case MOUSE.DOLLY:
1409
+ if (scope.enableZoom === false) return;
1410
+ handleMouseDownDolly(event);
1411
+ scope.state = STATE.DOLLY;
1412
+ break;
1413
+
1414
+ case MOUSE.ROTATE:
1415
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
1416
+ if (scope.enablePan === false) return;
1417
+ handleMouseDownPan(event);
1418
+ scope.state = STATE.PAN;
1419
+ } else {
1420
+ if (scope.enableRotate === false) return;
1421
+ handleMouseDownRotate(event);
1422
+ scope.state = STATE.ROTATE;
1423
+ }
1424
+ break;
1425
+
1426
+ case MOUSE.PAN:
1427
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
1428
+ if (scope.enableRotate === false) return;
1429
+ handleMouseDownRotate(event);
1430
+ scope.state = STATE.ROTATE;
1431
+ } else {
1432
+ if (scope.enablePan === false) return;
1433
+ handleMouseDownPan(event);
1434
+ scope.state = STATE.PAN;
1435
+ }
1436
+ break;
1437
+
1438
+ default:
1439
+ scope.state = STATE.NONE;
1440
+ }
1441
+ if (scope.state !== STATE.NONE) {
1442
+ scope.dispatchEvent(_startEvent);
1443
+ }
1444
+ }
1445
+ function onMouseMove(event) {
1446
+ switch (scope.state) {
1447
+ case STATE.ROTATE:
1448
+ if (scope.enableRotate === false) return;
1449
+ handleMouseMoveRotate(event);
1450
+ break;
1451
+
1452
+ case STATE.DOLLY:
1453
+ if (scope.enableZoom === false) return;
1454
+ handleMouseMoveDolly(event);
1455
+ break;
1456
+
1457
+ case STATE.PAN:
1458
+ if (scope.enablePan === false) return;
1459
+ handleMouseMovePan(event);
1460
+ break;
1461
+ }
1462
+ }
1463
+ function onMouseWheel(event) {
1464
+ if (scope.enabled === false || scope.enableZoom === false || scope.state !== STATE.NONE) return;
1465
+ event.preventDefault();
1466
+ scope.dispatchEvent(_startEvent);
1467
+ handleMouseWheel(event);
1468
+ scope.dispatchEvent(_endEvent);
1469
+ }
1470
+ function onKeyDown(event) {
1471
+ if (scope.enabled === false || scope.enablePan === false) return;
1472
+ handleKeyDown(event);
1473
+ }
1474
+ function onTouchStart(event) {
1475
+ trackPointer(event);
1476
+ switch (scope.pointers.length) {
1477
+ case 1:
1478
+ switch (scope.touches.ONE) {
1479
+ case TOUCH.ROTATE:
1480
+ if (scope.enableRotate === false) return;
1481
+ handleTouchStartRotate();
1482
+ scope.state = STATE.TOUCH_ROTATE;
1483
+ break;
1484
+
1485
+ case TOUCH.PAN:
1486
+ if (scope.enablePan === false) return;
1487
+ handleTouchStartPan();
1488
+ scope.state = STATE.TOUCH_PAN;
1489
+ break;
1490
+
1491
+ default:
1492
+ scope.state = STATE.NONE;
1493
+ }
1494
+ break;
1495
+
1496
+ case 2:
1497
+ switch (scope.touches.TWO) {
1498
+ case TOUCH.DOLLY_PAN:
1499
+ if (scope.enableZoom === false && scope.enablePan === false) return;
1500
+ handleTouchStartDollyPan();
1501
+ scope.state = STATE.TOUCH_DOLLY_PAN;
1502
+ break;
1503
+
1504
+ case TOUCH.DOLLY_ROTATE:
1505
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
1506
+ handleTouchStartDollyRotate();
1507
+ scope.state = STATE.TOUCH_DOLLY_ROTATE;
1508
+ break;
1509
+
1510
+ default:
1511
+ scope.state = STATE.NONE;
1512
+ }
1513
+ break;
1514
+
1515
+ default:
1516
+ scope.state = STATE.NONE;
1517
+ }
1518
+ if (scope.state !== STATE.NONE) {
1519
+ scope.dispatchEvent(_startEvent);
1520
+ }
1521
+ }
1522
+ function onTouchMove(event) {
1523
+ trackPointer(event);
1524
+ switch (scope.state) {
1525
+ case STATE.TOUCH_ROTATE:
1526
+ if (scope.enableRotate === false) return;
1527
+ handleTouchMoveRotate(event);
1528
+ scope.update();
1529
+ break;
1530
+
1531
+ case STATE.TOUCH_PAN:
1532
+ if (scope.enablePan === false) return;
1533
+ handleTouchMovePan(event);
1534
+ scope.update();
1535
+ break;
1536
+
1537
+ case STATE.TOUCH_DOLLY_PAN:
1538
+ if (scope.enableZoom === false && scope.enablePan === false) return;
1539
+ handleTouchMoveDollyPan(event);
1540
+ scope.update();
1541
+ break;
1542
+
1543
+ case STATE.TOUCH_DOLLY_ROTATE:
1544
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
1545
+ handleTouchMoveDollyRotate(event);
1546
+ scope.update();
1547
+ break;
1548
+
1549
+ default:
1550
+ scope.state = STATE.NONE;
1551
+ }
1552
+ }
1553
+ function onContextMenu(event) {
1554
+ if (scope.enabled === false) return;
1555
+ event.preventDefault();
1556
+ }
1557
+ function addPointer(event) {
1558
+ scope.pointers.push(event);
1559
+ }
1560
+ function removePointer(event) {
1561
+ delete scope.pointerPositions[event.pointerId];
1562
+ for (let i = 0; i < scope.pointers.length; i++) {
1563
+ if (scope.pointers[i].pointerId == event.pointerId) {
1564
+ scope.pointers.splice(i, 1);
1565
+ return;
1566
+ }
1567
+ }
1568
+ }
1569
+ function trackPointer(event) {
1570
+ let position = scope.pointerPositions[event.pointerId];
1571
+ if (position === undefined) {
1572
+ position = new Vector2;
1573
+ scope.pointerPositions[event.pointerId] = position;
1574
+ }
1575
+ position.set(event.pageX, event.pageY);
1576
+ }
1577
+ function getSecondPointerPosition(event) {
1578
+ const pointer = event.pointerId === scope.pointers[0].pointerId ? scope.pointers[1] : scope.pointers[0];
1579
+ return scope.pointerPositions[pointer.pointerId];
1580
+ }
1581
+ scope.domElement.addEventListener("contextmenu", onContextMenu);
1582
+ scope.domElement.addEventListener("pointerdown", onPointerDown);
1583
+ scope.domElement.addEventListener("pointercancel", onPointerUp);
1584
+ scope.domElement.addEventListener("wheel", onMouseWheel, {
1585
+ passive: false
1586
+ });
1587
+ this.update();
1588
+ }
1589
+ }
1590
+
894
1591
  class OrbitDragger {
895
1592
  constructor(viewer) {
896
1593
  this.updateControls = () => {
@@ -905,6 +1602,27 @@ class OrbitDragger {
905
1602
  this.controlsChange = () => {
906
1603
  this.viewer.target.copy(this.orbit.target);
907
1604
  this.viewer.update();
1605
+ switch (this.orbit.state) {
1606
+ case STATE.PAN:
1607
+ case STATE.TOUCH_PAN:
1608
+ this.viewer.emitEvent({
1609
+ type: "pan",
1610
+ x: this.orbit.panEnd.x,
1611
+ y: this.orbit.panEnd.y,
1612
+ dX: this.orbit.panDelta.x,
1613
+ dY: this.orbit.panDelta.y
1614
+ });
1615
+ break;
1616
+
1617
+ case STATE.DOLLY:
1618
+ this.viewer.emitEvent({
1619
+ type: "zoomat",
1620
+ data: this.orbit.dollyScale,
1621
+ x: this.orbit.dollyEnd.x,
1622
+ y: this.orbit.dollyEnd.y
1623
+ });
1624
+ break;
1625
+ }
908
1626
  this.changed = true;
909
1627
  };
910
1628
  this.stopContextMenu = event => {
@@ -936,10 +1654,10 @@ class OrbitDragger {
936
1654
  this.updateControls();
937
1655
  }
938
1656
  dispose() {
939
- this.viewer.off("contextmenu", this.stopContextMenu);
940
- this.viewer.off("zoom", this.updateControls);
941
- this.viewer.off("viewposition", this.updateControls);
942
1657
  this.viewer.off("geometryend", this.updateControls);
1658
+ this.viewer.off("viewposition", this.updateControls);
1659
+ this.viewer.off("zoom", this.updateControls);
1660
+ this.viewer.off("contextmenu", this.stopContextMenu);
943
1661
  this.orbit.removeEventListener("change", this.controlsChange);
944
1662
  this.orbit.dispose();
945
1663
  }
@@ -2489,12 +3207,15 @@ class Viewer extends EventEmitter2 {
2489
3207
  render(time) {
2490
3208
  if (!this.renderNeeded) return;
2491
3209
  if (!this.renderer) return;
2492
- const clippingPlanes = this.renderer.clippingPlanes;
3210
+ this.renderNeeded = false;
2493
3211
  this.renderer.setViewport(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
3212
+ this.renderer.autoClear = true;
2494
3213
  this.renderer.render(this.scene, this.camera);
3214
+ const clippingPlanes = this.renderer.clippingPlanes;
2495
3215
  this.renderer.clippingPlanes = [];
2496
3216
  this.renderer.autoClear = false;
2497
3217
  this.renderer.render(this.helpers, this.camera);
3218
+ this.renderer.clippingPlanes = clippingPlanes;
2498
3219
  const deltaTime = (time - this.renderTime) / 1e3;
2499
3220
  this.renderTime = time;
2500
3221
  this.emitEvent({
@@ -2502,9 +3223,6 @@ class Viewer extends EventEmitter2 {
2502
3223
  time: time,
2503
3224
  deltaTime: deltaTime
2504
3225
  });
2505
- this.renderer.autoClear = true;
2506
- this.renderer.clippingPlanes = clippingPlanes;
2507
- this.renderNeeded = false;
2508
3226
  }
2509
3227
  update(force = false) {
2510
3228
  this.renderNeeded = true;
@@ -2628,6 +3346,30 @@ class Viewer extends EventEmitter2 {
2628
3346
  this.update(true);
2629
3347
  return this;
2630
3348
  }
3349
+ getSelected() {
3350
+ return this.executeCommand("getSelected");
3351
+ }
3352
+ setSelected(handles) {
3353
+ this.executeCommand("setSelected", handles);
3354
+ }
3355
+ clearSelected() {
3356
+ this.executeCommand("clearSelected");
3357
+ }
3358
+ hideSelected() {
3359
+ this.executeCommand("hideSelected");
3360
+ }
3361
+ isolateSelected() {
3362
+ this.executeCommand("isolateSelected");
3363
+ }
3364
+ showAll() {
3365
+ this.executeCommand("showAll");
3366
+ }
3367
+ explode(index = 0) {
3368
+ this.executeCommand("explode", index);
3369
+ }
3370
+ collect() {
3371
+ this.executeCommand("collect");
3372
+ }
2631
3373
  activeDragger() {
2632
3374
  return this._activeDragger;
2633
3375
  }
@@ -2665,12 +3407,6 @@ class Viewer extends EventEmitter2 {
2665
3407
  is3D() {
2666
3408
  return true;
2667
3409
  }
2668
- getSelected() {
2669
- return this.executeCommand("getSelected");
2670
- }
2671
- setSelected(handles) {
2672
- this.executeCommand("setSelected", handles);
2673
- }
2674
3410
  executeCommand(id, ...args) {
2675
3411
  return commands("ThreeJS").executeCommand(id, this, ...args);
2676
3412
  }