@xeokit/xeokit-sdk 2.6.73 → 2.6.77-slim-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/xeokit-sdk.cjs.js +246 -126
  2. package/dist/xeokit-sdk.es.js +246 -126
  3. package/dist/xeokit-sdk.es5.js +316 -306
  4. package/dist/xeokit-sdk.min.cjs.js +8 -8
  5. package/dist/xeokit-sdk.min.es.js +8 -8
  6. package/dist/xeokit-sdk.min.es5.js +7 -7
  7. package/package.json +2 -1
  8. package/src/extras/ContextMenu/ContextMenu.js +25 -16
  9. package/src/extras/Skybox/Skybox.js +139 -0
  10. package/src/extras/index.js +2 -1
  11. package/src/plugins/CxConverterIFCLoaderPlugin/CxConverterIFCLoaderPlugin.js +81 -81
  12. package/src/plugins/CxConverterIFCLoaderPlugin/index.js +1 -1
  13. package/src/plugins/FastNavPlugin/FastNavPlugin.js +10 -18
  14. package/src/plugins/SectionPlanesPlugin/Control.js +1 -1
  15. package/src/plugins/TreeViewPlugin/RenderService.js +13 -4
  16. package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +1 -1
  17. package/src/plugins/index.js +0 -1
  18. package/src/viewer/Viewer.js +0 -16
  19. package/src/viewer/scene/CameraControl/lib/controllers/PivotController.js +29 -8
  20. package/src/viewer/scene/LineSet/LineSet.js +7 -2
  21. package/src/viewer/scene/camera/CameraFlightAnimation.js +2 -2
  22. package/src/viewer/scene/canvas/Canvas.js +7 -4
  23. package/src/viewer/scene/index.js +0 -1
  24. package/src/viewer/scene/model/dtx/triangles/renderers/DTXTrianglesColorRenderer.js +5 -0
  25. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesColorRenderer.js +5 -0
  26. package/src/viewer/scene/model/vbo/batching/triangles/renderers/TrianglesFlatColorRenderer.js +5 -0
  27. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesColorRenderer.js +5 -0
  28. package/src/viewer/scene/model/vbo/instancing/triangles/renderers/TrianglesFlatColorRenderer.js +5 -0
  29. package/types/plugins/FastNavPlugin/FastNavPlugin.d.ts +5 -0
  30. package/types/plugins/index.d.ts +0 -1
  31. package/types/viewer/scene/CameraControl/CameraControl.d.ts +168 -0
  32. package/types/viewer/scene/LineSet/LineSet.d.ts +1 -1
  33. package/types/viewer/scene/camera/CameraPath.d.ts +86 -6
  34. package/types/viewer/scene/camera/CameraPathAnimation.d.ts +2 -0
  35. package/types/viewer/scene/geometry/ReadableGeometry.d.ts +14 -0
  36. package/types/viewer/scene/geometry/VBOGeometry.d.ts +2 -0
  37. package/types/viewer/scene/geometry/index.d.ts +2 -1
  38. package/types/viewer/scene/geometry/loaders/index.d.ts +2 -0
  39. package/types/viewer/scene/geometry/loaders/load3DSGeometry.d.ts +17 -0
  40. package/types/viewer/scene/geometry/loaders/loadOBJGeometry.d.ts +18 -0
  41. package/types/viewer/scene/index.d.ts +1 -0
  42. package/types/viewer/scene/input/input.d.ts +117 -0
  43. package/types/viewer/scene/lights/AmbientLight.d.ts +41 -0
  44. package/types/viewer/scene/lights/CubeTexture.d.ts +27 -0
  45. package/types/viewer/scene/lights/DirLight.d.ts +77 -0
  46. package/types/viewer/scene/lights/LightMap.d.ts +27 -0
  47. package/types/viewer/scene/lights/PointLight.d.ts +135 -0
  48. package/types/viewer/scene/lights/ReflectionMap.d.ts +26 -0
  49. package/types/viewer/scene/lights/index.d.ts +4 -1
  50. package/types/viewer/scene/marker/Marker.d.ts +5 -0
  51. package/types/viewer/scene/materials/EmphasisMaterial.d.ts +5 -0
  52. package/types/viewer/scene/materials/Fresnel.d.ts +25 -62
  53. package/types/viewer/scene/materials/LambertMaterial.d.ts +192 -0
  54. package/types/viewer/scene/materials/MetallicMaterial.d.ts +359 -0
  55. package/types/viewer/scene/materials/PhongMaterial.d.ts +5 -0
  56. package/types/viewer/scene/materials/PointsMaterial.d.ts +5 -0
  57. package/types/viewer/scene/materials/SpecularMaterial.d.ts +342 -0
  58. package/types/viewer/scene/materials/Texture.d.ts +36 -78
  59. package/types/viewer/scene/materials/index.d.ts +2 -0
  60. package/types/viewer/scene/models/SceneModel.d.ts +134 -7
  61. package/types/viewer/scene/models/SceneModelEntity.d.ts +65 -0
  62. package/types/viewer/scene/models/SceneModelMesh.d.ts +12 -0
  63. package/types/viewer/scene/paths/CubicBezierCurve.d.ts +146 -0
  64. package/types/viewer/scene/paths/Curve.d.ts +75 -0
  65. package/types/viewer/scene/paths/Path.d.ts +119 -0
  66. package/types/viewer/scene/paths/QuadraticBezierCurve.d.ts +124 -0
  67. package/types/viewer/scene/paths/SplineCurve.d.ts +84 -0
  68. package/types/viewer/scene/paths/index.d.ts +5 -0
  69. package/types/viewer/scene/scene/Scene.d.ts +102 -0
  70. package/types/viewer/scene/sectionPlane/SectionPlane.d.ts +41 -0
  71. package/types/viewer/scene/webgl/PickResult.d.ts +19 -0
  72. package/src/plugins/SkyboxesPlugin/SkyboxesPlugin.js +0 -134
  73. package/src/plugins/SkyboxesPlugin/index.js +0 -1
  74. package/src/viewer/scene/skybox/Skybox.js +0 -123
  75. package/types/plugins/SkyboxesPlugin/SkyboxesPlugin.d.ts +0 -34
  76. package/types/plugins/SkyboxesPlugin/index.d.ts +0 -1
  77. /package/src/{viewer/scene/skybox → extras/Skybox}/index.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xeokit/xeokit-sdk",
3
- "version": "2.6.73",
3
+ "version": "2.6.77-slim-rc1",
4
4
  "description": "3D BIM IFC Viewer SDK for AEC engineering applications. Open Source JavaScript Toolkit based on pure WebGL for top performance, real-world coordinates and full double precision",
5
5
  "module": "./dist/xeokit-sdk.es.js",
6
6
  "main": "./dist/xeokit-sdk.cjs.js",
@@ -57,6 +57,7 @@
57
57
  "@loaders.gl/core": "^4.3.3",
58
58
  "@loaders.gl/gltf": "^4.3.3",
59
59
  "@loaders.gl/las": "^4.3.3",
60
+ "@rollup/plugin-replace": "^6.0.2",
60
61
  "html2canvas": "^1.4.1"
61
62
  },
62
63
  "devDependencies": {
@@ -298,7 +298,8 @@ class ContextMenu {
298
298
  this._shown = false; // True when the ContextMenu is visible
299
299
  this._nextId = 0;
300
300
  this._parentNode = cfg.parentNode || document.body;
301
-
301
+ this._offsetParent = (this._parentNode instanceof ShadowRoot) ? this._parentNode.host : this._parentNode;
302
+
302
303
  /**
303
304
  * Subscriptions to events fired at this ContextMenu.
304
305
  * @private
@@ -510,7 +511,7 @@ class ContextMenu {
510
511
  for (let i = 0, len = this._menuList.length; i < len; i++) {
511
512
  const menu = this._menuList[i];
512
513
  const menuElement = menu.menuElement;
513
- menuElement.parentElement.removeChild(menuElement);
514
+ menuElement.remove();
514
515
  }
515
516
  this._itemsCfg = [];
516
517
  this._rootMenu = null;
@@ -738,21 +739,22 @@ class ContextMenu {
738
739
 
739
740
  const itemRect = itemElement.getBoundingClientRect();
740
741
  const menuRect = subMenuElement.getBoundingClientRect();
742
+ const offsetRect = self._offsetParent.getBoundingClientRect();
741
743
 
742
744
  const subMenuWidth = 200; // TODO
743
- const showOnRight = (itemRect.right + subMenuWidth) < window.innerWidth;
744
- const showOnLeft = (itemRect.left - subMenuWidth) > 0;
745
-
745
+ const showOnRight = (itemRect.right + subMenuWidth) < offsetRect.right;
746
+ const showOnLeft = (itemRect.left - subMenuWidth) > offsetRect.left;
747
+
746
748
  if(showOnRight)
747
- self._showMenu(subMenu.id, itemRect.right - 5, itemRect.top - 1);
749
+ self._showMenu(subMenu.id, itemRect.right + window.scrollX - 5, itemRect.top + window.scrollY - 1);
748
750
  else if (showOnLeft)
749
- self._showMenu(subMenu.id, itemRect.left - subMenuWidth, itemRect.top - 1);
751
+ self._showMenu(subMenu.id, itemRect.left - subMenuWidth + window.scrollX, itemRect.top + window.scrollY - 1);
750
752
  else {
751
- const spaceOnLeft = itemRect.left, spaceOnRight = window.innerWidth - itemRect.right;
753
+ const spaceOnLeft = itemRect.left - offsetRect.left, spaceOnRight = offsetRect.right - itemRect.right;
752
754
  if(spaceOnRight > spaceOnLeft)
753
- self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top - 1);
755
+ self._showMenu(subMenu.id, itemRect.right - 5 - (subMenuWidth - spaceOnRight), itemRect.top + window.scrollY - 1);
754
756
  else
755
- self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top - 1);
757
+ self._showMenu(subMenu.id, itemRect.left - spaceOnLeft, itemRect.top + window.scrollY - 1);
756
758
  }
757
759
 
758
760
  lastSubMenu = subMenu;
@@ -945,14 +947,21 @@ class ContextMenu {
945
947
  menuElement.style.display = 'block';
946
948
  const menuHeight = menuElement.offsetHeight;
947
949
  const menuWidth = menuElement.offsetWidth;
948
- if ((pageY + menuHeight) > window.innerHeight) {
949
- pageY = window.innerHeight - menuHeight;
950
+
951
+ const offsetRect = this._offsetParent.getBoundingClientRect();
952
+
953
+ const bottomContainerBorder = offsetRect.bottom + window.scrollY;
954
+ const rightContainerBorder = offsetRect.right + window.scrollX;
955
+ if ((pageY + menuHeight) > bottomContainerBorder) {
956
+ pageY = bottomContainerBorder- menuHeight;
950
957
  }
951
- if ((pageX + menuWidth) > window.innerWidth) {
952
- pageX = window.innerWidth - menuWidth;
958
+ if ((pageX + menuWidth) > rightContainerBorder) {
959
+ pageX = rightContainerBorder - menuWidth;
953
960
  }
954
- menuElement.style.left = pageX + 'px';
955
- menuElement.style.top = pageY + 'px';
961
+
962
+
963
+ menuElement.style.left = pageX - offsetRect.left - window.scrollX + 'px';
964
+ menuElement.style.top = pageY - offsetRect.top - window.scrollY + 'px';
956
965
  }
957
966
 
958
967
  _hideMenuElement(menuElement) {
@@ -0,0 +1,139 @@
1
+ import {
2
+ ClampToEdgeWrapping,
3
+ LinearEncoding,
4
+ Mesh,
5
+ PhongMaterial,
6
+ ReadableGeometry,
7
+ Texture
8
+ } from "../../viewer/index.js";
9
+
10
+ /**
11
+ * @param {Component} scene
12
+ * @param {*} [cfg] Texture configuration
13
+ * @param {String[]} [cfg.src=null] Path to 6 images
14
+ * @param {Number} [cfg.encoding=LinearEncoding] Texture encoding format. See the {@link Texture#encoding} property for more info.
15
+ */
16
+
17
+ export async function createCombinedTexture(scene, cfg) {
18
+ if(!cfg.src || !Array.isArray(cfg.src) || cfg.src.length !== 6)
19
+ throw new Error("src requires path to 6 images");
20
+ const [
21
+ posX,
22
+ negX,
23
+ posY,
24
+ negY,
25
+ posZ,
26
+ negZ
27
+ ] = cfg.src;
28
+
29
+ if (!posX || !negX || !posY || !negY || !posZ || !negZ) {
30
+ throw new Error("All six images must be provided");
31
+ }
32
+
33
+ const canvas = document.createElement('canvas');
34
+ const ctx = canvas.getContext('2d');
35
+
36
+ const loadImage = src => {
37
+ return new Promise((resolve, reject) => {
38
+ const img = new Image();
39
+ img.crossOrigin = "anonymous";
40
+ img.onload = () => resolve(img);
41
+ img.onerror = () => reject(new Error(`Failed to load image: ${src}`));
42
+ img.src = src;
43
+ });
44
+ };
45
+
46
+ try {
47
+ const [imgPosX, imgNegX, imgPosY, imgNegY, imgPosZ, imgNegZ] = await Promise.all([
48
+ loadImage(posX),
49
+ loadImage(negX),
50
+ loadImage(posY),
51
+ loadImage(negY),
52
+ loadImage(posZ),
53
+ loadImage(negZ)
54
+ ]);
55
+
56
+ const imageSize = imgPosX.width;
57
+ if (
58
+ imgNegX.width !== imageSize || imgPosY.width !== imageSize ||
59
+ imgNegY.width !== imageSize || imgPosZ.width !== imageSize ||
60
+ imgNegZ.width !== imageSize
61
+ ) {
62
+ throw new Error("All skybox textures must have the same dimensions");
63
+ }
64
+
65
+ // Set canvas size for the Christ cross layout (3×4 grid)
66
+ canvas.width = imageSize * 4;
67
+ canvas.height = imageSize * 3;
68
+
69
+ ctx.fillStyle = 'black';
70
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
71
+
72
+ ctx.drawImage(imgNegX, imageSize * 0, imageSize * 1, imageSize, imageSize); // -X (left)
73
+ ctx.drawImage(imgPosX, imageSize * 2, imageSize * 1, imageSize, imageSize); // +X (right)
74
+ ctx.drawImage(imgPosY, imageSize * 1, imageSize * 0, imageSize, imageSize); // +Y (top)
75
+ ctx.drawImage(imgNegY, imageSize * 1, imageSize * 2, imageSize, imageSize); // -Y (bottom)
76
+ ctx.drawImage(imgPosZ, imageSize * 1, imageSize * 1, imageSize, imageSize); // +Z (front)
77
+ ctx.drawImage(imgNegZ, imageSize * 3, imageSize * 1, imageSize, imageSize); // -Z (back)
78
+
79
+ const combinedTexture = new Texture(scene, {
80
+ image: canvas,
81
+ flipY: true,
82
+ wrapS: ClampToEdgeWrapping,
83
+ wrapT: ClampToEdgeWrapping,
84
+ encoding: cfg.encoding || LinearEncoding
85
+ });
86
+
87
+ return combinedTexture;
88
+ } catch (error) {
89
+ console.error("Error creating combined skybox texture:", error);
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * @param {Component} scene
96
+ * @param {Texture} [texture] Texture to be used on the skybox mesh
97
+ */
98
+
99
+ export function createSkyboxMesh(scene, texture) {
100
+
101
+ return new Mesh(scene, {
102
+
103
+ geometry: new ReadableGeometry(scene, { // Box-shaped geometry
104
+ primitive: "triangles",
105
+ positions: [
106
+ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front
107
+ 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v5 right
108
+ 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v5-v6-v1 top
109
+ -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left
110
+ -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, // v7-v4-v3-v2 bottom
111
+ 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v5 back
112
+ ],
113
+ uv: [
114
+ 0.5, 0.6666, 0.25, 0.6666, 0.25, 0.3333, 0.5, 0.3333, 0.5, 0.6666, 0.5, 0.3333, 0.75, 0.3333, 0.75, 0.6666,
115
+ 0.5, 0.6666, 0.5, 1, 0.25, 1, 0.25, 0.6666, 0.25, 0.6666, 0.0, 0.6666, 0.0, 0.3333, 0.25, 0.3333,
116
+ 0.25, 0, 0.50, 0, 0.50, 0.3333, 0.25, 0.3333, 0.75, 0.3333, 1.0, 0.3333, 1.0, 0.6666, 0.75, 0.6666
117
+ ],
118
+ indices: [
119
+ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11,
120
+ 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23
121
+ ]
122
+ }),
123
+ background: true,
124
+ scale: [1000, 1000, 1000],
125
+ rotation: [0, -90, 0],
126
+ material: new PhongMaterial(scene, {
127
+ ambient: [0, 0, 0],
128
+ diffuse: [0, 0, 0],
129
+ specular: [0, 0, 0],
130
+ emissive: [1, 1, 1],
131
+ emissiveMap: texture,
132
+ backfaces: true // Show interior faces of our skybox geometry
133
+ }),
134
+ visible: true,
135
+ pickable: false,
136
+ clippable: false,
137
+ collidable: false
138
+ });
139
+ }
@@ -2,4 +2,5 @@ export * from "./ContextMenu/index.js";
2
2
  export * from "./PointerLens/index.js";
3
3
  export * from "./collision/index.js";
4
4
  export * from "./MarqueePicker/index.js";
5
- export * from "./PointerCircle/index.js";
5
+ export * from "./PointerCircle/index.js";
6
+ export * from "./Skybox/index.js";
@@ -1,86 +1,86 @@
1
- import { Plugin } from "../../viewer/Plugin.js";
2
- import { GLTFLoaderPlugin } from "../GLTFLoaderPlugin/GLTFLoaderPlugin.js";
3
- import { ifc2gltf } from "@creooxag/cx-converter";
1
+ // import { Plugin } from "../../viewer/Plugin.js";
2
+ // import { GLTFLoaderPlugin } from "../GLTFLoaderPlugin/GLTFLoaderPlugin.js";
3
+ // import { ifc2gltf } from "@creooxag/cx-converter";
4
4
 
5
- /**
6
- * Fetches a file from the given URL and returns its contents as text.
7
- *
8
- * @param {string} url - The URL to fetch the file from.
9
- * @returns {Promise<string>} A promise that resolves to the file contents.
10
- * @private
11
- */
12
- async function fetchFile(url) {
13
- try {
14
- const response = await fetch(url);
15
- if (!response.ok) {
16
- throw new Error(`HTTP error! Status: ${response.status}`);
17
- }
18
- return response.text();
19
- } catch (error) {
20
- console.error('Error fetching file:', error);
21
- }
22
- }
5
+ // /**
6
+ // * Fetches a file from the given URL and returns its contents as text.
7
+ // *
8
+ // * @param {string} url - The URL to fetch the file from.
9
+ // * @returns {Promise<string>} A promise that resolves to the file contents.
10
+ // * @private
11
+ // */
12
+ // async function fetchFile(url) {
13
+ // try {
14
+ // const response = await fetch(url);
15
+ // if (!response.ok) {
16
+ // throw new Error(`HTTP error! Status: ${response.status}`);
17
+ // }
18
+ // return response.text();
19
+ // } catch (error) {
20
+ // console.error('Error fetching file:', error);
21
+ // }
22
+ // }
23
23
 
24
- /**
25
- * {@link Viewer} plugin that uses [CxConverter](https://github.com/Creoox/cxconverter) to load BIM models directly from IFC files, using its WebAssembly buid from [npm package](https://www.npmjs.com/package/@creooxag/cx-converter).
26
- *
27
- * ## Overview
28
- * The WebAssembly build of CxConverter is still in alfa stage, so it may not work as expected. This documentation will be updated as the library and the plugin evolve. The example below shows how to use the plugin:
29
- * ````javascript
30
- * import { CxConverterIFCLoaderPlugin, Viewer } from "../../dist/xeokit-sdk.es.js";
31
- * const cxConverterIFCLoaderPlugin = new CxConverterIFCLoaderPlugin(viewer);
32
- *
33
- * const sceneModel = await cxConverterIFCLoaderPlugin.load({
34
- * src: "../../assets/models/ifc/Duplex.ifc"
35
- * });
36
- * ````
37
- See the code in action [here](https://xeokit.github.io/xeokit-sdk/examples/buildings/#cxConverterIFC_vbo_Duplex).
38
- */
24
+ // /**
25
+ // * {@link Viewer} plugin that uses [CxConverter](https://github.com/Creoox/cxconverter) to load BIM models directly from IFC files, using its WebAssembly buid from [npm package](https://www.npmjs.com/package/@creooxag/cx-converter).
26
+ // *
27
+ // * ## Overview
28
+ // * The WebAssembly build of CxConverter is still in alfa stage, so it may not work as expected. This documentation will be updated as the library and the plugin evolve. The example below shows how to use the plugin:
29
+ // * ````javascript
30
+ // * import { CxConverterIFCLoaderPlugin, Viewer } from "../../dist/xeokit-sdk.es.js";
31
+ // * const cxConverterIFCLoaderPlugin = new CxConverterIFCLoaderPlugin(viewer);
32
+ // *
33
+ // * const sceneModel = await cxConverterIFCLoaderPlugin.load({
34
+ // * src: "../../assets/models/ifc/Duplex.ifc"
35
+ // * });
36
+ // * ````
37
+ // See the code in action [here](https://xeokit.github.io/xeokit-sdk/examples/buildings/#cxConverterIFC_vbo_Duplex).
38
+ // */
39
39
 
40
- class CxConverterIFCLoaderPlugin extends Plugin {
41
- /**
42
- * @constructor
43
- * @param {Viewer} viewer The Viewer.
44
- * @param {Object} [cfg={}] Plugin configuration.
45
- */
46
- constructor(viewer, cfg = {}) {
47
- super("ifcLoader", viewer, cfg);
40
+ // class CxConverterIFCLoaderPlugin extends Plugin {
41
+ // /**
42
+ // * @constructor
43
+ // * @param {Viewer} viewer The Viewer.
44
+ // * @param {Object} [cfg={}] Plugin configuration.
45
+ // */
46
+ // constructor(viewer, cfg = {}) {
47
+ // super("ifcLoader", viewer, cfg);
48
48
 
49
- /**
50
- * The GLTFLoaderPlugin used internally to load the converted GLTF.
51
- * @type {GLTFLoaderPlugin}
52
- */
53
- this.gltfLoader = new GLTFLoaderPlugin(this.viewer);
54
- }
49
+ // /**
50
+ // * The GLTFLoaderPlugin used internally to load the converted GLTF.
51
+ // * @type {GLTFLoaderPlugin}
52
+ // */
53
+ // this.gltfLoader = new GLTFLoaderPlugin(this.viewer);
54
+ // }
55
55
 
56
- /**
57
- * Loads an IFC model from the given source.
58
- *
59
- * @param {Object} [params={}] Loading parameters.
60
- * @param {string} params.src Path to an IFC file.
61
- * @param {Function} [params.progressCallback] Callback to track loading progress.
62
- * @param {Function} [params.progressTextCallback] Callback to track loading progress with text updates.
63
- * @returns {Promise<SceneModel>} A promise that resolves to the loaded SceneModel.
64
- */
65
- async load(params = {}) {
66
- if (!params.src) {
67
- this.error("load() param expected: src");
68
- }
69
- const data = await fetchFile(params.src);
70
- const { gltf, metaData } = await ifc2gltf(
71
- data,
72
- {
73
- remote: true,
74
- progressCallback: params.progressCallback,
75
- progressTextCallback: params.progressTextCallback
76
- }
77
- );
78
- const sceneModel = this.gltfLoader.load({
79
- id: "myModel",
80
- gltf: gltf,
81
- metaModelJSON: metaData
82
- });
83
- return sceneModel;
84
- }
85
- }
86
- export { CxConverterIFCLoaderPlugin };
56
+ // /**
57
+ // * Loads an IFC model from the given source.
58
+ // *
59
+ // * @param {Object} [params={}] Loading parameters.
60
+ // * @param {string} params.src Path to an IFC file.
61
+ // * @param {Function} [params.progressCallback] Callback to track loading progress.
62
+ // * @param {Function} [params.progressTextCallback] Callback to track loading progress with text updates.
63
+ // * @returns {Promise<SceneModel>} A promise that resolves to the loaded SceneModel.
64
+ // */
65
+ // async load(params = {}) {
66
+ // if (!params.src) {
67
+ // this.error("load() param expected: src");
68
+ // }
69
+ // const data = await fetchFile(params.src);
70
+ // const { gltf, metaData } = await ifc2gltf(
71
+ // data,
72
+ // {
73
+ // remote: true,
74
+ // progressCallback: params.progressCallback,
75
+ // progressTextCallback: params.progressTextCallback
76
+ // }
77
+ // );
78
+ // const sceneModel = this.gltfLoader.load({
79
+ // id: "myModel",
80
+ // gltf: gltf,
81
+ // metaModelJSON: metaData
82
+ // });
83
+ // return sceneModel;
84
+ // }
85
+ // }
86
+ // export { CxConverterIFCLoaderPlugin };
@@ -1 +1 @@
1
- export * from "./CxConverterIFCLoaderPlugin.js";
1
+ // export * from "./CxConverterIFCLoaderPlugin.js";
@@ -108,6 +108,7 @@ class FastNavPlugin extends Plugin {
108
108
  * @param {Number} [cfg.scaleCanvasResolutionFactor=0.6] The factor by which we downscale the canvas resolution whenever we interact with the Viewer.
109
109
  * @param {Boolean} [cfg.delayBeforeRestore=true] Whether to temporarily have a delay before restoring normal rendering after we stop interacting with the Viewer.
110
110
  * @param {Number} [cfg.delayBeforeRestoreSeconds=0.5] Delay in seconds before restoring normal rendering after we stop interacting with the Viewer.
111
+ * @param {Function} [cfg.onMoved] Optional callback function fired during moving mode, should return the callback function that will be fired when the interaction stops.
111
112
  */
112
113
  constructor(viewer, cfg = {}) {
113
114
 
@@ -123,6 +124,8 @@ class FastNavPlugin extends Plugin {
123
124
  this._scaleCanvasResolutionFactor = cfg.scaleCanvasResolutionFactor || 0.6;
124
125
  this._delayBeforeRestore = (cfg.delayBeforeRestore !== false);
125
126
  this._delayBeforeRestoreSeconds = cfg.delayBeforeRestoreSeconds || 0.5;
127
+ this._onMoved = cfg.onMoved;
128
+ this._onStopped = null;
126
129
 
127
130
  let timer = this._delayBeforeRestoreSeconds * 1000;
128
131
  let fastMode = false;
@@ -141,6 +144,10 @@ class FastNavPlugin extends Plugin {
141
144
  } else {
142
145
  viewer.scene.canvas.resolutionScale = this._defaultScaleCanvasResolutionFactor;
143
146
  }
147
+ if (this._onMoved) {
148
+ this._onStopped = this._onMoved();
149
+ }
150
+
144
151
  fastMode = true;
145
152
  }
146
153
  };
@@ -152,10 +159,12 @@ class FastNavPlugin extends Plugin {
152
159
  viewer.scene._renderer.setPBREnabled(true);
153
160
  viewer.scene._renderer.setSAOEnabled(true);
154
161
  viewer.scene._renderer.setTransparentEnabled(true);
162
+ if (this._onStopped) {
163
+ this._onStopped();
164
+ }
155
165
  fastMode = false;
156
166
  };
157
167
 
158
- this._onCanvasBoundary = viewer.scene.canvas.on("boundary", switchToLowQuality);
159
168
  this._onCameraMatrix = viewer.scene.camera.on("matrix", switchToLowQuality);
160
169
 
161
170
  this._onSceneTick = viewer.scene.on("tick", (tickEvent) => {
@@ -167,23 +176,6 @@ class FastNavPlugin extends Plugin {
167
176
  switchToHighQuality();
168
177
  }
169
178
  });
170
-
171
- let down = false;
172
-
173
- this._onSceneMouseDown = viewer.scene.input.on("mousedown", () => {
174
- down = true;
175
- });
176
-
177
- this._onSceneMouseUp = viewer.scene.input.on("mouseup", () => {
178
- down = false;
179
- });
180
-
181
- this._onSceneMouseMove = viewer.scene.input.on("mousemove", () => {
182
- if (!down) {
183
- return;
184
- }
185
- switchToLowQuality();
186
- });
187
179
  }
188
180
 
189
181
  /**
@@ -460,7 +460,7 @@ class Control {
460
460
 
461
461
  { // Keep gizmo screen size constant
462
462
  let lastDist = -1;
463
- const setRootNodeScale = size => rootNode.scale = [size, size, size];
463
+ const setRootNodeScale = size => { if (size !== rootNode.scale[0]) { rootNode.scale = [size, size, size]; } };
464
464
  const onSceneTick = scene.on("tick", () => {
465
465
  const dist = Math.abs(math.distVec3(camera.eye, pos));
466
466
  if (camera.projection === "perspective") {
@@ -5,6 +5,15 @@ import { addContextMenuListener } from "../lib/html/MenuEvent.js";
5
5
  */
6
6
  export class RenderService {
7
7
 
8
+ /**
9
+ * @constructor
10
+ *
11
+ * @param {HTMLElement} treeViewContainer Container element for the tree which uses this render service.
12
+ */
13
+ constructor(treeViewContainer) {
14
+ this._treeViewContainer = treeViewContainer;
15
+ }
16
+
8
17
  /*
9
18
  * Creates the root node of the tree.
10
19
  * @return {HTMLElement} The root node of the tree.
@@ -129,7 +138,7 @@ export class RenderService {
129
138
  }
130
139
 
131
140
  getSwitchElement(nodeId) {
132
- return document.getElementById(`switch-${nodeId}`);
141
+ return this._treeViewContainer.querySelector(`[id="switch-${nodeId}"]`);
133
142
  }
134
143
 
135
144
  isChecked(element) {
@@ -137,7 +146,7 @@ export class RenderService {
137
146
  }
138
147
 
139
148
  setCheckbox(nodeId, checked, indeterminate = false) {
140
- const checkbox = document.getElementById(`checkbox-${nodeId}`);
149
+ const checkbox = this._treeViewContainer.querySelector(`[id="checkbox-${nodeId}"]`);
141
150
  if (checkbox) {
142
151
  if (checked !== checkbox.checked) {
143
152
  checkbox.checked = checked;
@@ -152,7 +161,7 @@ export class RenderService {
152
161
  }
153
162
 
154
163
  setXRayed(nodeId, xrayed) {
155
- const treeNode = document.getElementById(nodeId);
164
+ const treeNode = this._treeViewContainer.querySelector(`[id="${nodeId}"]`);
156
165
  if (treeNode) {
157
166
  if (xrayed) {
158
167
  treeNode.classList.add('xrayed-node');
@@ -163,7 +172,7 @@ export class RenderService {
163
172
  }
164
173
 
165
174
  setHighlighted(nodeId, highlighted) {
166
- const treeNode = document.getElementById(nodeId);
175
+ const treeNode = this._treeViewContainer.querySelector(`[id="${nodeId}"]`);
167
176
  if (treeNode) {
168
177
  if (highlighted) {
169
178
  treeNode.scrollIntoView({block: "center"});
@@ -415,7 +415,7 @@ export class TreeViewPlugin extends Plugin {
415
415
  this._sortNodes = cfg.sortNodes;
416
416
  this._pruneEmptyNodes = cfg.pruneEmptyNodes;
417
417
  this._showListItemElementId = null;
418
- this._renderService = cfg.renderService || new RenderService();
418
+ this._renderService = cfg.renderService || new RenderService(this._containerElement);
419
419
  this._showIndeterminate = cfg.showIndeterminate ?? false;
420
420
  this._showProjectNode = cfg.showProjectNode ?? false;
421
421
  this._elevationSortFunction = cfg.elevationSortFunction ?? undefined;
@@ -10,7 +10,6 @@ export * from "./OBJLoaderPlugin/index.js";
10
10
  export * from "./SectionPlanesPlugin/index.js";
11
11
  export * from "./StoreyViewsPlugin/index.js";
12
12
  export * from "./FaceAlignedSectionPlanesPlugin/index.js";
13
- export * from "./SkyboxesPlugin/index.js";
14
13
  export * from "./STLLoaderPlugin/index.js";
15
14
  export * from "./TreeViewPlugin/index.js";
16
15
  export * from "./ViewCullPlugin/index.js";
@@ -363,22 +363,6 @@ class Viewer {
363
363
  this.sendToPlugins("snapshotStarting"); // Tells plugins to hide things that shouldn't be in snapshot
364
364
  }
365
365
 
366
- const captured = {};
367
- for (let i = 0, len = this._plugins.length; i < len; i++) {
368
- const plugin = this._plugins[i];
369
- if (plugin.getContainerElement) {
370
- const container = plugin.getContainerElement();
371
- if (container !== document.body) {
372
- if (!captured[container.id]) {
373
- captured[container.id] = true;
374
- html2canvas(container).then(function (canvas) {
375
- document.body.appendChild(canvas);
376
- });
377
- }
378
- }
379
- }
380
- }
381
-
382
366
  // firing "rendering" is necessary to trigger DTX{Lines,Triangles}Layer::_uploadDeferredFlags
383
367
  this.scene.fire("rendering", { }, true);
384
368
 
@@ -13,6 +13,9 @@ const tempVec4a = math.vec4();
13
13
  const tempVec4b = math.vec4();
14
14
  const tempVec4c = math.vec4();
15
15
 
16
+ const TOP_LIMIT = 0.001;
17
+ const BOTTOM_LIMIT = Math.PI - 0.001;
18
+
16
19
 
17
20
  /** @private */
18
21
  class PivotController {
@@ -188,14 +191,9 @@ class PivotController {
188
191
  */
189
192
  startPivot() {
190
193
 
191
- if (this._cameraLookingDownwards()) {
192
- this._pivoting = false;
193
- return false;
194
- }
195
-
196
194
  const camera = this._scene.camera;
197
195
 
198
- let lookat = math.lookAtMat4v(camera.eye, camera.look, camera.worldUp);
196
+ let lookat = math.lookAtMat4v(camera.eye, camera.look, camera.up);
199
197
  math.transformPoint3(lookat, this.getPivotPos(), this._cameraOffset);
200
198
 
201
199
  const pivotPos = this.getPivotPos();
@@ -298,8 +296,31 @@ class PivotController {
298
296
  dx = -dx;
299
297
  }
300
298
  this._azimuth += -dx * .01;
301
- this._polar += dy * .01;
302
- this._polar = math.clamp(this._polar, .001, Math.PI - .001);
299
+
300
+ const isMovingUp = dy < 0;
301
+ const isMovingDown = dy > 0;
302
+
303
+ // Track if we're at limits - only check if we're very close to the limit
304
+ const atTopLimit = Math.abs(this._polar - TOP_LIMIT) < 0.005;
305
+ const atBottomLimit = Math.abs(this._polar - BOTTOM_LIMIT) < 0.005;
306
+
307
+ let newPolar = this._polar + dy * .01;
308
+
309
+ // Case 1: At top limit and trying to go beyond
310
+ if (atTopLimit && isMovingUp) {
311
+ newPolar = TOP_LIMIT;
312
+ }
313
+ // Case 2: At bottom limit and trying to go beyond
314
+ else if (atBottomLimit && isMovingDown) {
315
+ newPolar = BOTTOM_LIMIT;
316
+ }
317
+ // Case 3: Normal rotation or moving away from a limit
318
+ else {
319
+ newPolar = math.clamp(newPolar, TOP_LIMIT, BOTTOM_LIMIT);
320
+ }
321
+
322
+ this._polar = newPolar;
323
+
303
324
  const pos = [
304
325
  this._radius * Math.sin(this._polar) * Math.sin(this._azimuth),
305
326
  this._radius * Math.cos(this._polar),