@inweb/viewer-three 26.10.2 → 26.10.4

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.
@@ -958,7 +958,7 @@ class MeasureLineDragger extends OrbitDragger {
958
958
  this.overlay.render();
959
959
  };
960
960
  this.updateSnapper = () => {
961
- this.snapper.update(this.viewer);
961
+ this.snapper.setFromViewer(this.viewer);
962
962
  };
963
963
  this.updateSnapperCamera = () => {
964
964
  this.snapper.camera = this.viewer.camera;
@@ -995,7 +995,6 @@ class MeasureLineDragger extends OrbitDragger {
995
995
  this.viewer.removeEventListener("showall", this.updateSnapper);
996
996
  this.viewer.removeEventListener("changecameramode", this.updateSnapperCamera);
997
997
  this.snapper.dispose();
998
- this.snapper.dispose();
999
998
  this.overlay.detach();
1000
999
  this.overlay.dispose();
1001
1000
  super.dispose();
@@ -1012,6 +1011,7 @@ class MeasureSnapper {
1012
1011
  this.camera = camera;
1013
1012
  this.canvas = canvas;
1014
1013
  this.objects = [];
1014
+ this.clippingPlanes = [];
1015
1015
  this.raycaster = new Raycaster();
1016
1016
  this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
1017
1017
  this.edgesCache = new WeakMap();
@@ -1027,7 +1027,7 @@ class MeasureSnapper {
1027
1027
  getMousePosition(event, target) {
1028
1028
  return target.set(event.clientX, event.clientY);
1029
1029
  }
1030
- getPointerIntersects(mouse, objects) {
1030
+ getPointerIntersects(mouse) {
1031
1031
  const rect = this.canvas.getBoundingClientRect();
1032
1032
  const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
1033
1033
  const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
@@ -1041,7 +1041,11 @@ class MeasureSnapper {
1041
1041
  Points: { threshold: 0.01 },
1042
1042
  Sprite: {},
1043
1043
  };
1044
- return this.raycaster.intersectObjects(objects, false);
1044
+ let intersects = this.raycaster.intersectObjects(this.objects, false);
1045
+ this.clippingPlanes.forEach((plane) => {
1046
+ intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
1047
+ });
1048
+ return intersects;
1045
1049
  }
1046
1050
  getDetectRadius(point) {
1047
1051
  const camera = this.camera;
@@ -1062,7 +1066,7 @@ class MeasureSnapper {
1062
1066
  }
1063
1067
  getSnapPoint(event) {
1064
1068
  const mouse = this.getMousePosition(event, new Vector2());
1065
- const intersections = this.getPointerIntersects(mouse, this.objects);
1069
+ const intersections = this.getPointerIntersects(mouse);
1066
1070
  if (intersections.length === 0)
1067
1071
  return undefined;
1068
1072
  const object = intersections[0].object;
@@ -1110,40 +1114,47 @@ class MeasureSnapper {
1110
1114
  return object.localToWorld(snapPoint);
1111
1115
  return intersectionPoint.clone();
1112
1116
  }
1113
- update(viewer) {
1117
+ setFromViewer(viewer) {
1114
1118
  this.objects.length = 0;
1115
1119
  viewer.models.forEach((model) => {
1116
1120
  model.getVisibleObjects().forEach((object) => this.objects.push(object));
1117
1121
  });
1122
+ this.camera = viewer.camera;
1123
+ this.clippingPlanes = viewer.renderer.clippingPlanes || [];
1118
1124
  }
1119
1125
  }
1120
1126
  class MeasureOverlay {
1121
1127
  constructor(camera, canvas) {
1122
1128
  this.lines = [];
1129
+ this.resizeContainer = (entries) => {
1130
+ const { width, height } = entries[0].contentRect;
1131
+ if (!width || !height)
1132
+ return;
1133
+ this.container.style.width = `${width}px`;
1134
+ this.container.style.height = `${height}px`;
1135
+ };
1123
1136
  this.camera = camera;
1124
1137
  this.canvas = canvas;
1125
1138
  this.projector = new MeasureProjector(camera, canvas);
1139
+ this.resizeObserver = new ResizeObserver(this.resizeContainer);
1126
1140
  }
1127
1141
  attach() {
1128
1142
  this.container = document.createElement("div");
1129
1143
  this.container.id = "measure-container";
1130
- this.container.style.background = "rgba(0,0,0,0)";
1131
1144
  this.container.style.position = "absolute";
1132
- this.container.style.top = "0px";
1133
- this.container.style.left = "0px";
1134
- this.container.style.width = "100%";
1135
- this.container.style.height = "100%";
1136
1145
  this.container.style.outline = "none";
1137
1146
  this.container.style.pointerEvents = "none";
1138
1147
  this.container.style.overflow = "hidden";
1139
1148
  if (!this.canvas.parentElement)
1140
1149
  return;
1141
1150
  this.canvas.parentElement.appendChild(this.container);
1151
+ this.resizeObserver.observe(this.canvas.parentElement);
1142
1152
  }
1143
1153
  dispose() {
1144
1154
  this.clear();
1145
1155
  }
1146
1156
  detach() {
1157
+ this.resizeObserver.disconnect();
1147
1158
  this.container.remove();
1148
1159
  this.container = undefined;
1149
1160
  }
@@ -1569,11 +1580,205 @@ class WalkControls extends Controls {
1569
1580
  }
1570
1581
  }
1571
1582
 
1583
+ class JoyStickControls extends Controls {
1584
+ constructor(camera, domElement, canvasElement, groundObjects) {
1585
+ super(camera, domElement);
1586
+ this.EYE_HEIGHT = 1.7;
1587
+ this.FAILING_DISTANCE = 2;
1588
+ this.GROUND_FOLLOWING_SPEED = 0.05;
1589
+ this.WALK_SPEED_DELIMITER = 4;
1590
+ this.movementSpeed = 0.1;
1591
+ this.multiplier = 3;
1592
+ this.isActive = false;
1593
+ this.MAX_JOYSTICK_DISTANCE = 100;
1594
+ this.INTERNAL_RADIUS = 35;
1595
+ this.MAX_MOVE_STICK = 40;
1596
+ this.EXTERNAL_RADIUS = 65;
1597
+ this.CANVAS_SIZE = 200;
1598
+ this.pressed = false;
1599
+ this.onPointerDown = (event) => {
1600
+ event.preventDefault();
1601
+ this.pressed = true;
1602
+ };
1603
+ this.onPointerMove = (event) => {
1604
+ event.preventDefault();
1605
+ if (!this.pressed)
1606
+ return;
1607
+ let movedX = event.pageX;
1608
+ let movedY = event.pageY;
1609
+ if (this.joyStickCanvas.offsetParent &&
1610
+ this.joyStickCanvas.offsetParent.tagName.toUpperCase() === "BODY") {
1611
+ movedX -= this.joyStickCanvas.offsetLeft;
1612
+ movedY -= this.joyStickCanvas.offsetTop;
1613
+ }
1614
+ else if (this.joyStickCanvas.offsetParent) {
1615
+ movedX -= this.joyStickCanvas.offsetParent.offsetLeft;
1616
+ movedY -= this.joyStickCanvas.offsetParent.offsetTop;
1617
+ }
1618
+ const x = 100 * ((movedX - this.centerX) / this.MAX_MOVE_STICK);
1619
+ const y = 100 * ((movedY - this.centerY) / this.MAX_MOVE_STICK) * -1;
1620
+ const distance = Math.sqrt(x * x + y * y);
1621
+ if (distance > 20) {
1622
+ this.joyStickPosition.set(x, y);
1623
+ this.isActive = true;
1624
+ }
1625
+ else {
1626
+ this.joyStickPosition.set(0, 0);
1627
+ this.isActive = false;
1628
+ }
1629
+ this.draw();
1630
+ this.moveClock.start();
1631
+ this.update();
1632
+ };
1633
+ this.onPointerUp = (event) => {
1634
+ event.preventDefault();
1635
+ this.pressed = false;
1636
+ this.joyStickPosition.set(0, 0);
1637
+ this.isActive = false;
1638
+ this.moveClock.stop();
1639
+ this.draw();
1640
+ };
1641
+ this.onResize = () => {
1642
+ this.updateVisibility();
1643
+ this.updatePosition();
1644
+ };
1645
+ this.camera = camera;
1646
+ this.canvas = canvasElement;
1647
+ this.moveClock = new Clock(false);
1648
+ this.joyStickPosition = new Vector2(0, 0);
1649
+ this.groundObjects = groundObjects;
1650
+ this.raycaster = new Raycaster();
1651
+ this.raycaster.near = 0;
1652
+ this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
1653
+ this.centerX = this.CANVAS_SIZE / 2;
1654
+ this.centerY = this.CANVAS_SIZE / 2;
1655
+ this.overlayElement = document.createElement("div");
1656
+ this.overlayElement.id = "joyStickDiv";
1657
+ this.overlayElement.style.background = "rgba(0,0,0,0)";
1658
+ this.overlayElement.style.position = "fixed";
1659
+ this.overlayElement.style.zIndex = "0";
1660
+ this.overlayElement.style.touchAction = "none";
1661
+ document.body.appendChild(this.overlayElement);
1662
+ this.joyStickCanvas = document.createElement("canvas");
1663
+ this.joyStickCanvas.id = "joyStickCanvas";
1664
+ this.joyStickCanvas.width = this.CANVAS_SIZE;
1665
+ this.joyStickCanvas.height = this.CANVAS_SIZE;
1666
+ this.overlayElement.appendChild(this.joyStickCanvas);
1667
+ this.context = this.joyStickCanvas.getContext("2d");
1668
+ this.joyStickCanvas.addEventListener("pointerdown", this.onPointerDown);
1669
+ document.addEventListener("pointermove", this.onPointerMove);
1670
+ document.addEventListener("pointerup", this.onPointerUp);
1671
+ window.addEventListener("resize", this.onResize);
1672
+ document.addEventListener("fullscreenchange", this.onResize);
1673
+ this.updateVisibility();
1674
+ this.updatePosition();
1675
+ this.draw();
1676
+ }
1677
+ dispose() {
1678
+ this.joyStickCanvas.removeEventListener("pointerdown", this.onPointerDown);
1679
+ document.removeEventListener("pointermove", this.onPointerMove);
1680
+ document.removeEventListener("pointerup", this.onPointerUp);
1681
+ window.removeEventListener("resize", this.onResize);
1682
+ document.removeEventListener("fullscreenchange", this.onResize);
1683
+ this.overlayElement.remove();
1684
+ super.dispose();
1685
+ }
1686
+ updateVisibility() {
1687
+ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1688
+ const isNarrowScreen = window.innerWidth < 1024;
1689
+ if (isMobile || isNarrowScreen) {
1690
+ this.overlayElement.style.display = "block";
1691
+ }
1692
+ else {
1693
+ this.overlayElement.style.display = "none";
1694
+ }
1695
+ }
1696
+ updatePosition() {
1697
+ const rect = this.canvas.getBoundingClientRect();
1698
+ this.overlayElement.style.top = `${rect.height - this.CANVAS_SIZE}px`;
1699
+ this.overlayElement.style.left = `${rect.left}px`;
1700
+ this.overlayElement.style.width = `${this.CANVAS_SIZE}px`;
1701
+ this.overlayElement.style.height = `${this.CANVAS_SIZE}px`;
1702
+ }
1703
+ draw() {
1704
+ this.context.clearRect(0, 0, this.CANVAS_SIZE, this.CANVAS_SIZE);
1705
+ this.context.beginPath();
1706
+ this.context.arc(this.centerX, this.centerY, this.EXTERNAL_RADIUS, 0, 2 * Math.PI, false);
1707
+ this.context.lineWidth = 2;
1708
+ this.context.strokeStyle = "#35436E";
1709
+ this.context.globalAlpha = 0.5;
1710
+ this.context.stroke();
1711
+ let movedX = this.centerX + (this.joyStickPosition.x * this.MAX_MOVE_STICK) / 100;
1712
+ let movedY = this.centerY - (this.joyStickPosition.y * this.MAX_MOVE_STICK) / 100;
1713
+ movedX = Math.max(this.MAX_MOVE_STICK, Math.min(this.CANVAS_SIZE - this.MAX_MOVE_STICK, movedX));
1714
+ movedY = Math.max(this.MAX_MOVE_STICK, Math.min(this.CANVAS_SIZE - this.MAX_MOVE_STICK, movedY));
1715
+ this.context.beginPath();
1716
+ this.context.arc(movedX, movedY, this.INTERNAL_RADIUS, 0, 2 * Math.PI, false);
1717
+ this.context.fillStyle = "#35436E";
1718
+ this.context.lineWidth = 2;
1719
+ this.context.strokeStyle = "#35436E";
1720
+ this.context.globalAlpha = 0.5;
1721
+ this.context.fill();
1722
+ this.context.stroke();
1723
+ }
1724
+ updateGroundFollowing() {
1725
+ const up = new Vector3().copy(this.camera.up);
1726
+ this.raycaster.set(this.camera.position, up.negate());
1727
+ this.raycaster.params = this.raycaster.params = {
1728
+ Mesh: {},
1729
+ Line: { threshold: 0 },
1730
+ Line2: { threshold: 0 },
1731
+ LOD: { threshold: 0 },
1732
+ Points: { threshold: 0 },
1733
+ Sprite: { threshold: 0 },
1734
+ };
1735
+ const intersects = this.raycaster.intersectObjects(this.groundObjects, false);
1736
+ if (intersects.length > 0) {
1737
+ const groundY = intersects[0].point.y;
1738
+ const targetY = groundY + this.EYE_HEIGHT;
1739
+ this.camera.position.y = MathUtils.lerp(this.camera.position.y, targetY, this.GROUND_FOLLOWING_SPEED);
1740
+ }
1741
+ }
1742
+ update() {
1743
+ if (!this.isActive)
1744
+ return;
1745
+ const forwardInput = this.joyStickPosition.y / this.MAX_JOYSTICK_DISTANCE;
1746
+ const rightInput = this.joyStickPosition.x / this.MAX_JOYSTICK_DISTANCE;
1747
+ const timeDelta = this.moveClock.getDelta();
1748
+ const moveDelta = (timeDelta * this.multiplier * this.movementSpeed) / this.WALK_SPEED_DELIMITER;
1749
+ const forward = new Vector3();
1750
+ const sideways = new Vector3();
1751
+ this.camera.getWorldDirection(forward);
1752
+ if (this.groundObjects.length > 0) {
1753
+ forward.y = 0;
1754
+ }
1755
+ forward.normalize();
1756
+ sideways.setFromMatrixColumn(this.camera.matrix, 0);
1757
+ if (this.groundObjects.length > 0) {
1758
+ sideways.y = 0;
1759
+ }
1760
+ sideways.normalize();
1761
+ if (forwardInput !== 0) {
1762
+ this.camera.position.addScaledVector(forward, moveDelta * forwardInput);
1763
+ }
1764
+ if (rightInput !== 0) {
1765
+ this.camera.position.addScaledVector(sideways, moveDelta * rightInput);
1766
+ }
1767
+ if (forwardInput !== 0 || rightInput !== 0) {
1768
+ if (this.groundObjects.length > 0)
1769
+ this.updateGroundFollowing();
1770
+ this.dispatchEvent({ type: "change" });
1771
+ }
1772
+ }
1773
+ }
1774
+
1572
1775
  class WalkDragger {
1573
1776
  constructor(viewer) {
1574
1777
  this.updateControls = () => {
1575
1778
  const size = this.viewer.extents.getSize(new Vector3());
1576
1779
  this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
1780
+ this.joyStickControls.movementSpeed = this.controls.movementSpeed;
1781
+ this.joyStickControls.multiplier = this.controls.multiplier;
1577
1782
  };
1578
1783
  this.updateControlsCamera = () => {
1579
1784
  this.controls.object = this.viewer.camera;
@@ -1584,8 +1789,10 @@ class WalkDragger {
1584
1789
  };
1585
1790
  this.walkspeedChange = (event) => {
1586
1791
  this.viewer.emitEvent(event);
1792
+ this.joyStickControls.multiplier = this.controls.multiplier;
1587
1793
  };
1588
1794
  this.viewerRender = () => {
1795
+ this.joyStickControls.update();
1589
1796
  this.controls.update();
1590
1797
  };
1591
1798
  this.viewerZoom = () => {
@@ -1600,6 +1807,8 @@ class WalkDragger {
1600
1807
  this.controls = new WalkControls(viewer.camera, viewer.canvas, meshOnlyGround);
1601
1808
  this.controls.addEventListener("change", this.controlsChange);
1602
1809
  this.controls.addEventListener("walkspeedchange", this.walkspeedChange);
1810
+ this.joyStickControls = new JoyStickControls(viewer.camera, viewer.canvas, viewer.canvas, meshOnlyGround);
1811
+ this.joyStickControls.addEventListener("change", this.controlsChange);
1603
1812
  this.viewer = viewer;
1604
1813
  this.viewer.addEventListener("render", this.viewerRender);
1605
1814
  this.viewer.addEventListener("zoom", this.viewerZoom);
@@ -1613,6 +1822,8 @@ class WalkDragger {
1613
1822
  this.controls.removeEventListener("walkspeedchange", this.walkspeedChange);
1614
1823
  this.controls.removeEventListener("change", this.controlsChange);
1615
1824
  this.controls.dispose();
1825
+ this.joyStickControls.removeEventListener("change", this.controlsChange);
1826
+ this.joyStickControls.dispose();
1616
1827
  }
1617
1828
  }
1618
1829
 
@@ -1768,6 +1979,8 @@ class FlyDragger {
1768
1979
  this.updateControls = () => {
1769
1980
  const size = this.viewer.extents.getSize(new Vector3());
1770
1981
  this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
1982
+ this.joyStickControls.movementSpeed = this.controls.movementSpeed;
1983
+ this.joyStickControls.multiplier = this.controls.multiplier;
1771
1984
  };
1772
1985
  this.updateControlsCamera = () => {
1773
1986
  this.controls.object = this.viewer.camera;
@@ -1778,8 +1991,10 @@ class FlyDragger {
1778
1991
  };
1779
1992
  this.flyspeedChange = (event) => {
1780
1993
  this.viewer.emitEvent(event);
1994
+ this.joyStickControls.multiplier = this.controls.multiplier;
1781
1995
  };
1782
1996
  this.viewerRender = () => {
1997
+ this.joyStickControls.update();
1783
1998
  this.controls.update();
1784
1999
  };
1785
2000
  this.viewerZoom = () => {
@@ -1788,6 +2003,8 @@ class FlyDragger {
1788
2003
  this.controls = new FlyControls(viewer.camera, viewer.canvas);
1789
2004
  this.controls.addEventListener("change", this.controlsChange);
1790
2005
  this.controls.addEventListener("flyspeedchange", this.flyspeedChange);
2006
+ this.joyStickControls = new JoyStickControls(viewer.camera, viewer.canvas, viewer.canvas, []);
2007
+ this.joyStickControls.addEventListener("change", this.controlsChange);
1791
2008
  this.viewer = viewer;
1792
2009
  this.viewer.addEventListener("render", this.viewerRender);
1793
2010
  this.viewer.addEventListener("zoom", this.viewerZoom);
@@ -1801,6 +2018,8 @@ class FlyDragger {
1801
2018
  this.controls.removeEventListener("flyspeedchange", this.flyspeedChange);
1802
2019
  this.controls.removeEventListener("change", this.controlsChange);
1803
2020
  this.controls.dispose();
2021
+ this.joyStickControls.removeEventListener("change", this.controlsChange);
2022
+ this.joyStickControls.dispose();
1804
2023
  }
1805
2024
  }
1806
2025
 
@@ -2583,7 +2802,11 @@ class SelectionComponent {
2583
2802
  Points: { threshold: 0.01 },
2584
2803
  Sprite: {},
2585
2804
  };
2586
- return this.raycaster.intersectObjects(objects, false);
2805
+ let intersects = this.raycaster.intersectObjects(objects, false);
2806
+ (this.viewer.renderer.clippingPlanes || []).forEach((plane) => {
2807
+ intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
2808
+ });
2809
+ return intersects;
2587
2810
  }
2588
2811
  select(objects, model) {
2589
2812
  if (!model) {