@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.
@@ -103,7 +103,8 @@
103
103
  reverseZoomWheel: false,
104
104
  enableZoomWheel: true,
105
105
  enableGestures: true,
106
- geometryType: "vsfx"
106
+ geometryType: "vsfx",
107
+ rulerUnit: "Default"
107
108
  };
108
109
  }
109
110
 
@@ -363,6 +364,13 @@
363
364
  this._data.geometryType = value;
364
365
  this.change();
365
366
  }
367
+ get rulerUnit() {
368
+ return this._data.rulerUnit;
369
+ }
370
+ set rulerUnit(value) {
371
+ this._data.rulerUnit = value;
372
+ this.change();
373
+ }
366
374
  }
367
375
 
368
376
  const CanvasEvents = [ "click", "contextmenu", "dblclick", "mousedown", "mouseleave", "mousemove", "mouseup", "pointercancel", "pointerdown", "pointerleave", "pointermove", "pointerup", "touchcancel", "touchend", "touchmove", "touchstart", "wheel" ];
@@ -432,62 +440,6 @@
432
440
  commands("ThreeJS").registerCommand("clearMarkup", (viewer) => console.warn("clearMarkup not implemented"));
433
441
  commands("ThreeJS").registerCommandAlias("clearMarkup", "clearOverlay");
434
442
 
435
- ///////////////////////////////////////////////////////////////////////////////
436
- // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
437
- // All rights reserved.
438
- //
439
- // This software and its documentation and related materials are owned by
440
- // the Alliance. The software may only be incorporated into application
441
- // programs owned by members of the Alliance, subject to a signed
442
- // Membership Agreement and Supplemental Software License Agreement with the
443
- // Alliance. The structure and organization of this software are the valuable
444
- // trade secrets of the Alliance and its suppliers. The software is also
445
- // protected by copyright law and international treaty provisions. Application
446
- // programs incorporating this software must include the following statement
447
- // with their copyright notices:
448
- //
449
- // This application incorporates Open Design Alliance software pursuant to a
450
- // license agreement with Open Design Alliance.
451
- // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance.
452
- // All rights reserved.
453
- //
454
- // By use of this software, its documentation or related materials, you
455
- // acknowledge and accept the above terms.
456
- ///////////////////////////////////////////////////////////////////////////////
457
- function clearSlices(viewer) {
458
- viewer.renderer.clippingPlanes = [];
459
- viewer.update();
460
- }
461
- commands("ThreeJS").registerCommand("clearSlices", clearSlices);
462
-
463
- ///////////////////////////////////////////////////////////////////////////////
464
- // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
465
- // All rights reserved.
466
- //
467
- // This software and its documentation and related materials are owned by
468
- // the Alliance. The software may only be incorporated into application
469
- // programs owned by members of the Alliance, subject to a signed
470
- // Membership Agreement and Supplemental Software License Agreement with the
471
- // Alliance. The structure and organization of this software are the valuable
472
- // trade secrets of the Alliance and its suppliers. The software is also
473
- // protected by copyright law and international treaty provisions. Application
474
- // programs incorporating this software must include the following statement
475
- // with their copyright notices:
476
- //
477
- // This application incorporates Open Design Alliance software pursuant to a
478
- // license agreement with Open Design Alliance.
479
- // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance.
480
- // All rights reserved.
481
- //
482
- // By use of this software, its documentation or related materials, you
483
- // acknowledge and accept the above terms.
484
- ///////////////////////////////////////////////////////////////////////////////
485
- function createPreview(viewer, type = "image/jpeg", encoderOptions = 0.25) {
486
- viewer.update(true);
487
- return viewer.canvas.toDataURL(type, encoderOptions);
488
- }
489
- commands("ThreeJS").registerCommand("createPreview", createPreview);
490
-
491
443
  /**
492
444
  * @license
493
445
  * Copyright 2010-2023 Three.js Authors
@@ -37506,51 +37458,118 @@
37506
37458
  // By use of this software, its documentation or related materials, you
37507
37459
  // acknowledge and accept the above terms.
37508
37460
  ///////////////////////////////////////////////////////////////////////////////
37509
- function calcObjectDepth(object, depth) {
37510
- let res = depth;
37511
- object.children.forEach((x) => {
37512
- const objectDepth = calcObjectDepth(x, depth + 1);
37513
- if (res < objectDepth)
37514
- res = objectDepth;
37515
- });
37516
- object.originalPosition = object.position.clone();
37517
- return res;
37518
- }
37519
- function explodeScene(scene, scale = 0) {
37520
- scale /= 100;
37521
- if (!scene.maxDepth)
37522
- scene.maxDepth = calcObjectDepth(scene, 1);
37523
- const maxDepth = scene.maxDepth;
37524
- let explodeDepth = scale * (maxDepth - 1) + 1;
37525
- if (maxDepth === 1)
37526
- explodeDepth = 1;
37527
- function explodeObject(object, depth, parentCenter, parentOffset) {
37528
- const objectBox = new Box3().setFromObject(object);
37529
- const objectCenter = objectBox.getCenter(new Vector3());
37530
- const objectOffset = parentOffset.clone();
37531
- if (depth > 0 && depth <= explodeDepth) {
37532
- const offset = objectCenter.clone().sub(parentCenter).multiplyScalar(scale);
37533
- objectOffset.add(offset);
37534
- }
37535
- object.children.forEach((object) => explodeObject(object, depth + 1, objectCenter, objectOffset));
37536
- const originalPosition = object.originalPosition;
37537
- object.position.copy(originalPosition);
37538
- if (scale > 0) {
37539
- const direction = objectCenter.sub(parentCenter).normalize();
37540
- object.position.add(direction.add(objectOffset));
37541
- }
37461
+ class SelectionComponent {
37462
+ constructor(viewer) {
37463
+ this.onPointerDown = (event) => {
37464
+ if (!event.isPrimary || event.button !== 0)
37465
+ return;
37466
+ this.getMousePosition(event, this.downPosition);
37467
+ };
37468
+ this.onPointerUp = (event) => {
37469
+ if (!event.isPrimary)
37470
+ return;
37471
+ const upPosition = this.getMousePosition(event, new Vector2());
37472
+ if (this.downPosition.distanceTo(upPosition) !== 0)
37473
+ return;
37474
+ const intersects = this.getPointerIntersects(upPosition);
37475
+ this.clearSelection();
37476
+ if (intersects.length > 0)
37477
+ this.select(intersects[0].object);
37478
+ this.viewer.update();
37479
+ this.viewer.emitEvent({ type: "select", data: undefined, handles: this.viewer.getSelected() });
37480
+ };
37481
+ this.onDoubleClick = (event) => {
37482
+ if (event.button !== 0)
37483
+ return;
37484
+ this.viewer.executeCommand("zoomToSelected");
37485
+ };
37486
+ this.optionsChange = () => {
37487
+ const { facesColor, facesTransparancy } = this.viewer.options;
37488
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
37489
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
37490
+ this.viewer.update();
37491
+ };
37492
+ this.viewer = viewer;
37493
+ this.raycaster = new Raycaster();
37494
+ this.downPosition = new Vector2();
37495
+ const { facesColor, facesTransparancy } = this.viewer.options;
37496
+ this.facesMaterial = new MeshBasicMaterial();
37497
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
37498
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
37499
+ this.facesMaterial.transparent = true;
37500
+ this.viewer.addEventListener("pointerdown", this.onPointerDown);
37501
+ this.viewer.addEventListener("pointerup", this.onPointerUp);
37502
+ this.viewer.addEventListener("dblclick", this.onDoubleClick);
37503
+ this.viewer.addEventListener("optionschange", this.optionsChange);
37504
+ }
37505
+ dispose() {
37506
+ this.facesMaterial.dispose();
37507
+ this.viewer.removeEventListener("pointerdown", this.onPointerDown);
37508
+ this.viewer.removeEventListener("pointerup", this.onPointerUp);
37509
+ this.viewer.removeEventListener("dblclick", this.onDoubleClick);
37510
+ this.viewer.removeEventListener("optionschange", this.optionsChange);
37511
+ }
37512
+ getMousePosition(event, position) {
37513
+ const rect = this.viewer.canvas.getBoundingClientRect();
37514
+ position.setX((event.clientX - rect.left) / rect.width);
37515
+ position.setY((event.clientY - rect.top) / rect.height);
37516
+ return position;
37517
+ }
37518
+ getPointerIntersects(position) {
37519
+ const mouse = new Vector2(position.x * 2 - 1, -(position.y * 2) + 1);
37520
+ this.raycaster.setFromCamera(mouse, this.viewer.camera);
37521
+ const objects = [];
37522
+ this.viewer.scene.traverseVisible((child) => objects.push(child));
37523
+ return this.raycaster.intersectObjects(objects, false);
37524
+ }
37525
+ select(object) {
37526
+ if (object.isSelected)
37527
+ return;
37528
+ object.isSelected = true;
37529
+ object.originalMaterial = object.material;
37530
+ object.material = this.facesMaterial;
37531
+ this.viewer.selected.push(object);
37532
+ }
37533
+ clearSelection() {
37534
+ this.viewer.selected.forEach((object) => {
37535
+ object.isSelected = false;
37536
+ object.material = object.originalMaterial;
37537
+ });
37538
+ this.viewer.selected.length = 0;
37542
37539
  }
37543
- const sceneExtents = new Box3().setFromObject(scene);
37544
- const sceneCenter = sceneExtents.getCenter(new Vector3());
37545
- explodeObject(scene, 0, sceneCenter, new Vector3(0, 0, 0));
37546
37540
  }
37547
- function explode(viewer, index = 0) {
37548
- viewer.models.forEach((gltf) => explodeScene(gltf.scene, index));
37541
+
37542
+ ///////////////////////////////////////////////////////////////////////////////
37543
+ // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
37544
+ // All rights reserved.
37545
+ //
37546
+ // This software and its documentation and related materials are owned by
37547
+ // the Alliance. The software may only be incorporated into application
37548
+ // programs owned by members of the Alliance, subject to a signed
37549
+ // Membership Agreement and Supplemental Software License Agreement with the
37550
+ // Alliance. The structure and organization of this software are the valuable
37551
+ // trade secrets of the Alliance and its suppliers. The software is also
37552
+ // protected by copyright law and international treaty provisions. Application
37553
+ // programs incorporating this software must include the following statement
37554
+ // with their copyright notices:
37555
+ //
37556
+ // This application incorporates Open Design Alliance software pursuant to a
37557
+ // license agreement with Open Design Alliance.
37558
+ // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance.
37559
+ // All rights reserved.
37560
+ //
37561
+ // By use of this software, its documentation or related materials, you
37562
+ // acknowledge and accept the above terms.
37563
+ ///////////////////////////////////////////////////////////////////////////////
37564
+ function clearSelected(viewer) {
37565
+ const selection = new SelectionComponent(viewer);
37566
+ selection.clearSelection();
37567
+ selection.dispose();
37549
37568
  viewer.update();
37550
- viewer.emit({ type: "explode", data: index });
37569
+ viewer.emitEvent({ type: "select", data: undefined, handles: [] });
37551
37570
  }
37552
- commands("ThreeJS").registerCommand("explode", explode);
37553
- commands("ThreeJS").registerCommand("collect", (viewer) => explode(viewer, 0));
37571
+ commands("ThreeJS").registerCommand("clearSelected", clearSelected);
37572
+ commands("ThreeJS").registerCommandAlias("clearSelected", "unselect");
37554
37573
 
37555
37574
  ///////////////////////////////////////////////////////////////////////////////
37556
37575
  // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
@@ -37574,54 +37593,11 @@
37574
37593
  // By use of this software, its documentation or related materials, you
37575
37594
  // acknowledge and accept the above terms.
37576
37595
  ///////////////////////////////////////////////////////////////////////////////
37577
- const defaultViewPositions = {
37578
- top: new Vector3(0, 0, 1),
37579
- bottom: new Vector3(0, 0, -1),
37580
- left: new Vector3(-1, 0, 0),
37581
- right: new Vector3(1, 0, 0),
37582
- front: new Vector3(0, 1, 0),
37583
- back: new Vector3(0, -1, 0),
37584
- sw: new Vector3(-0.5, -0.5, 1.0).normalize(),
37585
- se: new Vector3(0.5, -0.5, 1.0).normalize(),
37586
- ne: new Vector3(0.5, 0.5, 1.0).normalize(),
37587
- nw: new Vector3(-0.5, 0.5, 1.0).normalize(),
37588
- };
37589
- function setDefaultViewPosition(viewer, position) {
37590
- const direction = defaultViewPositions[position] || defaultViewPositions["sw"];
37591
- const camera = viewer.camera;
37592
- const center = viewer.extents.getCenter(new Vector3());
37593
- const sphere = viewer.extents.getBoundingSphere(new Sphere());
37594
- const offset = new Vector3().copy(direction).multiplyScalar(sphere.radius);
37595
- camera.position.copy(center);
37596
- camera.position.add(offset);
37597
- camera.rotation.set(0, 0, 0);
37598
- camera.lookAt(center);
37599
- camera.updateProjectionMatrix();
37596
+ function clearSlices(viewer) {
37597
+ viewer.renderer.clippingPlanes = [];
37600
37598
  viewer.update();
37601
- viewer.emit({ type: "viewposition", data: position });
37602
- viewer.executeCommand("zoomToExtents");
37603
37599
  }
37604
- commands("ThreeJS").registerCommand("setDefaultViewPosition", setDefaultViewPosition);
37605
- commands("ThreeJS").registerCommand("top", (viewer) => setDefaultViewPosition(viewer, "top"));
37606
- commands("ThreeJS").registerCommand("bottom", (viewer) => setDefaultViewPosition(viewer, "bottom"));
37607
- commands("ThreeJS").registerCommand("left", (viewer) => setDefaultViewPosition(viewer, "left"));
37608
- commands("ThreeJS").registerCommand("right", (viewer) => setDefaultViewPosition(viewer, "right"));
37609
- commands("ThreeJS").registerCommand("front", (viewer) => setDefaultViewPosition(viewer, "front"));
37610
- commands("ThreeJS").registerCommand("back", (viewer) => setDefaultViewPosition(viewer, "back"));
37611
- commands("ThreeJS").registerCommand("sw", (viewer) => setDefaultViewPosition(viewer, "sw"));
37612
- commands("ThreeJS").registerCommand("se", (viewer) => setDefaultViewPosition(viewer, "se"));
37613
- commands("ThreeJS").registerCommand("ne", (viewer) => setDefaultViewPosition(viewer, "ne"));
37614
- commands("ThreeJS").registerCommand("nw", (viewer) => setDefaultViewPosition(viewer, "nw"));
37615
- commands("ThreeJS").registerCommandAlias("top", "k3DViewTop");
37616
- commands("ThreeJS").registerCommandAlias("bottom", "k3DViewBottom");
37617
- commands("ThreeJS").registerCommandAlias("left", "k3DViewLeft");
37618
- commands("ThreeJS").registerCommandAlias("right", "k3DViewRight");
37619
- commands("ThreeJS").registerCommandAlias("front", "k3DViewFront");
37620
- commands("ThreeJS").registerCommandAlias("back", "k3DViewBack");
37621
- commands("ThreeJS").registerCommandAlias("se", "k3DViewSE");
37622
- commands("ThreeJS").registerCommandAlias("sw", "k3DViewSW");
37623
- commands("ThreeJS").registerCommandAlias("ne", "k3DViewNE");
37624
- commands("ThreeJS").registerCommandAlias("nw", "k3DViewNW");
37600
+ commands("ThreeJS").registerCommand("clearSlices", clearSlices);
37625
37601
 
37626
37602
  ///////////////////////////////////////////////////////////////////////////////
37627
37603
  // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
@@ -37645,10 +37621,11 @@
37645
37621
  // By use of this software, its documentation or related materials, you
37646
37622
  // acknowledge and accept the above terms.
37647
37623
  ///////////////////////////////////////////////////////////////////////////////
37648
- function getDefaultViewPositions() {
37649
- return Object.keys(defaultViewPositions);
37624
+ function createPreview(viewer, type = "image/jpeg", encoderOptions = 0.25) {
37625
+ viewer.update(true);
37626
+ return viewer.canvas.toDataURL(type, encoderOptions);
37650
37627
  }
37651
- commands("ThreeJS").registerCommand("getDefaultViewPositions", getDefaultViewPositions);
37628
+ commands("ThreeJS").registerCommand("createPreview", createPreview);
37652
37629
 
37653
37630
  ///////////////////////////////////////////////////////////////////////////////
37654
37631
  // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
@@ -37672,11 +37649,51 @@
37672
37649
  // By use of this software, its documentation or related materials, you
37673
37650
  // acknowledge and accept the above terms.
37674
37651
  ///////////////////////////////////////////////////////////////////////////////
37675
- function getModels(viewer) {
37676
- const handles = viewer.models.map((model) => model.userData.handle || "").filter((handle) => handle);
37677
- return handles;
37652
+ function calcObjectDepth(object, depth) {
37653
+ let res = depth;
37654
+ object.children.forEach((x) => {
37655
+ const objectDepth = calcObjectDepth(x, depth + 1);
37656
+ if (res < objectDepth)
37657
+ res = objectDepth;
37658
+ });
37659
+ object.originalPosition = object.position.clone();
37660
+ return res;
37678
37661
  }
37679
- commands("ThreeJS").registerCommand("getModels", getModels);
37662
+ function explodeScene(scene, scale = 0) {
37663
+ scale /= 100;
37664
+ if (!scene.maxDepth)
37665
+ scene.maxDepth = calcObjectDepth(scene, 1);
37666
+ const maxDepth = scene.maxDepth;
37667
+ let explodeDepth = scale * (maxDepth - 1) + 1;
37668
+ if (maxDepth === 1)
37669
+ explodeDepth = 1;
37670
+ function explodeObject(object, depth, parentCenter, parentOffset) {
37671
+ const objectBox = new Box3().setFromObject(object);
37672
+ const objectCenter = objectBox.getCenter(new Vector3());
37673
+ const objectOffset = parentOffset.clone();
37674
+ if (depth > 0 && depth <= explodeDepth) {
37675
+ const offset = objectCenter.clone().sub(parentCenter).multiplyScalar(scale);
37676
+ objectOffset.add(offset);
37677
+ }
37678
+ object.children.forEach((object) => explodeObject(object, depth + 1, objectCenter, objectOffset));
37679
+ const originalPosition = object.originalPosition;
37680
+ object.position.copy(originalPosition);
37681
+ if (scale > 0) {
37682
+ const direction = objectCenter.sub(parentCenter).normalize();
37683
+ object.position.add(direction.add(objectOffset));
37684
+ }
37685
+ }
37686
+ const sceneExtents = new Box3().setFromObject(scene);
37687
+ const sceneCenter = sceneExtents.getCenter(new Vector3());
37688
+ explodeObject(scene, 0, sceneCenter, new Vector3(0, 0, 0));
37689
+ }
37690
+ function explode(viewer, index = 0) {
37691
+ viewer.models.forEach((gltf) => explodeScene(gltf.scene, index));
37692
+ viewer.update();
37693
+ viewer.emitEvent({ type: "explode", data: index });
37694
+ }
37695
+ commands("ThreeJS").registerCommand("explode", explode);
37696
+ commands("ThreeJS").registerCommand("collect", (viewer) => explode(viewer, 0));
37680
37697
 
37681
37698
  ///////////////////////////////////////////////////////////////////////////////
37682
37699
  // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
@@ -37700,10 +37717,54 @@
37700
37717
  // By use of this software, its documentation or related materials, you
37701
37718
  // acknowledge and accept the above terms.
37702
37719
  ///////////////////////////////////////////////////////////////////////////////
37703
- function getSelected(viewer) {
37704
- return viewer.selected.map((object) => { var _a; return (_a = object.userData) === null || _a === void 0 ? void 0 : _a.handle; }).filter((handle) => handle);
37720
+ const defaultViewPositions = {
37721
+ top: new Vector3(0, 0, 1),
37722
+ bottom: new Vector3(0, 0, -1),
37723
+ left: new Vector3(-1, 0, 0),
37724
+ right: new Vector3(1, 0, 0),
37725
+ front: new Vector3(0, 1, 0),
37726
+ back: new Vector3(0, -1, 0),
37727
+ sw: new Vector3(-0.5, -0.5, 1.0).normalize(),
37728
+ se: new Vector3(0.5, -0.5, 1.0).normalize(),
37729
+ ne: new Vector3(0.5, 0.5, 1.0).normalize(),
37730
+ nw: new Vector3(-0.5, 0.5, 1.0).normalize(),
37731
+ };
37732
+ function setDefaultViewPosition(viewer, position) {
37733
+ const direction = defaultViewPositions[position] || defaultViewPositions["sw"];
37734
+ const camera = viewer.camera;
37735
+ const center = viewer.extents.getCenter(new Vector3());
37736
+ const sphere = viewer.extents.getBoundingSphere(new Sphere());
37737
+ const offset = new Vector3().copy(direction).multiplyScalar(sphere.radius);
37738
+ camera.position.copy(center);
37739
+ camera.position.add(offset);
37740
+ camera.rotation.set(0, 0, 0);
37741
+ camera.lookAt(center);
37742
+ camera.updateProjectionMatrix();
37743
+ viewer.update();
37744
+ viewer.emit({ type: "viewposition", data: position });
37745
+ viewer.executeCommand("zoomToExtents");
37705
37746
  }
37706
- commands("ThreeJS").registerCommand("getSelected", getSelected);
37747
+ commands("ThreeJS").registerCommand("setDefaultViewPosition", setDefaultViewPosition);
37748
+ commands("ThreeJS").registerCommand("top", (viewer) => setDefaultViewPosition(viewer, "top"));
37749
+ commands("ThreeJS").registerCommand("bottom", (viewer) => setDefaultViewPosition(viewer, "bottom"));
37750
+ commands("ThreeJS").registerCommand("left", (viewer) => setDefaultViewPosition(viewer, "left"));
37751
+ commands("ThreeJS").registerCommand("right", (viewer) => setDefaultViewPosition(viewer, "right"));
37752
+ commands("ThreeJS").registerCommand("front", (viewer) => setDefaultViewPosition(viewer, "front"));
37753
+ commands("ThreeJS").registerCommand("back", (viewer) => setDefaultViewPosition(viewer, "back"));
37754
+ commands("ThreeJS").registerCommand("sw", (viewer) => setDefaultViewPosition(viewer, "sw"));
37755
+ commands("ThreeJS").registerCommand("se", (viewer) => setDefaultViewPosition(viewer, "se"));
37756
+ commands("ThreeJS").registerCommand("ne", (viewer) => setDefaultViewPosition(viewer, "ne"));
37757
+ commands("ThreeJS").registerCommand("nw", (viewer) => setDefaultViewPosition(viewer, "nw"));
37758
+ commands("ThreeJS").registerCommandAlias("top", "k3DViewTop");
37759
+ commands("ThreeJS").registerCommandAlias("bottom", "k3DViewBottom");
37760
+ commands("ThreeJS").registerCommandAlias("left", "k3DViewLeft");
37761
+ commands("ThreeJS").registerCommandAlias("right", "k3DViewRight");
37762
+ commands("ThreeJS").registerCommandAlias("front", "k3DViewFront");
37763
+ commands("ThreeJS").registerCommandAlias("back", "k3DViewBack");
37764
+ commands("ThreeJS").registerCommandAlias("se", "k3DViewSE");
37765
+ commands("ThreeJS").registerCommandAlias("sw", "k3DViewSW");
37766
+ commands("ThreeJS").registerCommandAlias("ne", "k3DViewNE");
37767
+ commands("ThreeJS").registerCommandAlias("nw", "k3DViewNW");
37707
37768
 
37708
37769
  ///////////////////////////////////////////////////////////////////////////////
37709
37770
  // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
@@ -37727,86 +37788,65 @@
37727
37788
  // By use of this software, its documentation or related materials, you
37728
37789
  // acknowledge and accept the above terms.
37729
37790
  ///////////////////////////////////////////////////////////////////////////////
37730
- class SelectionComponent {
37731
- constructor(viewer) {
37732
- this.onPointerDown = (event) => {
37733
- if (!event.isPrimary || event.button !== 0)
37734
- return;
37735
- this.getMousePosition(event, this.downPosition);
37736
- };
37737
- this.onPointerUp = (event) => {
37738
- if (!event.isPrimary)
37739
- return;
37740
- const upPosition = this.getMousePosition(event, new Vector2());
37741
- if (this.downPosition.distanceTo(upPosition) !== 0)
37742
- return;
37743
- const intersects = this.getPointerIntersects(upPosition);
37744
- this.clearSelection();
37745
- if (intersects.length > 0)
37746
- this.select(intersects[0].object);
37747
- this.viewer.update();
37748
- this.viewer.emitEvent({ type: "select", data: undefined, handles: this.viewer.getSelected() });
37749
- };
37750
- this.onDoubleClick = (event) => {
37751
- if (event.button !== 0)
37752
- return;
37753
- this.viewer.executeCommand("zoomToSelected");
37754
- };
37755
- this.optionsChange = () => {
37756
- const { facesColor, facesTransparancy } = this.viewer.options;
37757
- this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
37758
- this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
37759
- this.viewer.update();
37760
- };
37761
- this.viewer = viewer;
37762
- this.raycaster = new Raycaster();
37763
- this.downPosition = new Vector2();
37764
- const { facesColor, facesTransparancy } = this.viewer.options;
37765
- this.facesMaterial = new MeshBasicMaterial();
37766
- this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
37767
- this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
37768
- this.facesMaterial.transparent = true;
37769
- this.viewer.addEventListener("pointerdown", this.onPointerDown);
37770
- this.viewer.addEventListener("pointerup", this.onPointerUp);
37771
- this.viewer.addEventListener("dblclick", this.onDoubleClick);
37772
- this.viewer.addEventListener("optionschange", this.optionsChange);
37773
- }
37774
- dispose() {
37775
- this.facesMaterial.dispose();
37776
- this.viewer.removeEventListener("pointerdown", this.onPointerDown);
37777
- this.viewer.removeEventListener("pointerup", this.onPointerUp);
37778
- this.viewer.removeEventListener("dblclick", this.onDoubleClick);
37779
- this.viewer.removeEventListener("optionschange", this.optionsChange);
37780
- }
37781
- getMousePosition(event, position) {
37782
- const rect = this.viewer.canvas.getBoundingClientRect();
37783
- position.setX((event.clientX - rect.left) / rect.width);
37784
- position.setY((event.clientY - rect.top) / rect.height);
37785
- return position;
37786
- }
37787
- getPointerIntersects(position) {
37788
- const mouse = new Vector2(position.x * 2 - 1, -(position.y * 2) + 1);
37789
- this.raycaster.setFromCamera(mouse, this.viewer.camera);
37790
- const objects = [];
37791
- this.viewer.scene.traverseVisible((child) => objects.push(child));
37792
- return this.raycaster.intersectObjects(objects, false);
37793
- }
37794
- select(object) {
37795
- if (object.isSelected)
37796
- return;
37797
- object.isSelected = true;
37798
- object.originalMaterial = object.material;
37799
- object.material = this.facesMaterial;
37800
- this.viewer.selected.push(object);
37801
- }
37802
- clearSelection() {
37803
- this.viewer.selected.forEach((object) => {
37804
- object.isSelected = false;
37805
- object.material = object.originalMaterial;
37806
- });
37807
- this.viewer.selected.length = 0;
37808
- }
37791
+ function getDefaultViewPositions() {
37792
+ return Object.keys(defaultViewPositions);
37809
37793
  }
37794
+ commands("ThreeJS").registerCommand("getDefaultViewPositions", getDefaultViewPositions);
37795
+
37796
+ ///////////////////////////////////////////////////////////////////////////////
37797
+ // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
37798
+ // All rights reserved.
37799
+ //
37800
+ // This software and its documentation and related materials are owned by
37801
+ // the Alliance. The software may only be incorporated into application
37802
+ // programs owned by members of the Alliance, subject to a signed
37803
+ // Membership Agreement and Supplemental Software License Agreement with the
37804
+ // Alliance. The structure and organization of this software are the valuable
37805
+ // trade secrets of the Alliance and its suppliers. The software is also
37806
+ // protected by copyright law and international treaty provisions. Application
37807
+ // programs incorporating this software must include the following statement
37808
+ // with their copyright notices:
37809
+ //
37810
+ // This application incorporates Open Design Alliance software pursuant to a
37811
+ // license agreement with Open Design Alliance.
37812
+ // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance.
37813
+ // All rights reserved.
37814
+ //
37815
+ // By use of this software, its documentation or related materials, you
37816
+ // acknowledge and accept the above terms.
37817
+ ///////////////////////////////////////////////////////////////////////////////
37818
+ function getModels(viewer) {
37819
+ const handles = viewer.models.map((model) => model.userData.handle || "").filter((handle) => handle);
37820
+ return handles;
37821
+ }
37822
+ commands("ThreeJS").registerCommand("getModels", getModels);
37823
+
37824
+ ///////////////////////////////////////////////////////////////////////////////
37825
+ // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
37826
+ // All rights reserved.
37827
+ //
37828
+ // This software and its documentation and related materials are owned by
37829
+ // the Alliance. The software may only be incorporated into application
37830
+ // programs owned by members of the Alliance, subject to a signed
37831
+ // Membership Agreement and Supplemental Software License Agreement with the
37832
+ // Alliance. The structure and organization of this software are the valuable
37833
+ // trade secrets of the Alliance and its suppliers. The software is also
37834
+ // protected by copyright law and international treaty provisions. Application
37835
+ // programs incorporating this software must include the following statement
37836
+ // with their copyright notices:
37837
+ //
37838
+ // This application incorporates Open Design Alliance software pursuant to a
37839
+ // license agreement with Open Design Alliance.
37840
+ // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance.
37841
+ // All rights reserved.
37842
+ //
37843
+ // By use of this software, its documentation or related materials, you
37844
+ // acknowledge and accept the above terms.
37845
+ ///////////////////////////////////////////////////////////////////////////////
37846
+ function getSelected(viewer) {
37847
+ return viewer.selected.map((object) => { var _a; return (_a = object.userData) === null || _a === void 0 ? void 0 : _a.handle; }).filter((handle) => handle);
37848
+ }
37849
+ commands("ThreeJS").registerCommand("getSelected", getSelected);
37810
37850
 
37811
37851
  ///////////////////////////////////////////////////////////////////////////////
37812
37852
  // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
@@ -37836,8 +37876,8 @@
37836
37876
  selection.clearSelection();
37837
37877
  selection.dispose();
37838
37878
  viewer.update();
37839
- viewer.emit({ type: "hide" });
37840
- viewer.emit({ type: "select", data: undefined, handles: [] });
37879
+ viewer.emitEvent({ type: "hide" });
37880
+ viewer.emitEvent({ type: "select", data: undefined, handles: [] });
37841
37881
  }
37842
37882
  commands("ThreeJS").registerCommand("hideSelected", hideSelected);
37843
37883
 
@@ -37879,7 +37919,7 @@
37879
37919
  }
37880
37920
  isolateObject(viewer.scene, 0);
37881
37921
  viewer.update();
37882
- viewer.emit({ type: "isolate" });
37922
+ viewer.emitEvent({ type: "isolate" });
37883
37923
  }
37884
37924
  commands("ThreeJS").registerCommand("isolateSelected", isolateSelected);
37885
37925
 
@@ -37938,7 +37978,7 @@
37938
37978
  viewer.executeCommand("clearSlices");
37939
37979
  viewer.executeCommand("clearOverlay");
37940
37980
  viewer.executeCommand("setMarkupColor");
37941
- viewer.executeCommand("unselect");
37981
+ viewer.executeCommand("clearSelected");
37942
37982
  viewer.executeCommand("showAll");
37943
37983
  viewer.executeCommand("explode", 0);
37944
37984
  viewer.executeCommand("zoomToExtents", true);
@@ -38063,7 +38103,7 @@
38063
38103
  objects.forEach((object) => selection.select(object));
38064
38104
  selection.dispose();
38065
38105
  viewer.update();
38066
- viewer.emit({ type: "select", data: undefined, handles });
38106
+ viewer.emitEvent({ type: "select", data: undefined, handles });
38067
38107
  }
38068
38108
  commands("ThreeJS").registerCommand("setSelected", setSelected);
38069
38109
 
@@ -38092,41 +38132,10 @@
38092
38132
  function showAll(viewer) {
38093
38133
  viewer.scene.traverse((object) => (object.visible = true));
38094
38134
  viewer.update();
38095
- viewer.emit({ type: "showall" });
38135
+ viewer.emitEvent({ type: "showall" });
38096
38136
  }
38097
38137
  commands("ThreeJS").registerCommand("showAll", showAll);
38098
38138
 
38099
- ///////////////////////////////////////////////////////////////////////////////
38100
- // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
38101
- // All rights reserved.
38102
- //
38103
- // This software and its documentation and related materials are owned by
38104
- // the Alliance. The software may only be incorporated into application
38105
- // programs owned by members of the Alliance, subject to a signed
38106
- // Membership Agreement and Supplemental Software License Agreement with the
38107
- // Alliance. The structure and organization of this software are the valuable
38108
- // trade secrets of the Alliance and its suppliers. The software is also
38109
- // protected by copyright law and international treaty provisions. Application
38110
- // programs incorporating this software must include the following statement
38111
- // with their copyright notices:
38112
- //
38113
- // This application incorporates Open Design Alliance software pursuant to a
38114
- // license agreement with Open Design Alliance.
38115
- // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance.
38116
- // All rights reserved.
38117
- //
38118
- // By use of this software, its documentation or related materials, you
38119
- // acknowledge and accept the above terms.
38120
- ///////////////////////////////////////////////////////////////////////////////
38121
- function unselect(viewer) {
38122
- const selection = new SelectionComponent(viewer);
38123
- selection.clearSelection();
38124
- selection.dispose();
38125
- viewer.update();
38126
- viewer.emit({ type: "select", data: undefined, handles: [] });
38127
- }
38128
- commands("ThreeJS").registerCommand("unselect", unselect);
38129
-
38130
38139
  ///////////////////////////////////////////////////////////////////////////////
38131
38140
  // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
38132
38141
  // All rights reserved.
@@ -42922,1252 +42931,1001 @@
42922
42931
  // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
42923
42932
  // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
42924
42933
 
42925
- const _changeEvent$2 = { type: 'change' };
42926
- const _startEvent = { type: 'start' };
42927
- const _endEvent = { type: 'end' };
42934
+ const _changeEvent$2 = { type: "change" };
42935
+ const _startEvent = { type: "start" };
42936
+ const _endEvent = { type: "end" };
42937
+
42938
+ const STATE = {
42939
+ NONE: -1,
42940
+ ROTATE: 0,
42941
+ DOLLY: 1,
42942
+ PAN: 2,
42943
+ TOUCH_ROTATE: 3,
42944
+ TOUCH_PAN: 4,
42945
+ TOUCH_DOLLY_PAN: 5,
42946
+ TOUCH_DOLLY_ROTATE: 6,
42947
+ };
42928
42948
 
42929
42949
  class OrbitControls extends EventDispatcher {
42950
+ constructor(object, domElement) {
42951
+ super();
42930
42952
 
42931
- constructor( object, domElement ) {
42932
-
42933
- super();
42934
-
42935
- this.object = object;
42936
- this.domElement = domElement;
42937
- this.domElement.style.touchAction = 'none'; // disable touch scroll
42938
-
42939
- // Set to false to disable this control
42940
- this.enabled = true;
42941
-
42942
- // "target" sets the location of focus, where the object orbits around
42943
- this.target = new Vector3();
42944
-
42945
- // How far you can dolly in and out ( PerspectiveCamera only )
42946
- this.minDistance = 0;
42947
- this.maxDistance = Infinity;
42948
-
42949
- // How far you can zoom in and out ( OrthographicCamera only )
42950
- this.minZoom = 0;
42951
- this.maxZoom = Infinity;
42952
-
42953
- // How far you can orbit vertically, upper and lower limits.
42954
- // Range is 0 to Math.PI radians.
42955
- this.minPolarAngle = 0; // radians
42956
- this.maxPolarAngle = Math.PI; // radians
42957
-
42958
- // How far you can orbit horizontally, upper and lower limits.
42959
- // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
42960
- this.minAzimuthAngle = - Infinity; // radians
42961
- this.maxAzimuthAngle = Infinity; // radians
42962
-
42963
- // Set to true to enable damping (inertia)
42964
- // If damping is enabled, you must call controls.update() in your animation loop
42965
- this.enableDamping = false;
42966
- this.dampingFactor = 0.05;
42967
-
42968
- // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
42969
- // Set to false to disable zooming
42970
- this.enableZoom = true;
42971
- this.zoomSpeed = 1.0;
42972
-
42973
- // Set to false to disable rotating
42974
- this.enableRotate = true;
42975
- this.rotateSpeed = 1.0;
42976
-
42977
- // Set to false to disable panning
42978
- this.enablePan = true;
42979
- this.panSpeed = 1.0;
42980
- this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
42981
- this.keyPanSpeed = 7.0; // pixels moved per arrow key push
42982
-
42983
- // Set to true to automatically rotate around the target
42984
- // If auto-rotate is enabled, you must call controls.update() in your animation loop
42985
- this.autoRotate = false;
42986
- this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60
42987
-
42988
- // The four arrow keys
42989
- this.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };
42990
-
42991
- // Mouse buttons
42992
- this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };
42993
-
42994
- // Touch fingers
42995
- this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };
42996
-
42997
- // for reset
42998
- this.target0 = this.target.clone();
42999
- this.position0 = this.object.position.clone();
43000
- this.zoom0 = this.object.zoom;
43001
-
43002
- // the target DOM element for key events
43003
- this._domElementKeyEvents = null;
43004
-
43005
- //
43006
- // public methods
43007
- //
43008
-
43009
- this.getPolarAngle = function () {
43010
-
43011
- return spherical.phi;
43012
-
43013
- };
43014
-
43015
- this.getAzimuthalAngle = function () {
43016
-
43017
- return spherical.theta;
43018
-
43019
- };
43020
-
43021
- this.getDistance = function () {
43022
-
43023
- return this.object.position.distanceTo( this.target );
43024
-
43025
- };
43026
-
43027
- this.listenToKeyEvents = function ( domElement ) {
43028
-
43029
- domElement.addEventListener( 'keydown', onKeyDown );
43030
- this._domElementKeyEvents = domElement;
43031
-
43032
- };
43033
-
43034
- this.stopListenToKeyEvents = function () {
43035
-
43036
- this._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
43037
- this._domElementKeyEvents = null;
43038
-
43039
- };
43040
-
43041
- this.saveState = function () {
43042
-
43043
- scope.target0.copy( scope.target );
43044
- scope.position0.copy( scope.object.position );
43045
- scope.zoom0 = scope.object.zoom;
43046
-
43047
- };
43048
-
43049
- this.reset = function () {
43050
-
43051
- scope.target.copy( scope.target0 );
43052
- scope.object.position.copy( scope.position0 );
43053
- scope.object.zoom = scope.zoom0;
43054
-
43055
- scope.object.updateProjectionMatrix();
43056
- scope.dispatchEvent( _changeEvent$2 );
43057
-
43058
- scope.update();
43059
-
43060
- state = STATE.NONE;
43061
-
43062
- };
43063
-
43064
- // this method is exposed, but perhaps it would be better if we can make it private...
43065
- this.update = function () {
43066
-
43067
- const offset = new Vector3();
43068
-
43069
- // so camera.up is the orbit axis
43070
- const quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );
43071
- const quatInverse = quat.clone().invert();
43072
-
43073
- const lastPosition = new Vector3();
43074
- const lastQuaternion = new Quaternion();
43075
- const lastTargetPosition = new Vector3();
43076
-
43077
- const twoPI = 2 * Math.PI;
43078
-
43079
- return function update() {
43080
-
43081
- const position = scope.object.position;
43082
-
43083
- offset.copy( position ).sub( scope.target );
43084
-
43085
- // rotate offset to "y-axis-is-up" space
43086
- offset.applyQuaternion( quat );
43087
-
43088
- // angle from z-axis around y-axis
43089
- spherical.setFromVector3( offset );
43090
-
43091
- if ( scope.autoRotate && state === STATE.NONE ) {
43092
-
43093
- rotateLeft( getAutoRotationAngle() );
43094
-
43095
- }
43096
-
43097
- if ( scope.enableDamping ) {
43098
-
43099
- spherical.theta += sphericalDelta.theta * scope.dampingFactor;
43100
- spherical.phi += sphericalDelta.phi * scope.dampingFactor;
43101
-
43102
- } else {
43103
-
43104
- spherical.theta += sphericalDelta.theta;
43105
- spherical.phi += sphericalDelta.phi;
43106
-
43107
- }
43108
-
43109
- // restrict theta to be between desired limits
43110
-
43111
- let min = scope.minAzimuthAngle;
43112
- let max = scope.maxAzimuthAngle;
43113
-
43114
- if ( isFinite( min ) && isFinite( max ) ) {
43115
-
43116
- if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;
43117
-
43118
- if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;
43119
-
43120
- if ( min <= max ) {
43121
-
43122
- spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );
43123
-
43124
- } else {
43125
-
43126
- spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?
43127
- Math.max( min, spherical.theta ) :
43128
- Math.min( max, spherical.theta );
43129
-
43130
- }
43131
-
43132
- }
43133
-
43134
- // restrict phi to be between desired limits
43135
- spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
43136
-
43137
- spherical.makeSafe();
43138
-
43139
-
43140
- spherical.radius *= scale;
43141
-
43142
- // restrict radius to be between desired limits
43143
- spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
43144
-
43145
- // move target to panned location
43146
-
43147
- if ( scope.enableDamping === true ) {
43148
-
43149
- scope.target.addScaledVector( panOffset, scope.dampingFactor );
43150
-
43151
- } else {
43152
-
43153
- scope.target.add( panOffset );
43154
-
43155
- }
43156
-
43157
- offset.setFromSpherical( spherical );
43158
-
43159
- // rotate offset back to "camera-up-vector-is-up" space
43160
- offset.applyQuaternion( quatInverse );
43161
-
43162
- position.copy( scope.target ).add( offset );
43163
-
43164
- scope.object.lookAt( scope.target );
43165
-
43166
- if ( scope.enableDamping === true ) {
43167
-
43168
- sphericalDelta.theta *= ( 1 - scope.dampingFactor );
43169
- sphericalDelta.phi *= ( 1 - scope.dampingFactor );
43170
-
43171
- panOffset.multiplyScalar( 1 - scope.dampingFactor );
43172
-
43173
- } else {
43174
-
43175
- sphericalDelta.set( 0, 0, 0 );
43176
-
43177
- panOffset.set( 0, 0, 0 );
43178
-
43179
- }
43180
-
43181
- scale = 1;
43182
-
43183
- // update condition is:
43184
- // min(camera displacement, camera rotation in radians)^2 > EPS
43185
- // using small-angle approximation cos(x/2) = 1 - x^2 / 8
43186
-
43187
- if ( zoomChanged ||
43188
- lastPosition.distanceToSquared( scope.object.position ) > EPS ||
43189
- 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ||
43190
- lastTargetPosition.distanceToSquared( scope.target ) > 0 ) {
43191
-
43192
- scope.dispatchEvent( _changeEvent$2 );
43193
-
43194
- lastPosition.copy( scope.object.position );
43195
- lastQuaternion.copy( scope.object.quaternion );
43196
- lastTargetPosition.copy( scope.target );
43197
-
43198
- zoomChanged = false;
43199
-
43200
- return true;
43201
-
43202
- }
43203
-
43204
- return false;
43205
-
43206
- };
43207
-
43208
- }();
43209
-
43210
- this.dispose = function () {
43211
-
43212
- scope.domElement.removeEventListener( 'contextmenu', onContextMenu );
43213
-
43214
- scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
43215
- scope.domElement.removeEventListener( 'pointercancel', onPointerUp );
43216
- scope.domElement.removeEventListener( 'wheel', onMouseWheel );
43217
-
43218
- scope.domElement.removeEventListener( 'pointermove', onPointerMove );
43219
- scope.domElement.removeEventListener( 'pointerup', onPointerUp );
43220
-
43221
-
43222
- if ( scope._domElementKeyEvents !== null ) {
43223
-
43224
- scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
43225
- scope._domElementKeyEvents = null;
43226
-
43227
- }
43228
-
43229
- //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
43230
-
43231
- };
43232
-
43233
- //
43234
- // internals
43235
- //
43236
-
43237
- const scope = this;
43238
-
43239
- const STATE = {
43240
- NONE: - 1,
43241
- ROTATE: 0,
43242
- DOLLY: 1,
43243
- PAN: 2,
43244
- TOUCH_ROTATE: 3,
43245
- TOUCH_PAN: 4,
43246
- TOUCH_DOLLY_PAN: 5,
43247
- TOUCH_DOLLY_ROTATE: 6
43248
- };
43249
-
43250
- let state = STATE.NONE;
43251
-
43252
- const EPS = 0.000001;
43253
-
43254
- // current position in spherical coordinates
43255
- const spherical = new Spherical();
43256
- const sphericalDelta = new Spherical();
43257
-
43258
- let scale = 1;
43259
- const panOffset = new Vector3();
43260
- let zoomChanged = false;
43261
-
43262
- const rotateStart = new Vector2();
43263
- const rotateEnd = new Vector2();
43264
- const rotateDelta = new Vector2();
43265
-
43266
- const panStart = new Vector2();
43267
- const panEnd = new Vector2();
43268
- const panDelta = new Vector2();
43269
-
43270
- const dollyStart = new Vector2();
43271
- const dollyEnd = new Vector2();
43272
- const dollyDelta = new Vector2();
43273
-
43274
- const pointers = [];
43275
- const pointerPositions = {};
43276
-
43277
- function getAutoRotationAngle() {
43278
-
43279
- return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
43280
-
43281
- }
43282
-
43283
- function getZoomScale() {
43284
-
43285
- return Math.pow( 0.95, scope.zoomSpeed );
43286
-
43287
- }
43288
-
43289
- function rotateLeft( angle ) {
43290
-
43291
- sphericalDelta.theta -= angle;
43292
-
43293
- }
43294
-
43295
- function rotateUp( angle ) {
43296
-
43297
- sphericalDelta.phi -= angle;
43298
-
43299
- }
43300
-
43301
- const panLeft = function () {
43302
-
43303
- const v = new Vector3();
43304
-
43305
- return function panLeft( distance, objectMatrix ) {
43306
-
43307
- v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
43308
- v.multiplyScalar( - distance );
43309
-
43310
- panOffset.add( v );
43311
-
43312
- };
43313
-
43314
- }();
43315
-
43316
- const panUp = function () {
43317
-
43318
- const v = new Vector3();
43319
-
43320
- return function panUp( distance, objectMatrix ) {
43321
-
43322
- if ( scope.screenSpacePanning === true ) {
43323
-
43324
- v.setFromMatrixColumn( objectMatrix, 1 );
43325
-
43326
- } else {
43327
-
43328
- v.setFromMatrixColumn( objectMatrix, 0 );
43329
- v.crossVectors( scope.object.up, v );
43330
-
43331
- }
43332
-
43333
- v.multiplyScalar( distance );
43334
-
43335
- panOffset.add( v );
43336
-
43337
- };
43338
-
43339
- }();
43340
-
43341
- // deltaX and deltaY are in pixels; right and down are positive
43342
- const pan = function () {
43343
-
43344
- const offset = new Vector3();
43345
-
43346
- return function pan( deltaX, deltaY ) {
43347
-
43348
- const element = scope.domElement;
43349
-
43350
- if ( scope.object.isPerspectiveCamera ) {
43351
-
43352
- // perspective
43353
- const position = scope.object.position;
43354
- offset.copy( position ).sub( scope.target );
43355
- let targetDistance = offset.length();
43356
-
43357
- // half of the fov is center to top of screen
43358
- targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
43359
-
43360
- // we use only clientHeight here so aspect ratio does not distort speed
43361
- panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
43362
- panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
43363
-
43364
- } else if ( scope.object.isOrthographicCamera ) {
43365
-
43366
- // orthographic
43367
- panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
43368
- panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
43369
-
43370
- } else {
43371
-
43372
- // camera neither orthographic nor perspective
43373
- console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
43374
- scope.enablePan = false;
43375
-
43376
- }
43377
-
43378
- };
43379
-
43380
- }();
43381
-
43382
- function dollyOut( dollyScale ) {
43383
-
43384
- if ( scope.object.isPerspectiveCamera ) {
43385
-
43386
- scale /= dollyScale;
43387
-
43388
- } else if ( scope.object.isOrthographicCamera ) {
43389
-
43390
- scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
43391
- scope.object.updateProjectionMatrix();
43392
- zoomChanged = true;
43393
-
43394
- } else {
43395
-
43396
- console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
43397
- scope.enableZoom = false;
43398
-
43399
- }
43400
-
43401
- }
43402
-
43403
- function dollyIn( dollyScale ) {
43404
-
43405
- if ( scope.object.isPerspectiveCamera ) {
43406
-
43407
- scale *= dollyScale;
43408
-
43409
- } else if ( scope.object.isOrthographicCamera ) {
43410
-
43411
- scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
43412
- scope.object.updateProjectionMatrix();
43413
- zoomChanged = true;
43414
-
43415
- } else {
43416
-
43417
- console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
43418
- scope.enableZoom = false;
43419
-
43420
- }
43421
-
43422
- }
43423
-
43424
- //
43425
- // event callbacks - update the object state
43426
- //
43427
-
43428
- function handleMouseDownRotate( event ) {
43429
-
43430
- rotateStart.set( event.clientX, event.clientY );
43431
-
43432
- }
43433
-
43434
- function handleMouseDownDolly( event ) {
43435
-
43436
- dollyStart.set( event.clientX, event.clientY );
43437
-
43438
- }
43439
-
43440
- function handleMouseDownPan( event ) {
43441
-
43442
- panStart.set( event.clientX, event.clientY );
43443
-
43444
- }
43445
-
43446
- function handleMouseMoveRotate( event ) {
43447
-
43448
- rotateEnd.set( event.clientX, event.clientY );
43449
-
43450
- rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
43451
-
43452
- const element = scope.domElement;
43453
-
43454
- rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
43455
-
43456
- rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
43457
-
43458
- rotateStart.copy( rotateEnd );
43459
-
43460
- scope.update();
43461
-
43462
- }
43463
-
43464
- function handleMouseMoveDolly( event ) {
43465
-
43466
- dollyEnd.set( event.clientX, event.clientY );
43467
-
43468
- dollyDelta.subVectors( dollyEnd, dollyStart );
43469
-
43470
- if ( dollyDelta.y > 0 ) {
43471
-
43472
- dollyOut( getZoomScale() );
43473
-
43474
- } else if ( dollyDelta.y < 0 ) {
43475
-
43476
- dollyIn( getZoomScale() );
43477
-
43478
- }
43479
-
43480
- dollyStart.copy( dollyEnd );
42953
+ this.object = object;
42954
+ this.domElement = domElement;
42955
+ this.domElement.style.touchAction = "none"; // disable touch scroll
43481
42956
 
43482
- scope.update();
42957
+ // Set to false to disable this control
42958
+ this.enabled = true;
43483
42959
 
43484
- }
43485
-
43486
- function handleMouseMovePan( event ) {
43487
-
43488
- panEnd.set( event.clientX, event.clientY );
43489
-
43490
- panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
43491
-
43492
- pan( panDelta.x, panDelta.y );
43493
-
43494
- panStart.copy( panEnd );
43495
-
43496
- scope.update();
43497
-
43498
- }
43499
-
43500
- function handleMouseWheel( event ) {
43501
-
43502
- if ( event.deltaY < 0 ) {
43503
-
43504
- dollyIn( getZoomScale() );
43505
-
43506
- } else if ( event.deltaY > 0 ) {
43507
-
43508
- dollyOut( getZoomScale() );
43509
-
43510
- }
43511
-
43512
- scope.update();
43513
-
43514
- }
43515
-
43516
- function handleKeyDown( event ) {
43517
-
43518
- let needsUpdate = false;
43519
-
43520
- switch ( event.code ) {
43521
-
43522
- case scope.keys.UP:
43523
-
43524
- if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
43525
-
43526
- rotateUp( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
43527
-
43528
- } else {
43529
-
43530
- pan( 0, scope.keyPanSpeed );
43531
-
43532
- }
43533
-
43534
- needsUpdate = true;
43535
- break;
43536
-
43537
- case scope.keys.BOTTOM:
43538
-
43539
- if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
43540
-
43541
- rotateUp( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
43542
-
43543
- } else {
43544
-
43545
- pan( 0, - scope.keyPanSpeed );
43546
-
43547
- }
43548
-
43549
- needsUpdate = true;
43550
- break;
43551
-
43552
- case scope.keys.LEFT:
43553
-
43554
- if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
43555
-
43556
- rotateLeft( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
43557
-
43558
- } else {
43559
-
43560
- pan( scope.keyPanSpeed, 0 );
43561
-
43562
- }
43563
-
43564
- needsUpdate = true;
43565
- break;
43566
-
43567
- case scope.keys.RIGHT:
43568
-
43569
- if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
43570
-
43571
- rotateLeft( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
43572
-
43573
- } else {
43574
-
43575
- pan( - scope.keyPanSpeed, 0 );
43576
-
43577
- }
43578
-
43579
- needsUpdate = true;
43580
- break;
43581
-
43582
- }
43583
-
43584
- if ( needsUpdate ) {
43585
-
43586
- // prevent the browser from scrolling on cursor keys
43587
- event.preventDefault();
42960
+ // "target" sets the location of focus, where the object orbits around
42961
+ this.target = new Vector3();
43588
42962
 
43589
- scope.update();
42963
+ // How far you can dolly in and out ( PerspectiveCamera only )
42964
+ this.minDistance = 0;
42965
+ this.maxDistance = Infinity;
43590
42966
 
43591
- }
43592
-
43593
-
43594
- }
43595
-
43596
- function handleTouchStartRotate() {
43597
-
43598
- if ( pointers.length === 1 ) {
43599
-
43600
- rotateStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
43601
-
43602
- } else {
42967
+ // How far you can zoom in and out ( OrthographicCamera only )
42968
+ this.minZoom = 0;
42969
+ this.maxZoom = Infinity;
43603
42970
 
43604
- const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
43605
- const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
42971
+ // How far you can orbit vertically, upper and lower limits.
42972
+ // Range is 0 to Math.PI radians.
42973
+ this.minPolarAngle = 0; // radians
42974
+ this.maxPolarAngle = Math.PI; // radians
43606
42975
 
43607
- rotateStart.set( x, y );
42976
+ // How far you can orbit horizontally, upper and lower limits.
42977
+ // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
42978
+ this.minAzimuthAngle = -Infinity; // radians
42979
+ this.maxAzimuthAngle = Infinity; // radians
43608
42980
 
43609
- }
43610
-
43611
- }
42981
+ // Set to true to enable damping (inertia)
42982
+ // If damping is enabled, you must call controls.update() in your animation loop
42983
+ this.enableDamping = false;
42984
+ this.dampingFactor = 0.05;
43612
42985
 
43613
- function handleTouchStartPan() {
42986
+ // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
42987
+ // Set to false to disable zooming
42988
+ this.enableZoom = true;
42989
+ this.zoomSpeed = 1.0;
43614
42990
 
43615
- if ( pointers.length === 1 ) {
42991
+ // Set to false to disable rotating
42992
+ this.enableRotate = true;
42993
+ this.rotateSpeed = 1.0;
43616
42994
 
43617
- panStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
43618
-
43619
- } else {
42995
+ // Set to false to disable panning
42996
+ this.enablePan = true;
42997
+ this.panSpeed = 1.0;
42998
+ this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
42999
+ this.keyPanSpeed = 7.0; // pixels moved per arrow key push
43620
43000
 
43621
- const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
43622
- const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
43001
+ // Set to true to automatically rotate around the target
43002
+ // If auto-rotate is enabled, you must call controls.update() in your animation loop
43003
+ this.autoRotate = false;
43004
+ this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60
43623
43005
 
43624
- panStart.set( x, y );
43625
-
43626
- }
43627
-
43628
- }
43006
+ // The four arrow keys
43007
+ this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
43629
43008
 
43630
- function handleTouchStartDolly() {
43009
+ // Mouse buttons
43010
+ this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };
43631
43011
 
43632
- const dx = pointers[ 0 ].pageX - pointers[ 1 ].pageX;
43633
- const dy = pointers[ 0 ].pageY - pointers[ 1 ].pageY;
43012
+ // Touch fingers
43013
+ this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };
43634
43014
 
43635
- const distance = Math.sqrt( dx * dx + dy * dy );
43015
+ // for reset
43016
+ this.target0 = this.target.clone();
43017
+ this.position0 = this.object.position.clone();
43018
+ this.zoom0 = this.object.zoom;
43636
43019
 
43637
- dollyStart.set( 0, distance );
43638
-
43639
- }
43640
-
43641
- function handleTouchStartDollyPan() {
43642
-
43643
- if ( scope.enableZoom ) handleTouchStartDolly();
43644
-
43645
- if ( scope.enablePan ) handleTouchStartPan();
43646
-
43647
- }
43648
-
43649
- function handleTouchStartDollyRotate() {
43650
-
43651
- if ( scope.enableZoom ) handleTouchStartDolly();
43652
-
43653
- if ( scope.enableRotate ) handleTouchStartRotate();
43654
-
43655
- }
43656
-
43657
- function handleTouchMoveRotate( event ) {
43658
-
43659
- if ( pointers.length == 1 ) {
43660
-
43661
- rotateEnd.set( event.pageX, event.pageY );
43662
-
43663
- } else {
43020
+ // the target DOM element for key events
43021
+ this._domElementKeyEvents = null;
43664
43022
 
43665
- const position = getSecondPointerPosition( event );
43023
+ //
43024
+ // public methods
43025
+ //
43666
43026
 
43667
- const x = 0.5 * ( event.pageX + position.x );
43668
- const y = 0.5 * ( event.pageY + position.y );
43027
+ this.getPolarAngle = function () {
43028
+ return spherical.phi;
43029
+ };
43669
43030
 
43670
- rotateEnd.set( x, y );
43031
+ this.getAzimuthalAngle = function () {
43032
+ return spherical.theta;
43033
+ };
43671
43034
 
43672
- }
43035
+ this.getDistance = function () {
43036
+ return this.object.position.distanceTo(this.target);
43037
+ };
43673
43038
 
43674
- rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
43039
+ this.listenToKeyEvents = function (domElement) {
43040
+ domElement.addEventListener("keydown", onKeyDown);
43041
+ this._domElementKeyEvents = domElement;
43042
+ };
43675
43043
 
43676
- const element = scope.domElement;
43044
+ this.stopListenToKeyEvents = function () {
43045
+ this._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
43046
+ this._domElementKeyEvents = null;
43047
+ };
43677
43048
 
43678
- rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
43049
+ this.saveState = function () {
43050
+ scope.target0.copy(scope.target);
43051
+ scope.position0.copy(scope.object.position);
43052
+ scope.zoom0 = scope.object.zoom;
43053
+ };
43679
43054
 
43680
- rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
43055
+ this.reset = function () {
43056
+ scope.target.copy(scope.target0);
43057
+ scope.object.position.copy(scope.position0);
43058
+ scope.object.zoom = scope.zoom0;
43681
43059
 
43682
- rotateStart.copy( rotateEnd );
43060
+ scope.object.updateProjectionMatrix();
43061
+ scope.dispatchEvent(_changeEvent$2);
43683
43062
 
43684
- }
43063
+ scope.update();
43685
43064
 
43686
- function handleTouchMovePan( event ) {
43065
+ scope.state = STATE.NONE;
43066
+ };
43687
43067
 
43688
- if ( pointers.length === 1 ) {
43068
+ // this method is exposed, but perhaps it would be better if we can make it private...
43069
+ this.update = (function () {
43070
+ const offset = new Vector3();
43689
43071
 
43690
- panEnd.set( event.pageX, event.pageY );
43072
+ // so camera.up is the orbit axis
43073
+ const quat = new Quaternion().setFromUnitVectors(object.up, new Vector3(0, 1, 0));
43074
+ const quatInverse = quat.clone().invert();
43691
43075
 
43692
- } else {
43076
+ const lastPosition = new Vector3();
43077
+ const lastQuaternion = new Quaternion();
43078
+ const lastTargetPosition = new Vector3();
43693
43079
 
43694
- const position = getSecondPointerPosition( event );
43080
+ const twoPI = 2 * Math.PI;
43695
43081
 
43696
- const x = 0.5 * ( event.pageX + position.x );
43697
- const y = 0.5 * ( event.pageY + position.y );
43082
+ return function update() {
43083
+ const position = scope.object.position;
43698
43084
 
43699
- panEnd.set( x, y );
43085
+ offset.copy(position).sub(scope.target);
43700
43086
 
43701
- }
43087
+ // rotate offset to "y-axis-is-up" space
43088
+ offset.applyQuaternion(quat);
43702
43089
 
43703
- panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
43090
+ // angle from z-axis around y-axis
43091
+ spherical.setFromVector3(offset);
43704
43092
 
43705
- pan( panDelta.x, panDelta.y );
43093
+ if (scope.autoRotate && scope.state === STATE.NONE) {
43094
+ rotateLeft(getAutoRotationAngle());
43095
+ }
43706
43096
 
43707
- panStart.copy( panEnd );
43097
+ if (scope.enableDamping) {
43098
+ spherical.theta += sphericalDelta.theta * scope.dampingFactor;
43099
+ spherical.phi += sphericalDelta.phi * scope.dampingFactor;
43100
+ } else {
43101
+ spherical.theta += sphericalDelta.theta;
43102
+ spherical.phi += sphericalDelta.phi;
43103
+ }
43708
43104
 
43709
- }
43105
+ // restrict theta to be between desired limits
43710
43106
 
43711
- function handleTouchMoveDolly( event ) {
43107
+ let min = scope.minAzimuthAngle;
43108
+ let max = scope.maxAzimuthAngle;
43712
43109
 
43713
- const position = getSecondPointerPosition( event );
43110
+ if (isFinite(min) && isFinite(max)) {
43111
+ if (min < -Math.PI) min += twoPI;
43112
+ else if (min > Math.PI) min -= twoPI;
43714
43113
 
43715
- const dx = event.pageX - position.x;
43716
- const dy = event.pageY - position.y;
43114
+ if (max < -Math.PI) max += twoPI;
43115
+ else if (max > Math.PI) max -= twoPI;
43717
43116
 
43718
- const distance = Math.sqrt( dx * dx + dy * dy );
43117
+ if (min <= max) {
43118
+ spherical.theta = Math.max(min, Math.min(max, spherical.theta));
43119
+ } else {
43120
+ spherical.theta =
43121
+ spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
43122
+ }
43123
+ }
43719
43124
 
43720
- dollyEnd.set( 0, distance );
43125
+ // restrict phi to be between desired limits
43126
+ spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
43721
43127
 
43722
- dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );
43128
+ spherical.makeSafe();
43723
43129
 
43724
- dollyOut( dollyDelta.y );
43130
+ spherical.radius *= scope.scale;
43725
43131
 
43726
- dollyStart.copy( dollyEnd );
43132
+ // restrict radius to be between desired limits
43133
+ spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
43727
43134
 
43728
- }
43135
+ // move target to panned location
43729
43136
 
43730
- function handleTouchMoveDollyPan( event ) {
43137
+ if (scope.enableDamping === true) {
43138
+ scope.target.addScaledVector(scope.panOffset, scope.dampingFactor);
43139
+ } else {
43140
+ scope.target.add(scope.panOffset);
43141
+ }
43731
43142
 
43732
- if ( scope.enableZoom ) handleTouchMoveDolly( event );
43143
+ offset.setFromSpherical(spherical);
43733
43144
 
43734
- if ( scope.enablePan ) handleTouchMovePan( event );
43145
+ // rotate offset back to "camera-up-vector-is-up" space
43146
+ offset.applyQuaternion(quatInverse);
43735
43147
 
43736
- }
43148
+ position.copy(scope.target).add(offset);
43737
43149
 
43738
- function handleTouchMoveDollyRotate( event ) {
43150
+ scope.object.lookAt(scope.target);
43739
43151
 
43740
- if ( scope.enableZoom ) handleTouchMoveDolly( event );
43152
+ if (scope.enableDamping === true) {
43153
+ sphericalDelta.theta *= 1 - scope.dampingFactor;
43154
+ sphericalDelta.phi *= 1 - scope.dampingFactor;
43741
43155
 
43742
- if ( scope.enableRotate ) handleTouchMoveRotate( event );
43156
+ scope.panOffset.multiplyScalar(1 - scope.dampingFactor);
43157
+ } else {
43158
+ sphericalDelta.set(0, 0, 0);
43743
43159
 
43744
- }
43160
+ scope.panOffset.set(0, 0, 0);
43161
+ }
43745
43162
 
43746
- //
43747
- // event handlers - FSM: listen for events and reset state
43748
- //
43163
+ scope.scale = 1;
43749
43164
 
43750
- function onPointerDown( event ) {
43165
+ // update condition is:
43166
+ // min(camera displacement, camera rotation in radians)^2 > EPS
43167
+ // using small-angle approximation cos(x/2) = 1 - x^2 / 8
43751
43168
 
43752
- if ( scope.enabled === false ) return;
43169
+ if (
43170
+ scope.zoomChanged ||
43171
+ lastPosition.distanceToSquared(scope.object.position) > EPS ||
43172
+ 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS ||
43173
+ lastTargetPosition.distanceToSquared(scope.target) > 0
43174
+ ) {
43175
+ scope.dispatchEvent(_changeEvent$2);
43753
43176
 
43754
- if ( pointers.length === 0 ) {
43177
+ lastPosition.copy(scope.object.position);
43178
+ lastQuaternion.copy(scope.object.quaternion);
43179
+ lastTargetPosition.copy(scope.target);
43755
43180
 
43756
- scope.domElement.setPointerCapture( event.pointerId );
43181
+ scope.zoomChanged = false;
43757
43182
 
43758
- scope.domElement.addEventListener( 'pointermove', onPointerMove );
43759
- scope.domElement.addEventListener( 'pointerup', onPointerUp );
43183
+ return true;
43184
+ }
43760
43185
 
43761
- }
43186
+ return false;
43187
+ };
43188
+ })();
43762
43189
 
43763
- //
43190
+ this.dispose = function () {
43191
+ scope.domElement.removeEventListener("contextmenu", onContextMenu);
43764
43192
 
43765
- addPointer( event );
43193
+ scope.domElement.removeEventListener("pointerdown", onPointerDown);
43194
+ scope.domElement.removeEventListener("pointercancel", onPointerUp);
43195
+ scope.domElement.removeEventListener("wheel", onMouseWheel);
43766
43196
 
43767
- if ( event.pointerType === 'touch' ) {
43197
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
43198
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
43768
43199
 
43769
- onTouchStart( event );
43200
+ if (scope._domElementKeyEvents !== null) {
43201
+ scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
43202
+ scope._domElementKeyEvents = null;
43203
+ }
43770
43204
 
43771
- } else {
43205
+ //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
43206
+ };
43772
43207
 
43773
- onMouseDown( event );
43208
+ //
43209
+ // internals
43210
+ //
43774
43211
 
43775
- }
43212
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
43213
+ const scope = this;
43776
43214
 
43777
- }
43215
+ scope.state = STATE.NONE;
43778
43216
 
43779
- function onPointerMove( event ) {
43217
+ const EPS = 0.000001;
43780
43218
 
43781
- if ( scope.enabled === false ) return;
43219
+ // current position in spherical coordinates
43220
+ const spherical = new Spherical();
43221
+ const sphericalDelta = new Spherical();
43782
43222
 
43783
- if ( event.pointerType === 'touch' ) {
43223
+ scope.scale = 1;
43224
+ scope.panOffset = new Vector3();
43225
+ scope.zoomChanged = false;
43784
43226
 
43785
- onTouchMove( event );
43227
+ scope.rotateStart = new Vector2();
43228
+ scope.rotateEnd = new Vector2();
43229
+ scope.rotateDelta = new Vector2();
43786
43230
 
43787
- } else {
43231
+ scope.panStart = new Vector2();
43232
+ scope.panEnd = new Vector2();
43233
+ scope.panDelta = new Vector2();
43788
43234
 
43789
- onMouseMove( event );
43235
+ scope.dollyStart = new Vector2();
43236
+ scope.dollyEnd = new Vector2();
43237
+ scope.dollyDelta = new Vector2();
43238
+ scope.dollyScale = 0;
43790
43239
 
43791
- }
43240
+ scope.pointers = [];
43241
+ scope.pointerPositions = {};
43792
43242
 
43793
- }
43243
+ function getAutoRotationAngle() {
43244
+ return ((2 * Math.PI) / 60 / 60) * scope.autoRotateSpeed;
43245
+ }
43794
43246
 
43795
- function onPointerUp( event ) {
43247
+ function getZoomScale() {
43248
+ return Math.pow(0.95, scope.zoomSpeed);
43249
+ }
43796
43250
 
43797
- removePointer( event );
43251
+ function rotateLeft(angle) {
43252
+ sphericalDelta.theta -= angle;
43253
+ }
43798
43254
 
43799
- if ( pointers.length === 0 ) {
43255
+ function rotateUp(angle) {
43256
+ sphericalDelta.phi -= angle;
43257
+ }
43800
43258
 
43801
- scope.domElement.releasePointerCapture( event.pointerId );
43259
+ const panLeft = (function () {
43260
+ const v = new Vector3();
43802
43261
 
43803
- scope.domElement.removeEventListener( 'pointermove', onPointerMove );
43804
- scope.domElement.removeEventListener( 'pointerup', onPointerUp );
43262
+ return function panLeft(distance, objectMatrix) {
43263
+ v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix
43264
+ v.multiplyScalar(-distance);
43805
43265
 
43806
- }
43266
+ scope.panOffset.add(v);
43267
+ };
43268
+ })();
43807
43269
 
43808
- scope.dispatchEvent( _endEvent );
43270
+ const panUp = (function () {
43271
+ const v = new Vector3();
43809
43272
 
43810
- state = STATE.NONE;
43273
+ return function panUp(distance, objectMatrix) {
43274
+ if (scope.screenSpacePanning === true) {
43275
+ v.setFromMatrixColumn(objectMatrix, 1);
43276
+ } else {
43277
+ v.setFromMatrixColumn(objectMatrix, 0);
43278
+ v.crossVectors(scope.object.up, v);
43279
+ }
43811
43280
 
43812
- }
43281
+ v.multiplyScalar(distance);
43282
+
43283
+ scope.panOffset.add(v);
43284
+ };
43285
+ })();
43286
+
43287
+ // deltaX and deltaY are in pixels; right and down are positive
43288
+ const pan = (function () {
43289
+ const offset = new Vector3();
43290
+
43291
+ return function pan(deltaX, deltaY) {
43292
+ const element = scope.domElement;
43293
+
43294
+ if (scope.object.isPerspectiveCamera) {
43295
+ // perspective
43296
+ const position = scope.object.position;
43297
+ offset.copy(position).sub(scope.target);
43298
+ let targetDistance = offset.length();
43299
+
43300
+ // half of the fov is center to top of screen
43301
+ targetDistance *= Math.tan(((scope.object.fov / 2) * Math.PI) / 180.0);
43302
+
43303
+ // we use only clientHeight here so aspect ratio does not distort speed
43304
+ panLeft((2 * deltaX * targetDistance) / element.clientHeight, scope.object.matrix);
43305
+ panUp((2 * deltaY * targetDistance) / element.clientHeight, scope.object.matrix);
43306
+ } else if (scope.object.isOrthographicCamera) {
43307
+ // orthographic
43308
+ panLeft(
43309
+ (deltaX * (scope.object.right - scope.object.left)) / scope.object.zoom / element.clientWidth,
43310
+ scope.object.matrix
43311
+ );
43312
+ panUp(
43313
+ (deltaY * (scope.object.top - scope.object.bottom)) / scope.object.zoom / element.clientHeight,
43314
+ scope.object.matrix
43315
+ );
43316
+ } else {
43317
+ // camera neither orthographic nor perspective
43318
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
43319
+ scope.enablePan = false;
43320
+ }
43321
+ };
43322
+ })();
43323
+
43324
+ function dollyOut(dollyScale) {
43325
+ if (scope.object.isPerspectiveCamera) {
43326
+ scope.scale /= dollyScale;
43327
+ } else if (scope.object.isOrthographicCamera) {
43328
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
43329
+ scope.object.updateProjectionMatrix();
43330
+ scope.zoomChanged = true;
43331
+ } else {
43332
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
43333
+ scope.enableZoom = false;
43334
+ }
43335
+ }
43813
43336
 
43814
- function onMouseDown( event ) {
43337
+ function dollyIn(dollyScale) {
43338
+ if (scope.object.isPerspectiveCamera) {
43339
+ scope.scale *= dollyScale;
43340
+ } else if (scope.object.isOrthographicCamera) {
43341
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
43342
+ scope.object.updateProjectionMatrix();
43343
+ scope.zoomChanged = true;
43344
+ } else {
43345
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
43346
+ scope.enableZoom = false;
43347
+ }
43348
+ }
43815
43349
 
43816
- let mouseAction;
43350
+ //
43351
+ // event callbacks - update the object state
43352
+ //
43817
43353
 
43818
- switch ( event.button ) {
43354
+ function handleMouseDownRotate(event) {
43355
+ scope.rotateStart.set(event.clientX, event.clientY);
43356
+ }
43819
43357
 
43820
- case 0:
43358
+ function handleMouseDownDolly(event) {
43359
+ scope.dollyStart.set(event.clientX, event.clientY);
43360
+ }
43821
43361
 
43822
- mouseAction = scope.mouseButtons.LEFT;
43823
- break;
43362
+ function handleMouseDownPan(event) {
43363
+ scope.panStart.set(event.clientX, event.clientY);
43364
+ }
43824
43365
 
43825
- case 1:
43366
+ function handleMouseMoveRotate(event) {
43367
+ scope.rotateEnd.set(event.clientX, event.clientY);
43826
43368
 
43827
- mouseAction = scope.mouseButtons.MIDDLE;
43828
- break;
43369
+ scope.rotateDelta.subVectors(scope.rotateEnd, scope.rotateStart).multiplyScalar(scope.rotateSpeed);
43829
43370
 
43830
- case 2:
43371
+ const element = scope.domElement;
43831
43372
 
43832
- mouseAction = scope.mouseButtons.RIGHT;
43833
- break;
43373
+ rotateLeft((2 * Math.PI * scope.rotateDelta.x) / element.clientHeight); // yes, height
43834
43374
 
43835
- default:
43836
-
43837
- mouseAction = - 1;
43375
+ rotateUp((2 * Math.PI * scope.rotateDelta.y) / element.clientHeight);
43838
43376
 
43839
- }
43377
+ scope.rotateStart.copy(scope.rotateEnd);
43840
43378
 
43841
- switch ( mouseAction ) {
43379
+ scope.update();
43380
+ }
43842
43381
 
43843
- case MOUSE.DOLLY:
43382
+ function handleMouseMoveDolly(event) {
43383
+ scope.dollyEnd.set(event.clientX, event.clientY);
43844
43384
 
43845
- if ( scope.enableZoom === false ) return;
43385
+ scope.dollyDelta.subVectors(scope.dollyEnd, scope.dollyStart);
43846
43386
 
43847
- handleMouseDownDolly( event );
43387
+ if (scope.dollyDelta.y < 0) {
43388
+ scope.dollyScale = 1 / getZoomScale();
43389
+ dollyOut(getZoomScale());
43390
+ } else if (scope.dollyDelta.y > 0) {
43391
+ scope.dollyScale = getZoomScale();
43392
+ dollyIn(getZoomScale());
43393
+ }
43848
43394
 
43849
- state = STATE.DOLLY;
43395
+ scope.dollyStart.copy(scope.dollyEnd);
43850
43396
 
43851
- break;
43397
+ scope.update();
43398
+ }
43852
43399
 
43853
- case MOUSE.ROTATE:
43400
+ function handleMouseMovePan(event) {
43401
+ scope.panEnd.set(event.clientX, event.clientY);
43854
43402
 
43855
- if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
43403
+ scope.panDelta.subVectors(scope.panEnd, scope.panStart).multiplyScalar(scope.panSpeed);
43856
43404
 
43857
- if ( scope.enablePan === false ) return;
43405
+ pan(scope.panDelta.x, scope.panDelta.y);
43858
43406
 
43859
- handleMouseDownPan( event );
43407
+ scope.panStart.copy(scope.panEnd);
43860
43408
 
43861
- state = STATE.PAN;
43409
+ scope.update();
43410
+ }
43862
43411
 
43863
- } else {
43412
+ function handleMouseWheel(event) {
43413
+ scope.dollyEnd.set(scope.domElement.clientWidth / 2, scope.domElement.clientHeight / 2);
43864
43414
 
43865
- if ( scope.enableRotate === false ) return;
43415
+ scope.dollyDelta.set(event.deltaX, event.deltaY);
43866
43416
 
43867
- handleMouseDownRotate( event );
43417
+ if (event.deltaY < 0) {
43418
+ scope.dollyScale = 1 / getZoomScale();
43419
+ dollyIn(getZoomScale());
43420
+ } else if (event.deltaY > 0) {
43421
+ scope.dollyScale = getZoomScale();
43422
+ dollyOut(getZoomScale());
43423
+ }
43868
43424
 
43869
- state = STATE.ROTATE;
43425
+ scope.dollyStart.copy(scope.dollyEnd);
43870
43426
 
43871
- }
43427
+ scope.update();
43872
43428
 
43873
- break;
43429
+ if (event.deltaY !== 0) {
43430
+ scope.state = STATE.DOLLY;
43431
+ scope.dispatchEvent(_changeEvent$2);
43432
+ scope.state = STATE.NONE;
43433
+ }
43434
+ }
43874
43435
 
43875
- case MOUSE.PAN:
43436
+ function handleKeyDown(event) {
43437
+ let needsUpdate = false;
43438
+
43439
+ switch (event.code) {
43440
+ case scope.keys.UP:
43441
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
43442
+ rotateUp((2 * Math.PI * scope.rotateSpeed) / scope.domElement.clientHeight);
43443
+ } else {
43444
+ pan(0, scope.keyPanSpeed);
43445
+ }
43446
+
43447
+ needsUpdate = true;
43448
+ break;
43449
+
43450
+ case scope.keys.BOTTOM:
43451
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
43452
+ rotateUp((-2 * Math.PI * scope.rotateSpeed) / scope.domElement.clientHeight);
43453
+ } else {
43454
+ pan(0, -scope.keyPanSpeed);
43455
+ }
43456
+
43457
+ needsUpdate = true;
43458
+ break;
43459
+
43460
+ case scope.keys.LEFT:
43461
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
43462
+ rotateLeft((2 * Math.PI * scope.rotateSpeed) / scope.domElement.clientHeight);
43463
+ } else {
43464
+ pan(scope.keyPanSpeed, 0);
43465
+ }
43466
+
43467
+ needsUpdate = true;
43468
+ break;
43469
+
43470
+ case scope.keys.RIGHT:
43471
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
43472
+ rotateLeft((-2 * Math.PI * scope.rotateSpeed) / scope.domElement.clientHeight);
43473
+ } else {
43474
+ pan(-scope.keyPanSpeed, 0);
43475
+ }
43476
+
43477
+ needsUpdate = true;
43478
+ break;
43479
+ }
43480
+
43481
+ if (needsUpdate) {
43482
+ // prevent the browser from scrolling on cursor keys
43483
+ event.preventDefault();
43484
+
43485
+ scope.update();
43486
+ }
43487
+ }
43876
43488
 
43877
- if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
43489
+ function handleTouchStartRotate() {
43490
+ if (scope.pointers.length === 1) {
43491
+ scope.rotateStart.set(scope.pointers[0].pageX, scope.pointers[0].pageY);
43492
+ } else {
43493
+ const x = 0.5 * (scope.pointers[0].pageX + scope.pointers[1].pageX);
43494
+ const y = 0.5 * (scope.pointers[0].pageY + scope.pointers[1].pageY);
43878
43495
 
43879
- if ( scope.enableRotate === false ) return;
43496
+ scope.rotateStart.set(x, y);
43497
+ }
43498
+ }
43880
43499
 
43881
- handleMouseDownRotate( event );
43500
+ function handleTouchStartPan() {
43501
+ if (scope.pointers.length === 1) {
43502
+ scope.panStart.set(scope.pointers[0].pageX, scope.pointers[0].pageY);
43503
+ } else {
43504
+ const x = 0.5 * (scope.pointers[0].pageX + scope.pointers[1].pageX);
43505
+ const y = 0.5 * (scope.pointers[0].pageY + scope.pointers[1].pageY);
43882
43506
 
43883
- state = STATE.ROTATE;
43507
+ scope.panStart.set(x, y);
43508
+ }
43509
+ }
43884
43510
 
43885
- } else {
43511
+ function handleTouchStartDolly() {
43512
+ const dx = scope.pointers[0].pageX - scope.pointers[1].pageX;
43513
+ const dy = scope.pointers[0].pageY - scope.pointers[1].pageY;
43886
43514
 
43887
- if ( scope.enablePan === false ) return;
43515
+ const distance = Math.sqrt(dx * dx + dy * dy);
43888
43516
 
43889
- handleMouseDownPan( event );
43517
+ scope.dollyStart.set(0, distance);
43518
+ }
43890
43519
 
43891
- state = STATE.PAN;
43520
+ function handleTouchStartDollyPan() {
43521
+ if (scope.enableZoom) handleTouchStartDolly();
43892
43522
 
43893
- }
43523
+ if (scope.enablePan) handleTouchStartPan();
43524
+ }
43894
43525
 
43895
- break;
43526
+ function handleTouchStartDollyRotate() {
43527
+ if (scope.enableZoom) handleTouchStartDolly();
43896
43528
 
43897
- default:
43529
+ if (scope.enableRotate) handleTouchStartRotate();
43530
+ }
43898
43531
 
43899
- state = STATE.NONE;
43532
+ function handleTouchMoveRotate(event) {
43533
+ if (scope.pointers.length == 1) {
43534
+ scope.rotateEnd.set(event.pageX, event.pageY);
43535
+ } else {
43536
+ const position = getSecondPointerPosition(event);
43900
43537
 
43901
- }
43538
+ const x = 0.5 * (event.pageX + position.x);
43539
+ const y = 0.5 * (event.pageY + position.y);
43902
43540
 
43903
- if ( state !== STATE.NONE ) {
43541
+ scope.rotateEnd.set(x, y);
43542
+ }
43904
43543
 
43905
- scope.dispatchEvent( _startEvent );
43544
+ scope.rotateDelta.subVectors(scope.rotateEnd, scope.rotateStart).multiplyScalar(scope.rotateSpeed);
43906
43545
 
43907
- }
43546
+ const element = scope.domElement;
43908
43547
 
43909
- }
43548
+ rotateLeft((2 * Math.PI * scope.rotateDelta.x) / element.clientHeight); // yes, height
43910
43549
 
43911
- function onMouseMove( event ) {
43550
+ rotateUp((2 * Math.PI * scope.rotateDelta.y) / element.clientHeight);
43912
43551
 
43913
- switch ( state ) {
43552
+ scope.rotateStart.copy(scope.rotateEnd);
43553
+ }
43914
43554
 
43915
- case STATE.ROTATE:
43555
+ function handleTouchMovePan(event) {
43556
+ if (scope.pointers.length === 1) {
43557
+ scope.panEnd.set(event.pageX, event.pageY);
43558
+ } else {
43559
+ const position = getSecondPointerPosition(event);
43916
43560
 
43917
- if ( scope.enableRotate === false ) return;
43561
+ const x = 0.5 * (event.pageX + position.x);
43562
+ const y = 0.5 * (event.pageY + position.y);
43918
43563
 
43919
- handleMouseMoveRotate( event );
43564
+ scope.panEnd.set(x, y);
43565
+ }
43920
43566
 
43921
- break;
43567
+ scope.panDelta.subVectors(scope.panEnd, scope.panStart).multiplyScalar(scope.panSpeed);
43922
43568
 
43923
- case STATE.DOLLY:
43569
+ pan(scope.panDelta.x, scope.panDelta.y);
43924
43570
 
43925
- if ( scope.enableZoom === false ) return;
43571
+ scope.panStart.copy(scope.panEnd);
43572
+ }
43926
43573
 
43927
- handleMouseMoveDolly( event );
43574
+ function handleTouchMoveDolly(event) {
43575
+ const position = getSecondPointerPosition(event);
43928
43576
 
43929
- break;
43577
+ const dx = event.pageX - position.x;
43578
+ const dy = event.pageY - position.y;
43930
43579
 
43931
- case STATE.PAN:
43580
+ const distance = Math.sqrt(dx * dx + dy * dy);
43932
43581
 
43933
- if ( scope.enablePan === false ) return;
43582
+ scope.dollyEnd.set(0, distance);
43934
43583
 
43935
- handleMouseMovePan( event );
43584
+ scope.dollyDelta.set(0, Math.pow(scope.dollyEnd.y / scope.dollyStart.y, scope.zoomSpeed));
43936
43585
 
43937
- break;
43586
+ dollyOut(scope.dollyDelta.y);
43938
43587
 
43939
- }
43588
+ scope.dollyStart.copy(scope.dollyEnd);
43589
+ }
43940
43590
 
43941
- }
43591
+ function handleTouchMoveDollyPan(event) {
43592
+ if (scope.enableZoom) handleTouchMoveDolly(event);
43942
43593
 
43943
- function onMouseWheel( event ) {
43594
+ if (scope.enablePan) handleTouchMovePan(event);
43595
+ }
43944
43596
 
43945
- if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return;
43597
+ function handleTouchMoveDollyRotate(event) {
43598
+ if (scope.enableZoom) handleTouchMoveDolly(event);
43946
43599
 
43947
- event.preventDefault();
43600
+ if (scope.enableRotate) handleTouchMoveRotate(event);
43601
+ }
43948
43602
 
43949
- scope.dispatchEvent( _startEvent );
43603
+ //
43604
+ // event handlers - FSM: listen for events and reset state
43605
+ //
43950
43606
 
43951
- handleMouseWheel( event );
43607
+ function onPointerDown(event) {
43608
+ if (scope.enabled === false) return;
43952
43609
 
43953
- scope.dispatchEvent( _endEvent );
43610
+ if (scope.pointers.length === 0) {
43611
+ scope.domElement.setPointerCapture(event.pointerId);
43954
43612
 
43955
- }
43613
+ scope.domElement.addEventListener("pointermove", onPointerMove);
43614
+ scope.domElement.addEventListener("pointerup", onPointerUp);
43615
+ }
43956
43616
 
43957
- function onKeyDown( event ) {
43617
+ //
43958
43618
 
43959
- if ( scope.enabled === false || scope.enablePan === false ) return;
43619
+ addPointer(event);
43960
43620
 
43961
- handleKeyDown( event );
43621
+ if (event.pointerType === "touch") {
43622
+ onTouchStart(event);
43623
+ } else {
43624
+ onMouseDown(event);
43625
+ }
43626
+ }
43962
43627
 
43963
- }
43628
+ function onPointerMove(event) {
43629
+ if (scope.enabled === false) return;
43964
43630
 
43965
- function onTouchStart( event ) {
43631
+ if (event.pointerType === "touch") {
43632
+ onTouchMove(event);
43633
+ } else {
43634
+ onMouseMove(event);
43635
+ }
43636
+ }
43966
43637
 
43967
- trackPointer( event );
43638
+ function onPointerUp(event) {
43639
+ removePointer(event);
43968
43640
 
43969
- switch ( pointers.length ) {
43641
+ if (scope.pointers.length === 0) {
43642
+ scope.domElement.releasePointerCapture(event.pointerId);
43970
43643
 
43971
- case 1:
43644
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
43645
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
43646
+ }
43972
43647
 
43973
- switch ( scope.touches.ONE ) {
43648
+ scope.dispatchEvent(_endEvent);
43974
43649
 
43975
- case TOUCH.ROTATE:
43650
+ scope.state = STATE.NONE;
43651
+ }
43976
43652
 
43977
- if ( scope.enableRotate === false ) return;
43653
+ function onMouseDown(event) {
43654
+ let mouseAction;
43978
43655
 
43979
- handleTouchStartRotate();
43656
+ switch (event.button) {
43657
+ case 0:
43658
+ mouseAction = scope.mouseButtons.LEFT;
43659
+ break;
43980
43660
 
43981
- state = STATE.TOUCH_ROTATE;
43661
+ case 1:
43662
+ mouseAction = scope.mouseButtons.MIDDLE;
43663
+ break;
43982
43664
 
43983
- break;
43665
+ case 2:
43666
+ mouseAction = scope.mouseButtons.RIGHT;
43667
+ break;
43984
43668
 
43985
- case TOUCH.PAN:
43669
+ default:
43670
+ mouseAction = -1;
43671
+ }
43986
43672
 
43987
- if ( scope.enablePan === false ) return;
43673
+ switch (mouseAction) {
43674
+ case MOUSE.DOLLY:
43675
+ if (scope.enableZoom === false) return;
43988
43676
 
43989
- handleTouchStartPan();
43677
+ handleMouseDownDolly(event);
43990
43678
 
43991
- state = STATE.TOUCH_PAN;
43679
+ scope.state = STATE.DOLLY;
43992
43680
 
43993
- break;
43681
+ break;
43994
43682
 
43995
- default:
43683
+ case MOUSE.ROTATE:
43684
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
43685
+ if (scope.enablePan === false) return;
43996
43686
 
43997
- state = STATE.NONE;
43687
+ handleMouseDownPan(event);
43998
43688
 
43999
- }
43689
+ scope.state = STATE.PAN;
43690
+ } else {
43691
+ if (scope.enableRotate === false) return;
44000
43692
 
44001
- break;
43693
+ handleMouseDownRotate(event);
44002
43694
 
44003
- case 2:
43695
+ scope.state = STATE.ROTATE;
43696
+ }
44004
43697
 
44005
- switch ( scope.touches.TWO ) {
43698
+ break;
44006
43699
 
44007
- case TOUCH.DOLLY_PAN:
43700
+ case MOUSE.PAN:
43701
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
43702
+ if (scope.enableRotate === false) return;
44008
43703
 
44009
- if ( scope.enableZoom === false && scope.enablePan === false ) return;
43704
+ handleMouseDownRotate(event);
44010
43705
 
44011
- handleTouchStartDollyPan();
43706
+ scope.state = STATE.ROTATE;
43707
+ } else {
43708
+ if (scope.enablePan === false) return;
44012
43709
 
44013
- state = STATE.TOUCH_DOLLY_PAN;
43710
+ handleMouseDownPan(event);
44014
43711
 
44015
- break;
43712
+ scope.state = STATE.PAN;
43713
+ }
44016
43714
 
44017
- case TOUCH.DOLLY_ROTATE:
43715
+ break;
44018
43716
 
44019
- if ( scope.enableZoom === false && scope.enableRotate === false ) return;
43717
+ default:
43718
+ scope.state = STATE.NONE;
43719
+ }
44020
43720
 
44021
- handleTouchStartDollyRotate();
43721
+ if (scope.state !== STATE.NONE) {
43722
+ scope.dispatchEvent(_startEvent);
43723
+ }
43724
+ }
44022
43725
 
44023
- state = STATE.TOUCH_DOLLY_ROTATE;
43726
+ function onMouseMove(event) {
43727
+ switch (scope.state) {
43728
+ case STATE.ROTATE:
43729
+ if (scope.enableRotate === false) return;
44024
43730
 
44025
- break;
43731
+ handleMouseMoveRotate(event);
44026
43732
 
44027
- default:
43733
+ break;
44028
43734
 
44029
- state = STATE.NONE;
43735
+ case STATE.DOLLY:
43736
+ if (scope.enableZoom === false) return;
44030
43737
 
44031
- }
43738
+ handleMouseMoveDolly(event);
44032
43739
 
44033
- break;
43740
+ break;
44034
43741
 
44035
- default:
43742
+ case STATE.PAN:
43743
+ if (scope.enablePan === false) return;
44036
43744
 
44037
- state = STATE.NONE;
43745
+ handleMouseMovePan(event);
44038
43746
 
44039
- }
43747
+ break;
43748
+ }
43749
+ }
44040
43750
 
44041
- if ( state !== STATE.NONE ) {
43751
+ function onMouseWheel(event) {
43752
+ if (scope.enabled === false || scope.enableZoom === false || scope.state !== STATE.NONE) return;
44042
43753
 
44043
- scope.dispatchEvent( _startEvent );
43754
+ event.preventDefault();
44044
43755
 
44045
- }
43756
+ scope.dispatchEvent(_startEvent);
44046
43757
 
44047
- }
43758
+ handleMouseWheel(event);
44048
43759
 
44049
- function onTouchMove( event ) {
43760
+ scope.dispatchEvent(_endEvent);
43761
+ }
44050
43762
 
44051
- trackPointer( event );
43763
+ function onKeyDown(event) {
43764
+ if (scope.enabled === false || scope.enablePan === false) return;
44052
43765
 
44053
- switch ( state ) {
43766
+ handleKeyDown(event);
43767
+ }
44054
43768
 
44055
- case STATE.TOUCH_ROTATE:
43769
+ function onTouchStart(event) {
43770
+ trackPointer(event);
44056
43771
 
44057
- if ( scope.enableRotate === false ) return;
43772
+ switch (scope.pointers.length) {
43773
+ case 1:
43774
+ switch (scope.touches.ONE) {
43775
+ case TOUCH.ROTATE:
43776
+ if (scope.enableRotate === false) return;
44058
43777
 
44059
- handleTouchMoveRotate( event );
43778
+ handleTouchStartRotate();
44060
43779
 
44061
- scope.update();
43780
+ scope.state = STATE.TOUCH_ROTATE;
44062
43781
 
44063
- break;
43782
+ break;
44064
43783
 
44065
- case STATE.TOUCH_PAN:
43784
+ case TOUCH.PAN:
43785
+ if (scope.enablePan === false) return;
44066
43786
 
44067
- if ( scope.enablePan === false ) return;
43787
+ handleTouchStartPan();
44068
43788
 
44069
- handleTouchMovePan( event );
43789
+ scope.state = STATE.TOUCH_PAN;
44070
43790
 
44071
- scope.update();
43791
+ break;
44072
43792
 
44073
- break;
43793
+ default:
43794
+ scope.state = STATE.NONE;
43795
+ }
44074
43796
 
44075
- case STATE.TOUCH_DOLLY_PAN:
43797
+ break;
44076
43798
 
44077
- if ( scope.enableZoom === false && scope.enablePan === false ) return;
43799
+ case 2:
43800
+ switch (scope.touches.TWO) {
43801
+ case TOUCH.DOLLY_PAN:
43802
+ if (scope.enableZoom === false && scope.enablePan === false) return;
44078
43803
 
44079
- handleTouchMoveDollyPan( event );
43804
+ handleTouchStartDollyPan();
44080
43805
 
44081
- scope.update();
43806
+ scope.state = STATE.TOUCH_DOLLY_PAN;
44082
43807
 
44083
- break;
43808
+ break;
44084
43809
 
44085
- case STATE.TOUCH_DOLLY_ROTATE:
43810
+ case TOUCH.DOLLY_ROTATE:
43811
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
44086
43812
 
44087
- if ( scope.enableZoom === false && scope.enableRotate === false ) return;
43813
+ handleTouchStartDollyRotate();
44088
43814
 
44089
- handleTouchMoveDollyRotate( event );
43815
+ scope.state = STATE.TOUCH_DOLLY_ROTATE;
44090
43816
 
44091
- scope.update();
43817
+ break;
44092
43818
 
44093
- break;
43819
+ default:
43820
+ scope.state = STATE.NONE;
43821
+ }
44094
43822
 
44095
- default:
43823
+ break;
44096
43824
 
44097
- state = STATE.NONE;
43825
+ default:
43826
+ scope.state = STATE.NONE;
43827
+ }
44098
43828
 
44099
- }
43829
+ if (scope.state !== STATE.NONE) {
43830
+ scope.dispatchEvent(_startEvent);
43831
+ }
43832
+ }
44100
43833
 
44101
- }
43834
+ function onTouchMove(event) {
43835
+ trackPointer(event);
44102
43836
 
44103
- function onContextMenu( event ) {
43837
+ switch (scope.state) {
43838
+ case STATE.TOUCH_ROTATE:
43839
+ if (scope.enableRotate === false) return;
44104
43840
 
44105
- if ( scope.enabled === false ) return;
43841
+ handleTouchMoveRotate(event);
44106
43842
 
44107
- event.preventDefault();
43843
+ scope.update();
44108
43844
 
44109
- }
43845
+ break;
44110
43846
 
44111
- function addPointer( event ) {
43847
+ case STATE.TOUCH_PAN:
43848
+ if (scope.enablePan === false) return;
44112
43849
 
44113
- pointers.push( event );
43850
+ handleTouchMovePan(event);
44114
43851
 
44115
- }
43852
+ scope.update();
44116
43853
 
44117
- function removePointer( event ) {
43854
+ break;
44118
43855
 
44119
- delete pointerPositions[ event.pointerId ];
43856
+ case STATE.TOUCH_DOLLY_PAN:
43857
+ if (scope.enableZoom === false && scope.enablePan === false) return;
44120
43858
 
44121
- for ( let i = 0; i < pointers.length; i ++ ) {
43859
+ handleTouchMoveDollyPan(event);
44122
43860
 
44123
- if ( pointers[ i ].pointerId == event.pointerId ) {
43861
+ scope.update();
44124
43862
 
44125
- pointers.splice( i, 1 );
44126
- return;
43863
+ break;
44127
43864
 
44128
- }
43865
+ case STATE.TOUCH_DOLLY_ROTATE:
43866
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
44129
43867
 
44130
- }
43868
+ handleTouchMoveDollyRotate(event);
44131
43869
 
44132
- }
43870
+ scope.update();
44133
43871
 
44134
- function trackPointer( event ) {
43872
+ break;
44135
43873
 
44136
- let position = pointerPositions[ event.pointerId ];
44137
-
44138
- if ( position === undefined ) {
43874
+ default:
43875
+ scope.state = STATE.NONE;
43876
+ }
43877
+ }
44139
43878
 
44140
- position = new Vector2();
44141
- pointerPositions[ event.pointerId ] = position;
43879
+ function onContextMenu(event) {
43880
+ if (scope.enabled === false) return;
44142
43881
 
44143
- }
43882
+ event.preventDefault();
43883
+ }
44144
43884
 
44145
- position.set( event.pageX, event.pageY );
43885
+ function addPointer(event) {
43886
+ scope.pointers.push(event);
43887
+ }
44146
43888
 
44147
- }
43889
+ function removePointer(event) {
43890
+ delete scope.pointerPositions[event.pointerId];
44148
43891
 
44149
- function getSecondPointerPosition( event ) {
43892
+ for (let i = 0; i < scope.pointers.length; i++) {
43893
+ if (scope.pointers[i].pointerId == event.pointerId) {
43894
+ scope.pointers.splice(i, 1);
43895
+ return;
43896
+ }
43897
+ }
43898
+ }
44150
43899
 
44151
- const pointer = ( event.pointerId === pointers[ 0 ].pointerId ) ? pointers[ 1 ] : pointers[ 0 ];
43900
+ function trackPointer(event) {
43901
+ let position = scope.pointerPositions[event.pointerId];
44152
43902
 
44153
- return pointerPositions[ pointer.pointerId ];
43903
+ if (position === undefined) {
43904
+ position = new Vector2();
43905
+ scope.pointerPositions[event.pointerId] = position;
43906
+ }
44154
43907
 
44155
- }
43908
+ position.set(event.pageX, event.pageY);
43909
+ }
44156
43910
 
44157
- //
43911
+ function getSecondPointerPosition(event) {
43912
+ const pointer = event.pointerId === scope.pointers[0].pointerId ? scope.pointers[1] : scope.pointers[0];
44158
43913
 
44159
- scope.domElement.addEventListener( 'contextmenu', onContextMenu );
43914
+ return scope.pointerPositions[pointer.pointerId];
43915
+ }
44160
43916
 
44161
- scope.domElement.addEventListener( 'pointerdown', onPointerDown );
44162
- scope.domElement.addEventListener( 'pointercancel', onPointerUp );
44163
- scope.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );
43917
+ //
44164
43918
 
44165
- // force an update at start
43919
+ scope.domElement.addEventListener("contextmenu", onContextMenu);
44166
43920
 
44167
- this.update();
43921
+ scope.domElement.addEventListener("pointerdown", onPointerDown);
43922
+ scope.domElement.addEventListener("pointercancel", onPointerUp);
43923
+ scope.domElement.addEventListener("wheel", onMouseWheel, { passive: false });
44168
43924
 
44169
- }
43925
+ // force an update at start
44170
43926
 
43927
+ this.update();
43928
+ }
44171
43929
  }
44172
43930
 
44173
43931
  ///////////////////////////////////////////////////////////////////////////////
@@ -44206,6 +43964,26 @@
44206
43964
  this.controlsChange = () => {
44207
43965
  this.viewer.target.copy(this.orbit.target);
44208
43966
  this.viewer.update();
43967
+ switch (this.orbit.state) {
43968
+ case STATE.PAN:
43969
+ case STATE.TOUCH_PAN:
43970
+ this.viewer.emitEvent({
43971
+ type: "pan",
43972
+ x: this.orbit.panEnd.x,
43973
+ y: this.orbit.panEnd.y,
43974
+ dX: this.orbit.panDelta.x,
43975
+ dY: this.orbit.panDelta.y,
43976
+ });
43977
+ break;
43978
+ case STATE.DOLLY:
43979
+ this.viewer.emitEvent({
43980
+ type: "zoomat",
43981
+ data: this.orbit.dollyScale,
43982
+ x: this.orbit.dollyEnd.x,
43983
+ y: this.orbit.dollyEnd.y,
43984
+ });
43985
+ break;
43986
+ }
44209
43987
  this.changed = true;
44210
43988
  };
44211
43989
  this.stopContextMenu = (event) => {
@@ -44230,10 +44008,10 @@
44230
44008
  this.updateControls();
44231
44009
  }
44232
44010
  dispose() {
44233
- this.viewer.off("contextmenu", this.stopContextMenu);
44234
- this.viewer.off("zoom", this.updateControls);
44235
- this.viewer.off("viewposition", this.updateControls);
44236
44011
  this.viewer.off("geometryend", this.updateControls);
44012
+ this.viewer.off("viewposition", this.updateControls);
44013
+ this.viewer.off("zoom", this.updateControls);
44014
+ this.viewer.off("contextmenu", this.stopContextMenu);
44237
44015
  this.orbit.removeEventListener("change", this.controlsChange);
44238
44016
  this.orbit.dispose();
44239
44017
  }
@@ -46937,18 +46715,18 @@
46937
46715
  return;
46938
46716
  if (!this.renderer)
46939
46717
  return;
46940
- const clippingPlanes = this.renderer.clippingPlanes;
46718
+ this.renderNeeded = false;
46941
46719
  this.renderer.setViewport(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);
46720
+ this.renderer.autoClear = true;
46942
46721
  this.renderer.render(this.scene, this.camera);
46722
+ const clippingPlanes = this.renderer.clippingPlanes;
46943
46723
  this.renderer.clippingPlanes = [];
46944
46724
  this.renderer.autoClear = false;
46945
46725
  this.renderer.render(this.helpers, this.camera);
46726
+ this.renderer.clippingPlanes = clippingPlanes;
46946
46727
  const deltaTime = (time - this.renderTime) / 1000;
46947
46728
  this.renderTime = time;
46948
46729
  this.emitEvent({ type: "render", time, deltaTime });
46949
- this.renderer.autoClear = true;
46950
- this.renderer.clippingPlanes = clippingPlanes;
46951
- this.renderNeeded = false;
46952
46730
  }
46953
46731
  update(force = false) {
46954
46732
  this.renderNeeded = true;
@@ -47145,6 +46923,30 @@
47145
46923
  this.update(true);
47146
46924
  return this;
47147
46925
  }
46926
+ getSelected() {
46927
+ return this.executeCommand("getSelected");
46928
+ }
46929
+ setSelected(handles) {
46930
+ this.executeCommand("setSelected", handles);
46931
+ }
46932
+ clearSelected() {
46933
+ this.executeCommand("clearSelected");
46934
+ }
46935
+ hideSelected() {
46936
+ this.executeCommand("hideSelected");
46937
+ }
46938
+ isolateSelected() {
46939
+ this.executeCommand("isolateSelected");
46940
+ }
46941
+ showAll() {
46942
+ this.executeCommand("showAll");
46943
+ }
46944
+ explode(index = 0) {
46945
+ this.executeCommand("explode", index);
46946
+ }
46947
+ collect() {
46948
+ this.executeCommand("collect");
46949
+ }
47148
46950
  activeDragger() {
47149
46951
  return this._activeDragger;
47150
46952
  }
@@ -47184,12 +46986,6 @@
47184
46986
  is3D() {
47185
46987
  return true;
47186
46988
  }
47187
- getSelected() {
47188
- return this.executeCommand("getSelected");
47189
- }
47190
- setSelected(handles) {
47191
- this.executeCommand("setSelected", handles);
47192
- }
47193
46989
  executeCommand(id, ...args) {
47194
46990
  return commands("ThreeJS").executeCommand(id, this, ...args);
47195
46991
  }