@xtctwins/tctwins-core 1.0.31 → 1.0.33
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.
- package/dist/tctwins-core.es.js +3718 -3691
- package/dist/tctwins-core.min.es.js +10 -10
- package/package.json +1 -1
- package/types/viewer/metadata/MetaModel.d.ts +63 -63
- package/types/viewer/scene/scene/Scene.d.ts +893 -893
|
@@ -1504,7 +1504,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1504
1504
|
\********************************************************/
|
|
1505
1505
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1506
1506
|
|
|
1507
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AxisGizmoPlugin: () => (/* binding */ AxisGizmoPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _viewer_scene_lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/lights/AmbientLight.js */ \"./src/viewer/scene/lights/AmbientLight.js\");\n/* harmony import */ var _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildVectorTextGeometry.js */ \"./src/viewer/scene/geometry/builders/buildVectorTextGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n * {@link Viewer} plugin that shows the axii of the World-space coordinate system.\r\n *\r\n * ## Usage\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#gizmos_AxisGizmoPlugin)]\r\n *\r\n * ````JavaScript````\r\n * import {Viewer, XTCLoaderPlugin, AxisGizmoPlugin} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * new AxisGizmoPlugin(viewer, {\r\n * canvasId: \"myAxisGizmoCanvas\"\r\n * });\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"../assets/models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n * ````\r\n */\r\nclass AxisGizmoPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {Object} cfg Plugin configuration.\r\n\t * @param {String} [cfg.id=\"AxisGizmo\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas to display the AxisGizmo - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas to display the AxisGizmo - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t */\r\n\tconstructor(viewer, cfg) {\r\n\t\tcfg = cfg || {};\r\n\r\n\t\tsuper(\"AxisGizmo\", viewer, cfg);\r\n\r\n\t\tconst camera = viewer.scene.camera;\r\n\r\n\t\tif (!cfg.canvasId && !cfg.canvasElement) {\r\n\t\t\tthis.error(\"Config expected: either 'canvasId' or 'canvasElement'\");\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tthis._axisGizmoScene = new _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__.Scene(viewer, {\r\n\t\t\t\tcanvasId: cfg.canvasId,\r\n\t\t\t\tcanvasElement: cfg.canvasElement,\r\n\t\t\t\ttransparent: true\r\n\t\t\t});\r\n\t\t} catch (error) {\r\n\t\t\tthis.error(error);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst axisGizmoScene = this._axisGizmoScene;\r\n\r\n\t\taxisGizmoScene.clearLights();\r\n\r\n\t\tnew _viewer_scene_lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_2__.AmbientLight(axisGizmoScene, { color: [0.45, 0.45, 0.5], intensity: 0.9 });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(axisGizmoScene, { dir: [-0.5, 0.5, -0.6], color: [0.8, 0.8, 0.7], intensity: 1.0, space: \"view\" });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(axisGizmoScene, { dir: [0.5, -0.5, -0.6], color: [0.8, 0.8, 0.8], intensity: 1.0, space: \"view\" });\r\n\r\n\t\t// Rotate helper in synch with target camera\r\n\r\n\t\tconst helperCamera = axisGizmoScene.camera;\r\n\r\n\t\tcamera.on(\"matrix\", function () {\r\n\t\t\tconst eye = camera.eye;\r\n\t\t\tconst look = camera.look;\r\n\t\t\tconst up = camera.up;\r\n\r\n\t\t\tconst eyeLook = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__.math.mulVec3Scalar(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__.math.normalizeVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__.math.subVec3(eye, look, [])), 22);\r\n\r\n\t\t\thelperCamera.look = [0, 0, 0];\r\n\t\t\thelperCamera.eye = eyeLook;\r\n\t\t\thelperCamera.up = up;\r\n\t\t});\r\n\r\n\t\t// ----------------- Components that are shared among more than one mesh ---------------\r\n\r\n\t\tconst arrowHead = new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\taxisGizmoScene,\r\n\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_6__.buildCylinderGeometry)({\r\n\t\t\t\tradiusTop: 0.01,\r\n\t\t\t\tradiusBottom: 0.6,\r\n\t\t\t\theight: 1.7,\r\n\t\t\t\tradialSegments: 20,\r\n\t\t\t\theightSegments: 1,\r\n\t\t\t\topenEnded: false\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst arrowShaft = new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\taxisGizmoScene,\r\n\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_6__.buildCylinderGeometry)({\r\n\t\t\t\tradiusTop: 0.2,\r\n\t\t\t\tradiusBottom: 0.2,\r\n\t\t\t\theight: 4.5,\r\n\t\t\t\tradialSegments: 20,\r\n\t\t\t\theightSegments: 1,\r\n\t\t\t\topenEnded: false\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst xAxisMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Red by convention\r\n\t\t\tdiffuse: [1, 0.3, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst xAxisLabelMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Red by convention\r\n\t\t\temissive: [1, 0.3, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst yAxisMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Green by convention\r\n\t\t\tdiffuse: [0.3, 1, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst yAxisLabelMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Green by convention\r\n\t\t\temissive: [0.3, 1, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst zAxisMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Blue by convention\r\n\t\t\tdiffuse: [0.3, 0.3, 1],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst zAxisLabelMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\temissive: [0.3, 0.3, 1],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst ballMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\tdiffuse: [0.5, 0.5, 0.5],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\t// ----------------- Meshes ------------------------------\r\n\r\n\t\tthis._meshes = [\r\n\t\t\t// Sphere behind gnomon\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\t\t\taxisGizmoScene,\r\n\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_7__.buildSphereGeometry)({\r\n\t\t\t\t\t\tradius: 9.0,\r\n\t\t\t\t\t\theightSegments: 60,\r\n\t\t\t\t\t\twidthSegments: 60\r\n\t\t\t\t\t})\r\n\t\t\t\t),\r\n\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t\t\tdiffuse: [0.0, 0.0, 0.0],\r\n\t\t\t\t\temissive: [0.1, 0.1, 0.1],\r\n\t\t\t\t\tambient: [0.1, 0.1, 0.2],\r\n\t\t\t\t\tspecular: [0, 0, 0],\r\n\t\t\t\t\talpha: 0.4,\r\n\t\t\t\t\talphaMode: \"blend\",\r\n\t\t\t\t\tfrontface: \"cw\"\r\n\t\t\t\t}),\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false\r\n\t\t\t}),\r\n\r\n\t\t\t// Ball at center of axis\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\t\t\taxisGizmoScene,\r\n\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_7__.buildSphereGeometry)({\r\n\t\t\t\t\t\tradius: 1.0\r\n\t\t\t\t\t})\r\n\t\t\t\t),\r\n\t\t\t\tmaterial: ballMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false\r\n\t\t\t}),\r\n\r\n\t\t\t// X-axis arrow, shaft and label\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: arrowHead,\r\n\t\t\t\tmaterial: xAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [5, 0, 0],\r\n\t\t\t\trotation: [0, 0, -90]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Shaft\r\n\t\t\t\tgeometry: arrowShaft,\r\n\t\t\t\tmaterial: xAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [2, 0, 0],\r\n\t\t\t\trotation: [0, 0, 90]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Label\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(axisGizmoScene, (0,_viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildVectorTextGeometry)({ text: \"X\", size: 1.5 })),\r\n\t\t\t\tmaterial: xAxisLabelMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [7, 0, 0],\r\n\t\t\t\tbillboard: \"spherical\"\r\n\t\t\t}),\r\n\r\n\t\t\t// Y-axis arrow, shaft and label\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: arrowHead,\r\n\t\t\t\tmaterial: yAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 5, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Shaft\r\n\t\t\t\tgeometry: arrowShaft,\r\n\t\t\t\tmaterial: yAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 2, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Label\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(axisGizmoScene, (0,_viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildVectorTextGeometry)({ text: \"Y\", size: 1.5 })),\r\n\t\t\t\tmaterial: yAxisLabelMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 7, 0],\r\n\t\t\t\tbillboard: \"spherical\"\r\n\t\t\t}),\r\n\r\n\t\t\t// Z-axis arrow, shaft and label\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: arrowHead,\r\n\t\t\t\tmaterial: zAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 0, 5],\r\n\t\t\t\trotation: [90, 0, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Shaft\r\n\t\t\t\tgeometry: arrowShaft,\r\n\t\t\t\tmaterial: zAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 0, 2],\r\n\t\t\t\trotation: [90, 0, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Label\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(axisGizmoScene, (0,_viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildVectorTextGeometry)({ text: \"Z\", size: 1.5 })),\r\n\t\t\t\tmaterial: zAxisLabelMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 0, 7],\r\n\t\t\t\tbillboard: \"spherical\"\r\n\t\t\t})\r\n\t\t];\r\n\t}\r\n\r\n\t/** Shows or hides this AxisGizmoPlugin.\r\n\t *\r\n\t * @param visible\r\n\t */\r\n\tsetVisible(visible) {\r\n\t\tfor (let i = 0; i < this._meshes.length; i++) {\r\n\t\t\tthis._meshes[i].visible = visible;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this AxisGizmoPlugin.\r\n\t */\r\n\tdestroy() {\r\n\t\tthis._axisGizmoCanvas = null;\r\n\t\tthis._axisGizmoScene.destroy();\r\n\t\tthis._axisGizmoScene = null;\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/AxisGizmoPlugin/AxisGizmoPlugin.js?");
|
|
1507
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AxisGizmoPlugin: () => (/* binding */ AxisGizmoPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _viewer_scene_lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/lights/AmbientLight.js */ \"./src/viewer/scene/lights/AmbientLight.js\");\n/* harmony import */ var _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/scene/lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildVectorTextGeometry.js */ \"./src/viewer/scene/geometry/builders/buildVectorTextGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n * {@link Viewer} plugin that shows the axii of the World-space coordinate system.\r\n *\r\n * ## Usage\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#gizmos_AxisGizmoPlugin)]\r\n *\r\n * ````JavaScript````\r\n * import {Viewer, XTCLoaderPlugin, AxisGizmoPlugin} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * new AxisGizmoPlugin(viewer, {\r\n * canvasId: \"myAxisGizmoCanvas\"\r\n * });\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"../assets/models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n * ````\r\n */\r\nclass AxisGizmoPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {Object} cfg Plugin configuration.\r\n\t * @param {String} [cfg.id=\"AxisGizmo\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas to display the AxisGizmo - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas to display the AxisGizmo - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t */\r\n\tconstructor(viewer, cfg) {\r\n\t\tcfg = cfg || {};\r\n\r\n\t\tsuper(\"AxisGizmo\", viewer, cfg);\r\n\r\n\t\tconst camera = viewer.scene.camera;\r\n\r\n\t\tif (!cfg.canvasId && !cfg.canvasElement) {\r\n\t\t\tthis.error(\"Config expected: either 'canvasId' or 'canvasElement'\");\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\tthis._axisGizmoScene = new _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__.Scene(viewer, {\r\n\t\t\t\tcanvasId: cfg.canvasId,\r\n\t\t\t\tcanvasElement: cfg.canvasElement,\r\n\t\t\t\ttransparent: true,\r\n\t\t\t\tspinnerElementId: \"axisgizmoscene_spinner\"\r\n\t\t\t});\r\n\t\t} catch (error) {\r\n\t\t\tthis.error(error);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst axisGizmoScene = this._axisGizmoScene;\r\n\r\n\t\taxisGizmoScene.clearLights();\r\n\r\n\t\tnew _viewer_scene_lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_2__.AmbientLight(axisGizmoScene, { color: [0.45, 0.45, 0.5], intensity: 0.9 });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(axisGizmoScene, { dir: [-0.5, 0.5, -0.6], color: [0.8, 0.8, 0.7], intensity: 1.0, space: \"view\" });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(axisGizmoScene, { dir: [0.5, -0.5, -0.6], color: [0.8, 0.8, 0.8], intensity: 1.0, space: \"view\" });\r\n\r\n\t\t// Rotate helper in synch with target camera\r\n\r\n\t\tconst helperCamera = axisGizmoScene.camera;\r\n\r\n\t\tcamera.on(\"matrix\", function () {\r\n\t\t\tconst eye = camera.eye;\r\n\t\t\tconst look = camera.look;\r\n\t\t\tconst up = camera.up;\r\n\r\n\t\t\tconst eyeLook = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__.math.mulVec3Scalar(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__.math.normalizeVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_10__.math.subVec3(eye, look, [])), 22);\r\n\r\n\t\t\thelperCamera.look = [0, 0, 0];\r\n\t\t\thelperCamera.eye = eyeLook;\r\n\t\t\thelperCamera.up = up;\r\n\t\t});\r\n\r\n\t\t// ----------------- Components that are shared among more than one mesh ---------------\r\n\r\n\t\tconst arrowHead = new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\taxisGizmoScene,\r\n\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_6__.buildCylinderGeometry)({\r\n\t\t\t\tradiusTop: 0.01,\r\n\t\t\t\tradiusBottom: 0.6,\r\n\t\t\t\theight: 1.7,\r\n\t\t\t\tradialSegments: 20,\r\n\t\t\t\theightSegments: 1,\r\n\t\t\t\topenEnded: false\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst arrowShaft = new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\taxisGizmoScene,\r\n\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_6__.buildCylinderGeometry)({\r\n\t\t\t\tradiusTop: 0.2,\r\n\t\t\t\tradiusBottom: 0.2,\r\n\t\t\t\theight: 4.5,\r\n\t\t\t\tradialSegments: 20,\r\n\t\t\t\theightSegments: 1,\r\n\t\t\t\topenEnded: false\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst xAxisMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Red by convention\r\n\t\t\tdiffuse: [1, 0.3, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst xAxisLabelMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Red by convention\r\n\t\t\temissive: [1, 0.3, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst yAxisMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Green by convention\r\n\t\t\tdiffuse: [0.3, 1, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst yAxisLabelMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Green by convention\r\n\t\t\temissive: [0.3, 1, 0.3],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst zAxisMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t// Blue by convention\r\n\t\t\tdiffuse: [0.3, 0.3, 1],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst zAxisLabelMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\temissive: [0.3, 0.3, 1],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\tconst ballMaterial = new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\tdiffuse: [0.5, 0.5, 0.5],\r\n\t\t\tambient: [0.0, 0.0, 0.0],\r\n\t\t\tspecular: [0.6, 0.6, 0.3],\r\n\t\t\tshininess: 80,\r\n\t\t\tlineWidth: 2\r\n\t\t});\r\n\r\n\t\t// ----------------- Meshes ------------------------------\r\n\r\n\t\tthis._meshes = [\r\n\t\t\t// Sphere behind gnomon\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\t\t\taxisGizmoScene,\r\n\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_7__.buildSphereGeometry)({\r\n\t\t\t\t\t\tradius: 9.0,\r\n\t\t\t\t\t\theightSegments: 60,\r\n\t\t\t\t\t\twidthSegments: 60\r\n\t\t\t\t\t})\r\n\t\t\t\t),\r\n\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_9__.PhongMaterial(axisGizmoScene, {\r\n\t\t\t\t\tdiffuse: [0.0, 0.0, 0.0],\r\n\t\t\t\t\temissive: [0.1, 0.1, 0.1],\r\n\t\t\t\t\tambient: [0.1, 0.1, 0.2],\r\n\t\t\t\t\tspecular: [0, 0, 0],\r\n\t\t\t\t\talpha: 0.4,\r\n\t\t\t\t\talphaMode: \"blend\",\r\n\t\t\t\t\tfrontface: \"cw\"\r\n\t\t\t\t}),\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false\r\n\t\t\t}),\r\n\r\n\t\t\t// Ball at center of axis\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\t\t\taxisGizmoScene,\r\n\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_7__.buildSphereGeometry)({\r\n\t\t\t\t\t\tradius: 1.0\r\n\t\t\t\t\t})\r\n\t\t\t\t),\r\n\t\t\t\tmaterial: ballMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false\r\n\t\t\t}),\r\n\r\n\t\t\t// X-axis arrow, shaft and label\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: arrowHead,\r\n\t\t\t\tmaterial: xAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [5, 0, 0],\r\n\t\t\t\trotation: [0, 0, -90]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Shaft\r\n\t\t\t\tgeometry: arrowShaft,\r\n\t\t\t\tmaterial: xAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [2, 0, 0],\r\n\t\t\t\trotation: [0, 0, 90]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Label\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(axisGizmoScene, (0,_viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildVectorTextGeometry)({ text: \"X\", size: 1.5 })),\r\n\t\t\t\tmaterial: xAxisLabelMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [7, 0, 0],\r\n\t\t\t\tbillboard: \"spherical\"\r\n\t\t\t}),\r\n\r\n\t\t\t// Y-axis arrow, shaft and label\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: arrowHead,\r\n\t\t\t\tmaterial: yAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 5, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Shaft\r\n\t\t\t\tgeometry: arrowShaft,\r\n\t\t\t\tmaterial: yAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 2, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Label\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(axisGizmoScene, (0,_viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildVectorTextGeometry)({ text: \"Y\", size: 1.5 })),\r\n\t\t\t\tmaterial: yAxisLabelMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 7, 0],\r\n\t\t\t\tbillboard: \"spherical\"\r\n\t\t\t}),\r\n\r\n\t\t\t// Z-axis arrow, shaft and label\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Arrow\r\n\t\t\t\tgeometry: arrowHead,\r\n\t\t\t\tmaterial: zAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 0, 5],\r\n\t\t\t\trotation: [90, 0, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Shaft\r\n\t\t\t\tgeometry: arrowShaft,\r\n\t\t\t\tmaterial: zAxisMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 0, 2],\r\n\t\t\t\trotation: [90, 0, 0]\r\n\t\t\t}),\r\n\r\n\t\t\tnew _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(axisGizmoScene, {\r\n\t\t\t\t// Label\r\n\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(axisGizmoScene, (0,_viewer_scene_geometry_builders_buildVectorTextGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildVectorTextGeometry)({ text: \"Z\", size: 1.5 })),\r\n\t\t\t\tmaterial: zAxisLabelMaterial,\r\n\t\t\t\tpickable: false,\r\n\t\t\t\tcollidable: false,\r\n\t\t\t\tvisible: cfg.visible !== false,\r\n\t\t\t\tposition: [0, 0, 7],\r\n\t\t\t\tbillboard: \"spherical\"\r\n\t\t\t})\r\n\t\t];\r\n\t}\r\n\r\n\t/** Shows or hides this AxisGizmoPlugin.\r\n\t *\r\n\t * @param visible\r\n\t */\r\n\tsetVisible(visible) {\r\n\t\tfor (let i = 0; i < this._meshes.length; i++) {\r\n\t\t\tthis._meshes[i].visible = visible;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this AxisGizmoPlugin.\r\n\t */\r\n\tdestroy() {\r\n\t\tthis._axisGizmoCanvas = null;\r\n\t\tthis._axisGizmoScene.destroy();\r\n\t\tthis._axisGizmoScene = null;\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/AxisGizmoPlugin/AxisGizmoPlugin.js?");
|
|
1508
1508
|
|
|
1509
1509
|
/***/ }),
|
|
1510
1510
|
|
|
@@ -1794,7 +1794,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1794
1794
|
\****************************************************/
|
|
1795
1795
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1796
1796
|
|
|
1797
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ NavCubePlugin: () => (/* binding */ NavCubePlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./../../viewer/scene/lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_Texture_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/materials/Texture.js */ \"./src/viewer/scene/materials/Texture.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _CubeTextureCanvas_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./CubeTextureCanvas.js */ \"./src/plugins/NavCubePlugin/CubeTextureCanvas.js\");\n/* harmony import */ var _viewer_scene_constants_constants_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../viewer/scene/constants/constants.js */ \"./src/viewer/scene/constants/constants.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\nconst tempVec3b = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\nconst tempMat4a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n\r\n/**\r\n * {@link Viewer} plugin that lets us look at the entire {@link Scene} from along a chosen axis or diagonal.\r\n *\r\n * [<img src=\"https://user-images.githubusercontent.com/83100/55674490-c93c2e00-58b5-11e9-8a28-eb08876947c0.gif\">](https://xeokit.github.io/xeokit-sdk/examples/#gizmos_NavCubePlugin)\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#gizmos_NavCubePlugin)]\r\n *\r\n * ## Overview\r\n *\r\n * * Rotating the NavCube causes the Viewer's {@link Camera} to orbit its current\r\n * point-of-interest. Conversely, orbiting the Camera causes the NavCube to rotate accordingly.\r\n * * The faces of the NavCube are aligned with the Viewer's {@link Scene}'s World-space coordinate axis. Clicking on a face moves\r\n * the Camera to look at the entire Scene along the corresponding axis. Clicking on an edge or a corner looks at\r\n * the entire Scene along a diagonal.\r\n * * The NavCube can be configured to either jump or fly the Camera to each new position. We can configure how tightly the\r\n * NavCube fits the Scene to view, and when flying, we can configure how fast it flies. We can also configure whether the\r\n * NavCube fits all objects to view, or just the currently visible objects. See below for a usage example.\r\n * * Clicking the NavCube also sets {@link CameraControl#pivotPos} to the center of the fitted objects.\r\n *\r\n * ## Usage\r\n *\r\n * In the example below, we'll create a Viewer and add a NavCubePlugin, which will create a NavCube gizmo in the canvas\r\n * with the given ID. Then we'll use the {@link XTCLoaderPlugin} to load a model into the Viewer's Scene. We can then\r\n * use the NavCube to look at the model along each axis or diagonal.\r\n *\r\n * ````JavaScript\r\n * import {Viewer, XTCLoaderPlugin, NavCubePlugin} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.camera.eye = [-3.93, 2.85, 27.01];\r\n * viewer.camera.look = [4.40, 3.72, 8.89];\r\n * viewer.camera.up = [-0.01, 0.99, 0.03];\r\n *\r\n * const navCube = new NavCubePlugin(viewer, {\r\n *\r\n * canvasID: \"myNavCubeCanvas\",\r\n *\r\n * visible: true, // Initially visible (default)\r\n *\r\n * cameraFly: true, // Fly camera to each selected axis/diagonal\r\n * cameraFitFOV: 45, // How much field-of-view the scene takes once camera has fitted it to view\r\n * cameraFlyDuration: 0.5,// How long (in seconds) camera takes to fly to each new axis/diagonal\r\n *\r\n * fitVisible: false, // Fit whole scene, including invisible objects (default)\r\n *\r\n * synchProjection: false // Keep NavCube in perspective projection, even when camera switches to ortho (default)\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * edges: true\r\n * });\r\n * ````\r\n */\r\nclass NavCubePlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t * @param {Viewer} viewer The {@link Viewer}.\r\n\t * @param {Object} cfg NavCubePlugin configuration.\r\n\t * @param {String} [cfg.id=\"NavCube\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas to display the NavCube - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas to display the NavCube - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {div} [cfg.viewerElement] Reference of an existing div to contain the canvas\r\n\t * @param {Boolean} [cfg.visible=true] Initial visibility.\r\n\t * @param {Boolean} [cfg.shadowVisible=true] Whether the shadow of the cube is visible.\r\n\t * @param {String} [cfg.cameraFly=true] Whether the {@link Camera} flies or jumps to each selected axis or diagonal.\r\n\t * @param {String} [cfg.cameraFitFOV=45] How much of the field-of-view, in degrees, that the 3D scene should fill the {@link Canvas} when the {@link Camera} moves to an axis or diagonal.\r\n\t * @param {String} [cfg.cameraFlyDuration=0.5] When flying the {@link Camera} to each new axis or diagonal, how long, in seconds, that the Camera takes to get there.\r\n\t * @param {String} [cfg.color=\"lightgrey\"] Custom uniform color for the faces of the NavCube.\r\n\t * @param {String} [cfg.frontColor=\"#55FF55\"] Custom color for the front face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.backColor=\"#55FF55\"] Custom color for the back face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.leftColor=\"#FF5555\"] Custom color for the left face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.rightColor=\"#FF5555\"] Custom color for the right face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.topColor=\"#5555FF\"] Custom color for the top face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.bottomColor=\"#5555FF\"] Custom color for the bottom face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.hoverColor=\"rgba(0,0,0,0.4)\"] Custom color for highlighting regions on the NavCube as we hover the pointer over them.\r\n\t * @param {String} [cfg.textColor=\"black\"] Custom text color for labels of the NavCube.\r\n\t * @param {Boolean} [cfg.fitVisible=false] Sets whether the axis, corner and edge-aligned views will fit the\r\n\t * view to the entire {@link Scene} or just to visible object-{@link Entity}s. Entitys are visible objects when {@link Entity#isObject} and {@link Entity#visible} are both ````true````.\r\n\t * @param {Boolean} [cfg.synchProjection=false] Sets whether the NavCube switches between perspective and orthographic projections in synchrony with the {@link Camera}. When ````false````, the NavCube will always be rendered with perspective projection.\r\n\t * @param {Boolean} [cfg.isProjectNorth] sets whether the NavCube switches between true north and project north - using the project north offset angle.\r\n\t * @param {number} [cfg.projectNorthOffsetAngle] sets the NavCube project north offset angle - when the {@link isProjectNorth} is true.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"NavCube\", viewer, cfg);\r\n\r\n\t\tviewer.navCube = this;\r\n\r\n\t\tvar visible = true;\r\n\r\n\t\ttry {\r\n\t\t\tthis._navCubeScene = new _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_2__.Scene(viewer, {\r\n\t\t\t\tcanvasId: cfg.canvasId,\r\n\t\t\t\tcanvasElement: cfg.canvasElement,\r\n\t\t\t\ttransparent: true\r\n\t\t\t});\r\n\r\n\t\t\tthis._navCubeCanvas = this._navCubeScene.canvas.canvas;\r\n\r\n\t\t\tthis._navCubeScene.input.keyboardEnabled = false; // Don't want keyboard input in the NavCube\r\n\t\t} catch (error) {\r\n\t\t\tthis.error(error);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst navCubeScene = this._navCubeScene;\r\n\r\n\t\tnavCubeScene.clearLights();\r\n\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(navCubeScene, { dir: [0.4, -0.4, 0.8], color: [0.8, 1.0, 1.0], intensity: 1.0, space: \"view\" });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(navCubeScene, { dir: [-0.8, -0.3, -0.4], color: [0.8, 0.8, 0.8], intensity: 1.0, space: \"view\" });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(navCubeScene, { dir: [0.8, -0.6, -0.8], color: [1.0, 1.0, 1.0], intensity: 1.0, space: \"view\" });\r\n\r\n\t\tthis._navCubeCamera = navCubeScene.camera;\r\n\t\tthis._navCubeCamera.ortho.scale = 7.0;\r\n\t\tthis._navCubeCamera.ortho.near = 0.1;\r\n\t\tthis._navCubeCamera.ortho.far = 2000;\r\n\r\n\t\tnavCubeScene.edgeMaterial.edgeColor = [0.2, 0.2, 0.2];\r\n\t\tnavCubeScene.edgeMaterial.edgeAlpha = 0.6;\r\n\r\n\t\tthis._zUp = Boolean(viewer.camera.zUp);\r\n\r\n\t\tvar self = this;\r\n\r\n\t\tthis.setIsProjectNorth(cfg.isProjectNorth);\r\n\t\tthis.setProjectNorthOffsetAngle(cfg.projectNorthOffsetAngle);\r\n\r\n\t\tconst rotateTrueNorth = (this.rotateTrueNorth = (function () {\r\n\t\t\tconst trueNorthMatrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n\t\t\treturn function (dir, vec, dest) {\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.identityMat4(trueNorthMatrix);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.rotationMat4v(dir * self._projectNorthOffsetAngle * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.DEGTORAD, [0, 1, 0], trueNorthMatrix);\r\n\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(trueNorthMatrix, vec, dest);\r\n\t\t\t};\r\n\t\t})());\r\n\r\n\t\tthis._synchCamera = (function () {\r\n\t\t\tvar matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.rotationMat4c(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.DEGTORAD, 1, 0, 0);\r\n\t\t\tvar eyeLookVec = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\tvar eyeLookVecCube = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\tvar upCube = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\treturn function () {\r\n\t\t\t\tvar eye = viewer.camera.eye;\r\n\t\t\t\tvar look = viewer.camera.look;\r\n\t\t\t\tvar up = viewer.camera.up;\r\n\t\t\t\teyeLookVec = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulVec3Scalar(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.normalizeVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.subVec3(eye, look, eyeLookVec)), 5);\r\n\r\n\t\t\t\tif (self._isProjectNorth && self._projectNorthOffsetAngle) {\r\n\t\t\t\t\teyeLookVec = rotateTrueNorth(-1, eyeLookVec, tempVec3a);\r\n\t\t\t\t\tup = rotateTrueNorth(-1, up, tempVec3b);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (self._zUp) {\r\n\t\t\t\t\t// +Z up\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(matrix, eyeLookVec, eyeLookVecCube);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(matrix, up, upCube);\r\n\t\t\t\t\tself._navCubeCamera.look = [0, 0, 0];\r\n\t\t\t\t\tself._navCubeCamera.eye = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(matrix, eyeLookVec, eyeLookVecCube);\r\n\t\t\t\t\tself._navCubeCamera.up = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPoint3(matrix, up, upCube);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// +Y up\r\n\t\t\t\t\tself._navCubeCamera.look = [0, 0, 0];\r\n\t\t\t\t\tself._navCubeCamera.eye = eyeLookVec;\r\n\t\t\t\t\tself._navCubeCamera.up = up;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tthis._cubeTextureCanvas = new _CubeTextureCanvas_js__WEBPACK_IMPORTED_MODULE_9__.CubeTextureCanvas(viewer, navCubeScene, cfg);\r\n\r\n\t\tthis._cubeSampler = new _viewer_scene_materials_Texture_js__WEBPACK_IMPORTED_MODULE_7__.Texture(navCubeScene, {\r\n\t\t\timage: this._cubeTextureCanvas.getImage(),\r\n\t\t\tflipY: true,\r\n\t\t\twrapS: _viewer_scene_constants_constants_js__WEBPACK_IMPORTED_MODULE_10__.ClampToEdgeWrapping,\r\n\t\t\twrapT: _viewer_scene_constants_constants_js__WEBPACK_IMPORTED_MODULE_10__.ClampToEdgeWrapping\r\n\t\t});\r\n\r\n\t\tthis._cubeMesh = new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(navCubeScene, {\r\n\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(navCubeScene, {\r\n\t\t\t\tprimitive: \"triangles\",\r\n\t\t\t\tnormals: [\r\n\t\t\t\t\t0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,\r\n\t\t\t\t\t-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1,\r\n\t\t\t\t\t0, 0, -1\r\n\t\t\t\t],\r\n\t\t\t\tpositions: [\r\n\t\t\t\t\t1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1,\r\n\t\t\t\t\t-1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1,\r\n\t\t\t\t\t-1, -1, -1, -1, 1, -1, 1, 1, -1\r\n\t\t\t\t],\r\n\t\t\t\tuv: [\r\n\t\t\t\t\t0.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,\r\n\t\t\t\t\t0.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, 0.25, 0,\r\n\t\t\t\t\t0.5, 0, 0.5, 0.3333, 0.25, 0.3333, 0.75, 0.3333, 1.0, 0.3333, 1.0, 0.6666, 0.75, 0.6666\r\n\t\t\t\t],\r\n\t\t\t\tindices: [\r\n\t\t\t\t\t0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20,\r\n\t\t\t\t\t21, 22, 20, 22, 23\r\n\t\t\t\t]\r\n\t\t\t}),\r\n\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_6__.PhongMaterial(navCubeScene, {\r\n\t\t\t\tdiffuse: [0.4, 0.4, 0.4],\r\n\t\t\t\tspecular: [0.4, 0.4, 0.4],\r\n\t\t\t\temissive: [0.6, 0.6, 0.6],\r\n\t\t\t\tdiffuseMap: this._cubeSampler,\r\n\t\t\t\temissiveMap: this._cubeSampler\r\n\t\t\t}),\r\n\t\t\tvisible: !!visible,\r\n\t\t\tedges: true\r\n\t\t});\r\n\r\n\t\tthis._shadow =\r\n\t\t\tcfg.shadowVisible === false\r\n\t\t\t\t? null\r\n\t\t\t\t: new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(navCubeScene, {\r\n\t\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\t\t\t\t\tnavCubeScene,\r\n\t\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildCylinderGeometry)({\r\n\t\t\t\t\t\t\t\tcenter: [0, 0, 0],\r\n\t\t\t\t\t\t\t\tradiusTop: 0.001,\r\n\t\t\t\t\t\t\t\tradiusBottom: 1.4,\r\n\t\t\t\t\t\t\t\theight: 0.01,\r\n\t\t\t\t\t\t\t\tradialSegments: 20,\r\n\t\t\t\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\t\t\t\topenEnded: true\r\n\t\t\t\t\t\t\t})\r\n\t\t\t\t\t\t),\r\n\t\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_6__.PhongMaterial(navCubeScene, {\r\n\t\t\t\t\t\t\tdiffuse: [0.0, 0.0, 0.0],\r\n\t\t\t\t\t\t\tspecular: [0, 0, 0],\r\n\t\t\t\t\t\t\temissive: [0.0, 0.0, 0.0],\r\n\t\t\t\t\t\t\talpha: 0.5\r\n\t\t\t\t\t\t}),\r\n\t\t\t\t\t\tposition: [0, -1.5, 0],\r\n\t\t\t\t\t\tvisible: !!visible,\r\n\t\t\t\t\t\tpickable: false,\r\n\t\t\t\t\t\tbackfaces: false\r\n\t\t\t\t });\r\n\r\n\t\tthis._onCameraMatrix = viewer.camera.on(\"matrix\", this._synchCamera);\r\n\t\tthis._onCameraWorldAxis = viewer.camera.on(\"worldAxis\", () => {\r\n\t\t\tif (viewer.camera.zUp) {\r\n\t\t\t\tthis._zUp = true;\r\n\t\t\t\tthis._cubeTextureCanvas.setZUp();\r\n\t\t\t\tthis._repaint();\r\n\t\t\t\tthis._synchCamera();\r\n\t\t\t} else if (viewer.camera.yUp) {\r\n\t\t\t\tthis._zUp = false;\r\n\t\t\t\tthis._cubeTextureCanvas.setYUp();\r\n\t\t\t\tthis._repaint();\r\n\t\t\t\tthis._synchCamera();\r\n\t\t\t}\r\n\t\t});\r\n\t\tthis._onCameraFOV = viewer.camera.perspective.on(\"fov\", (fov) => {\r\n\t\t\tif (this._synchProjection) {\r\n\t\t\t\tthis._navCubeCamera.perspective.fov = fov;\r\n\t\t\t}\r\n\t\t});\r\n\t\tthis._onCameraProjection = viewer.camera.on(\"projection\", (projection) => {\r\n\t\t\tif (this._synchProjection) {\r\n\t\t\t\tthis._navCubeCamera.projection =\r\n\t\t\t\t\tprojection === \"ortho\" || projection === \"perspective\" ? projection : \"perspective\";\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tvar lastAreaId = -1;\r\n\r\n\t\tfunction actionMove(posX, posY) {\r\n\t\t\tvar yawInc = (posX - lastX) * -sensitivity;\r\n\t\t\tvar pitchInc = (posY - lastY) * -sensitivity;\r\n\t\t\tyaw -= yawInc;\r\n\t\t\tpitch -= pitchInc;\r\n\t\t\tif (minPitch !== undefined && pitch < minPitch) {\r\n\t\t\t\tpitch = minPitch;\r\n\t\t\t}\r\n\t\t\tif (maxPitch !== undefined && pitch > maxPitch) {\r\n\t\t\t\tpitch = maxPitch;\r\n\t\t\t}\r\n\t\t\tviewer.camera.orbitYaw(yawInc);\r\n\t\t\tviewer.camera.orbitPitch(-pitchInc);\r\n\t\t\tlastX = posX;\r\n\t\t\tlastY = posY;\r\n\t\t}\r\n\r\n\t\tfunction getCoordsWithinElement(event) {\r\n\t\t\tvar coords = [0, 0];\r\n\t\t\tif (!event) {\r\n\t\t\t\tevent = window.event;\r\n\t\t\t\tcoords[0] = event.x;\r\n\t\t\t\tcoords[1] = event.y;\r\n\t\t\t} else {\r\n\t\t\t\tvar element = event.target;\r\n\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\tvar totalOffsetTop = 0;\r\n\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t}\r\n\t\t\t\tcoords[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\tcoords[1] = event.pageY - totalOffsetTop;\r\n\t\t\t}\r\n\t\t\treturn coords;\r\n\t\t}\r\n\r\n\t\t{\r\n\t\t\tvar downX = null;\r\n\t\t\tvar downY = null;\r\n\t\t\tvar down = false;\r\n\t\t\tvar over = false;\r\n\r\n\t\t\tvar yaw = 0;\r\n\t\t\tvar pitch = 0;\r\n\t\t\tvar minPitch = null;\r\n\t\t\tvar maxPitch = null;\r\n\t\t\tvar sensitivity = 0.5;\r\n\r\n\t\t\tvar lastX;\r\n\t\t\tvar lastY;\r\n\r\n\t\t\tself._navCubeCanvas.addEventListener(\r\n\t\t\t\t\"mouseenter\",\r\n\t\t\t\t(self._onMouseEnter = function (e) {\r\n\t\t\t\t\tover = true;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tself._navCubeCanvas.addEventListener(\r\n\t\t\t\t\"mouseleave\",\r\n\t\t\t\t(self._onMouseLeave = function (e) {\r\n\t\t\t\t\tover = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tself._navCubeCanvas.addEventListener(\r\n\t\t\t\t\"mousedown\",\r\n\t\t\t\t(self._onMouseDown = function (e) {\r\n\t\t\t\t\tif (e.which !== 1) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdownX = e.x;\r\n\t\t\t\t\tdownY = e.y;\r\n\t\t\t\t\tlastX = e.clientX;\r\n\t\t\t\t\tlastY = e.clientY;\r\n\t\t\t\t\tvar canvasPos = getCoordsWithinElement(e);\r\n\t\t\t\t\tvar hit = navCubeScene.pick({\r\n\t\t\t\t\t\tcanvasPos: canvasPos\r\n\t\t\t\t\t});\r\n\t\t\t\t\tif (hit) {\r\n\t\t\t\t\t\tdown = true;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tdown = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tdocument.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(self._onMouseUp = function (e) {\r\n\t\t\t\t\tif (e.which !== 1) {\r\n\t\t\t\t\t\t// Left button\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tif (downX === null) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getCoordsWithinElement(e);\r\n\t\t\t\t\tvar hit = navCubeScene.pick({\r\n\t\t\t\t\t\tcanvasPos: canvasPos,\r\n\t\t\t\t\t\tpickSurface: true\r\n\t\t\t\t\t});\r\n\t\t\t\t\tif (hit) {\r\n\t\t\t\t\t\tif (hit.uv) {\r\n\t\t\t\t\t\t\tvar areaId = self._cubeTextureCanvas.getArea(hit.uv);\r\n\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(areaId, true);\r\n\t\t\t\t\t\t\t\t\tlastAreaId = areaId;\r\n\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\tif (e.x < downX - 3 || e.x > downX + 3 || e.y < downY - 3 || e.y > downY + 3) {\r\n\t\t\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tvar dir = self._cubeTextureCanvas.getAreaDir(areaId);\r\n\t\t\t\t\t\t\t\t\tif (dir) {\r\n\t\t\t\t\t\t\t\t\t\tvar up = self._cubeTextureCanvas.getAreaUp(areaId);\r\n\t\t\t\t\t\t\t\t\t\tif (self._isProjectNorth && self._projectNorthOffsetAngle) {\r\n\t\t\t\t\t\t\t\t\t\t\tdir = rotateTrueNorth(+1, dir, tempVec3a);\r\n\t\t\t\t\t\t\t\t\t\t\tup = rotateTrueNorth(+1, up, tempVec3b);\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\tflyTo(dir, up, function () {\r\n\t\t\t\t\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(areaId, false);\r\n\t\t\t\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tdocument.addEventListener(\r\n\t\t\t\t\"mousemove\",\r\n\t\t\t\t(self._onMouseMove = function (e) {\r\n\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (e.buttons === 1 && !down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (down) {\r\n\t\t\t\t\t\tvar posX = e.clientX;\r\n\t\t\t\t\t\tvar posY = e.clientY;\r\n\t\t\t\t\t\tdocument.body.style.cursor = \"move\";\r\n\t\t\t\t\t\tactionMove(posX, posY);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!over) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getCoordsWithinElement(e);\r\n\t\t\t\t\tvar hit = navCubeScene.pick({\r\n\t\t\t\t\t\tcanvasPos: canvasPos,\r\n\t\t\t\t\t\tpickSurface: true\r\n\t\t\t\t\t});\r\n\t\t\t\t\tif (hit) {\r\n\t\t\t\t\t\tif (hit.uv) {\r\n\t\t\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t\t\t\tvar areaId = self._cubeTextureCanvas.getArea(hit.uv);\r\n\t\t\t\t\t\t\tif (areaId === lastAreaId) {\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(areaId, true);\r\n\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\tlastAreaId = areaId;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tdocument.body.style.cursor = \"default\";\r\n\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tvar flyTo = (this.flyTo = (function () {\r\n\t\t\t\tvar center = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\t\treturn function (dir, up, ok) {\r\n\t\t\t\t\tvar aabb = self._fitVisible ? viewer.scene.getAABB(viewer.scene.visibleObjectIds) : viewer.scene.aabb;\r\n\t\t\t\t\tvar diag = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.getAABB3Diag(aabb);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.getAABB3Center(aabb, center);\r\n\t\t\t\t\tvar dist = Math.abs(diag / Math.tan(self._cameraFitFOV * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.DEGTORAD));\r\n\t\t\t\t\tviewer.cameraControl.pivotPos = center;\r\n\t\t\t\t\tif (self._cameraFly) {\r\n\t\t\t\t\t\tviewer.cameraFlight.flyTo(\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tlook: center,\r\n\t\t\t\t\t\t\t\teye: [center[0] - dist * dir[0], center[1] - dist * dir[1], center[2] - dist * dir[2]],\r\n\t\t\t\t\t\t\t\tup: up || [0, 1, 0],\r\n\t\t\t\t\t\t\t\torthoScale: diag * 1.1,\r\n\t\t\t\t\t\t\t\tfitFOV: self._cameraFitFOV,\r\n\t\t\t\t\t\t\t\tduration: self._cameraFlyDuration\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tok\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tviewer.cameraFlight.jumpTo(\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tlook: center,\r\n\t\t\t\t\t\t\t\teye: [center[0] - dist * dir[0], center[1] - dist * dir[1], center[2] - dist * dir[2]],\r\n\t\t\t\t\t\t\t\tup: up || [0, 1, 0],\r\n\t\t\t\t\t\t\t\torthoScale: diag * 1.1,\r\n\t\t\t\t\t\t\t\tfitFOV: self._cameraFitFOV\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tok\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t})());\r\n\t\t}\r\n\r\n\t\tthis._onUpdated = viewer.localeService.on(\"updated\", () => {\r\n\t\t\tthis._cubeTextureCanvas.clear();\r\n\t\t\tthis._repaint();\r\n\t\t});\r\n\r\n\t\tthis.setVisible(cfg.visible);\r\n\t\tthis.setCameraFitFOV(cfg.cameraFitFOV);\r\n\t\tthis.setCameraFly(cfg.cameraFly);\r\n\t\tthis.setCameraFlyDuration(cfg.cameraFlyDuration);\r\n\t\tthis.setFitVisible(cfg.fitVisible);\r\n\t\tthis.setSynchProjection(cfg.synchProjection);\r\n\t}\r\n\r\n\tflyByClick(areaId) {\r\n\t\tif (areaId >= 0) {\r\n\t\t\tthis._cubeTextureCanvas.setAreaHighlighted(areaId, true);\r\n\t\t\tthis._repaint();\r\n\t\t\tvar dir = this._cubeTextureCanvas.getAreaDir(areaId);\r\n\t\t\tif (dir) {\r\n\t\t\t\tvar up = this._cubeTextureCanvas.getAreaUp(areaId);\r\n\t\t\t\tif (this._isProjectNorth && this._projectNorthOffsetAngle) {\r\n\t\t\t\t\tdir = this.rotateTrueNorth(+1, dir, tempVec3a);\r\n\t\t\t\t\tup = this.rotateTrueNorth(+1, up, tempVec3b);\r\n\t\t\t\t}\r\n\t\t\t\tthis.flyTo(dir, up, function () {\r\n\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tget navCubeScene() {\r\n\t\treturn this._navCubeScene;\r\n\t}\r\n\r\n\tsend(name, value) {\r\n\t\tswitch (name) {\r\n\t\t\tcase \"language\":\r\n\t\t\t\tthis._cubeTextureCanvas.clear();\r\n\t\t\t\tthis._repaint(); // CubeTextureCanvas gets language from Viewer\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t_repaint() {\r\n\t\tconst image = this._cubeTextureCanvas.getImage();\r\n\t\tthis._cubeMesh.material.diffuseMap.image = image;\r\n\t\tthis._cubeMesh.material.emissiveMap.image = image;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if the NavCube is visible.\r\n\t *\r\n\t * @param {Boolean} visible Whether or not the NavCube is visible.\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tif (!this._navCubeCanvas) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._cubeMesh.visible = visible;\r\n\t\tif (this._shadow) {\r\n\t\t\tthis._shadow.visible = visible;\r\n\t\t}\r\n\t\tthis._navCubeCanvas.style.visibility = visible ? \"visible\" : \"hidden\";\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if the NavCube is visible.\r\n\t *\r\n\t * @return {Boolean} True when the NavCube is visible.\r\n\t */\r\n\tgetVisible() {\r\n\t\tif (!this._navCubeCanvas) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn this._cubeMesh.visible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the axis, corner and edge-aligned views will fit the\r\n\t * view to the entire {@link Scene} or just to visible object-{@link Entity}s.\r\n\t *\r\n\t * Entitys are visible objects when {@link Entity#isObject} and {@link Entity#visible} are both ````true````.\r\n\t *\r\n\t * @param {Boolean} fitVisible Set ````true```` to fit only visible object-Entitys.\r\n\t */\r\n\tsetFitVisible(fitVisible = false) {\r\n\t\tthis._fitVisible = fitVisible;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the axis, corner and edge-aligned views will fit the\r\n\t * view to the entire {@link Scene} or just to visible object-{@link Entity}s.\r\n\t *\r\n\t * Entitys are visible objects when {@link Entity#isObject} and {@link Entity#visible} are both ````true````.\r\n\t *\r\n\t * @return {Boolean} True when fitting only visible object-Entitys.\r\n\t */\r\n\tgetFitVisible() {\r\n\t\treturn this._fitVisible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the {@link Camera} flies or jumps to each selected axis or diagonal.\r\n\t *\r\n\t * Default is ````true````, to fly.\r\n\t *\r\n\t * @param {Boolean} cameraFly Set ````true```` to fly, else ````false```` to jump.\r\n\t */\r\n\tsetCameraFly(cameraFly = true) {\r\n\t\tthis._cameraFly = cameraFly;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the {@link Camera} flies or jumps to each selected axis or diagonal.\r\n\t *\r\n\t * Default is ````true````, to fly.\r\n\t *\r\n\t * @returns {Boolean} Returns ````true```` to fly, else ````false```` to jump.\r\n\t */\r\n\tgetCameraFly() {\r\n\t\treturn this._cameraFly;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets how much of the field-of-view, in degrees, that the {@link Scene} should\r\n\t * fill the canvas when flying or jumping the {@link Camera} to each selected axis or diagonal.\r\n\t *\r\n\t * Default value is ````45````.\r\n\t *\r\n\t * @param {Number} cameraFitFOV New FOV value.\r\n\t */\r\n\tsetCameraFitFOV(cameraFitFOV = 45) {\r\n\t\tthis._cameraFitFOV = cameraFitFOV;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets how much of the field-of-view, in degrees, that the {@link Scene} should\r\n\t * fill the canvas when flying or jumping the {@link Camera} to each selected axis or diagonal.\r\n\t *\r\n\t * Default value is ````45````.\r\n\t *\r\n\t * @returns {Number} Current FOV value.\r\n\t */\r\n\tgetCameraFitFOV() {\r\n\t\treturn this._cameraFitFOV;\r\n\t}\r\n\r\n\t/**\r\n\t * When flying the {@link Camera} to each new axis or diagonal, sets how long, in seconds, that the Camera takes to get there.\r\n\t *\r\n\t * Default is ````0.5````.\r\n\t *\r\n\t * @param {Boolean} cameraFlyDuration Camera flight duration in seconds.\r\n\t */\r\n\tsetCameraFlyDuration(cameraFlyDuration = 0.5) {\r\n\t\tthis._cameraFlyDuration = cameraFlyDuration;\r\n\t}\r\n\r\n\t/**\r\n\t * When flying the {@link Camera} to each new axis or diagonal, gets how long, in seconds, that the Camera takes to get there.\r\n\t *\r\n\t * Default is ````0.5````.\r\n\t *\r\n\t * @returns {Boolean} Camera flight duration in seconds.\r\n\t */\r\n\tgetCameraFlyDuration() {\r\n\t\treturn this._cameraFlyDuration;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the NavCube switches between perspective and orthographic projections in synchrony with\r\n\t * the {@link Camera}. When ````false````, the NavCube will always be rendered with perspective projection.\r\n\t *\r\n\t * @param {Boolean} synchProjection Set ````true```` to keep NavCube projection synchronized with {@link Camera#projection}.\r\n\t */\r\n\tsetSynchProjection(synchProjection = false) {\r\n\t\tthis._synchProjection = synchProjection;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the NavCube switches between perspective and orthographic projections in synchrony with\r\n\t * the {@link Camera}. When ````false````, the NavCube will always be rendered with perspective projection.\r\n\t *\r\n\t * @return {Boolean} True when NavCube projection is synchronized with {@link Camera#projection}.\r\n\t */\r\n\tgetSynchProjection() {\r\n\t\treturn this._synchProjection;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the NavCube switches between project north and true north\r\n\t *\r\n\t * @param {Boolean} isProjectNorth Set ````true```` to use project north offset\r\n\t */\r\n\tsetIsProjectNorth(isProjectNorth = false) {\r\n\t\tthis._isProjectNorth = isProjectNorth;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the NavCube switches between project north and true north\r\n\t *\r\n\t * @return {Boolean} isProjectNorth when ````true```` - use project north offset\r\n\t */\r\n\tgetIsProjectNorth() {\r\n\t\treturn this._isProjectNorth;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the NavCube project north offset angle (used when {@link isProjectNorth} is ````true````\r\n\t *\r\n\t * @param {number} projectNorthOffsetAngle Set the vector offset for project north\r\n\t */\r\n\tsetProjectNorthOffsetAngle(projectNorthOffsetAngle) {\r\n\t\tthis._projectNorthOffsetAngle = projectNorthOffsetAngle;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the offset angle between project north and true north\r\n\t *\r\n\t * @return {number} projectNorthOffsetAngle\r\n\t */\r\n\tgetProjectNorthOffsetAngle() {\r\n\t\treturn this._projectNorthOffsetAngle;\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this NavCubePlugin.\r\n\t *\r\n\t * Does not destroy the canvas the NavCubePlugin was configured with.\r\n\t */\r\n\tdestroy() {\r\n\t\tif (this._navCubeCanvas) {\r\n\t\t\tthis.viewer.localeService.off(this._onUpdated);\r\n\t\t\tthis.viewer.camera.off(this._onCameraMatrix);\r\n\t\t\tthis.viewer.camera.off(this._onCameraWorldAxis);\r\n\t\t\tthis.viewer.camera.perspective.off(this._onCameraFOV);\r\n\t\t\tthis.viewer.camera.off(this._onCameraProjection);\r\n\r\n\t\t\tthis._navCubeCanvas.removeEventListener(\"mouseenter\", this._onMouseEnter);\r\n\t\t\tthis._navCubeCanvas.removeEventListener(\"mouseleave\", this._onMouseLeave);\r\n\t\t\tthis._navCubeCanvas.removeEventListener(\"mousedown\", this._onMouseDown);\r\n\r\n\t\t\tdocument.removeEventListener(\"mousemove\", this._onMouseMove);\r\n\t\t\tdocument.removeEventListener(\"mouseup\", this._onMouseUp);\r\n\r\n\t\t\tthis._navCubeCanvas = null;\r\n\t\t\tthis._cubeTextureCanvas.destroy();\r\n\t\t\tthis._cubeTextureCanvas = null;\r\n\r\n\t\t\tthis._onMouseEnter = null;\r\n\t\t\tthis._onMouseLeave = null;\r\n\t\t\tthis._onMouseDown = null;\r\n\t\t\tthis._onMouseMove = null;\r\n\t\t\tthis._onMouseUp = null;\r\n\t\t}\r\n\r\n\t\tthis._navCubeScene.destroy();\r\n\t\tthis._navCubeScene = null;\r\n\t\tthis._cubeMesh = null;\r\n\t\tthis._shadow = null;\r\n\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/NavCubePlugin/NavCubePlugin.js?");
|
|
1797
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ NavCubePlugin: () => (/* binding */ NavCubePlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./../../viewer/scene/lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./../../viewer/scene/mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/scene/geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../viewer/scene/materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _viewer_scene_materials_Texture_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../viewer/scene/materials/Texture.js */ \"./src/viewer/scene/materials/Texture.js\");\n/* harmony import */ var _viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../viewer/scene/geometry/builders/buildCylinderGeometry.js */ \"./src/viewer/scene/geometry/builders/buildCylinderGeometry.js\");\n/* harmony import */ var _CubeTextureCanvas_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./CubeTextureCanvas.js */ \"./src/plugins/NavCubePlugin/CubeTextureCanvas.js\");\n/* harmony import */ var _viewer_scene_constants_constants_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../viewer/scene/constants/constants.js */ \"./src/viewer/scene/constants/constants.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst tempVec3a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\nconst tempVec3b = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\nconst tempMat4a = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n\r\n/**\r\n * {@link Viewer} plugin that lets us look at the entire {@link Scene} from along a chosen axis or diagonal.\r\n *\r\n * [<img src=\"https://user-images.githubusercontent.com/83100/55674490-c93c2e00-58b5-11e9-8a28-eb08876947c0.gif\">](https://xeokit.github.io/xeokit-sdk/examples/#gizmos_NavCubePlugin)\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#gizmos_NavCubePlugin)]\r\n *\r\n * ## Overview\r\n *\r\n * * Rotating the NavCube causes the Viewer's {@link Camera} to orbit its current\r\n * point-of-interest. Conversely, orbiting the Camera causes the NavCube to rotate accordingly.\r\n * * The faces of the NavCube are aligned with the Viewer's {@link Scene}'s World-space coordinate axis. Clicking on a face moves\r\n * the Camera to look at the entire Scene along the corresponding axis. Clicking on an edge or a corner looks at\r\n * the entire Scene along a diagonal.\r\n * * The NavCube can be configured to either jump or fly the Camera to each new position. We can configure how tightly the\r\n * NavCube fits the Scene to view, and when flying, we can configure how fast it flies. We can also configure whether the\r\n * NavCube fits all objects to view, or just the currently visible objects. See below for a usage example.\r\n * * Clicking the NavCube also sets {@link CameraControl#pivotPos} to the center of the fitted objects.\r\n *\r\n * ## Usage\r\n *\r\n * In the example below, we'll create a Viewer and add a NavCubePlugin, which will create a NavCube gizmo in the canvas\r\n * with the given ID. Then we'll use the {@link XTCLoaderPlugin} to load a model into the Viewer's Scene. We can then\r\n * use the NavCube to look at the model along each axis or diagonal.\r\n *\r\n * ````JavaScript\r\n * import {Viewer, XTCLoaderPlugin, NavCubePlugin} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.camera.eye = [-3.93, 2.85, 27.01];\r\n * viewer.camera.look = [4.40, 3.72, 8.89];\r\n * viewer.camera.up = [-0.01, 0.99, 0.03];\r\n *\r\n * const navCube = new NavCubePlugin(viewer, {\r\n *\r\n * canvasID: \"myNavCubeCanvas\",\r\n *\r\n * visible: true, // Initially visible (default)\r\n *\r\n * cameraFly: true, // Fly camera to each selected axis/diagonal\r\n * cameraFitFOV: 45, // How much field-of-view the scene takes once camera has fitted it to view\r\n * cameraFlyDuration: 0.5,// How long (in seconds) camera takes to fly to each new axis/diagonal\r\n *\r\n * fitVisible: false, // Fit whole scene, including invisible objects (default)\r\n *\r\n * synchProjection: false // Keep NavCube in perspective projection, even when camera switches to ortho (default)\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * edges: true\r\n * });\r\n * ````\r\n */\r\nclass NavCubePlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t * @param {Viewer} viewer The {@link Viewer}.\r\n\t * @param {Object} cfg NavCubePlugin configuration.\r\n\t * @param {String} [cfg.id=\"NavCube\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas to display the NavCube - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas to display the NavCube - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {div} [cfg.viewerElement] Reference of an existing div to contain the canvas\r\n\t * @param {Boolean} [cfg.visible=true] Initial visibility.\r\n\t * @param {Boolean} [cfg.shadowVisible=true] Whether the shadow of the cube is visible.\r\n\t * @param {String} [cfg.cameraFly=true] Whether the {@link Camera} flies or jumps to each selected axis or diagonal.\r\n\t * @param {String} [cfg.cameraFitFOV=45] How much of the field-of-view, in degrees, that the 3D scene should fill the {@link Canvas} when the {@link Camera} moves to an axis or diagonal.\r\n\t * @param {String} [cfg.cameraFlyDuration=0.5] When flying the {@link Camera} to each new axis or diagonal, how long, in seconds, that the Camera takes to get there.\r\n\t * @param {String} [cfg.color=\"lightgrey\"] Custom uniform color for the faces of the NavCube.\r\n\t * @param {String} [cfg.frontColor=\"#55FF55\"] Custom color for the front face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.backColor=\"#55FF55\"] Custom color for the back face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.leftColor=\"#FF5555\"] Custom color for the left face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.rightColor=\"#FF5555\"] Custom color for the right face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.topColor=\"#5555FF\"] Custom color for the top face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.bottomColor=\"#5555FF\"] Custom color for the bottom face of the NavCube. Overrides ````color````.\r\n\t * @param {String} [cfg.hoverColor=\"rgba(0,0,0,0.4)\"] Custom color for highlighting regions on the NavCube as we hover the pointer over them.\r\n\t * @param {String} [cfg.textColor=\"black\"] Custom text color for labels of the NavCube.\r\n\t * @param {Boolean} [cfg.fitVisible=false] Sets whether the axis, corner and edge-aligned views will fit the\r\n\t * view to the entire {@link Scene} or just to visible object-{@link Entity}s. Entitys are visible objects when {@link Entity#isObject} and {@link Entity#visible} are both ````true````.\r\n\t * @param {Boolean} [cfg.synchProjection=false] Sets whether the NavCube switches between perspective and orthographic projections in synchrony with the {@link Camera}. When ````false````, the NavCube will always be rendered with perspective projection.\r\n\t * @param {Boolean} [cfg.isProjectNorth] sets whether the NavCube switches between true north and project north - using the project north offset angle.\r\n\t * @param {number} [cfg.projectNorthOffsetAngle] sets the NavCube project north offset angle - when the {@link isProjectNorth} is true.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"NavCube\", viewer, cfg);\r\n\r\n\t\tviewer.navCube = this;\r\n\r\n\t\tvar visible = true;\r\n\r\n\t\ttry {\r\n\t\t\tthis._navCubeScene = new _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_2__.Scene(viewer, {\r\n\t\t\t\tcanvasId: cfg.canvasId,\r\n\t\t\t\tcanvasElement: cfg.canvasElement,\r\n\t\t\t\ttransparent: true,\r\n\t\t\t\tspinnerElementId: \"navcube_spinner\"\r\n\t\t\t});\r\n\r\n\t\t\tthis._navCubeCanvas = this._navCubeScene.canvas.canvas;\r\n\r\n\t\t\tthis._navCubeScene.input.keyboardEnabled = false; // Don't want keyboard input in the NavCube\r\n\t\t} catch (error) {\r\n\t\t\tthis.error(error);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst navCubeScene = this._navCubeScene;\r\n\r\n\t\tnavCubeScene.clearLights();\r\n\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(navCubeScene, { dir: [0.4, -0.4, 0.8], color: [0.8, 1.0, 1.0], intensity: 1.0, space: \"view\" });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(navCubeScene, { dir: [-0.8, -0.3, -0.4], color: [0.8, 0.8, 0.8], intensity: 1.0, space: \"view\" });\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_3__.DirLight(navCubeScene, { dir: [0.8, -0.6, -0.8], color: [1.0, 1.0, 1.0], intensity: 1.0, space: \"view\" });\r\n\r\n\t\tthis._navCubeCamera = navCubeScene.camera;\r\n\t\tthis._navCubeCamera.ortho.scale = 7.0;\r\n\t\tthis._navCubeCamera.ortho.near = 0.1;\r\n\t\tthis._navCubeCamera.ortho.far = 2000;\r\n\r\n\t\tnavCubeScene.edgeMaterial.edgeColor = [0.2, 0.2, 0.2];\r\n\t\tnavCubeScene.edgeMaterial.edgeAlpha = 0.6;\r\n\r\n\t\tthis._zUp = Boolean(viewer.camera.zUp);\r\n\r\n\t\tvar self = this;\r\n\r\n\t\tthis.setIsProjectNorth(cfg.isProjectNorth);\r\n\t\tthis.setProjectNorthOffsetAngle(cfg.projectNorthOffsetAngle);\r\n\r\n\t\tconst rotateTrueNorth = (this.rotateTrueNorth = (function () {\r\n\t\t\tconst trueNorthMatrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mat4();\r\n\t\t\treturn function (dir, vec, dest) {\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.identityMat4(trueNorthMatrix);\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.rotationMat4v(dir * self._projectNorthOffsetAngle * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.DEGTORAD, [0, 1, 0], trueNorthMatrix);\r\n\t\t\t\treturn _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(trueNorthMatrix, vec, dest);\r\n\t\t\t};\r\n\t\t})());\r\n\r\n\t\tthis._synchCamera = (function () {\r\n\t\t\tvar matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.rotationMat4c(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.DEGTORAD, 1, 0, 0);\r\n\t\t\tvar eyeLookVec = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\tvar eyeLookVecCube = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\tvar upCube = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\treturn function () {\r\n\t\t\t\tvar eye = viewer.camera.eye;\r\n\t\t\t\tvar look = viewer.camera.look;\r\n\t\t\t\tvar up = viewer.camera.up;\r\n\t\t\t\teyeLookVec = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.mulVec3Scalar(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.normalizeVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.subVec3(eye, look, eyeLookVec)), 5);\r\n\r\n\t\t\t\tif (self._isProjectNorth && self._projectNorthOffsetAngle) {\r\n\t\t\t\t\teyeLookVec = rotateTrueNorth(-1, eyeLookVec, tempVec3a);\r\n\t\t\t\t\tup = rotateTrueNorth(-1, up, tempVec3b);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (self._zUp) {\r\n\t\t\t\t\t// +Z up\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(matrix, eyeLookVec, eyeLookVecCube);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(matrix, up, upCube);\r\n\t\t\t\t\tself._navCubeCamera.look = [0, 0, 0];\r\n\t\t\t\t\tself._navCubeCamera.eye = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformVec3(matrix, eyeLookVec, eyeLookVecCube);\r\n\t\t\t\t\tself._navCubeCamera.up = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.transformPoint3(matrix, up, upCube);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// +Y up\r\n\t\t\t\t\tself._navCubeCamera.look = [0, 0, 0];\r\n\t\t\t\t\tself._navCubeCamera.eye = eyeLookVec;\r\n\t\t\t\t\tself._navCubeCamera.up = up;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tthis._cubeTextureCanvas = new _CubeTextureCanvas_js__WEBPACK_IMPORTED_MODULE_9__.CubeTextureCanvas(viewer, navCubeScene, cfg);\r\n\r\n\t\tthis._cubeSampler = new _viewer_scene_materials_Texture_js__WEBPACK_IMPORTED_MODULE_7__.Texture(navCubeScene, {\r\n\t\t\timage: this._cubeTextureCanvas.getImage(),\r\n\t\t\tflipY: true,\r\n\t\t\twrapS: _viewer_scene_constants_constants_js__WEBPACK_IMPORTED_MODULE_10__.ClampToEdgeWrapping,\r\n\t\t\twrapT: _viewer_scene_constants_constants_js__WEBPACK_IMPORTED_MODULE_10__.ClampToEdgeWrapping\r\n\t\t});\r\n\r\n\t\tthis._cubeMesh = new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(navCubeScene, {\r\n\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(navCubeScene, {\r\n\t\t\t\tprimitive: \"triangles\",\r\n\t\t\t\tnormals: [\r\n\t\t\t\t\t0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,\r\n\t\t\t\t\t-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1,\r\n\t\t\t\t\t0, 0, -1\r\n\t\t\t\t],\r\n\t\t\t\tpositions: [\r\n\t\t\t\t\t1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1,\r\n\t\t\t\t\t-1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1,\r\n\t\t\t\t\t-1, -1, -1, -1, 1, -1, 1, 1, -1\r\n\t\t\t\t],\r\n\t\t\t\tuv: [\r\n\t\t\t\t\t0.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,\r\n\t\t\t\t\t0.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, 0.25, 0,\r\n\t\t\t\t\t0.5, 0, 0.5, 0.3333, 0.25, 0.3333, 0.75, 0.3333, 1.0, 0.3333, 1.0, 0.6666, 0.75, 0.6666\r\n\t\t\t\t],\r\n\t\t\t\tindices: [\r\n\t\t\t\t\t0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20,\r\n\t\t\t\t\t21, 22, 20, 22, 23\r\n\t\t\t\t]\r\n\t\t\t}),\r\n\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_6__.PhongMaterial(navCubeScene, {\r\n\t\t\t\tdiffuse: [0.4, 0.4, 0.4],\r\n\t\t\t\tspecular: [0.4, 0.4, 0.4],\r\n\t\t\t\temissive: [0.6, 0.6, 0.6],\r\n\t\t\t\tdiffuseMap: this._cubeSampler,\r\n\t\t\t\temissiveMap: this._cubeSampler\r\n\t\t\t}),\r\n\t\t\tvisible: !!visible,\r\n\t\t\tedges: true\r\n\t\t});\r\n\r\n\t\tthis._shadow =\r\n\t\t\tcfg.shadowVisible === false\r\n\t\t\t\t? null\r\n\t\t\t\t: new _viewer_scene_mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_4__.Mesh(navCubeScene, {\r\n\t\t\t\t\t\tgeometry: new _viewer_scene_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_5__.ReadableGeometry(\r\n\t\t\t\t\t\t\tnavCubeScene,\r\n\t\t\t\t\t\t\t(0,_viewer_scene_geometry_builders_buildCylinderGeometry_js__WEBPACK_IMPORTED_MODULE_8__.buildCylinderGeometry)({\r\n\t\t\t\t\t\t\t\tcenter: [0, 0, 0],\r\n\t\t\t\t\t\t\t\tradiusTop: 0.001,\r\n\t\t\t\t\t\t\t\tradiusBottom: 1.4,\r\n\t\t\t\t\t\t\t\theight: 0.01,\r\n\t\t\t\t\t\t\t\tradialSegments: 20,\r\n\t\t\t\t\t\t\t\theightSegments: 1,\r\n\t\t\t\t\t\t\t\topenEnded: true\r\n\t\t\t\t\t\t\t})\r\n\t\t\t\t\t\t),\r\n\t\t\t\t\t\tmaterial: new _viewer_scene_materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_6__.PhongMaterial(navCubeScene, {\r\n\t\t\t\t\t\t\tdiffuse: [0.0, 0.0, 0.0],\r\n\t\t\t\t\t\t\tspecular: [0, 0, 0],\r\n\t\t\t\t\t\t\temissive: [0.0, 0.0, 0.0],\r\n\t\t\t\t\t\t\talpha: 0.5\r\n\t\t\t\t\t\t}),\r\n\t\t\t\t\t\tposition: [0, -1.5, 0],\r\n\t\t\t\t\t\tvisible: !!visible,\r\n\t\t\t\t\t\tpickable: false,\r\n\t\t\t\t\t\tbackfaces: false\r\n\t\t\t\t });\r\n\r\n\t\tthis._onCameraMatrix = viewer.camera.on(\"matrix\", this._synchCamera);\r\n\t\tthis._onCameraWorldAxis = viewer.camera.on(\"worldAxis\", () => {\r\n\t\t\tif (viewer.camera.zUp) {\r\n\t\t\t\tthis._zUp = true;\r\n\t\t\t\tthis._cubeTextureCanvas.setZUp();\r\n\t\t\t\tthis._repaint();\r\n\t\t\t\tthis._synchCamera();\r\n\t\t\t} else if (viewer.camera.yUp) {\r\n\t\t\t\tthis._zUp = false;\r\n\t\t\t\tthis._cubeTextureCanvas.setYUp();\r\n\t\t\t\tthis._repaint();\r\n\t\t\t\tthis._synchCamera();\r\n\t\t\t}\r\n\t\t});\r\n\t\tthis._onCameraFOV = viewer.camera.perspective.on(\"fov\", (fov) => {\r\n\t\t\tif (this._synchProjection) {\r\n\t\t\t\tthis._navCubeCamera.perspective.fov = fov;\r\n\t\t\t}\r\n\t\t});\r\n\t\tthis._onCameraProjection = viewer.camera.on(\"projection\", (projection) => {\r\n\t\t\tif (this._synchProjection) {\r\n\t\t\t\tthis._navCubeCamera.projection =\r\n\t\t\t\t\tprojection === \"ortho\" || projection === \"perspective\" ? projection : \"perspective\";\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tvar lastAreaId = -1;\r\n\r\n\t\tfunction actionMove(posX, posY) {\r\n\t\t\tvar yawInc = (posX - lastX) * -sensitivity;\r\n\t\t\tvar pitchInc = (posY - lastY) * -sensitivity;\r\n\t\t\tyaw -= yawInc;\r\n\t\t\tpitch -= pitchInc;\r\n\t\t\tif (minPitch !== undefined && pitch < minPitch) {\r\n\t\t\t\tpitch = minPitch;\r\n\t\t\t}\r\n\t\t\tif (maxPitch !== undefined && pitch > maxPitch) {\r\n\t\t\t\tpitch = maxPitch;\r\n\t\t\t}\r\n\t\t\tviewer.camera.orbitYaw(yawInc);\r\n\t\t\tviewer.camera.orbitPitch(-pitchInc);\r\n\t\t\tlastX = posX;\r\n\t\t\tlastY = posY;\r\n\t\t}\r\n\r\n\t\tfunction getCoordsWithinElement(event) {\r\n\t\t\tvar coords = [0, 0];\r\n\t\t\tif (!event) {\r\n\t\t\t\tevent = window.event;\r\n\t\t\t\tcoords[0] = event.x;\r\n\t\t\t\tcoords[1] = event.y;\r\n\t\t\t} else {\r\n\t\t\t\tvar element = event.target;\r\n\t\t\t\tvar totalOffsetLeft = 0;\r\n\t\t\t\tvar totalOffsetTop = 0;\r\n\t\t\t\twhile (element.offsetParent) {\r\n\t\t\t\t\ttotalOffsetLeft += element.offsetLeft;\r\n\t\t\t\t\ttotalOffsetTop += element.offsetTop;\r\n\t\t\t\t\telement = element.offsetParent;\r\n\t\t\t\t}\r\n\t\t\t\tcoords[0] = event.pageX - totalOffsetLeft;\r\n\t\t\t\tcoords[1] = event.pageY - totalOffsetTop;\r\n\t\t\t}\r\n\t\t\treturn coords;\r\n\t\t}\r\n\r\n\t\t{\r\n\t\t\tvar downX = null;\r\n\t\t\tvar downY = null;\r\n\t\t\tvar down = false;\r\n\t\t\tvar over = false;\r\n\r\n\t\t\tvar yaw = 0;\r\n\t\t\tvar pitch = 0;\r\n\t\t\tvar minPitch = null;\r\n\t\t\tvar maxPitch = null;\r\n\t\t\tvar sensitivity = 0.5;\r\n\r\n\t\t\tvar lastX;\r\n\t\t\tvar lastY;\r\n\r\n\t\t\tself._navCubeCanvas.addEventListener(\r\n\t\t\t\t\"mouseenter\",\r\n\t\t\t\t(self._onMouseEnter = function (e) {\r\n\t\t\t\t\tover = true;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tself._navCubeCanvas.addEventListener(\r\n\t\t\t\t\"mouseleave\",\r\n\t\t\t\t(self._onMouseLeave = function (e) {\r\n\t\t\t\t\tover = false;\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tself._navCubeCanvas.addEventListener(\r\n\t\t\t\t\"mousedown\",\r\n\t\t\t\t(self._onMouseDown = function (e) {\r\n\t\t\t\t\tif (e.which !== 1) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdownX = e.x;\r\n\t\t\t\t\tdownY = e.y;\r\n\t\t\t\t\tlastX = e.clientX;\r\n\t\t\t\t\tlastY = e.clientY;\r\n\t\t\t\t\tvar canvasPos = getCoordsWithinElement(e);\r\n\t\t\t\t\tvar hit = navCubeScene.pick({\r\n\t\t\t\t\t\tcanvasPos: canvasPos\r\n\t\t\t\t\t});\r\n\t\t\t\t\tif (hit) {\r\n\t\t\t\t\t\tdown = true;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tdown = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tdocument.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(self._onMouseUp = function (e) {\r\n\t\t\t\t\tif (e.which !== 1) {\r\n\t\t\t\t\t\t// Left button\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdown = false;\r\n\t\t\t\t\tif (downX === null) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getCoordsWithinElement(e);\r\n\t\t\t\t\tvar hit = navCubeScene.pick({\r\n\t\t\t\t\t\tcanvasPos: canvasPos,\r\n\t\t\t\t\t\tpickSurface: true\r\n\t\t\t\t\t});\r\n\t\t\t\t\tif (hit) {\r\n\t\t\t\t\t\tif (hit.uv) {\r\n\t\t\t\t\t\t\tvar areaId = self._cubeTextureCanvas.getArea(hit.uv);\r\n\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(areaId, true);\r\n\t\t\t\t\t\t\t\t\tlastAreaId = areaId;\r\n\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\tif (e.x < downX - 3 || e.x > downX + 3 || e.y < downY - 3 || e.y > downY + 3) {\r\n\t\t\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tvar dir = self._cubeTextureCanvas.getAreaDir(areaId);\r\n\t\t\t\t\t\t\t\t\tif (dir) {\r\n\t\t\t\t\t\t\t\t\t\tvar up = self._cubeTextureCanvas.getAreaUp(areaId);\r\n\t\t\t\t\t\t\t\t\t\tif (self._isProjectNorth && self._projectNorthOffsetAngle) {\r\n\t\t\t\t\t\t\t\t\t\t\tdir = rotateTrueNorth(+1, dir, tempVec3a);\r\n\t\t\t\t\t\t\t\t\t\t\tup = rotateTrueNorth(+1, up, tempVec3b);\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\tflyTo(dir, up, function () {\r\n\t\t\t\t\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(areaId, false);\r\n\t\t\t\t\t\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tdocument.addEventListener(\r\n\t\t\t\t\"mousemove\",\r\n\t\t\t\t(self._onMouseMove = function (e) {\r\n\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (e.buttons === 1 && !down) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (down) {\r\n\t\t\t\t\t\tvar posX = e.clientX;\r\n\t\t\t\t\t\tvar posY = e.clientY;\r\n\t\t\t\t\t\tdocument.body.style.cursor = \"move\";\r\n\t\t\t\t\t\tactionMove(posX, posY);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!over) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvar canvasPos = getCoordsWithinElement(e);\r\n\t\t\t\t\tvar hit = navCubeScene.pick({\r\n\t\t\t\t\t\tcanvasPos: canvasPos,\r\n\t\t\t\t\t\tpickSurface: true\r\n\t\t\t\t\t});\r\n\t\t\t\t\tif (hit) {\r\n\t\t\t\t\t\tif (hit.uv) {\r\n\t\t\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t\t\t\tvar areaId = self._cubeTextureCanvas.getArea(hit.uv);\r\n\t\t\t\t\t\t\tif (areaId === lastAreaId) {\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (areaId >= 0) {\r\n\t\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(areaId, true);\r\n\t\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\t\tlastAreaId = areaId;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tdocument.body.style.cursor = \"default\";\r\n\t\t\t\t\t\tif (lastAreaId >= 0) {\r\n\t\t\t\t\t\t\tself._cubeTextureCanvas.setAreaHighlighted(lastAreaId, false);\r\n\t\t\t\t\t\t\tself._repaint();\r\n\t\t\t\t\t\t\tlastAreaId = -1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tvar flyTo = (this.flyTo = (function () {\r\n\t\t\t\tvar center = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.vec3();\r\n\t\t\t\treturn function (dir, up, ok) {\r\n\t\t\t\t\tvar aabb = self._fitVisible ? viewer.scene.getAABB(viewer.scene.visibleObjectIds) : viewer.scene.aabb;\r\n\t\t\t\t\tvar diag = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.getAABB3Diag(aabb);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.getAABB3Center(aabb, center);\r\n\t\t\t\t\tvar dist = Math.abs(diag / Math.tan(self._cameraFitFOV * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_1__.math.DEGTORAD));\r\n\t\t\t\t\tviewer.cameraControl.pivotPos = center;\r\n\t\t\t\t\tif (self._cameraFly) {\r\n\t\t\t\t\t\tviewer.cameraFlight.flyTo(\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tlook: center,\r\n\t\t\t\t\t\t\t\teye: [center[0] - dist * dir[0], center[1] - dist * dir[1], center[2] - dist * dir[2]],\r\n\t\t\t\t\t\t\t\tup: up || [0, 1, 0],\r\n\t\t\t\t\t\t\t\torthoScale: diag * 1.1,\r\n\t\t\t\t\t\t\t\tfitFOV: self._cameraFitFOV,\r\n\t\t\t\t\t\t\t\tduration: self._cameraFlyDuration\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tok\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tviewer.cameraFlight.jumpTo(\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tlook: center,\r\n\t\t\t\t\t\t\t\teye: [center[0] - dist * dir[0], center[1] - dist * dir[1], center[2] - dist * dir[2]],\r\n\t\t\t\t\t\t\t\tup: up || [0, 1, 0],\r\n\t\t\t\t\t\t\t\torthoScale: diag * 1.1,\r\n\t\t\t\t\t\t\t\tfitFOV: self._cameraFitFOV\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tok\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t})());\r\n\t\t}\r\n\r\n\t\tthis._onUpdated = viewer.localeService.on(\"updated\", () => {\r\n\t\t\tthis._cubeTextureCanvas.clear();\r\n\t\t\tthis._repaint();\r\n\t\t});\r\n\r\n\t\tthis.setVisible(cfg.visible);\r\n\t\tthis.setCameraFitFOV(cfg.cameraFitFOV);\r\n\t\tthis.setCameraFly(cfg.cameraFly);\r\n\t\tthis.setCameraFlyDuration(cfg.cameraFlyDuration);\r\n\t\tthis.setFitVisible(cfg.fitVisible);\r\n\t\tthis.setSynchProjection(cfg.synchProjection);\r\n\t}\r\n\r\n\tflyByClick(areaId) {\r\n\t\tif (areaId >= 0) {\r\n\t\t\tthis._cubeTextureCanvas.setAreaHighlighted(areaId, true);\r\n\t\t\tthis._repaint();\r\n\t\t\tvar dir = this._cubeTextureCanvas.getAreaDir(areaId);\r\n\t\t\tif (dir) {\r\n\t\t\t\tvar up = this._cubeTextureCanvas.getAreaUp(areaId);\r\n\t\t\t\tif (this._isProjectNorth && this._projectNorthOffsetAngle) {\r\n\t\t\t\t\tdir = this.rotateTrueNorth(+1, dir, tempVec3a);\r\n\t\t\t\t\tup = this.rotateTrueNorth(+1, up, tempVec3b);\r\n\t\t\t\t}\r\n\t\t\t\tthis.flyTo(dir, up, function () {\r\n\t\t\t\t\tdocument.body.style.cursor = \"pointer\";\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tget navCubeScene() {\r\n\t\treturn this._navCubeScene;\r\n\t}\r\n\r\n\tsend(name, value) {\r\n\t\tswitch (name) {\r\n\t\t\tcase \"language\":\r\n\t\t\t\tthis._cubeTextureCanvas.clear();\r\n\t\t\t\tthis._repaint(); // CubeTextureCanvas gets language from Viewer\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\t_repaint() {\r\n\t\tconst image = this._cubeTextureCanvas.getImage();\r\n\t\tthis._cubeMesh.material.diffuseMap.image = image;\r\n\t\tthis._cubeMesh.material.emissiveMap.image = image;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if the NavCube is visible.\r\n\t *\r\n\t * @param {Boolean} visible Whether or not the NavCube is visible.\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tif (!this._navCubeCanvas) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._cubeMesh.visible = visible;\r\n\t\tif (this._shadow) {\r\n\t\t\tthis._shadow.visible = visible;\r\n\t\t}\r\n\t\tthis._navCubeCanvas.style.visibility = visible ? \"visible\" : \"hidden\";\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if the NavCube is visible.\r\n\t *\r\n\t * @return {Boolean} True when the NavCube is visible.\r\n\t */\r\n\tgetVisible() {\r\n\t\tif (!this._navCubeCanvas) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn this._cubeMesh.visible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the axis, corner and edge-aligned views will fit the\r\n\t * view to the entire {@link Scene} or just to visible object-{@link Entity}s.\r\n\t *\r\n\t * Entitys are visible objects when {@link Entity#isObject} and {@link Entity#visible} are both ````true````.\r\n\t *\r\n\t * @param {Boolean} fitVisible Set ````true```` to fit only visible object-Entitys.\r\n\t */\r\n\tsetFitVisible(fitVisible = false) {\r\n\t\tthis._fitVisible = fitVisible;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the axis, corner and edge-aligned views will fit the\r\n\t * view to the entire {@link Scene} or just to visible object-{@link Entity}s.\r\n\t *\r\n\t * Entitys are visible objects when {@link Entity#isObject} and {@link Entity#visible} are both ````true````.\r\n\t *\r\n\t * @return {Boolean} True when fitting only visible object-Entitys.\r\n\t */\r\n\tgetFitVisible() {\r\n\t\treturn this._fitVisible;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the {@link Camera} flies or jumps to each selected axis or diagonal.\r\n\t *\r\n\t * Default is ````true````, to fly.\r\n\t *\r\n\t * @param {Boolean} cameraFly Set ````true```` to fly, else ````false```` to jump.\r\n\t */\r\n\tsetCameraFly(cameraFly = true) {\r\n\t\tthis._cameraFly = cameraFly;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the {@link Camera} flies or jumps to each selected axis or diagonal.\r\n\t *\r\n\t * Default is ````true````, to fly.\r\n\t *\r\n\t * @returns {Boolean} Returns ````true```` to fly, else ````false```` to jump.\r\n\t */\r\n\tgetCameraFly() {\r\n\t\treturn this._cameraFly;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets how much of the field-of-view, in degrees, that the {@link Scene} should\r\n\t * fill the canvas when flying or jumping the {@link Camera} to each selected axis or diagonal.\r\n\t *\r\n\t * Default value is ````45````.\r\n\t *\r\n\t * @param {Number} cameraFitFOV New FOV value.\r\n\t */\r\n\tsetCameraFitFOV(cameraFitFOV = 45) {\r\n\t\tthis._cameraFitFOV = cameraFitFOV;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets how much of the field-of-view, in degrees, that the {@link Scene} should\r\n\t * fill the canvas when flying or jumping the {@link Camera} to each selected axis or diagonal.\r\n\t *\r\n\t * Default value is ````45````.\r\n\t *\r\n\t * @returns {Number} Current FOV value.\r\n\t */\r\n\tgetCameraFitFOV() {\r\n\t\treturn this._cameraFitFOV;\r\n\t}\r\n\r\n\t/**\r\n\t * When flying the {@link Camera} to each new axis or diagonal, sets how long, in seconds, that the Camera takes to get there.\r\n\t *\r\n\t * Default is ````0.5````.\r\n\t *\r\n\t * @param {Boolean} cameraFlyDuration Camera flight duration in seconds.\r\n\t */\r\n\tsetCameraFlyDuration(cameraFlyDuration = 0.5) {\r\n\t\tthis._cameraFlyDuration = cameraFlyDuration;\r\n\t}\r\n\r\n\t/**\r\n\t * When flying the {@link Camera} to each new axis or diagonal, gets how long, in seconds, that the Camera takes to get there.\r\n\t *\r\n\t * Default is ````0.5````.\r\n\t *\r\n\t * @returns {Boolean} Camera flight duration in seconds.\r\n\t */\r\n\tgetCameraFlyDuration() {\r\n\t\treturn this._cameraFlyDuration;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the NavCube switches between perspective and orthographic projections in synchrony with\r\n\t * the {@link Camera}. When ````false````, the NavCube will always be rendered with perspective projection.\r\n\t *\r\n\t * @param {Boolean} synchProjection Set ````true```` to keep NavCube projection synchronized with {@link Camera#projection}.\r\n\t */\r\n\tsetSynchProjection(synchProjection = false) {\r\n\t\tthis._synchProjection = synchProjection;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the NavCube switches between perspective and orthographic projections in synchrony with\r\n\t * the {@link Camera}. When ````false````, the NavCube will always be rendered with perspective projection.\r\n\t *\r\n\t * @return {Boolean} True when NavCube projection is synchronized with {@link Camera#projection}.\r\n\t */\r\n\tgetSynchProjection() {\r\n\t\treturn this._synchProjection;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether the NavCube switches between project north and true north\r\n\t *\r\n\t * @param {Boolean} isProjectNorth Set ````true```` to use project north offset\r\n\t */\r\n\tsetIsProjectNorth(isProjectNorth = false) {\r\n\t\tthis._isProjectNorth = isProjectNorth;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the NavCube switches between project north and true north\r\n\t *\r\n\t * @return {Boolean} isProjectNorth when ````true```` - use project north offset\r\n\t */\r\n\tgetIsProjectNorth() {\r\n\t\treturn this._isProjectNorth;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the NavCube project north offset angle (used when {@link isProjectNorth} is ````true````\r\n\t *\r\n\t * @param {number} projectNorthOffsetAngle Set the vector offset for project north\r\n\t */\r\n\tsetProjectNorthOffsetAngle(projectNorthOffsetAngle) {\r\n\t\tthis._projectNorthOffsetAngle = projectNorthOffsetAngle;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the offset angle between project north and true north\r\n\t *\r\n\t * @return {number} projectNorthOffsetAngle\r\n\t */\r\n\tgetProjectNorthOffsetAngle() {\r\n\t\treturn this._projectNorthOffsetAngle;\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this NavCubePlugin.\r\n\t *\r\n\t * Does not destroy the canvas the NavCubePlugin was configured with.\r\n\t */\r\n\tdestroy() {\r\n\t\tif (this._navCubeCanvas) {\r\n\t\t\tthis.viewer.localeService.off(this._onUpdated);\r\n\t\t\tthis.viewer.camera.off(this._onCameraMatrix);\r\n\t\t\tthis.viewer.camera.off(this._onCameraWorldAxis);\r\n\t\t\tthis.viewer.camera.perspective.off(this._onCameraFOV);\r\n\t\t\tthis.viewer.camera.off(this._onCameraProjection);\r\n\r\n\t\t\tthis._navCubeCanvas.removeEventListener(\"mouseenter\", this._onMouseEnter);\r\n\t\t\tthis._navCubeCanvas.removeEventListener(\"mouseleave\", this._onMouseLeave);\r\n\t\t\tthis._navCubeCanvas.removeEventListener(\"mousedown\", this._onMouseDown);\r\n\r\n\t\t\tdocument.removeEventListener(\"mousemove\", this._onMouseMove);\r\n\t\t\tdocument.removeEventListener(\"mouseup\", this._onMouseUp);\r\n\r\n\t\t\tthis._navCubeCanvas = null;\r\n\t\t\tthis._cubeTextureCanvas.destroy();\r\n\t\t\tthis._cubeTextureCanvas = null;\r\n\r\n\t\t\tthis._onMouseEnter = null;\r\n\t\t\tthis._onMouseLeave = null;\r\n\t\t\tthis._onMouseDown = null;\r\n\t\t\tthis._onMouseMove = null;\r\n\t\t\tthis._onMouseUp = null;\r\n\t\t}\r\n\r\n\t\tthis._navCubeScene.destroy();\r\n\t\tthis._navCubeScene = null;\r\n\t\tthis._cubeMesh = null;\r\n\t\tthis._shadow = null;\r\n\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/NavCubePlugin/NavCubePlugin.js?");
|
|
1798
1798
|
|
|
1799
1799
|
/***/ }),
|
|
1800
1800
|
|
|
@@ -1914,7 +1914,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
1914
1914
|
\*****************************************************/
|
|
1915
1915
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1916
1916
|
|
|
1917
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Overview: () => (/* binding */ Overview)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./../../viewer/scene/lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _Plane_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Plane.js */ \"./src/plugins/SectionPlanesPlugin/Plane.js\");\n\r\n\r\n\r\n\r\n\r\n/**\r\n * @desc An interactive 3D overview for navigating the {@link SectionPlane}s created by its {@link SectionPlanesPlugin}.\r\n *\r\n * * Located at {@link SectionPlanesPlugin#overview}.\r\n * * Renders the overview on a separate canvas at a corner of the {@link Viewer}'s {@link Scene} {@link Canvas}.\r\n * * The overview shows a 3D plane object for each {@link SectionPlane} in the {@link Scene}.\r\n * * Click a plane object in the overview to toggle the visibility of a 3D gizmo to edit the position and orientation of its {@link SectionPlane}.\r\n *\r\n * @private\r\n */\r\nclass Overview {\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tconstructor(plugin, cfg) {\r\n\t\tif (!cfg.onHoverEnterPlane || !cfg.onHoverLeavePlane || !cfg.onClickedNothing || !cfg.onClickedPlane) {\r\n\t\t\tthrow \"Missing config(s): onHoverEnterPlane, onHoverLeavePlane, onClickedNothing || onClickedPlane\";\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * The {@link SectionPlanesPlugin} that owns this SectionPlanesOverview.\r\n\t\t *\r\n\t\t * @type {SectionPlanesPlugin}\r\n\t\t */\r\n\t\tthis.plugin = plugin;\r\n\r\n\t\tthis._viewer = plugin.viewer;\r\n\r\n\t\tthis._onHoverEnterPlane = cfg.onHoverEnterPlane;\r\n\t\tthis._onHoverLeavePlane = cfg.onHoverLeavePlane;\r\n\t\tthis._onClickedNothing = cfg.onClickedNothing;\r\n\t\tthis._onClickedPlane = cfg.onClickedPlane;\r\n\t\tthis._visible = true;\r\n\r\n\t\tthis._planes = {};\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Init canvas\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\tthis._canvas = cfg.overviewCanvas;\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Init scene\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\tthis._scene = new _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__.Scene(this._viewer, {\r\n\t\t\tcanvasId: this._canvas.id,\r\n\t\t\ttransparent: true\r\n\t\t});\r\n\t\tthis._scene.clearLights();\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__.DirLight(this._scene, {\r\n\t\t\tdir: [0.4, -0.4, 0.8],\r\n\t\t\tcolor: [0.8, 1.0, 1.0],\r\n\t\t\tintensity: 1.0,\r\n\t\t\tspace: \"view\"\r\n\t\t});\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__.DirLight(this._scene, {\r\n\t\t\tdir: [-0.8, -0.3, -0.4],\r\n\t\t\tcolor: [0.8, 0.8, 0.8],\r\n\t\t\tintensity: 1.0,\r\n\t\t\tspace: \"view\"\r\n\t\t});\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__.DirLight(this._scene, {\r\n\t\t\tdir: [0.8, -0.6, -0.8],\r\n\t\t\tcolor: [1.0, 1.0, 1.0],\r\n\t\t\tintensity: 1.0,\r\n\t\t\tspace: \"view\"\r\n\t\t});\r\n\r\n\t\tthis._scene.camera;\r\n\t\tthis._scene.camera.perspective.fov = 70;\r\n\r\n\t\tthis._zUp = false;\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Synchronize overview scene camera with viewer camera\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\t{\r\n\t\t\tconst camera = this._scene.camera;\r\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4c(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, 1, 0, 0);\r\n\t\t\tconst eyeLookVec = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst eyeLookVecOverview = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst upOverview = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\t\tthis._synchCamera = () => {\r\n\t\t\t\tconst eye = this._viewer.camera.eye;\r\n\t\t\t\tconst look = this._viewer.camera.look;\r\n\t\t\t\tconst up = this._viewer.camera.up;\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(eye, look, eyeLookVec)), 7);\r\n\t\t\t\tif (this._zUp) {\r\n\t\t\t\t\t// +Z up\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(matrix, eyeLookVec, eyeLookVecOverview);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(matrix, up, upOverview);\r\n\t\t\t\t\tcamera.look = [0, 0, 0];\r\n\t\t\t\t\tcamera.eye = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(matrix, eyeLookVec, eyeLookVecOverview);\r\n\t\t\t\t\tcamera.up = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint3(matrix, up, upOverview);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// +Y up\r\n\t\t\t\t\tcamera.look = [0, 0, 0];\r\n\t\t\t\t\tcamera.eye = eyeLookVec;\r\n\t\t\t\t\tcamera.up = up;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tthis._onViewerCameraMatrix = this._viewer.camera.on(\"matrix\", this._synchCamera);\r\n\r\n\t\tthis._onViewerCameraWorldAxis = this._viewer.camera.on(\"worldAxis\", this._synchCamera);\r\n\r\n\t\tthis._onViewerCameraFOV = this._viewer.camera.perspective.on(\"fov\", (fov) => {\r\n\t\t\tthis._scene.camera.perspective.fov = fov;\r\n\t\t});\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Bind overview canvas events\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\t{\r\n\t\t\tvar hoveredEntity = null;\r\n\r\n\t\t\tthis._onInputMouseMove = this._scene.input.on(\"mousemove\", (coords) => {\r\n\t\t\t\tconst hit = this._scene.pick({\r\n\t\t\t\t\tcanvasPos: coords\r\n\t\t\t\t});\r\n\t\t\t\tif (hit) {\r\n\t\t\t\t\tif (!hoveredEntity || hit.entity.id !== hoveredEntity.id) {\r\n\t\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\t\tconst plane = this._planes[hoveredEntity.id];\r\n\t\t\t\t\t\t\tif (plane) {\r\n\t\t\t\t\t\t\t\tthis._onHoverLeavePlane(hoveredEntity.id);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\thoveredEntity = hit.entity;\r\n\t\t\t\t\t\tconst plane = this._planes[hoveredEntity.id];\r\n\t\t\t\t\t\tif (plane) {\r\n\t\t\t\t\t\t\tthis._onHoverEnterPlane(hoveredEntity.id);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\tthis._onHoverLeavePlane(hoveredEntity.id);\r\n\t\t\t\t\t\thoveredEntity = null;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tthis._scene.canvas.canvas.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(this._onCanvasMouseUp = () => {\r\n\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\tconst plane = this._planes[hoveredEntity.id];\r\n\t\t\t\t\t\tif (plane) {\r\n\t\t\t\t\t\t\tthis._onClickedPlane(hoveredEntity.id);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis._onClickedNothing();\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._scene.canvas.canvas.addEventListener(\r\n\t\t\t\t\"mouseout\",\r\n\t\t\t\t(this._onCanvasMouseOut = () => {\r\n\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\tthis._onHoverLeavePlane(hoveredEntity.id);\r\n\t\t\t\t\t\thoveredEntity = null;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Configure overview\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\tthis.setVisible(cfg.overviewVisible);\r\n\t}\r\n\r\n\t/** Called by SectionPlanesPlugin#createSectionPlane()\r\n\t * @private\r\n\t */\r\n\taddSectionPlane(sectionPlane) {\r\n\t\tthis._planes[sectionPlane.id] = new _Plane_js__WEBPACK_IMPORTED_MODULE_3__.Plane(this, this._scene, sectionPlane);\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tsetPlaneHighlighted(id, highlighted) {\r\n\t\tconst plane = this._planes[id];\r\n\t\tif (plane) {\r\n\t\t\tplane.setHighlighted(highlighted);\r\n\t\t}\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tsetPlaneSelected(id, selected) {\r\n\t\tconst plane = this._planes[id];\r\n\t\tif (plane) {\r\n\t\t\tplane.setSelected(selected);\r\n\t\t}\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tremoveSectionPlane(sectionPlane) {\r\n\t\tconst plane = this._planes[sectionPlane.id];\r\n\t\tif (plane) {\r\n\t\t\tplane.destroy();\r\n\t\t\tdelete this._planes[sectionPlane.id];\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this SectionPlanesOverview is visible.\r\n\t *\r\n\t * @param {Boolean} visible Whether or not this SectionPlanesOverview is visible.\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tthis._visible = visible;\r\n\t\tthis._canvas.style.visibility = visible ? \"visible\" : \"hidden\";\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if this SectionPlanesOverview is visible.\r\n\t *\r\n\t * @return {Boolean} True when this SectionPlanesOverview is visible.\r\n\t */\r\n\tgetVisible() {\r\n\t\treturn this._visible;\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tdestroy() {\r\n\t\tthis._viewer.camera.off(this._onViewerCameraMatrix);\r\n\t\tthis._viewer.camera.off(this._onViewerCameraWorldAxis);\r\n\t\tthis._viewer.camera.perspective.off(this._onViewerCameraFOV);\r\n\r\n\t\tthis._scene.input.off(this._onInputMouseMove);\r\n\t\tthis._scene.canvas.canvas.removeEventListener(\"mouseup\", this._onCanvasMouseUp);\r\n\t\tthis._scene.canvas.canvas.removeEventListener(\"mouseout\", this._onCanvasMouseOut);\r\n\t\tthis._scene.destroy();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/Overview.js?");
|
|
1917
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Overview: () => (/* binding */ Overview)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/scene/Scene.js */ \"./src/viewer/scene/scene/Scene.js\");\n/* harmony import */ var _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./../../viewer/scene/lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _Plane_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Plane.js */ \"./src/plugins/SectionPlanesPlugin/Plane.js\");\n\r\n\r\n\r\n\r\n\r\n/**\r\n * @desc An interactive 3D overview for navigating the {@link SectionPlane}s created by its {@link SectionPlanesPlugin}.\r\n *\r\n * * Located at {@link SectionPlanesPlugin#overview}.\r\n * * Renders the overview on a separate canvas at a corner of the {@link Viewer}'s {@link Scene} {@link Canvas}.\r\n * * The overview shows a 3D plane object for each {@link SectionPlane} in the {@link Scene}.\r\n * * Click a plane object in the overview to toggle the visibility of a 3D gizmo to edit the position and orientation of its {@link SectionPlane}.\r\n *\r\n * @private\r\n */\r\nclass Overview {\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tconstructor(plugin, cfg) {\r\n\t\tif (!cfg.onHoverEnterPlane || !cfg.onHoverLeavePlane || !cfg.onClickedNothing || !cfg.onClickedPlane) {\r\n\t\t\tthrow \"Missing config(s): onHoverEnterPlane, onHoverLeavePlane, onClickedNothing || onClickedPlane\";\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * The {@link SectionPlanesPlugin} that owns this SectionPlanesOverview.\r\n\t\t *\r\n\t\t * @type {SectionPlanesPlugin}\r\n\t\t */\r\n\t\tthis.plugin = plugin;\r\n\r\n\t\tthis._viewer = plugin.viewer;\r\n\r\n\t\tthis._onHoverEnterPlane = cfg.onHoverEnterPlane;\r\n\t\tthis._onHoverLeavePlane = cfg.onHoverLeavePlane;\r\n\t\tthis._onClickedNothing = cfg.onClickedNothing;\r\n\t\tthis._onClickedPlane = cfg.onClickedPlane;\r\n\t\tthis._visible = true;\r\n\r\n\t\tthis._planes = {};\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Init canvas\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\tthis._canvas = cfg.overviewCanvas;\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Init scene\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\tthis._scene = new _viewer_scene_scene_Scene_js__WEBPACK_IMPORTED_MODULE_1__.Scene(this._viewer, {\r\n\t\t\tcanvasId: this._canvas.id,\r\n\t\t\ttransparent: true,\r\n\t\t\tspinnerElementId: \"overviewer_spinner\"\r\n\t\t});\r\n\t\tthis._scene.clearLights();\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__.DirLight(this._scene, {\r\n\t\t\tdir: [0.4, -0.4, 0.8],\r\n\t\t\tcolor: [0.8, 1.0, 1.0],\r\n\t\t\tintensity: 1.0,\r\n\t\t\tspace: \"view\"\r\n\t\t});\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__.DirLight(this._scene, {\r\n\t\t\tdir: [-0.8, -0.3, -0.4],\r\n\t\t\tcolor: [0.8, 0.8, 0.8],\r\n\t\t\tintensity: 1.0,\r\n\t\t\tspace: \"view\"\r\n\t\t});\r\n\t\tnew _viewer_scene_lights_DirLight_js__WEBPACK_IMPORTED_MODULE_2__.DirLight(this._scene, {\r\n\t\t\tdir: [0.8, -0.6, -0.8],\r\n\t\t\tcolor: [1.0, 1.0, 1.0],\r\n\t\t\tintensity: 1.0,\r\n\t\t\tspace: \"view\"\r\n\t\t});\r\n\r\n\t\tthis._scene.camera;\r\n\t\tthis._scene.camera.perspective.fov = 70;\r\n\r\n\t\tthis._zUp = false;\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Synchronize overview scene camera with viewer camera\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\t{\r\n\t\t\tconst camera = this._scene.camera;\r\n\t\t\tconst matrix = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.rotationMat4c(-90 * _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.DEGTORAD, 1, 0, 0);\r\n\t\t\tconst eyeLookVec = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst eyeLookVecOverview = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t\tconst upOverview = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\t\tthis._synchCamera = () => {\r\n\t\t\t\tconst eye = this._viewer.camera.eye;\r\n\t\t\t\tconst look = this._viewer.camera.look;\r\n\t\t\t\tconst up = this._viewer.camera.up;\r\n\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(eye, look, eyeLookVec)), 7);\r\n\t\t\t\tif (this._zUp) {\r\n\t\t\t\t\t// +Z up\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(matrix, eyeLookVec, eyeLookVecOverview);\r\n\t\t\t\t\t_viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(matrix, up, upOverview);\r\n\t\t\t\t\tcamera.look = [0, 0, 0];\r\n\t\t\t\t\tcamera.eye = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(matrix, eyeLookVec, eyeLookVecOverview);\r\n\t\t\t\t\tcamera.up = _viewer_scene_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint3(matrix, up, upOverview);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// +Y up\r\n\t\t\t\t\tcamera.look = [0, 0, 0];\r\n\t\t\t\t\tcamera.eye = eyeLookVec;\r\n\t\t\t\t\tcamera.up = up;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tthis._onViewerCameraMatrix = this._viewer.camera.on(\"matrix\", this._synchCamera);\r\n\r\n\t\tthis._onViewerCameraWorldAxis = this._viewer.camera.on(\"worldAxis\", this._synchCamera);\r\n\r\n\t\tthis._onViewerCameraFOV = this._viewer.camera.perspective.on(\"fov\", (fov) => {\r\n\t\t\tthis._scene.camera.perspective.fov = fov;\r\n\t\t});\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Bind overview canvas events\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\t{\r\n\t\t\tvar hoveredEntity = null;\r\n\r\n\t\t\tthis._onInputMouseMove = this._scene.input.on(\"mousemove\", (coords) => {\r\n\t\t\t\tconst hit = this._scene.pick({\r\n\t\t\t\t\tcanvasPos: coords\r\n\t\t\t\t});\r\n\t\t\t\tif (hit) {\r\n\t\t\t\t\tif (!hoveredEntity || hit.entity.id !== hoveredEntity.id) {\r\n\t\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\t\tconst plane = this._planes[hoveredEntity.id];\r\n\t\t\t\t\t\t\tif (plane) {\r\n\t\t\t\t\t\t\t\tthis._onHoverLeavePlane(hoveredEntity.id);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\thoveredEntity = hit.entity;\r\n\t\t\t\t\t\tconst plane = this._planes[hoveredEntity.id];\r\n\t\t\t\t\t\tif (plane) {\r\n\t\t\t\t\t\t\tthis._onHoverEnterPlane(hoveredEntity.id);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\tthis._onHoverLeavePlane(hoveredEntity.id);\r\n\t\t\t\t\t\thoveredEntity = null;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tthis._scene.canvas.canvas.addEventListener(\r\n\t\t\t\t\"mouseup\",\r\n\t\t\t\t(this._onCanvasMouseUp = () => {\r\n\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\tconst plane = this._planes[hoveredEntity.id];\r\n\t\t\t\t\t\tif (plane) {\r\n\t\t\t\t\t\t\tthis._onClickedPlane(hoveredEntity.id);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis._onClickedNothing();\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\r\n\t\t\tthis._scene.canvas.canvas.addEventListener(\r\n\t\t\t\t\"mouseout\",\r\n\t\t\t\t(this._onCanvasMouseOut = () => {\r\n\t\t\t\t\tif (hoveredEntity) {\r\n\t\t\t\t\t\tthis._onHoverLeavePlane(hoveredEntity.id);\r\n\t\t\t\t\t\thoveredEntity = null;\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\t\t// Configure overview\r\n\t\t//--------------------------------------------------------------------------------------------------------------\r\n\r\n\t\tthis.setVisible(cfg.overviewVisible);\r\n\t}\r\n\r\n\t/** Called by SectionPlanesPlugin#createSectionPlane()\r\n\t * @private\r\n\t */\r\n\taddSectionPlane(sectionPlane) {\r\n\t\tthis._planes[sectionPlane.id] = new _Plane_js__WEBPACK_IMPORTED_MODULE_3__.Plane(this, this._scene, sectionPlane);\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tsetPlaneHighlighted(id, highlighted) {\r\n\t\tconst plane = this._planes[id];\r\n\t\tif (plane) {\r\n\t\t\tplane.setHighlighted(highlighted);\r\n\t\t}\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tsetPlaneSelected(id, selected) {\r\n\t\tconst plane = this._planes[id];\r\n\t\tif (plane) {\r\n\t\t\tplane.setSelected(selected);\r\n\t\t}\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tremoveSectionPlane(sectionPlane) {\r\n\t\tconst plane = this._planes[sectionPlane.id];\r\n\t\tif (plane) {\r\n\t\t\tplane.destroy();\r\n\t\t\tdelete this._planes[sectionPlane.id];\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if this SectionPlanesOverview is visible.\r\n\t *\r\n\t * @param {Boolean} visible Whether or not this SectionPlanesOverview is visible.\r\n\t */\r\n\tsetVisible(visible = true) {\r\n\t\tthis._visible = visible;\r\n\t\tthis._canvas.style.visibility = visible ? \"visible\" : \"hidden\";\r\n\t}\r\n\r\n\t/**\r\n\t * Gets if this SectionPlanesOverview is visible.\r\n\t *\r\n\t * @return {Boolean} True when this SectionPlanesOverview is visible.\r\n\t */\r\n\tgetVisible() {\r\n\t\treturn this._visible;\r\n\t}\r\n\r\n\t/** @private\r\n\t */\r\n\tdestroy() {\r\n\t\tthis._viewer.camera.off(this._onViewerCameraMatrix);\r\n\t\tthis._viewer.camera.off(this._onViewerCameraWorldAxis);\r\n\t\tthis._viewer.camera.perspective.off(this._onViewerCameraFOV);\r\n\r\n\t\tthis._scene.input.off(this._onInputMouseMove);\r\n\t\tthis._scene.canvas.canvas.removeEventListener(\"mouseup\", this._onCanvasMouseUp);\r\n\t\tthis._scene.canvas.canvas.removeEventListener(\"mouseout\", this._onCanvasMouseOut);\r\n\t\tthis._scene.destroy();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/SectionPlanesPlugin/Overview.js?");
|
|
1918
1918
|
|
|
1919
1919
|
/***/ }),
|
|
1920
1920
|
|
|
@@ -2024,7 +2024,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2024
2024
|
\******************************************************/
|
|
2025
2025
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2026
2026
|
|
|
2027
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TreeViewPlugin: () => (/* binding */ TreeViewPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _RenderService_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RenderService.js */ \"./src/plugins/TreeViewPlugin/RenderService.js\");\n\r\n\r\n\r\nconst treeViews = [];\r\n\r\n/**\r\n * @desc A {@link Viewer} plugin that provides an HTML tree view to navigate the IFC elements in models.\r\n * <br>\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XKT_WestRiverSideHospital\" style=\"border: 1px solid black;\"><img src=\"http://xeokit.io/img/docs/TreeViewPlugin/TreeViewPlugin.png\"></a>\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XKT_WestRiverSideHospital)]\r\n *\r\n * ## Overview\r\n *\r\n * * A fast HTML tree view, with zero external dependencies, that works with huge numbers of objects.\r\n * * Each tree node has a checkbox to control the visibility of its object.\r\n * * Has three hierarchy modes: \"containment\", \"types\" and \"storeys\".\r\n * * Automatically contains all models (that have metadata) that are currently in the {@link Scene}.\r\n * * Sorts tree nodes by default - spatially, from top-to-bottom for ````IfcBuildingStorey```` nodes, and alphanumerically for other nodes.\r\n * * Allows custom CSS styling.\r\n * * Use {@link ContextMenu} to create a context menu for the tree nodes.\r\n *\r\n * ## Credits\r\n *\r\n * TreeViewPlugin is based on techniques described in [*Super Fast Tree View in JavaScript*](https://chrissmith.xyz/super-fast-tree-view-in-javascript/) by [Chris Smith](https://twitter.com/chris22smith).\r\n *\r\n * ## Usage\r\n *\r\n * In the example below, we'll add a TreeViewPlugin which, by default, will automatically show the structural\r\n * hierarchy of the IFC elements in each model we load.\r\n *\r\n * Then we'll use an {@link XTCLoaderPlugin} to load the Schependomlaan model from an\r\n * [.xtc file](https://github.com/xeokit/xeokit-sdk/tree/master/examples/models/xtc/schependomlaan).\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XKT_Schependomlaan)]\r\n *\r\n * ````javascript\r\n * import {Viewer, XTCLoaderPlugin, TreeViewPlugin} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\")\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n * ````\r\n *\r\n * ## Manually Adding Models\r\n *\r\n * Instead of adding models automatically, we can control which models appear in our TreeViewPlugin by adding them manually.\r\n *\r\n * In the next example, we'll configure the TreeViewPlugin to not add models automatically. Then, once the model\r\n * has loaded, we'll add it manually using {@link TreeViewPlugin#addModel}.\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * autoAddModels: false // <<---------------- Don't auto-add models\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n *\r\n * model.on(\"loaded\", () => {\r\n * treeView.addModel(model.id);\r\n * });\r\n * ````\r\n *\r\n * Adding models manually also allows us to set some options for the model. For example, the ````rootName```` option allows us to provide a custom name for\r\n * the root node, which is sometimes desirable when the model's \"IfcProject\" element's name is not suitable:\r\n *\r\n * ````javascript\r\n * model.on(\"loaded\", () => {\r\n * treeView.addModel(model.id, {\r\n * rootName: \"Schependomlaan Model\"\r\n * });\r\n * });\r\n * ````\r\n *\r\n * ## Initially Expanding the Hierarchy\r\n *\r\n * We can also configure TreeViewPlugin to initially expand each model's nodes to a given depth.\r\n *\r\n * Let's automatically expand the first three nodes from the root, for every model added:\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * autoExpandDepth: 3\r\n * });\r\n * ````\r\n *\r\n * ## Showing a Node by ID\r\n *\r\n * We can show a given node using its ID. This causes the TreeViewPlugin to collapse, then expand and scroll the node into view, then highlight the node.\r\n *\r\n * See the documentation for the {@link TreeViewPlugin#showNode} method for more information, including how to define a custom highlighted appearance for the node using CSS.\r\n *\r\n * Let's make the TreeViewPlugin show the node corresponding to whatever object {@link Entity} that we pick:\r\n *\r\n * ````javascript\r\n * viewer.cameraControl.on(\"picked\", function (e) {\r\n * var objectId = e.entity.id;\r\n * treeView.showNode(objectId);\r\n * });\r\n * ````\r\n *\r\n * This will de-highlight any node that was previously shown by this method.\r\n *\r\n * Note that this method only works if the picked {@link Entity} is an object that belongs to a model that's represented in the TreeViewPlugin.\r\n *\r\n * ## Customizing Appearance\r\n *\r\n * We can customize the appearance of our TreeViewPlugin by defining custom CSS for its HTML\r\n * elements. See our example's [source code](https://github.com/xeokit/xeokit-sdk/blob/master/examples/BIMOffline_XKT_Schependomlaan.html)\r\n * for an example of custom CSS rules.\r\n *\r\n * ## Model Hierarchies\r\n *\r\n * TreeViewPlugin has three hierarchies for organizing its nodes:\r\n *\r\n * * \"containment\" - organizes the tree nodes to indicate the containment hierarchy of the {@link MetaObject}s.\r\n * * \"types\" - groups nodes by their IFC types.\r\n * * \"storeys\" - groups nodes within their ````IfcBuildingStoreys````, and sub-groups them by their IFC types.\r\n *\r\n * <br>\r\n * The table below shows what the hierarchies look like:\r\n * <br>\r\n *\r\n * | 1. Containment Hierarchy | 2. Types Hierarchy | 3. Storeys Hierarchy |\r\n * |---|---|---|\r\n * | <img src=\"http://xeokit.io/img/docs/TreeViewPlugin/structureMode.png\"> | <img src=\"http://xeokit.io/img/docs/TreeViewPlugin/typesMode.png\"> | <img src=\"http://xeokit.io/img/docs/TreeViewPlugin/storeysMode.png\"> |\r\n * <br>\r\n *\r\n * Let's create a TreeViewPlugin that groups nodes by their building stories and IFC types:\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * hierarchy: \"stories\"\r\n * });\r\n * ````\r\n *\r\n * ## Sorting Nodes\r\n *\r\n * TreeViewPlugin sorts its tree nodes by default. For a \"storeys\" hierarchy, it orders ````IfcBuildingStorey```` nodes\r\n * spatially, with the node for the highest story at the top, down to the lowest at the bottom.\r\n *\r\n * For all the hierarchy types (\"containment\", \"classes\" and \"storeys\"), TreeViewPlugin sorts the other node types\r\n * alphanumerically on their titles.\r\n *\r\n * If for some reason you need to prevent sorting, create your TreeViewPlugin with the option disabled, like so:\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * hierarchy: \"stories\",\r\n * sortNodes: false // <<------ Disable node sorting\r\n * });\r\n * ````\r\n *\r\n * Note that, for all hierarchy modes, node sorting is only done for each model at the time that it is added to the TreeViewPlugin, and will not\r\n * update dynamically if we later transform the {@link Entity}s corresponding to the nodes.\r\n *\r\n * ## Pruning empty nodes\r\n *\r\n * Sometimes a model contains subtrees of objects that don't have any geometry. These are models whose\r\n * {@link MetaModel} contains trees of {@link MetaObject}s that don't have any {@link Entity}s in the {@link Scene}.\r\n *\r\n * For these models, the tree view would contain nodes that don't do anything in the Scene when we interact with them,\r\n * which is undesirable.\r\n *\r\n * By default, TreeViewPlugin will not create nodes for those objects. However, we can override that behaviour if we want\r\n * to have nodes for those objects (perhaps for debugging the model):\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * hierarchy: \"stories\",\r\n * pruneEmptyNodes: false // <<------ Create nodes for object subtrees without geometry\r\n * });\r\n * ````\r\n *\r\n * ## Context Menu\r\n *\r\n * TreeViewPlugin fires a \"contextmenu\" event whenever we right-click on a tree node.\r\n *\r\n * The event contains:\r\n *\r\n * * ````event```` - the original [contextmenu](https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event) [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)\r\n * * ````viewer```` - the {@link Viewer}\r\n * * ````treeViewPlugin```` - the TreeViewPlugin\r\n * * ````treeViewNode```` - the {@link TreeViewNode} representing the tree node\r\n *<br><br>\r\n *\r\n * Let's use {@link ContextMenu} to show a simple context menu for the node we clicked.\r\n *\r\n * [[Run an example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)]\r\n *\r\n * ````javascript\r\n * import {ContextMenu} from \"../src/extras/ContextMenu/ContextMenu.js\";\r\n *\r\n * const treeViewContextMenu = new ContextMenu({\r\n * items: [\r\n * [\r\n * [\r\n * {\r\n * title: \"Hide\",\r\n * doAction: function (context) {\r\n * context.treeViewPlugin.withNodeTree(context.treeViewNode, (treeViewNode) => {\r\n * if (treeViewNode.objectId) {\r\n * const entity = context.viewer.scene.objects[treeViewNode.objectId];\r\n * if (entity) {\r\n * entity.visible = false;\r\n * }\r\n * }\r\n * });\r\n * }\r\n * },\r\n * {\r\n * title: \"Hide all\",\r\n * doAction: function (context) {\r\n * context.viewer.scene.setObjectsVisible(context.viewer.scene.visibleObjectIds, false);\r\n * }\r\n * }\r\n * ],\r\n * [\r\n * {\r\n * title: \"Show\",\r\n * doAction: function (context) {\r\n * context.treeViewPlugin.withNodeTree(context.treeViewNode, (treeViewNode) => {\r\n * if (treeViewNode.objectId) {\r\n * const entity = context.viewer.scene.objects[treeViewNode.objectId];\r\n * if (entity) {\r\n * entity.visible = true;\r\n * entity.xrayed = false;\r\n * entity.selected = false;\r\n * }\r\n * }\r\n * });\r\n * }\r\n * },\r\n * {\r\n * title: \"Show all\",\r\n * doAction: function (context) {\r\n * const scene = context.viewer.scene;\r\n * scene.setObjectsVisible(scene.objectIds, true);\r\n * scene.setObjectsXRayed(scene.xrayedObjectIds, false);\r\n * scene.setObjectsSelected(scene.selectedObjectIds, false);\r\n * }\r\n * }\r\n * ]\r\n * ]\r\n * ]\r\n * });\r\n *\r\n * treeView.on(\"contextmenu\", (e) => {\r\n *\r\n * const event = e.event; // MouseEvent\r\n * const viewer = e.viewer; // Viewer\r\n * const treeViewPlugin = e.treeViewPlugin; // TreeViewPlugin\r\n * const treeViewNode = e.treeViewNode; // TreeViewNode\r\n *\r\n * treeViewContextMenu.show(e.event.pageX, e.event.pageY);\r\n *\r\n * treeViewContextMenu.context = {\r\n * viewer: e.viewer,\r\n * treeViewPlugin: e.treeViewPlugin,\r\n * treeViewNode: e.treeViewNode\r\n * };\r\n * });\r\n * ````\r\n *\r\n * ## Clicking Node Titles\r\n *\r\n * TreeViewPlugin fires a \"nodeTitleClicked\" event whenever we left-click on a tree node.\r\n *\r\n * Like the \"contextmenu\" event, this event contains:\r\n *\r\n * * ````event```` - the original [click](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)\r\n * * ````viewer```` - the {@link Viewer}\r\n * * ````treeViewPlugin```` - the TreeViewPlugin\r\n * * ````treeViewNode```` - the {@link TreeViewNode} representing the tree node\r\n *<br><br>\r\n *\r\n * Let's register a callback to isolate and fit-to-view the {@link Entity}(s) represented by the node. This callback is\r\n * going to X-ray all the other Entitys, fly the camera to fit the Entity(s) for the clicked node, then hide the other Entitys.\r\n *\r\n * [[Run an example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)]\r\n *\r\n * ````javascript\r\n * treeView.on(\"nodeTitleClicked\", (e) => {\r\n * const scene = viewer.scene;\r\n * const objectIds = [];\r\n * e.treeViewPlugin.withNodeTree(e.treeViewNode, (treeViewNode) => {\r\n * if (treeViewNode.objectId) {\r\n * objectIds.push(treeViewNode.objectId);\r\n * }\r\n * });\r\n * scene.setObjectsXRayed(scene.objectIds, true);\r\n * scene.setObjectsVisible(scene.objectIds, true);\r\n * scene.setObjectsXRayed(objectIds, false);\r\n * viewer.cameraFlight.flyTo({\r\n * aabb: scene.getAABB(objectIds),\r\n * duration: 0.5\r\n * }, () => {\r\n * setTimeout(function () {\r\n * scene.setObjectsVisible(scene.xrayedObjectIds, false);\r\n * scene.setObjectsXRayed(scene.xrayedObjectIds, false);\r\n * }, 500);\r\n * });\r\n * });\r\n * ````\r\n *\r\n * To make the cursor change to a pointer when we hover over the node titles, and also to make the titles change to blue, we'll also define this CSS for the ````<span>```` elements\r\n * that represent the titles of our TreeViewPlugin nodes:\r\n *\r\n * ````css\r\n * #treeViewContainer ul li span:hover {\r\n * color: blue;\r\n * cursor: pointer;\r\n * }\r\n * ````\r\n *\r\n * @class TreeViewPlugin\r\n */\r\nclass TreeViewPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t *\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {*} cfg Plugin configuration.\r\n\t * @param {String} [cfg.containerElementId] ID of an existing HTML element to contain the TreeViewPlugin - either this or containerElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLElement} cfg.containerElement DOM element to contain the TreeViewPlugin.\r\n\t * @param {Boolean} [cfg.autoAddModels=true] When ````true```` (default), will automatically add each model as it's created. Set this ````false```` if you want to manually add models using {@link TreeViewPlugin#addModel} instead.\r\n\t * @param {Number} [cfg.autoExpandDepth] Optional depth to which to initially expand the tree.\r\n\t * @param {String} [cfg.hierarchy=\"containment\"] How to organize the tree nodes: \"containment\", \"storeys\" or \"types\". See the class documentation for details.\r\n\t * @param {Boolean} [cfg.sortNodes=true] When true, will sort the children of each node. For a \"storeys\" hierarchy, the\r\n\t * ````IfcBuildingStorey```` nodes will be ordered spatially, from the highest storey down to the lowest, on the\r\n\t * vertical World axis. For all hierarchy types, other node types will be ordered in the ascending alphanumeric order of their titles.\r\n\t * @param {Boolean} [cfg.pruneEmptyNodes=true] When true, will not contain nodes that don't have content in the {@link Scene}. These are nodes whose {@link MetaObject}s don't have {@link Entity}s.\r\n\t * @param {RenderService} [cfg.renderService] Optional {@link RenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"TreeViewPlugin\", viewer);\r\n\r\n\t\t/**\r\n\t\t * Contains messages for any errors found while last rebuilding this TreeView.\r\n\t\t * @type {String[]}\r\n\t\t */\r\n\t\tthis.errors = [];\r\n\r\n\t\t/**\r\n\t\t * True if errors were found generating this TreeView.\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.valid = true;\r\n\r\n\t\t// const containerElement =\r\n\t\t// cfg.containerElement || document.getElementById(cfg.containerElementId);\r\n\r\n\t\t// if (!(containerElement instanceof HTMLElement)) {\r\n\t\t// this.error(\r\n\t\t// \"Mandatory config expected: valid containerElementId or containerElement\"\r\n\t\t// );\r\n\t\t// return;\r\n\t\t// }\r\n\r\n\t\tfor (let i = 0; ; i++) {\r\n\t\t\tif (!treeViews[i]) {\r\n\t\t\t\ttreeViews[i] = this;\r\n\t\t\t\tthis._index = i;\r\n\t\t\t\tthis._id = `tree-${i}`;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// this._containerElement = containerElement;\r\n\t\tthis._metaModels = {};\r\n\t\tthis._autoAddModels = cfg.autoAddModels !== false;\r\n\t\tthis._autoExpandDepth = cfg.autoExpandDepth || 0;\r\n\t\tthis._sortNodes = cfg.sortNodes !== false;\r\n\t\tthis._viewer = viewer;\r\n\t\tthis._rootElement = null;\r\n\t\tthis._muteSceneEvents = false;\r\n\t\tthis._muteTreeEvents = false;\r\n\t\tthis._rootNodes = [];\r\n\t\tthis._objectNodes = {}; // Object ID -> Node\r\n\t\tthis._nodeNodes = {}; // Node ID -> Node\r\n\t\tthis._rootNames = {}; // Node ID -> Root name\r\n\t\tthis._sortNodes = cfg.sortNodes;\r\n\t\tthis._pruneEmptyNodes = cfg.pruneEmptyNodes;\r\n\t\tthis._showListItemElementId = null;\r\n\t\t// this._renderService = cfg.renderService || new RenderService();\r\n\r\n\t\t// if (!this._renderService) {\r\n\t\t// throw new Error('TreeViewPlugin: no render service set');\r\n\t\t// }\r\n\r\n\t\t// this._containerElement.oncontextmenu = (e) => {\r\n\t\t// e.preventDefault();\r\n\t\t// };\r\n\r\n\t\tthis._onObjectVisibility = this._viewer.scene.on(\"objectVisibility\", (entity) => {\r\n\t\t\tif (this._muteSceneEvents) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst objectId = entity.id;\r\n\t\t\tconst node = this._objectNodes[objectId];\r\n\t\t\tif (!node) {\r\n\t\t\t\treturn; // Not in this tree\r\n\t\t\t}\r\n\t\t\tconst visible = entity.visible;\r\n\t\t\tconst updated = visible !== node.checked;\r\n\t\t\tif (!updated) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis._muteTreeEvents = true;\r\n\t\t\tnode.checked = visible;\r\n\t\t\tif (visible) {\r\n\t\t\t\tnode.numVisibleEntities++;\r\n\t\t\t} else {\r\n\t\t\t\tnode.numVisibleEntities--;\r\n\t\t\t}\r\n\r\n\t\t\t// this._renderService.setCheckbox(node.nodeId, visible);\r\n\r\n\t\t\tlet parent = node.parent;\r\n\t\t\twhile (parent) {\r\n\t\t\t\tparent.checked = visible;\r\n\t\t\t\tif (visible) {\r\n\t\t\t\t\tparent.numVisibleEntities++;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tparent.numVisibleEntities--;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// this._renderService.setCheckbox(parent.nodeId, (parent.numVisibleEntities > 0));\r\n\r\n\t\t\t\tparent = parent.parent;\r\n\t\t\t}\r\n\r\n\t\t\tthis._muteTreeEvents = false;\r\n\t\t});\r\n\r\n\t\tthis._onObjectXrayed = this._viewer.scene.on(\"objectXRayed\", (entity) => {\r\n\t\t\tif (this._muteSceneEvents) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst objectId = entity.id;\r\n\t\t\tconst node = this._objectNodes[objectId];\r\n\t\t\tif (!node) {\r\n\t\t\t\treturn; // Not in this tree\r\n\t\t\t}\r\n\t\t\tthis._muteTreeEvents = true;\r\n\t\t\tconst xrayed = entity.xrayed;\r\n\t\t\tconst updated = xrayed !== node.xrayed;\r\n\t\t\tif (!updated) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tnode.xrayed = xrayed;\r\n\r\n\t\t\t// this._renderService.setXRayed(node.nodeId, xrayed);\r\n\t\t\tthis._muteTreeEvents = false;\r\n\t\t});\r\n\r\n\t\t// this._switchExpandHandler = (event) => {\r\n\t\t// this.switchExpandHandler(event)\r\n\t\t// };\r\n\r\n\t\t// this._switchCollapseHandler = (event) => {\r\n\t\t// this.switchCollapseHandler(event)\r\n\t\t// };\r\n\r\n\t\t// this._checkboxChangeHandler = (event) => {\r\n\t\t// this.checkboxChangeHandler(event)\r\n\t\t// };\r\n\r\n\t\tthis._hierarchy = cfg.hierarchy || \"containment\";\r\n\t\tthis._autoExpandDepth = cfg.autoExpandDepth || 0;\r\n\r\n\t\tif (this._autoAddModels) {\r\n\t\t\tconst modelIds = Object.keys(this.viewer.metaScene.metaModels);\r\n\t\t\tfor (let i = 0, len = modelIds.length; i < len; i++) {\r\n\t\t\t\tconst modelId = modelIds[i];\r\n\t\t\t\tconst metaModel = this.viewer.metaScene.metaModels[modelId];\r\n\t\t\t\tif (metaModel.finalized) {\r\n\t\t\t\t\tthis.addModel(modelId);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tthis.viewer.scene.on(\"modelLoaded\", (modelId) => {\r\n\t\t\t\tif (this.viewer.metaScene.metaModels[modelId]) {\r\n\t\t\t\t\tthis.addModel(modelId);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tthis.hierarchy = cfg.hierarchy;\r\n\t}\r\n\r\n\t//展开点击事件\r\n\tswitchExpandHandler(event) {\r\n\t\tevent.preventDefault();\r\n\t\tevent.stopPropagation();\r\n\t\tconst switchElement = event.target;\r\n\t\t// this._expandSwitchElement(switchElement);\r\n\t\tthis.fire(\"ExpandHandler\", event);\r\n\t}\r\n\r\n\t//收起点击事件\r\n\tswitchCollapseHandler(event) {\r\n\t\tevent.preventDefault();\r\n\t\tevent.stopPropagation();\r\n\t\t// const switchElement = event.target;\r\n\t\t// this._collapseSwitchElement(switchElement);\r\n\t\tthis.fire(\"CollapseHandler\", event);\r\n\t}\r\n\r\n\t//勾选框点击事件\r\n\tcheckboxChangeHandler(event) {\r\n\t\tthis.fire(\"checkBoxChanged\", event);\r\n\t\tif (this._muteTreeEvents) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._muteSceneEvents = true;\r\n\t\tconst checkbox = event.target; //勾选框html对象\r\n\t\tconst visible = checkbox.checked; //获取勾选状态\r\n\t\tconst nodeId = checkbox.id.replace(\"checkbox-\", \"\"); //获取勾选框对应节点id\r\n\t\tconst checkedNode = this._nodeNodes[nodeId];\r\n\t\tconst objects = this._viewer.scene.objects;\r\n\t\tlet numUpdated = 0;\r\n\r\n\t\tthis._withNodeTree(checkedNode, (node) => {\r\n\t\t\tconst objectId = node.objectId;\r\n\t\t\tconst entity = objects[objectId];\r\n\t\t\tconst isLeaf = node.children.length === 0;\r\n\t\t\tnode.numVisibleEntities = visible ? node.numEntities : 0;\r\n\t\t\tif (isLeaf && visible !== node.checked) {\r\n\t\t\t\tnumUpdated++;\r\n\t\t\t}\r\n\t\t\tnode.checked = visible;\r\n\r\n\t\t\tsetCheckbox(node.nodeId, visible);\r\n\r\n\t\t\tif (entity) {\r\n\t\t\t\tentity.visible = visible;\r\n\t\t\t}\r\n\r\n\t\t\tfunction setCheckbox(nodeId, checked) {\r\n\t\t\t\tconst checkbox = document.getElementById(`checkbox-${nodeId}`);\r\n\t\t\t\tif (checkbox) {\r\n\t\t\t\t\tif (checked !== checkbox.checked) {\r\n\t\t\t\t\t\tcheckbox.checked = checked;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tlet parent = checkedNode.parent;\r\n\t\twhile (parent) {\r\n\t\t\tparent.checked = visible;\r\n\r\n\t\t\tif (visible) {\r\n\t\t\t\tparent.numVisibleEntities += numUpdated;\r\n\t\t\t} else {\r\n\t\t\t\tparent.numVisibleEntities -= numUpdated;\r\n\t\t\t}\r\n\r\n\t\t\t// this._renderService.setCheckbox(parent.nodeId, (parent.numVisibleEntities > 0));\r\n\t\t\tsetCheckbox(parent.nodeId, parent.numVisibleEntities > 0);\r\n\t\t\tparent = parent.parent;\r\n\t\t}\r\n\t\tthis._muteSceneEvents = false;\r\n\r\n\t\tfunction setCheckbox(nodeId, checked) {\r\n\t\t\tconst checkbox = document.getElementById(`checkbox-${nodeId}`);\r\n\t\t\tif (checkbox) {\r\n\t\t\t\tif (checked !== checkbox.checked) {\r\n\t\t\t\t\tcheckbox.checked = checked;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets how the nodes are organized within this tree view.\r\n\t *\r\n\t * Accepted values are:\r\n\t *\r\n\t * * \"containment\" - organizes the nodes to indicate the containment hierarchy of the IFC objects.\r\n\t * * \"types\" - groups the nodes within their IFC types.\r\n\t * * \"storeys\" - groups the nodes within ````IfcBuildingStoreys```` and sub-groups them by their IFC types.\r\n\t *\r\n\t * <br>\r\n\t * This can be updated dynamically.\r\n\t *\r\n\t * Default value is \"containment\".\r\n\t *\r\n\t * @type {String}\r\n\t */\r\n\tset hierarchy(hierarchy) {\r\n\t\thierarchy = hierarchy || \"containment\";\r\n\t\tif (hierarchy !== \"containment\" && hierarchy !== \"storeys\" && hierarchy !== \"types\") {\r\n\t\t\tthis.error(\"Unsupported value for `hierarchy' - defaulting to 'containment'\");\r\n\t\t\thierarchy = \"containment\";\r\n\t\t}\r\n\t\tif (this._hierarchy === hierarchy) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._hierarchy = hierarchy;\r\n\t\tthis._createNodes();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets how the nodes are organized within this tree view.\r\n\t *\r\n\t * @type {String}\r\n\t */\r\n\tget hierarchy() {\r\n\t\treturn this._hierarchy;\r\n\t}\r\n\r\n\t/**\r\n\t * get _muteTreeEvents\r\n\t * @type {boolean}\r\n\t */\r\n\tget muteTreeEvents() {\r\n\t\treturn this._muteTreeEvents;\r\n\t}\r\n\r\n\t/**\r\n\t * set _muteTreeEvents\r\n\t */\r\n\tset muteTreeEvents(mute) {\r\n\t\tthis._muteTreeEvents = mute;\r\n\t}\r\n\r\n\t/**\r\n\t * 获取nodeNodes\r\n\t */\r\n\tget nodeNodes() {\r\n\t\treturn this._nodeNodes;\r\n\t}\r\n\r\n\t//创建根节点tree---------11111111111111111\r\n\t_createNodes() {\r\n\t\tif (this._rootElement) {\r\n\t\t\tthis._rootElement.parentNode.removeChild(this._rootElement);\r\n\t\t\tthis._rootElement = null;\r\n\t\t}\r\n\r\n\t\tthis._rootNodes = [];\r\n\t\tthis._objectNodes = {};\r\n\t\tthis._nodeNodes = {};\r\n\t\tthis._validate();\r\n\t\tif (this.valid || this._hierarchy !== \"storeys\") {\r\n\t\t\tthis._createEnabledNodes();\r\n\t\t} else {\r\n\t\t\t// this._createDisabledNodes();\r\n\t\t}\r\n\t}\r\n\r\n\t//创建节点tree----------222222222222222222\r\n\t_createEnabledNodes() {\r\n\t\tif (this._pruneEmptyNodes) {\r\n\t\t\tthis._findEmptyNodes();\r\n\t\t}\r\n\t\tswitch (this._hierarchy) {\r\n\t\t\tcase \"storeys\":\r\n\t\t\t\tthis._createStoreysNodes();\r\n\t\t\t\tif (this._rootNodes.length === 0) {\r\n\t\t\t\t\tthis.error(\"Failed to build storeys hierarchy\");\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"types\":\r\n\t\t\t\tthis._createTypesNodes();\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"containment\":\r\n\t\t\tdefault:\r\n\t\t\t\tthis._createContainmentNodes();\r\n\t\t}\r\n\t\tif (this._sortNodes) {\r\n\t\t\tthis._doSortNodes();\r\n\t\t}\r\n\t\tthis._synchNodesToEntities(); //同步scene和metaScene中的内容\r\n\r\n\t\tthis.fire(\"nodeNodes_Created\", this._nodeNodes);\r\n\t\tthis.fire(\"rootNodes_Created\", this._rootNodes);\r\n\t\tthis.fire(\"objectNodes_Created\", this._objectNodes);\r\n\r\n\t\t// this._createTrees(); //创建html tree\r\n\t\t// this.expandToDepth(this._autoExpandDepth); //展开几层与否\r\n\t}\r\n\r\n\t// //创建\r\n\t// _createDisabledNodes() {\r\n\t// const rootNode = this._renderService.createRootNode();\r\n\t// this._rootElement = rootNode;\r\n\t// this._containerElement.appendChild(rootNode);\r\n\r\n\t// const rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\r\n\t// for (let objectId in rootMetaObjects) {\r\n\t// const rootMetaObject = rootMetaObjects[objectId];\r\n\t// const metaObjectType = rootMetaObject.type;\r\n\t// const metaObjectName = rootMetaObject.name;\r\n\t// const rootName =\r\n\t// metaObjectName &&\r\n\t// metaObjectName !== \"\" &&\r\n\t// metaObjectName !== \"Undefined\" &&\r\n\t// metaObjectName !== \"Default\"\r\n\t// ? metaObjectName\r\n\t// : metaObjectType;\r\n\r\n\t// // const childNode = this._renderService.createDisabledNodeElement(rootName);\r\n\t// // rootNode.appendChild(childNode);\r\n\t// }\r\n\t// }\r\n\r\n\t//创建storeys菜单的根节点\r\n\t_createStoreysNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let id in rootMetaObjects) {\r\n\t\t\tthis._createStoreysNodes2(rootMetaObjects[id], null, null, null);\r\n\t\t}\r\n\t}\r\n\t//创建storeys菜单的各层级节点\r\n\t_createStoreysNodes2(metaObject, buildingNode, storeyNode, typeNodes) {\r\n\t\tif (this._pruneEmptyNodes && metaObject._countEntities === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst metaObjectType = metaObject.type;\r\n\t\tconst metaObjectName = metaObject.name;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tif (metaObjectType === \"IfcBuilding\") {\r\n\t\t\tbuildingNode = {\r\n\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\tobjectId: objectId,\r\n\t\t\t\ttitle:\r\n\t\t\t\t\tmetaObject.metaModels.length === 0\r\n\t\t\t\t\t\t? \"na\"\r\n\t\t\t\t\t\t: this._rootNames[metaObject.metaModels[0].id] ||\r\n\t\t\t\t\t\t (metaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t\t\t: metaObjectType),\r\n\t\t\t\ttype: metaObjectType,\r\n\t\t\t\tparent: null,\r\n\t\t\t\tnumEntities: 0,\r\n\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\tchecked: false,\r\n\t\t\t\txrayed: false,\r\n\t\t\t\tchildren: []\r\n\t\t\t};\r\n\t\t\tthis._rootNodes.push(buildingNode);\r\n\t\t\tthis._objectNodes[buildingNode.objectId] = buildingNode;\r\n\t\t\tthis._nodeNodes[buildingNode.nodeId] = buildingNode;\r\n\t\t} else if (metaObjectType === \"IfcBuildingStorey\") {\r\n\t\t\tif (!buildingNode) {\r\n\t\t\t\tthis.error(\r\n\t\t\t\t\t\"Failed to build storeys hierarchy for model '\" +\r\n\t\t\t\t\t\tthis.metaModel.id +\r\n\t\t\t\t\t\t\"' - model does not have an IfcBuilding object, or is not an IFC model\"\r\n\t\t\t\t);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tstoreyNode = {\r\n\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\tobjectId: objectId,\r\n\t\t\t\ttitle:\r\n\t\t\t\t\tmetaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t: metaObjectType,\r\n\t\t\t\ttype: metaObjectType,\r\n\t\t\t\tparent: buildingNode,\r\n\t\t\t\tnumEntities: 0,\r\n\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\tchecked: false,\r\n\t\t\t\txrayed: false,\r\n\t\t\t\tchildren: []\r\n\t\t\t};\r\n\t\t\tbuildingNode.children.push(storeyNode);\r\n\t\t\tthis._objectNodes[storeyNode.objectId] = storeyNode;\r\n\t\t\tthis._nodeNodes[storeyNode.nodeId] = storeyNode;\r\n\t\t\ttypeNodes = {};\r\n\t\t} else {\r\n\t\t\tif (storeyNode) {\r\n\t\t\t\tconst objects = this._viewer.scene.objects;\r\n\t\t\t\tconst object = objects[objectId];\r\n\t\t\t\tif (object) {\r\n\t\t\t\t\ttypeNodes = typeNodes || {};\r\n\t\t\t\t\tlet typeNode = typeNodes[metaObjectType];\r\n\t\t\t\t\tif (!typeNode) {\r\n\t\t\t\t\t\ttypeNode = {\r\n\t\t\t\t\t\t\tnodeId: `${this._id}-${storeyNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\tobjectId: `${storeyNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\ttitle: metaObjectType,\r\n\t\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\t\tparent: storeyNode,\r\n\t\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tstoreyNode.children.push(typeNode);\r\n\t\t\t\t\t\tthis._objectNodes[typeNode.objectId] = typeNode;\r\n\t\t\t\t\t\tthis._nodeNodes[typeNode.nodeId] = typeNode;\r\n\t\t\t\t\t\ttypeNodes[metaObjectType] = typeNode;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst node = {\r\n\t\t\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\t\t\tobjectId: objectId,\r\n\t\t\t\t\t\ttitle:\r\n\t\t\t\t\t\t\tmetaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t\t\t: metaObjectType,\r\n\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\tparent: typeNode,\r\n\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t};\r\n\t\t\t\t\ttypeNode.children.push(node);\r\n\t\t\t\t\tthis._objectNodes[node.objectId] = node;\r\n\t\t\t\t\tthis._nodeNodes[node.nodeId] = node;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tthis._createStoreysNodes2(childMetaObject, buildingNode, storeyNode, typeNodes);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//创建Classes菜单的根节点\r\n\t_createTypesNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let id in rootMetaObjects) {\r\n\t\t\tthis._createTypesNodes2(rootMetaObjects[id], null, null);\r\n\t\t}\r\n\t}\r\n\t//创建Classes菜单的根节点\r\n\t_createTypesNodes2(metaObject, rootNode, typeNodes) {\r\n\t\tif (this._pruneEmptyNodes && metaObject._countEntities === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst metaObjectType = metaObject.type;\r\n\t\tconst metaObjectName = metaObject.name;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tif (!metaObject.parent) {\r\n\t\t\trootNode = {\r\n\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\tobjectId: objectId,\r\n\t\t\t\ttitle:\r\n\t\t\t\t\tmetaObject.metaModels.length === 0\r\n\t\t\t\t\t\t? \"na\"\r\n\t\t\t\t\t\t: this._rootNames[metaObject.metaModels[0].id] ||\r\n\t\t\t\t\t\t (metaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t\t\t: metaObjectType),\r\n\t\t\t\ttype: metaObjectType,\r\n\t\t\t\tparent: null,\r\n\t\t\t\tnumEntities: 0,\r\n\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\tchecked: false,\r\n\t\t\t\txrayed: false,\r\n\t\t\t\tchildren: []\r\n\t\t\t};\r\n\t\t\tthis._rootNodes.push(rootNode);\r\n\t\t\tthis._objectNodes[rootNode.objectId] = rootNode;\r\n\t\t\tthis._nodeNodes[rootNode.nodeId] = rootNode;\r\n\t\t\ttypeNodes = {};\r\n\t\t} else {\r\n\t\t\tif (rootNode) {\r\n\t\t\t\tconst objects = this._viewer.scene.objects;\r\n\t\t\t\tconst object = objects[objectId];\r\n\t\t\t\tif (object) {\r\n\t\t\t\t\tlet typeNode = typeNodes[metaObjectType];\r\n\t\t\t\t\tif (!typeNode) {\r\n\t\t\t\t\t\ttypeNode = {\r\n\t\t\t\t\t\t\tnodeId: `${this._id}-${rootNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\tobjectId: `${rootNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\ttitle: metaObjectType,\r\n\t\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\t\tparent: rootNode,\r\n\t\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\trootNode.children.push(typeNode);\r\n\t\t\t\t\t\tthis._objectNodes[typeNode.objectId] = typeNode;\r\n\t\t\t\t\t\tthis._nodeNodes[typeNode.nodeId] = typeNode;\r\n\t\t\t\t\t\ttypeNodes[metaObjectType] = typeNode;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst node = {\r\n\t\t\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\t\t\tobjectId: objectId,\r\n\t\t\t\t\t\ttitle:\r\n\t\t\t\t\t\t\tmetaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Default\" ? metaObjectName : metaObjectType,\r\n\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\tparent: typeNode,\r\n\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t};\r\n\t\t\t\t\ttypeNode.children.push(node);\r\n\t\t\t\t\tthis._objectNodes[node.objectId] = node;\r\n\t\t\t\t\tthis._nodeNodes[node.nodeId] = node;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tthis._createTypesNodes2(childMetaObject, rootNode, typeNodes);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//创建Object菜单的根节点\r\n\t_createContainmentNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let id in rootMetaObjects) {\r\n\t\t\tthis._createContainmentNodes2(rootMetaObjects[id], null);\r\n\t\t}\r\n\t}\r\n\t//创建Object菜单的各层级节点\r\n\t_createContainmentNodes2(metaObject, parent) {\r\n\t\tif (this._pruneEmptyNodes && metaObject._countEntities === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst metaObjectType = metaObject.type;\r\n\t\tconst metaObjectName = metaObject.name || metaObjectType;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tconst node = {\r\n\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\tobjectId: objectId,\r\n\t\t\ttitle: !parent\r\n\t\t\t\t? metaObject.metaModels.length === 0\r\n\t\t\t\t\t? \"na\"\r\n\t\t\t\t\t: this._rootNames[metaObject.metaModels[0].id] || metaObjectName\r\n\t\t\t\t: metaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t? metaObjectName\r\n\t\t\t\t: metaObjectType,\r\n\t\t\ttype: metaObjectType,\r\n\t\t\tparent: parent,\r\n\t\t\tnumEntities: 0,\r\n\t\t\tnumVisibleEntities: 0,\r\n\t\t\tchecked: false,\r\n\t\t\txrayed: false,\r\n\t\t\tchildren: []\r\n\t\t};\r\n\t\tif (parent) {\r\n\t\t\tparent.children.push(node);\r\n\t\t} else {\r\n\t\t\tthis._rootNodes.push(node);\r\n\t\t}\r\n\t\tthis._objectNodes[node.objectId] = node;\r\n\t\tthis._nodeNodes[node.nodeId] = node;\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tthis._createContainmentNodes2(childMetaObject, node);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//同步scene和metaScene中的内容\r\n\t_synchNodesToEntities() {\r\n\t\tconst objectIds = Object.keys(this.viewer.metaScene.metaObjects);\r\n\t\tconst metaObjects = this._viewer.metaScene.metaObjects;\r\n\t\tconst objects = this._viewer.scene.objects;\r\n\t\tfor (let i = 0, len = objectIds.length; i < len; i++) {\r\n\t\t\tconst objectId = objectIds[i];\r\n\t\t\tconst metaObject = metaObjects[objectId];\r\n\t\t\tif (metaObject) {\r\n\t\t\t\tconst node = this._objectNodes[objectId];\r\n\t\t\t\tif (node) {\r\n\t\t\t\t\tconst entity = objects[objectId];\r\n\t\t\t\t\tif (entity) {\r\n\t\t\t\t\t\tconst visible = entity.visible;\r\n\t\t\t\t\t\tnode.numEntities = 1;\r\n\t\t\t\t\t\tnode.xrayed = entity.xrayed;\r\n\t\t\t\t\t\tif (visible) {\r\n\t\t\t\t\t\t\tnode.numVisibleEntities = 1;\r\n\t\t\t\t\t\t\tnode.checked = true;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnode.numVisibleEntities = 0;\r\n\t\t\t\t\t\t\tnode.checked = false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tlet parent = node.parent; // Synch parents\r\n\t\t\t\t\t\twhile (parent) {\r\n\t\t\t\t\t\t\tparent.numEntities++;\r\n\t\t\t\t\t\t\tif (visible) {\r\n\t\t\t\t\t\t\t\tparent.numVisibleEntities++;\r\n\t\t\t\t\t\t\t\tparent.checked = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tparent = parent.parent;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//判断是否合法\r\n\t_validate() {\r\n\t\tthis.errors = [];\r\n\t\tswitch (this._hierarchy) {\r\n\t\t\tcase \"storeys\":\r\n\t\t\t\tthis.valid = this._validateMetaModelForStoreysHierarchy();\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"types\":\r\n\t\t\t\tthis.valid = this._rootNodes.length > 0;\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"containment\":\r\n\t\t\tdefault:\r\n\t\t\t\tthis.valid = this._rootNodes.length > 0;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\treturn this.valid;\r\n\t}\r\n\r\n\t_validateMetaModelForStoreysHierarchy(level = 0, ctx, buildingNode) {\r\n\t\t// ctx = ctx || {\r\n\t\t// foundIFCBuildingStoreys: false\r\n\t\t// };\r\n\t\t// const metaObjectType = metaObject.type;\r\n\t\t// const children = metaObject.children;\r\n\t\t// if (metaObjectType === \"IfcBuilding\") {\r\n\t\t// buildingNode = true;\r\n\t\t// } else if (metaObjectType === \"IfcBuildingStorey\") {\r\n\t\t// if (!buildingNode) {\r\n\t\t// errors.push(\"Can't build storeys hierarchy: IfcBuildingStorey found without parent IfcBuilding\");\r\n\t\t// return false;\r\n\t\t// }\r\n\t\t// ctx.foundIFCBuildingStoreys = true;\r\n\t\t// }\r\n\t\t// if (children) {\r\n\t\t// for (let i = 0, len = children.length; i < len; i++) {\r\n\t\t// const childMetaObject = children[i];\r\n\t\t// if (!this._validateMetaModelForStoreysHierarchy(childMetaObject, errors, level + 1, ctx, buildingNode)) {\r\n\t\t// return false;\r\n\t\t// }\r\n\t\t// }\r\n\t\t// }\r\n\t\t// if (level === 0) {\r\n\t\t// if (!ctx.foundIFCBuildingStoreys) {\r\n\t\t// // errors.push(\"Can't build storeys hierarchy: no IfcBuildingStoreys found\");\r\n\t\t// }\r\n\t\t// }\r\n\t\treturn true;\r\n\t}\r\n\r\n\t/**\r\n\t * Adds a model to this tree view.\r\n\t *\r\n\t * The model will be automatically removed when destroyed.\r\n\t *\r\n\t * To automatically add each model as it's created, instead of manually calling this method each time,\r\n\t * provide a ````autoAddModels: true```` to the TreeViewPlugin constructor.\r\n\t *\r\n\t * @param {String} modelId ID of a model {@link Entity} in {@link Scene#models}.\r\n\t * @param {Object} [options] Options for model in the tree view.\r\n\t * @param {String} [options.rootName] Optional display name for the root node. Ordinary, for \"containment\"\r\n\t * and \"storeys\" hierarchy types, the tree would derive the root node name from the model's \"IfcProject\" element\r\n\t * name. This option allows to override that name when it is not suitable as a display name.\r\n\t */\r\n\taddModel(modelId, options = {}) {\r\n\t\t// if (!this._containerElement) {\r\n\t\t// return;\r\n\t\t// }\r\n\t\tconst model = this.viewer.scene.models[modelId];\r\n\t\tif (!model) {\r\n\t\t\tthrow \"Model not found: \" + modelId;\r\n\t\t}\r\n\t\tconst metaModel = this.viewer.metaScene.metaModels[modelId];\r\n\t\tif (!metaModel) {\r\n\t\t\tthis.error(\"MetaModel not found: \" + modelId);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._metaModels[modelId]) {\r\n\t\t\tthis.warn(\"Model already added: \" + modelId);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._metaModels[modelId] = metaModel;\r\n\r\n\t\tif (options && options.rootName) {\r\n\t\t\tthis._rootNames[modelId] = options.rootName;\r\n\t\t}\r\n\r\n\t\tmodel.on(\"destroyed\", () => {\r\n\t\t\tthis.removeModel(model.id);\r\n\t\t});\r\n\t\tthis._createNodes();\r\n\t}\r\n\r\n\t/**\r\n\t * Removes a model from this tree view.\r\n\t *\r\n\t * Does nothing if model not currently in tree view.\r\n\t *\r\n\t * @param {String} modelId ID of a model {@link Entity} in {@link Scene#models}.\r\n\t */\r\n\tremoveModel(modelId) {\r\n\t\t// if (!this._containerElement) {\r\n\t\t// return;\r\n\t\t// }\r\n\t\tconst metaModel = this._metaModels[modelId];\r\n\t\tif (!metaModel) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (this._rootNames[modelId]) {\r\n\t\t\tdelete this._rootNames[modelId];\r\n\t\t}\r\n\r\n\t\tdelete this._metaModels[modelId];\r\n\t\tthis._createNodes();\r\n\t}\r\n\r\n\t/**\r\n\t * Highlights the tree view node that represents the given object {@link Entity}.\r\n\t *\r\n\t * This causes the tree view to collapse, then expand to reveal the node, then highlight the node.\r\n\t *\r\n\t * If a node is previously highlighted, de-highlights that node and collapses the tree first.\r\n\t *\r\n\t * Note that if the TreeViewPlugin was configured with ````pruneEmptyNodes: true```` (default configuration), then the\r\n\t * node won't exist in the tree if it has no Entitys in the {@link Scene}. in that case, nothing will happen.\r\n\t *\r\n\t * Within the DOM, the node is represented by an ````<li>```` element. This method will add a ````.highlighted-node```` class to\r\n\t * the element to make it appear highlighted, removing that class when de-highlighting it again. See the CSS rules\r\n\t * in the TreeViewPlugin examples for an example of that class.\r\n\t *\r\n\t * @param {String} objectId ID of the {@link Entity}.\r\n\t */\r\n\tshowNode(objectId) {\r\n\t\tthis.unShowNode();\r\n\t\tconst node = this._objectNodes[objectId];\r\n\t\tif (!node) {\r\n\t\t\treturn; // Node may not exist for the given object if (this._pruneEmptyNodes == true)\r\n\t\t}\r\n\t\tconst nodeId = node.nodeId;\r\n\t\t// const switchElement = this._renderService.getSwitchElement(nodeId);\r\n\t\t// if (switchElement) {\r\n\t\t// this._expandSwitchElement(switchElement);\r\n\t\t// switchElement.scrollIntoView();\r\n\t\t// return true;\r\n\t\t// }\r\n\t\tconst path = [];\r\n\t\tpath.unshift(node);\r\n\t\tlet parent = node.parent;\r\n\t\twhile (parent) {\r\n\t\t\tpath.unshift(parent);\r\n\t\t\tparent = parent.parent;\r\n\t\t}\r\n\t\t// for (let i = 0, len = path.length; i < len; i++) {\r\n\t\t// const switchElement = this._renderService.getSwitchElement(\r\n\t\t// path[i].nodeId\r\n\t\t// );\r\n\t\t// if (switchElement) {\r\n\t\t// this._expandSwitchElement(switchElement);\r\n\t\t// }\r\n\t\t// }\r\n\t\t// this._renderService.setHighlighted(nodeId, true);\r\n\t\tthis._showListItemElementId = nodeId;\r\n\t}\r\n\r\n\t/**\r\n\t * De-highlights the node previously shown with {@link TreeViewPlugin#showNode}.\r\n\t *\r\n\t * Does nothing if no node is currently shown.\r\n\t *\r\n\t * If the node is currently scrolled into view, keeps the node in view.\r\n\t */\r\n\tunShowNode() {\r\n\t\tif (!this._showListItemElementId) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// this._renderService.setHighlighted(this._showListItemElementId, false);\r\n\r\n\t\tthis._showListItemElementId = null;\r\n\t}\r\n\r\n\t/**\r\n\t * Expands the tree to the given depth.\r\n\t *\r\n\t * Collapses the tree first.\r\n\t *\r\n\t * @param {Number} depth Depth to expand to.\r\n\t */\r\n\t// expandToDepth(depth) {\r\n\t// this.collapse();\r\n\t// const expand = (node, countDepth) => {\r\n\t// if (countDepth === depth) {\r\n\t// return;\r\n\t// }\r\n\r\n\t// // const switchElement = this._renderService.getSwitchElement(node.nodeId);\r\n\t// if (switchElement) {\r\n\t// this._expandSwitchElement(switchElement);\r\n\t// const childNodes = node.children;\r\n\t// for (var i = 0, len = childNodes.length; i < len; i++) {\r\n\t// const childNode = childNodes[i];\r\n\t// expand(childNode, countDepth + 1);\r\n\t// }\r\n\t// }\r\n\t// };\r\n\t// for (let i = 0, len = this._rootNodes.length; i < len; i++) {\r\n\t// const rootNode = this._rootNodes[i];\r\n\t// expand(rootNode, 0);\r\n\t// }\r\n\t// }\r\n\r\n\t/**\r\n\t * Closes all the nodes in the tree.\r\n\t */\r\n\t// collapse() {\r\n\t// for (let i = 0, len = this._rootNodes.length; i < len; i++) {\r\n\t// const rootNode = this._rootNodes[i];\r\n\t// const objectId = rootNode.objectId;\r\n\t// // this._collapseNode(objectId);\r\n\t// }\r\n\t// }\r\n\r\n\t/**\r\n\t * Iterates over a subtree of the tree view's {@link TreeViewNode}s, calling the given callback for each\r\n\t * node in depth-first pre-order.\r\n\t *\r\n\t * @param {TreeViewNode} node Root of the subtree.\r\n\t * @param {Function} callback Callback called at each {@link TreeViewNode}, with the TreeViewNode given as the argument.\r\n\t */\r\n\twithNodeTree(node, callback) {\r\n\t\tcallback(node);\r\n\t\tconst children = node.children;\r\n\t\tif (!children) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\tthis.withNodeTree(children[i], callback);\r\n\t\t}\r\n\t}\r\n\r\n\t//遍历树指定节点下的子节点\r\n\t_withNodeTree(node, callback) {\r\n\t\tcallback(node);\r\n\t\tconst children = node.children;\r\n\t\tif (!children) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\tthis._withNodeTree(children[i], callback);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 获取指定id节点的children\r\n\t * @param {*} nodeId\r\n\t * @returns node Children[]\r\n\t */\r\n\tgetChildrenById(nodeId) {\r\n\t\treturn this._nodeNodes[nodeId].children;\r\n\t}\r\n\r\n\t/**\r\n\t * 获取指定id的节点\r\n\t * @param {*} nodeId\r\n\t * @returns\r\n\t */\r\n\tgetNodeById(nodeId) {\r\n\t\treturn this._nodeNodes[nodeId];\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this TreeViewPlugin.\r\n\t */\r\n\tdestroy() {\r\n\t\t// if (!this._containerElement) {\r\n\t\t// return;\r\n\t\t// }\r\n\t\tthis._metaModels = {};\r\n\t\tif (this._rootElement && !this._destroyed) {\r\n\t\t\tthis._rootElement.parentNode.removeChild(this._rootElement);\r\n\t\t\tthis._viewer.scene.off(this._onObjectVisibility);\r\n\t\t\tthis._destroyed = true;\r\n\t\t}\r\n\t\tdelete treeViews[this._index];\r\n\t\tsuper.destroy();\r\n\t}\r\n\r\n\t_findEmptyNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let objectId in rootMetaObjects) {\r\n\t\t\tthis._findEmptyNodes2(rootMetaObjects[objectId]);\r\n\t\t}\r\n\t}\r\n\r\n\t_findEmptyNodes2(metaObject, countEntities = 0) {\r\n\t\tconst viewer = this.viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tconst entity = scene.objects[objectId];\r\n\t\tmetaObject._countEntities = 0;\r\n\t\tif (entity) {\r\n\t\t\tmetaObject._countEntities++;\r\n\t\t}\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tchildMetaObject._countEntities = this._findEmptyNodes2(childMetaObject);\r\n\t\t\t\tmetaObject._countEntities += childMetaObject._countEntities;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn metaObject._countEntities;\r\n\t}\r\n\r\n\t_doSortNodes() {\r\n\t\tfor (let i = 0, len = this._rootNodes.length; i < len; i++) {\r\n\t\t\tconst rootNode = this._rootNodes[i];\r\n\t\t\tthis._sortChildren(rootNode);\r\n\t\t}\r\n\t}\r\n\r\n\t_sortChildren(node) {\r\n\t\tconst children = node.children;\r\n\t\tif (!children || children.length === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._hierarchy === \"storeys\" && node.type === \"IfcBuilding\") {\r\n\t\t\t// Assumes that children of an IfcBuilding will always be IfcBuildingStoreys\r\n\t\t\tchildren.sort(this._getSpatialSortFunc());\r\n\t\t} else {\r\n\t\t\tchildren.sort(this._alphaSortFunc);\r\n\t\t}\r\n\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\tconst node = children[i];\r\n\t\t\tthis._sortChildren(node);\r\n\t\t}\r\n\t}\r\n\r\n\t_getSpatialSortFunc() {\r\n\t\t// Creates cached sort func with Viewer in scope\r\n\t\tconst viewer = this.viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst camera = scene.camera;\r\n\t\tconst metaScene = viewer.metaScene;\r\n\t\treturn (\r\n\t\t\tthis._spatialSortFunc ||\r\n\t\t\t(this._spatialSortFunc = (node1, node2) => {\r\n\t\t\t\tif (!node1.aabb || !node2.aabb) {\r\n\t\t\t\t\t// Sorting on lowest point of the AABB is likely more more robust when objects could overlap storeys\r\n\t\t\t\t\tif (!node1.aabb) {\r\n\t\t\t\t\t\tnode1.aabb = scene.getAABB(metaScene.getObjectIDsInSubtree(node1.objectId));\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!node2.aabb) {\r\n\t\t\t\t\t\tnode2.aabb = scene.getAABB(metaScene.getObjectIDsInSubtree(node2.objectId));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tlet idx = 0;\r\n\t\t\t\tif (camera.xUp) {\r\n\t\t\t\t\tidx = 0;\r\n\t\t\t\t} else if (camera.yUp) {\r\n\t\t\t\t\tidx = 1;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tidx = 2;\r\n\t\t\t\t}\r\n\t\t\t\tif (node1.aabb[idx] > node2.aabb[idx]) {\r\n\t\t\t\t\treturn -1;\r\n\t\t\t\t}\r\n\t\t\t\tif (node1.aabb[idx] < node2.aabb[idx]) {\r\n\t\t\t\t\treturn 1;\r\n\t\t\t\t}\r\n\t\t\t\treturn 0;\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t_alphaSortFunc(node1, node2) {\r\n\t\tconst title1 = node1.title.toUpperCase(); // FIXME: Should be case sensitive?\r\n\t\tconst title2 = node2.title.toUpperCase();\r\n\t\tif (title1 < title2) {\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tif (title1 > title2) {\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// //将所有节点内容添加到html tree里面\r\n\t// _createTrees() {\r\n\t// if (this._rootNodes.length === 0) {\r\n\t// return;\r\n\t// }\r\n\t// const rootNodeElements = this._rootNodes.map((rootNode) => {\r\n\t// return this._createNodeElement(rootNode);\r\n\t// });\r\n\r\n\t// const rootNode = this._renderService.createRootNode();\r\n\t// rootNodeElements.forEach((nodeElement) => {\r\n\t// rootNode.appendChild(nodeElement);\r\n\t// });\r\n\r\n\t// this._containerElement.appendChild(rootNode);\r\n\t// this._rootElement = rootNode;\r\n\t// }\r\n\r\n\t//创建每一个节点项的html部分\r\n\t// _createNodeElement(node) {\r\n\t// const contextmenuHandler = (event) =>{\r\n\t// this.fire(\"contextmenu\", {\r\n\t// event: event,\r\n\t// viewer: this._viewer,\r\n\t// treeViewPlugin: this,\r\n\t// treeViewNode: node\r\n\t// });\r\n\t// event.preventDefault();\r\n\t// };\r\n\t// const onclickHandler = (event) => {\r\n\t// this.fire(\"nodeTitleClicked\", {\r\n\t// event: event,\r\n\t// viewer: this._viewer,\r\n\t// treeViewPlugin: this,\r\n\t// treeViewNode: node\r\n\t// });\r\n\t// event.preventDefault();\r\n\t// };\r\n\r\n\t// return this._renderService.createNodeElement(node, this._switchExpandHandler, this._checkboxChangeHandler, contextmenuHandler, onclickHandler);\r\n\t// }\r\n\r\n\t// _expandSwitchElement(switchElement) {\r\n\t// const expanded = this._renderService.isExpanded(switchElement);\r\n\t// if (expanded) {\r\n\t// return;\r\n\t// }\r\n\r\n\t// const nodeId = this._renderService.getId(switchElement);\r\n\r\n\t// const nodeElements = this._nodeNodes[nodeId].children.map((node) => {\r\n\t// return this._createNodeElement(node);\r\n\t// });\r\n\r\n\t// this._renderService.addChildren(switchElement, nodeElements)\r\n\r\n\t// this._renderService.expand(switchElement, this._switchExpandHandler, this._switchCollapseHandler);\r\n\t// }\r\n\r\n\t// _collapseNode(nodeId) {\r\n\t// const switchElement = this._renderService.getSwitchElement(nodeId);\r\n\t// this._collapseSwitchElement(switchElement);\r\n\t// }\r\n\r\n\t// _collapseSwitchElement(switchElement) {\r\n\t// this._renderService.collapse(switchElement, this._switchExpandHandler, this._switchCollapseHandler);\r\n\t// }\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/TreeViewPlugin/TreeViewPlugin.js?");
|
|
2027
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TreeViewPlugin: () => (/* binding */ TreeViewPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _RenderService_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./RenderService.js */ \"./src/plugins/TreeViewPlugin/RenderService.js\");\n\r\n\r\n\r\nconst treeViews = [];\r\n\r\n/**\r\n * @desc A {@link Viewer} plugin that provides an HTML tree view to navigate the IFC elements in models.\r\n * <br>\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XKT_WestRiverSideHospital\" style=\"border: 1px solid black;\"><img src=\"http://xeokit.io/img/docs/TreeViewPlugin/TreeViewPlugin.png\"></a>\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XKT_WestRiverSideHospital)]\r\n *\r\n * ## Overview\r\n *\r\n * * A fast HTML tree view, with zero external dependencies, that works with huge numbers of objects.\r\n * * Each tree node has a checkbox to control the visibility of its object.\r\n * * Has three hierarchy modes: \"containment\", \"types\" and \"storeys\".\r\n * * Automatically contains all models (that have metadata) that are currently in the {@link Scene}.\r\n * * Sorts tree nodes by default - spatially, from top-to-bottom for ````IfcBuildingStorey```` nodes, and alphanumerically for other nodes.\r\n * * Allows custom CSS styling.\r\n * * Use {@link ContextMenu} to create a context menu for the tree nodes.\r\n *\r\n * ## Credits\r\n *\r\n * TreeViewPlugin is based on techniques described in [*Super Fast Tree View in JavaScript*](https://chrissmith.xyz/super-fast-tree-view-in-javascript/) by [Chris Smith](https://twitter.com/chris22smith).\r\n *\r\n * ## Usage\r\n *\r\n * In the example below, we'll add a TreeViewPlugin which, by default, will automatically show the structural\r\n * hierarchy of the IFC elements in each model we load.\r\n *\r\n * Then we'll use an {@link XTCLoaderPlugin} to load the Schependomlaan model from an\r\n * [.xtc file](https://github.com/xeokit/xeokit-sdk/tree/master/examples/models/xtc/schependomlaan).\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XKT_Schependomlaan)]\r\n *\r\n * ````javascript\r\n * import {Viewer, XTCLoaderPlugin, TreeViewPlugin} from \"xeokit-sdk.es.js\";\r\n *\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\")\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n * ````\r\n *\r\n * ## Manually Adding Models\r\n *\r\n * Instead of adding models automatically, we can control which models appear in our TreeViewPlugin by adding them manually.\r\n *\r\n * In the next example, we'll configure the TreeViewPlugin to not add models automatically. Then, once the model\r\n * has loaded, we'll add it manually using {@link TreeViewPlugin#addModel}.\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * autoAddModels: false // <<---------------- Don't auto-add models\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n *\r\n * model.on(\"loaded\", () => {\r\n * treeView.addModel(model.id);\r\n * });\r\n * ````\r\n *\r\n * Adding models manually also allows us to set some options for the model. For example, the ````rootName```` option allows us to provide a custom name for\r\n * the root node, which is sometimes desirable when the model's \"IfcProject\" element's name is not suitable:\r\n *\r\n * ````javascript\r\n * model.on(\"loaded\", () => {\r\n * treeView.addModel(model.id, {\r\n * rootName: \"Schependomlaan Model\"\r\n * });\r\n * });\r\n * ````\r\n *\r\n * ## Initially Expanding the Hierarchy\r\n *\r\n * We can also configure TreeViewPlugin to initially expand each model's nodes to a given depth.\r\n *\r\n * Let's automatically expand the first three nodes from the root, for every model added:\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * autoExpandDepth: 3\r\n * });\r\n * ````\r\n *\r\n * ## Showing a Node by ID\r\n *\r\n * We can show a given node using its ID. This causes the TreeViewPlugin to collapse, then expand and scroll the node into view, then highlight the node.\r\n *\r\n * See the documentation for the {@link TreeViewPlugin#showNode} method for more information, including how to define a custom highlighted appearance for the node using CSS.\r\n *\r\n * Let's make the TreeViewPlugin show the node corresponding to whatever object {@link Entity} that we pick:\r\n *\r\n * ````javascript\r\n * viewer.cameraControl.on(\"picked\", function (e) {\r\n * var objectId = e.entity.id;\r\n * treeView.showNode(objectId);\r\n * });\r\n * ````\r\n *\r\n * This will de-highlight any node that was previously shown by this method.\r\n *\r\n * Note that this method only works if the picked {@link Entity} is an object that belongs to a model that's represented in the TreeViewPlugin.\r\n *\r\n * ## Customizing Appearance\r\n *\r\n * We can customize the appearance of our TreeViewPlugin by defining custom CSS for its HTML\r\n * elements. See our example's [source code](https://github.com/xeokit/xeokit-sdk/blob/master/examples/BIMOffline_XKT_Schependomlaan.html)\r\n * for an example of custom CSS rules.\r\n *\r\n * ## Model Hierarchies\r\n *\r\n * TreeViewPlugin has three hierarchies for organizing its nodes:\r\n *\r\n * * \"containment\" - organizes the tree nodes to indicate the containment hierarchy of the {@link MetaObject}s.\r\n * * \"types\" - groups nodes by their IFC types.\r\n * * \"storeys\" - groups nodes within their ````IfcBuildingStoreys````, and sub-groups them by their IFC types.\r\n *\r\n * <br>\r\n * The table below shows what the hierarchies look like:\r\n * <br>\r\n *\r\n * | 1. Containment Hierarchy | 2. Types Hierarchy | 3. Storeys Hierarchy |\r\n * |---|---|---|\r\n * | <img src=\"http://xeokit.io/img/docs/TreeViewPlugin/structureMode.png\"> | <img src=\"http://xeokit.io/img/docs/TreeViewPlugin/typesMode.png\"> | <img src=\"http://xeokit.io/img/docs/TreeViewPlugin/storeysMode.png\"> |\r\n * <br>\r\n *\r\n * Let's create a TreeViewPlugin that groups nodes by their building stories and IFC types:\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * hierarchy: \"stories\"\r\n * });\r\n * ````\r\n *\r\n * ## Sorting Nodes\r\n *\r\n * TreeViewPlugin sorts its tree nodes by default. For a \"storeys\" hierarchy, it orders ````IfcBuildingStorey```` nodes\r\n * spatially, with the node for the highest story at the top, down to the lowest at the bottom.\r\n *\r\n * For all the hierarchy types (\"containment\", \"classes\" and \"storeys\"), TreeViewPlugin sorts the other node types\r\n * alphanumerically on their titles.\r\n *\r\n * If for some reason you need to prevent sorting, create your TreeViewPlugin with the option disabled, like so:\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * hierarchy: \"stories\",\r\n * sortNodes: false // <<------ Disable node sorting\r\n * });\r\n * ````\r\n *\r\n * Note that, for all hierarchy modes, node sorting is only done for each model at the time that it is added to the TreeViewPlugin, and will not\r\n * update dynamically if we later transform the {@link Entity}s corresponding to the nodes.\r\n *\r\n * ## Pruning empty nodes\r\n *\r\n * Sometimes a model contains subtrees of objects that don't have any geometry. These are models whose\r\n * {@link MetaModel} contains trees of {@link MetaObject}s that don't have any {@link Entity}s in the {@link Scene}.\r\n *\r\n * For these models, the tree view would contain nodes that don't do anything in the Scene when we interact with them,\r\n * which is undesirable.\r\n *\r\n * By default, TreeViewPlugin will not create nodes for those objects. However, we can override that behaviour if we want\r\n * to have nodes for those objects (perhaps for debugging the model):\r\n *\r\n * ````javascript\r\n * const treeView = new TreeViewPlugin(viewer, {\r\n * containerElement: document.getElementById(\"myTreeViewContainer\"),\r\n * hierarchy: \"stories\",\r\n * pruneEmptyNodes: false // <<------ Create nodes for object subtrees without geometry\r\n * });\r\n * ````\r\n *\r\n * ## Context Menu\r\n *\r\n * TreeViewPlugin fires a \"contextmenu\" event whenever we right-click on a tree node.\r\n *\r\n * The event contains:\r\n *\r\n * * ````event```` - the original [contextmenu](https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event) [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)\r\n * * ````viewer```` - the {@link Viewer}\r\n * * ````treeViewPlugin```` - the TreeViewPlugin\r\n * * ````treeViewNode```` - the {@link TreeViewNode} representing the tree node\r\n *<br><br>\r\n *\r\n * Let's use {@link ContextMenu} to show a simple context menu for the node we clicked.\r\n *\r\n * [[Run an example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)]\r\n *\r\n * ````javascript\r\n * import {ContextMenu} from \"../src/extras/ContextMenu/ContextMenu.js\";\r\n *\r\n * const treeViewContextMenu = new ContextMenu({\r\n * items: [\r\n * [\r\n * [\r\n * {\r\n * title: \"Hide\",\r\n * doAction: function (context) {\r\n * context.treeViewPlugin.withNodeTree(context.treeViewNode, (treeViewNode) => {\r\n * if (treeViewNode.objectId) {\r\n * const entity = context.viewer.scene.objects[treeViewNode.objectId];\r\n * if (entity) {\r\n * entity.visible = false;\r\n * }\r\n * }\r\n * });\r\n * }\r\n * },\r\n * {\r\n * title: \"Hide all\",\r\n * doAction: function (context) {\r\n * context.viewer.scene.setObjectsVisible(context.viewer.scene.visibleObjectIds, false);\r\n * }\r\n * }\r\n * ],\r\n * [\r\n * {\r\n * title: \"Show\",\r\n * doAction: function (context) {\r\n * context.treeViewPlugin.withNodeTree(context.treeViewNode, (treeViewNode) => {\r\n * if (treeViewNode.objectId) {\r\n * const entity = context.viewer.scene.objects[treeViewNode.objectId];\r\n * if (entity) {\r\n * entity.visible = true;\r\n * entity.xrayed = false;\r\n * entity.selected = false;\r\n * }\r\n * }\r\n * });\r\n * }\r\n * },\r\n * {\r\n * title: \"Show all\",\r\n * doAction: function (context) {\r\n * const scene = context.viewer.scene;\r\n * scene.setObjectsVisible(scene.objectIds, true);\r\n * scene.setObjectsXRayed(scene.xrayedObjectIds, false);\r\n * scene.setObjectsSelected(scene.selectedObjectIds, false);\r\n * }\r\n * }\r\n * ]\r\n * ]\r\n * ]\r\n * });\r\n *\r\n * treeView.on(\"contextmenu\", (e) => {\r\n *\r\n * const event = e.event; // MouseEvent\r\n * const viewer = e.viewer; // Viewer\r\n * const treeViewPlugin = e.treeViewPlugin; // TreeViewPlugin\r\n * const treeViewNode = e.treeViewNode; // TreeViewNode\r\n *\r\n * treeViewContextMenu.show(e.event.pageX, e.event.pageY);\r\n *\r\n * treeViewContextMenu.context = {\r\n * viewer: e.viewer,\r\n * treeViewPlugin: e.treeViewPlugin,\r\n * treeViewNode: e.treeViewNode\r\n * };\r\n * });\r\n * ````\r\n *\r\n * ## Clicking Node Titles\r\n *\r\n * TreeViewPlugin fires a \"nodeTitleClicked\" event whenever we left-click on a tree node.\r\n *\r\n * Like the \"contextmenu\" event, this event contains:\r\n *\r\n * * ````event```` - the original [click](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)\r\n * * ````viewer```` - the {@link Viewer}\r\n * * ````treeViewPlugin```` - the TreeViewPlugin\r\n * * ````treeViewNode```` - the {@link TreeViewNode} representing the tree node\r\n *<br><br>\r\n *\r\n * Let's register a callback to isolate and fit-to-view the {@link Entity}(s) represented by the node. This callback is\r\n * going to X-ray all the other Entitys, fly the camera to fit the Entity(s) for the clicked node, then hide the other Entitys.\r\n *\r\n * [[Run an example](https://xeokit.github.io/xeokit-sdk/examples/#ContextMenu_Canvas_TreeViewPlugin_Custom)]\r\n *\r\n * ````javascript\r\n * treeView.on(\"nodeTitleClicked\", (e) => {\r\n * const scene = viewer.scene;\r\n * const objectIds = [];\r\n * e.treeViewPlugin.withNodeTree(e.treeViewNode, (treeViewNode) => {\r\n * if (treeViewNode.objectId) {\r\n * objectIds.push(treeViewNode.objectId);\r\n * }\r\n * });\r\n * scene.setObjectsXRayed(scene.objectIds, true);\r\n * scene.setObjectsVisible(scene.objectIds, true);\r\n * scene.setObjectsXRayed(objectIds, false);\r\n * viewer.cameraFlight.flyTo({\r\n * aabb: scene.getAABB(objectIds),\r\n * duration: 0.5\r\n * }, () => {\r\n * setTimeout(function () {\r\n * scene.setObjectsVisible(scene.xrayedObjectIds, false);\r\n * scene.setObjectsXRayed(scene.xrayedObjectIds, false);\r\n * }, 500);\r\n * });\r\n * });\r\n * ````\r\n *\r\n * To make the cursor change to a pointer when we hover over the node titles, and also to make the titles change to blue, we'll also define this CSS for the ````<span>```` elements\r\n * that represent the titles of our TreeViewPlugin nodes:\r\n *\r\n * ````css\r\n * #treeViewContainer ul li span:hover {\r\n * color: blue;\r\n * cursor: pointer;\r\n * }\r\n * ````\r\n *\r\n * @class TreeViewPlugin\r\n */\r\nclass TreeViewPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_0__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t *\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {*} cfg Plugin configuration.\r\n\t * @param {String} [cfg.containerElementId] ID of an existing HTML element to contain the TreeViewPlugin - either this or containerElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLElement} cfg.containerElement DOM element to contain the TreeViewPlugin.\r\n\t * @param {Boolean} [cfg.autoAddModels=true] When ````true```` (default), will automatically add each model as it's created. Set this ````false```` if you want to manually add models using {@link TreeViewPlugin#addModel} instead.\r\n\t * @param {Number} [cfg.autoExpandDepth] Optional depth to which to initially expand the tree.\r\n\t * @param {String} [cfg.hierarchy=\"containment\"] How to organize the tree nodes: \"containment\", \"storeys\" or \"types\". See the class documentation for details.\r\n\t * @param {Boolean} [cfg.sortNodes=true] When true, will sort the children of each node. For a \"storeys\" hierarchy, the\r\n\t * ````IfcBuildingStorey```` nodes will be ordered spatially, from the highest storey down to the lowest, on the\r\n\t * vertical World axis. For all hierarchy types, other node types will be ordered in the ascending alphanumeric order of their titles.\r\n\t * @param {Boolean} [cfg.pruneEmptyNodes=true] When true, will not contain nodes that don't have content in the {@link Scene}. These are nodes whose {@link MetaObject}s don't have {@link Entity}s.\r\n\t * @param {RenderService} [cfg.renderService] Optional {@link RenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"TreeViewPlugin\", viewer);\r\n\r\n\t\t/**\r\n\t\t * Contains messages for any errors found while last rebuilding this TreeView.\r\n\t\t * @type {String[]}\r\n\t\t */\r\n\t\tthis.errors = [];\r\n\r\n\t\t/**\r\n\t\t * True if errors were found generating this TreeView.\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis.valid = true;\r\n\r\n\t\t// const containerElement =\r\n\t\t// cfg.containerElement || document.getElementById(cfg.containerElementId);\r\n\r\n\t\t// if (!(containerElement instanceof HTMLElement)) {\r\n\t\t// this.error(\r\n\t\t// \"Mandatory config expected: valid containerElementId or containerElement\"\r\n\t\t// );\r\n\t\t// return;\r\n\t\t// }\r\n\r\n\t\tfor (let i = 0; ; i++) {\r\n\t\t\tif (!treeViews[i]) {\r\n\t\t\t\ttreeViews[i] = this;\r\n\t\t\t\tthis._index = i;\r\n\t\t\t\tthis._id = `tree-${i}`;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// this._containerElement = containerElement;\r\n\t\tthis._metaModels = {};\r\n\t\tthis._autoAddModels = cfg.autoAddModels !== false;\r\n\t\tthis._autoExpandDepth = cfg.autoExpandDepth || 0;\r\n\t\tthis._sortNodes = cfg.sortNodes !== false;\r\n\t\tthis._viewer = viewer;\r\n\t\tthis._rootElement = null;\r\n\t\tthis._muteSceneEvents = false;\r\n\t\tthis._muteTreeEvents = false;\r\n\t\tthis._rootNodes = [];\r\n\t\tthis._objectNodes = {}; // Object ID -> Node\r\n\t\tthis._nodeNodes = {}; // Node ID -> Node\r\n\t\tthis._rootNames = {}; // Node ID -> Root name\r\n\t\tthis._sortNodes = cfg.sortNodes;\r\n\t\tthis._pruneEmptyNodes = cfg.pruneEmptyNodes;\r\n\t\tthis._showListItemElementId = null;\r\n\t\t// this._renderService = cfg.renderService || new RenderService();\r\n\r\n\t\t// if (!this._renderService) {\r\n\t\t// throw new Error('TreeViewPlugin: no render service set');\r\n\t\t// }\r\n\r\n\t\t// this._containerElement.oncontextmenu = (e) => {\r\n\t\t// e.preventDefault();\r\n\t\t// };\r\n\r\n\t\tthis._onObjectVisibility = this._viewer.scene.on(\"objectVisibility\", (entity) => {\r\n\t\t\tif (this._muteSceneEvents) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst objectId = entity.id;\r\n\t\t\tconst node = this._objectNodes[objectId];\r\n\t\t\tif (!node) {\r\n\t\t\t\treturn; // Not in this tree\r\n\t\t\t}\r\n\t\t\tconst visible = entity.visible;\r\n\t\t\tconst updated = visible !== node.checked;\r\n\t\t\tif (!updated) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis._muteTreeEvents = true;\r\n\t\t\tnode.checked = visible;\r\n\t\t\tif (visible) {\r\n\t\t\t\tnode.numVisibleEntities++;\r\n\t\t\t} else {\r\n\t\t\t\tnode.numVisibleEntities--;\r\n\t\t\t}\r\n\r\n\t\t\t// this._renderService.setCheckbox(node.nodeId, visible);\r\n\r\n\t\t\tlet parent = node.parent;\r\n\t\t\twhile (parent) {\r\n\t\t\t\tparent.checked = visible;\r\n\t\t\t\tif (visible) {\r\n\t\t\t\t\tparent.numVisibleEntities++;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tparent.numVisibleEntities--;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// this._renderService.setCheckbox(parent.nodeId, (parent.numVisibleEntities > 0));\r\n\r\n\t\t\t\tparent = parent.parent;\r\n\t\t\t}\r\n\r\n\t\t\tthis._muteTreeEvents = false;\r\n\t\t});\r\n\r\n\t\tthis._onObjectXrayed = this._viewer.scene.on(\"objectXRayed\", (entity) => {\r\n\t\t\tif (this._muteSceneEvents) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tconst objectId = entity.id;\r\n\t\t\tconst node = this._objectNodes[objectId];\r\n\t\t\tif (!node) {\r\n\t\t\t\treturn; // Not in this tree\r\n\t\t\t}\r\n\t\t\tthis._muteTreeEvents = true;\r\n\t\t\tconst xrayed = entity.xrayed;\r\n\t\t\tconst updated = xrayed !== node.xrayed;\r\n\t\t\tif (!updated) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tnode.xrayed = xrayed;\r\n\r\n\t\t\t// this._renderService.setXRayed(node.nodeId, xrayed);\r\n\t\t\tthis._muteTreeEvents = false;\r\n\t\t});\r\n\r\n\t\t// this._switchExpandHandler = (event) => {\r\n\t\t// this.switchExpandHandler(event)\r\n\t\t// };\r\n\r\n\t\t// this._switchCollapseHandler = (event) => {\r\n\t\t// this.switchCollapseHandler(event)\r\n\t\t// };\r\n\r\n\t\t// this._checkboxChangeHandler = (event) => {\r\n\t\t// this.checkboxChangeHandler(event)\r\n\t\t// };\r\n\r\n\t\tthis._hierarchy = cfg.hierarchy || \"containment\";\r\n\t\tthis._autoExpandDepth = cfg.autoExpandDepth || 0;\r\n\r\n\t\tif (this._autoAddModels) {\r\n\t\t\tconst modelIds = Object.keys(this.viewer.metaScene.metaModels);\r\n\t\t\tfor (let i = 0, len = modelIds.length; i < len; i++) {\r\n\t\t\t\tconst modelId = modelIds[i];\r\n\t\t\t\tconst metaModel = this.viewer.metaScene.metaModels[modelId];\r\n\t\t\t\tif (metaModel.finalized) {\r\n\t\t\t\t\tthis.addModel(modelId);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tthis.viewer.scene.on(\"modelLoaded\", (modelId) => {\r\n\t\t\t\tif (this.viewer.metaScene.metaModels[modelId]) {\r\n\t\t\t\t\tthis.addModel(modelId);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tthis.hierarchy = cfg.hierarchy;\r\n\t}\r\n\r\n\t//展开点击事件\r\n\tswitchExpandHandler(event) {\r\n\t\tevent.preventDefault();\r\n\t\tevent.stopPropagation();\r\n\t\tconst switchElement = event.target;\r\n\t\t// this._expandSwitchElement(switchElement);\r\n\t\tthis.fire(\"ExpandHandler\", event);\r\n\t}\r\n\r\n\t//收起点击事件\r\n\tswitchCollapseHandler(event) {\r\n\t\tevent.preventDefault();\r\n\t\tevent.stopPropagation();\r\n\t\t// const switchElement = event.target;\r\n\t\t// this._collapseSwitchElement(switchElement);\r\n\t\tthis.fire(\"CollapseHandler\", event);\r\n\t}\r\n\r\n\t//勾选框点击事件\r\n\tcheckboxChangeHandler(event) {\r\n\t\tthis.fire(\"checkBoxChanged\", event);\r\n\t\tif (this._muteTreeEvents) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._muteSceneEvents = true;\r\n\t\tconst checkbox = event.target; //勾选框html对象\r\n\t\tconst visible = checkbox.checked; //获取勾选状态\r\n\t\tconst nodeId = checkbox.id.replace(\"checkbox-\", \"\"); //获取勾选框对应节点id\r\n\t\tconst checkedNode = this._nodeNodes[nodeId];\r\n\t\tconst objects = this._viewer.scene.objects;\r\n\t\tlet numUpdated = 0;\r\n\r\n\t\tthis._withNodeTree(checkedNode, (node) => {\r\n\t\t\tconst objectId = node.objectId;\r\n\t\t\tconst entity = objects[objectId];\r\n\t\t\tconst isLeaf = node.children.length === 0;\r\n\t\t\tnode.numVisibleEntities = visible ? node.numEntities : 0;\r\n\t\t\tif (isLeaf && visible !== node.checked) {\r\n\t\t\t\tnumUpdated++;\r\n\t\t\t}\r\n\t\t\tnode.checked = visible;\r\n\r\n\t\t\tsetCheckbox(node.nodeId, visible);\r\n\r\n\t\t\tif (entity) {\r\n\t\t\t\tentity.visible = visible;\r\n\t\t\t}\r\n\r\n\t\t\tfunction setCheckbox(nodeId, checked) {\r\n\t\t\t\tconst checkbox = document.getElementById(`checkbox-${nodeId}`);\r\n\t\t\t\tif (checkbox) {\r\n\t\t\t\t\tif (checked !== checkbox.checked) {\r\n\t\t\t\t\t\tcheckbox.checked = checked;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tlet parent = checkedNode.parent;\r\n\t\twhile (parent) {\r\n\t\t\tparent.checked = visible;\r\n\r\n\t\t\tif (visible) {\r\n\t\t\t\tparent.numVisibleEntities += numUpdated;\r\n\t\t\t} else {\r\n\t\t\t\tparent.numVisibleEntities -= numUpdated;\r\n\t\t\t}\r\n\r\n\t\t\t// this._renderService.setCheckbox(parent.nodeId, (parent.numVisibleEntities > 0));\r\n\t\t\tsetCheckbox(parent.nodeId, parent.numVisibleEntities > 0);\r\n\t\t\tparent = parent.parent;\r\n\t\t}\r\n\t\tthis._muteSceneEvents = false;\r\n\r\n\t\tfunction setCheckbox(nodeId, checked) {\r\n\t\t\tconst checkbox = document.getElementById(`checkbox-${nodeId}`);\r\n\t\t\tif (checkbox) {\r\n\t\t\t\tif (checked !== checkbox.checked) {\r\n\t\t\t\t\tcheckbox.checked = checked;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Sets how the nodes are organized within this tree view.\r\n\t *\r\n\t * Accepted values are:\r\n\t *\r\n\t * * \"containment\" - organizes the nodes to indicate the containment hierarchy of the IFC objects.\r\n\t * * \"types\" - groups the nodes within their IFC types.\r\n\t * * \"storeys\" - groups the nodes within ````IfcBuildingStoreys```` and sub-groups them by their IFC types.\r\n\t *\r\n\t * <br>\r\n\t * This can be updated dynamically.\r\n\t *\r\n\t * Default value is \"containment\".\r\n\t *\r\n\t * @type {String}\r\n\t */\r\n\tset hierarchy(hierarchy) {\r\n\t\thierarchy = hierarchy || \"containment\";\r\n\t\tif (hierarchy !== \"containment\" && hierarchy !== \"storeys\" && hierarchy !== \"types\") {\r\n\t\t\tthis.error(\"Unsupported value for `hierarchy' - defaulting to 'containment'\");\r\n\t\t\thierarchy = \"containment\";\r\n\t\t}\r\n\t\tif (this._hierarchy === hierarchy) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._hierarchy = hierarchy;\r\n\t\tthis._createNodes();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets how the nodes are organized within this tree view.\r\n\t *\r\n\t * @type {String}\r\n\t */\r\n\tget hierarchy() {\r\n\t\treturn this._hierarchy;\r\n\t}\r\n\r\n\t/**\r\n\t * get _muteTreeEvents\r\n\t * @type {boolean}\r\n\t */\r\n\tget muteTreeEvents() {\r\n\t\treturn this._muteTreeEvents;\r\n\t}\r\n\r\n\t/**\r\n\t * set _muteTreeEvents\r\n\t */\r\n\tset muteTreeEvents(mute) {\r\n\t\tthis._muteTreeEvents = mute;\r\n\t}\r\n\r\n\t/**\r\n\t * 获取nodeNodes\r\n\t */\r\n\tget nodeNodes() {\r\n\t\treturn this._nodeNodes;\r\n\t}\r\n\r\n\t//创建根节点tree---------11111111111111111\r\n\t_createNodes() {\r\n\t\tif (this._rootElement) {\r\n\t\t\tthis._rootElement.parentNode.removeChild(this._rootElement);\r\n\t\t\tthis._rootElement = null;\r\n\t\t}\r\n\r\n\t\tthis._rootNodes = [];\r\n\t\tthis._objectNodes = {};\r\n\t\tthis._nodeNodes = {};\r\n\t\tthis._validate();\r\n\t\tif (this.valid || this._hierarchy !== \"storeys\") {\r\n\t\t\tthis._createEnabledNodes();\r\n\t\t} else {\r\n\t\t\t// this._createDisabledNodes();\r\n\t\t}\r\n\t}\r\n\r\n\t//创建节点tree----------222222222222222222\r\n\t_createEnabledNodes() {\r\n\t\tif (this._pruneEmptyNodes) {\r\n\t\t\tthis._findEmptyNodes();\r\n\t\t}\r\n\t\tswitch (this._hierarchy) {\r\n\t\t\tcase \"storeys\":\r\n\t\t\t\tthis._createStoreysNodes();\r\n\t\t\t\tif (this._rootNodes.length === 0) {\r\n\t\t\t\t\tthis.error(\"Failed to build storeys hierarchy\");\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"types\":\r\n\t\t\t\tthis._createTypesNodes();\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"containment\":\r\n\t\t\tdefault:\r\n\t\t\t\tthis._createContainmentNodes();\r\n\t\t}\r\n\t\tif (this._sortNodes) {\r\n\t\t\tthis._doSortNodes();\r\n\t\t}\r\n\t\tthis._synchNodesToEntities(); //同步scene和metaScene中的内容\r\n\r\n\t\tthis.fire(\"nodeNodes_Created\", this._nodeNodes);\r\n\t\tthis.fire(\"rootNodes_Created\", this._rootNodes);\r\n\t\tthis.fire(\"objectNodes_Created\", this._objectNodes);\r\n\r\n\t\t// this._createTrees(); //创建html tree\r\n\t\t// this.expandToDepth(this._autoExpandDepth); //展开几层与否\r\n\t}\r\n\r\n\t// //创建\r\n\t// _createDisabledNodes() {\r\n\t// const rootNode = this._renderService.createRootNode();\r\n\t// this._rootElement = rootNode;\r\n\t// this._containerElement.appendChild(rootNode);\r\n\r\n\t// const rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\r\n\t// for (let objectId in rootMetaObjects) {\r\n\t// const rootMetaObject = rootMetaObjects[objectId];\r\n\t// const metaObjectType = rootMetaObject.type;\r\n\t// const metaObjectName = rootMetaObject.name;\r\n\t// const rootName =\r\n\t// metaObjectName &&\r\n\t// metaObjectName !== \"\" &&\r\n\t// metaObjectName !== \"Undefined\" &&\r\n\t// metaObjectName !== \"Default\"\r\n\t// ? metaObjectName\r\n\t// : metaObjectType;\r\n\r\n\t// // const childNode = this._renderService.createDisabledNodeElement(rootName);\r\n\t// // rootNode.appendChild(childNode);\r\n\t// }\r\n\t// }\r\n\r\n\t//创建storeys菜单的根节点\r\n\t_createStoreysNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let id in rootMetaObjects) {\r\n\t\t\tthis._createStoreysNodes2(rootMetaObjects[id], null, null, null);\r\n\t\t}\r\n\t}\r\n\t//创建storeys菜单的各层级节点\r\n\t_createStoreysNodes2(metaObject, buildingNode, storeyNode, typeNodes) {\r\n\t\tif (this._pruneEmptyNodes && metaObject._countEntities === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst metaObjectType = metaObject.type;\r\n\t\tconst metaObjectName = metaObject.name;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tif (metaObjectType === \"IfcBuilding\") {\r\n\t\t\tbuildingNode = {\r\n\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\tobjectId: objectId,\r\n\t\t\t\ttitle:\r\n\t\t\t\t\tmetaObject.metaModels.length === 0\r\n\t\t\t\t\t\t? \"na\"\r\n\t\t\t\t\t\t: this._rootNames[metaObject.metaModels[0].id] ||\r\n\t\t\t\t\t\t (metaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t\t\t: metaObjectType),\r\n\t\t\t\ttype: metaObjectType,\r\n\t\t\t\tparent: null,\r\n\t\t\t\tnumEntities: 0,\r\n\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\tchecked: false,\r\n\t\t\t\txrayed: false,\r\n\t\t\t\tchildren: []\r\n\t\t\t};\r\n\t\t\tthis._rootNodes.push(buildingNode);\r\n\t\t\tthis._objectNodes[buildingNode.objectId] = buildingNode;\r\n\t\t\tthis._nodeNodes[buildingNode.nodeId] = buildingNode;\r\n\t\t} else if (metaObjectType === \"IfcBuildingStorey\") {\r\n\t\t\tif (!buildingNode) {\r\n\t\t\t\tthis.error(\r\n\t\t\t\t\t\"Failed to build storeys hierarchy for model '\" +\r\n\t\t\t\t\t\tthis.metaModel.id +\r\n\t\t\t\t\t\t\"' - model does not have an IfcBuilding object, or is not an IFC model\"\r\n\t\t\t\t);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tstoreyNode = {\r\n\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\tobjectId: objectId,\r\n\t\t\t\ttitle:\r\n\t\t\t\t\tmetaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t: metaObjectType,\r\n\t\t\t\ttype: metaObjectType,\r\n\t\t\t\tparent: buildingNode,\r\n\t\t\t\tnumEntities: 0,\r\n\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\tchecked: false,\r\n\t\t\t\txrayed: false,\r\n\t\t\t\tchildren: []\r\n\t\t\t};\r\n\t\t\tbuildingNode.children.push(storeyNode);\r\n\t\t\tthis._objectNodes[storeyNode.objectId] = storeyNode;\r\n\t\t\tthis._nodeNodes[storeyNode.nodeId] = storeyNode;\r\n\t\t\ttypeNodes = {};\r\n\t\t} else {\r\n\t\t\tif (storeyNode) {\r\n\t\t\t\tconst objects = this._viewer.scene.objects;\r\n\t\t\t\tconst object = objects[objectId];\r\n\t\t\t\tif (object) {\r\n\t\t\t\t\ttypeNodes = typeNodes || {};\r\n\t\t\t\t\tlet typeNode = typeNodes[metaObjectType];\r\n\t\t\t\t\tif (!typeNode) {\r\n\t\t\t\t\t\ttypeNode = {\r\n\t\t\t\t\t\t\tnodeId: `${this._id}-${storeyNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\tobjectId: `${storeyNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\ttitle: metaObjectType,\r\n\t\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\t\tparent: storeyNode,\r\n\t\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tstoreyNode.children.push(typeNode);\r\n\t\t\t\t\t\tthis._objectNodes[typeNode.objectId] = typeNode;\r\n\t\t\t\t\t\tthis._nodeNodes[typeNode.nodeId] = typeNode;\r\n\t\t\t\t\t\ttypeNodes[metaObjectType] = typeNode;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst node = {\r\n\t\t\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\t\t\tobjectId: objectId,\r\n\t\t\t\t\t\ttitle:\r\n\t\t\t\t\t\t\tmetaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t\t\t: metaObjectType,\r\n\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\tparent: typeNode,\r\n\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t};\r\n\t\t\t\t\ttypeNode.children.push(node);\r\n\t\t\t\t\tthis._objectNodes[node.objectId] = node;\r\n\t\t\t\t\tthis._nodeNodes[node.nodeId] = node;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tthis._createStoreysNodes2(childMetaObject, buildingNode, storeyNode, typeNodes);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//创建Classes菜单的根节点\r\n\t_createTypesNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let id in rootMetaObjects) {\r\n\t\t\tthis._createTypesNodes2(rootMetaObjects[id], null, null);\r\n\t\t}\r\n\t}\r\n\t//创建Classes菜单的根节点\r\n\t_createTypesNodes2(metaObject, rootNode, typeNodes) {\r\n\t\tif (this._pruneEmptyNodes && metaObject._countEntities === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst metaObjectType = metaObject.type;\r\n\t\tconst metaObjectName = metaObject.name;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tif (!metaObject.parent) {\r\n\t\t\trootNode = {\r\n\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\tobjectId: objectId,\r\n\t\t\t\ttitle:\r\n\t\t\t\t\tmetaObject.metaModels.length === 0\r\n\t\t\t\t\t\t? \"na\"\r\n\t\t\t\t\t\t: this._rootNames[metaObject.metaModels[0].id] ||\r\n\t\t\t\t\t\t (metaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t\t\t\t\t? metaObjectName\r\n\t\t\t\t\t\t\t\t: metaObjectType),\r\n\t\t\t\ttype: metaObjectType,\r\n\t\t\t\tparent: null,\r\n\t\t\t\tnumEntities: 0,\r\n\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\tchecked: false,\r\n\t\t\t\txrayed: false,\r\n\t\t\t\tchildren: []\r\n\t\t\t};\r\n\t\t\tthis._rootNodes.push(rootNode);\r\n\t\t\tthis._objectNodes[rootNode.objectId] = rootNode;\r\n\t\t\tthis._nodeNodes[rootNode.nodeId] = rootNode;\r\n\t\t\ttypeNodes = {};\r\n\t\t} else {\r\n\t\t\tif (rootNode) {\r\n\t\t\t\tconst objects = this._viewer.scene.objects;\r\n\t\t\t\tconst object = objects[objectId];\r\n\t\t\t\tif (object) {\r\n\t\t\t\t\tlet typeNode = typeNodes[metaObjectType];\r\n\t\t\t\t\tif (!typeNode) {\r\n\t\t\t\t\t\ttypeNode = {\r\n\t\t\t\t\t\t\tnodeId: `${this._id}-${rootNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\tobjectId: `${rootNode.objectId}-${metaObjectType}`,\r\n\t\t\t\t\t\t\ttitle: metaObjectType,\r\n\t\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\t\tparent: rootNode,\r\n\t\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\trootNode.children.push(typeNode);\r\n\t\t\t\t\t\tthis._objectNodes[typeNode.objectId] = typeNode;\r\n\t\t\t\t\t\tthis._nodeNodes[typeNode.nodeId] = typeNode;\r\n\t\t\t\t\t\ttypeNodes[metaObjectType] = typeNode;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst node = {\r\n\t\t\t\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\t\t\t\tobjectId: objectId,\r\n\t\t\t\t\t\ttitle:\r\n\t\t\t\t\t\t\tmetaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Default\" ? metaObjectName : metaObjectType,\r\n\t\t\t\t\t\ttype: metaObjectType,\r\n\t\t\t\t\t\tparent: typeNode,\r\n\t\t\t\t\t\tnumEntities: 0,\r\n\t\t\t\t\t\tnumVisibleEntities: 0,\r\n\t\t\t\t\t\tchecked: false,\r\n\t\t\t\t\t\txrayed: false,\r\n\t\t\t\t\t\tchildren: []\r\n\t\t\t\t\t};\r\n\t\t\t\t\ttypeNode.children.push(node);\r\n\t\t\t\t\tthis._objectNodes[node.objectId] = node;\r\n\t\t\t\t\tthis._nodeNodes[node.nodeId] = node;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tthis._createTypesNodes2(childMetaObject, rootNode, typeNodes);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//创建Object菜单的根节点\r\n\t_createContainmentNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let id in rootMetaObjects) {\r\n\t\t\tthis._createContainmentNodes2(rootMetaObjects[id], null);\r\n\t\t}\r\n\t}\r\n\t//创建Object菜单的各层级节点\r\n\t_createContainmentNodes2(metaObject, parent) {\r\n\t\tif (this._pruneEmptyNodes && metaObject._countEntities === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst metaObjectType = metaObject.type;\r\n\t\tconst metaObjectName = metaObject.name || metaObjectType;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tconst node = {\r\n\t\t\tnodeId: `${this._id}-${objectId}`,\r\n\t\t\tobjectId: objectId,\r\n\t\t\ttitle: !parent\r\n\t\t\t\t? metaObject.metaModels.length === 0\r\n\t\t\t\t\t? \"na\"\r\n\t\t\t\t\t: this._rootNames[metaObject.metaModels[0].id] || metaObjectName\r\n\t\t\t\t: metaObjectName && metaObjectName !== \"\" && metaObjectName !== \"Undefined\" && metaObjectName !== \"Default\"\r\n\t\t\t\t? metaObjectName\r\n\t\t\t\t: metaObjectType,\r\n\t\t\ttype: metaObjectType,\r\n\t\t\tparent: parent,\r\n\t\t\tnumEntities: 0,\r\n\t\t\tnumVisibleEntities: 0,\r\n\t\t\tchecked: false,\r\n\t\t\txrayed: false,\r\n\t\t\tchildren: []\r\n\t\t};\r\n\t\tif (parent) {\r\n\t\t\tparent.children.push(node);\r\n\t\t} else {\r\n\t\t\tthis._rootNodes.push(node);\r\n\t\t}\r\n\t\tthis._objectNodes[node.objectId] = node;\r\n\t\tthis._nodeNodes[node.nodeId] = node;\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tthis._createContainmentNodes2(childMetaObject, node);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//同步scene和metaScene中的内容\r\n\t_synchNodesToEntities() {\r\n\t\tconst objectIds = Object.keys(this.viewer.metaScene.metaObjects);\r\n\t\tconst metaObjects = this._viewer.metaScene.metaObjects;\r\n\t\tconst objects = this._viewer.scene.objects;\r\n\t\tfor (let i = 0, len = objectIds.length; i < len; i++) {\r\n\t\t\tconst objectId = objectIds[i];\r\n\t\t\tconst metaObject = metaObjects[objectId];\r\n\t\t\tif (metaObject) {\r\n\t\t\t\tconst node = this._objectNodes[objectId];\r\n\t\t\t\tif (node) {\r\n\t\t\t\t\tconst entity = objects[objectId];\r\n\t\t\t\t\tif (entity) {\r\n\t\t\t\t\t\tconst visible = entity.visible;\r\n\t\t\t\t\t\tnode.numEntities = 1;\r\n\t\t\t\t\t\tnode.xrayed = entity.xrayed;\r\n\t\t\t\t\t\tif (visible) {\r\n\t\t\t\t\t\t\tnode.numVisibleEntities = 1;\r\n\t\t\t\t\t\t\tnode.checked = true;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnode.numVisibleEntities = 0;\r\n\t\t\t\t\t\t\tnode.checked = false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tlet parent = node.parent; // Synch parents\r\n\t\t\t\t\t\twhile (parent) {\r\n\t\t\t\t\t\t\tparent.numEntities++;\r\n\t\t\t\t\t\t\tif (visible) {\r\n\t\t\t\t\t\t\t\tparent.numVisibleEntities++;\r\n\t\t\t\t\t\t\t\tparent.checked = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tparent = parent.parent;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t//判断是否合法\r\n\t_validate() {\r\n\t\tthis.errors = [];\r\n\t\tswitch (this._hierarchy) {\r\n\t\t\tcase \"storeys\":\r\n\t\t\t\tthis.valid = this._validateMetaModelForStoreysHierarchy();\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"types\":\r\n\t\t\t\tthis.valid = this._rootNodes.length > 0;\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"containment\":\r\n\t\t\tdefault:\r\n\t\t\t\tthis.valid = this._rootNodes.length > 0;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\treturn this.valid;\r\n\t}\r\n\r\n\t_validateMetaModelForStoreysHierarchy(level = 0, ctx, buildingNode) {\r\n\t\t// ctx = ctx || {\r\n\t\t// foundIFCBuildingStoreys: false\r\n\t\t// };\r\n\t\t// const metaObjectType = metaObject.type;\r\n\t\t// const children = metaObject.children;\r\n\t\t// if (metaObjectType === \"IfcBuilding\") {\r\n\t\t// buildingNode = true;\r\n\t\t// } else if (metaObjectType === \"IfcBuildingStorey\") {\r\n\t\t// if (!buildingNode) {\r\n\t\t// errors.push(\"Can't build storeys hierarchy: IfcBuildingStorey found without parent IfcBuilding\");\r\n\t\t// return false;\r\n\t\t// }\r\n\t\t// ctx.foundIFCBuildingStoreys = true;\r\n\t\t// }\r\n\t\t// if (children) {\r\n\t\t// for (let i = 0, len = children.length; i < len; i++) {\r\n\t\t// const childMetaObject = children[i];\r\n\t\t// if (!this._validateMetaModelForStoreysHierarchy(childMetaObject, errors, level + 1, ctx, buildingNode)) {\r\n\t\t// return false;\r\n\t\t// }\r\n\t\t// }\r\n\t\t// }\r\n\t\t// if (level === 0) {\r\n\t\t// if (!ctx.foundIFCBuildingStoreys) {\r\n\t\t// // errors.push(\"Can't build storeys hierarchy: no IfcBuildingStoreys found\");\r\n\t\t// }\r\n\t\t// }\r\n\t\treturn true;\r\n\t}\r\n\r\n\t/**\r\n\t * Adds a model to this tree view.\r\n\t *\r\n\t * The model will be automatically removed when destroyed.\r\n\t *\r\n\t * To automatically add each model as it's created, instead of manually calling this method each time,\r\n\t * provide a ````autoAddModels: true```` to the TreeViewPlugin constructor.\r\n\t *\r\n\t * @param {String} modelId ID of a model {@link Entity} in {@link Scene#models}.\r\n\t * @param {Object} [options] Options for model in the tree view.\r\n\t * @param {String} [options.rootName] Optional display name for the root node. Ordinary, for \"containment\"\r\n\t * and \"storeys\" hierarchy types, the tree would derive the root node name from the model's \"IfcProject\" element\r\n\t * name. This option allows to override that name when it is not suitable as a display name.\r\n\t */\r\n\taddModel(modelId, options = {}) {\r\n\t\t// if (!this._containerElement) {\r\n\t\t// return;\r\n\t\t// }\r\n\t\tconst model = this.viewer.scene.models[modelId];\r\n\t\tif (!model) {\r\n\t\t\tthrow \"Model not found: \" + modelId;\r\n\t\t}\r\n\t\tconst metaModel = this.viewer.metaScene.metaModels[modelId];\r\n\t\tif (!metaModel) {\r\n\t\t\tthis.error(\"MetaModel not found: \" + modelId);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._metaModels[modelId]) {\r\n\t\t\tthis._metaModels[modelId] = null;\r\n\t\t\t// this.warn(\"Model already added: \" + modelId);\r\n\t\t\t// return;\r\n\t\t}\r\n\t\tthis._metaModels[modelId] = metaModel;\r\n\r\n\t\tif (options && options.rootName) {\r\n\t\t\tthis._rootNames[modelId] = options.rootName;\r\n\t\t}\r\n\r\n\t\tmodel.on(\"destroyed\", () => {\r\n\t\t\tthis.removeModel(model.id);\r\n\t\t});\r\n\t\tthis._createNodes();\r\n\t}\r\n\r\n\t/**\r\n\t * Removes a model from this tree view.\r\n\t *\r\n\t * Does nothing if model not currently in tree view.\r\n\t *\r\n\t * @param {String} modelId ID of a model {@link Entity} in {@link Scene#models}.\r\n\t */\r\n\tremoveModel(modelId) {\r\n\t\t// if (!this._containerElement) {\r\n\t\t// return;\r\n\t\t// }\r\n\t\tconst metaModel = this._metaModels[modelId];\r\n\t\tif (!metaModel) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (this._rootNames[modelId]) {\r\n\t\t\tdelete this._rootNames[modelId];\r\n\t\t}\r\n\r\n\t\tdelete this._metaModels[modelId];\r\n\t\tthis._createNodes();\r\n\t}\r\n\r\n\t/**\r\n\t * Highlights the tree view node that represents the given object {@link Entity}.\r\n\t *\r\n\t * This causes the tree view to collapse, then expand to reveal the node, then highlight the node.\r\n\t *\r\n\t * If a node is previously highlighted, de-highlights that node and collapses the tree first.\r\n\t *\r\n\t * Note that if the TreeViewPlugin was configured with ````pruneEmptyNodes: true```` (default configuration), then the\r\n\t * node won't exist in the tree if it has no Entitys in the {@link Scene}. in that case, nothing will happen.\r\n\t *\r\n\t * Within the DOM, the node is represented by an ````<li>```` element. This method will add a ````.highlighted-node```` class to\r\n\t * the element to make it appear highlighted, removing that class when de-highlighting it again. See the CSS rules\r\n\t * in the TreeViewPlugin examples for an example of that class.\r\n\t *\r\n\t * @param {String} objectId ID of the {@link Entity}.\r\n\t */\r\n\tshowNode(objectId) {\r\n\t\tthis.unShowNode();\r\n\t\tconst node = this._objectNodes[objectId];\r\n\t\tif (!node) {\r\n\t\t\treturn; // Node may not exist for the given object if (this._pruneEmptyNodes == true)\r\n\t\t}\r\n\t\tconst nodeId = node.nodeId;\r\n\t\t// const switchElement = this._renderService.getSwitchElement(nodeId);\r\n\t\t// if (switchElement) {\r\n\t\t// this._expandSwitchElement(switchElement);\r\n\t\t// switchElement.scrollIntoView();\r\n\t\t// return true;\r\n\t\t// }\r\n\t\tconst path = [];\r\n\t\tpath.unshift(node);\r\n\t\tlet parent = node.parent;\r\n\t\twhile (parent) {\r\n\t\t\tpath.unshift(parent);\r\n\t\t\tparent = parent.parent;\r\n\t\t}\r\n\t\t// for (let i = 0, len = path.length; i < len; i++) {\r\n\t\t// const switchElement = this._renderService.getSwitchElement(\r\n\t\t// path[i].nodeId\r\n\t\t// );\r\n\t\t// if (switchElement) {\r\n\t\t// this._expandSwitchElement(switchElement);\r\n\t\t// }\r\n\t\t// }\r\n\t\t// this._renderService.setHighlighted(nodeId, true);\r\n\t\tthis._showListItemElementId = nodeId;\r\n\t}\r\n\r\n\t/**\r\n\t * De-highlights the node previously shown with {@link TreeViewPlugin#showNode}.\r\n\t *\r\n\t * Does nothing if no node is currently shown.\r\n\t *\r\n\t * If the node is currently scrolled into view, keeps the node in view.\r\n\t */\r\n\tunShowNode() {\r\n\t\tif (!this._showListItemElementId) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// this._renderService.setHighlighted(this._showListItemElementId, false);\r\n\r\n\t\tthis._showListItemElementId = null;\r\n\t}\r\n\r\n\t/**\r\n\t * Expands the tree to the given depth.\r\n\t *\r\n\t * Collapses the tree first.\r\n\t *\r\n\t * @param {Number} depth Depth to expand to.\r\n\t */\r\n\t// expandToDepth(depth) {\r\n\t// this.collapse();\r\n\t// const expand = (node, countDepth) => {\r\n\t// if (countDepth === depth) {\r\n\t// return;\r\n\t// }\r\n\r\n\t// // const switchElement = this._renderService.getSwitchElement(node.nodeId);\r\n\t// if (switchElement) {\r\n\t// this._expandSwitchElement(switchElement);\r\n\t// const childNodes = node.children;\r\n\t// for (var i = 0, len = childNodes.length; i < len; i++) {\r\n\t// const childNode = childNodes[i];\r\n\t// expand(childNode, countDepth + 1);\r\n\t// }\r\n\t// }\r\n\t// };\r\n\t// for (let i = 0, len = this._rootNodes.length; i < len; i++) {\r\n\t// const rootNode = this._rootNodes[i];\r\n\t// expand(rootNode, 0);\r\n\t// }\r\n\t// }\r\n\r\n\t/**\r\n\t * Closes all the nodes in the tree.\r\n\t */\r\n\t// collapse() {\r\n\t// for (let i = 0, len = this._rootNodes.length; i < len; i++) {\r\n\t// const rootNode = this._rootNodes[i];\r\n\t// const objectId = rootNode.objectId;\r\n\t// // this._collapseNode(objectId);\r\n\t// }\r\n\t// }\r\n\r\n\t/**\r\n\t * Iterates over a subtree of the tree view's {@link TreeViewNode}s, calling the given callback for each\r\n\t * node in depth-first pre-order.\r\n\t *\r\n\t * @param {TreeViewNode} node Root of the subtree.\r\n\t * @param {Function} callback Callback called at each {@link TreeViewNode}, with the TreeViewNode given as the argument.\r\n\t */\r\n\twithNodeTree(node, callback) {\r\n\t\tcallback(node);\r\n\t\tconst children = node.children;\r\n\t\tif (!children) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\tthis.withNodeTree(children[i], callback);\r\n\t\t}\r\n\t}\r\n\r\n\t//遍历树指定节点下的子节点\r\n\t_withNodeTree(node, callback) {\r\n\t\tcallback(node);\r\n\t\tconst children = node.children;\r\n\t\tif (!children) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\tthis._withNodeTree(children[i], callback);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * 获取指定id节点的children\r\n\t * @param {*} nodeId\r\n\t * @returns node Children[]\r\n\t */\r\n\tgetChildrenById(nodeId) {\r\n\t\treturn this._nodeNodes[nodeId].children;\r\n\t}\r\n\r\n\t/**\r\n\t * 获取指定id的节点\r\n\t * @param {*} nodeId\r\n\t * @returns\r\n\t */\r\n\tgetNodeById(nodeId) {\r\n\t\treturn this._nodeNodes[nodeId];\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this TreeViewPlugin.\r\n\t */\r\n\tdestroy() {\r\n\t\t// if (!this._containerElement) {\r\n\t\t// return;\r\n\t\t// }\r\n\t\tthis._metaModels = {};\r\n\t\tif (this._rootElement && !this._destroyed) {\r\n\t\t\tthis._rootElement.parentNode.removeChild(this._rootElement);\r\n\t\t\tthis._viewer.scene.off(this._onObjectVisibility);\r\n\t\t\tthis._destroyed = true;\r\n\t\t}\r\n\t\tdelete treeViews[this._index];\r\n\t\tsuper.destroy();\r\n\t}\r\n\r\n\t_findEmptyNodes() {\r\n\t\tconst rootMetaObjects = this._viewer.metaScene.rootMetaObjects;\r\n\t\tfor (let objectId in rootMetaObjects) {\r\n\t\t\tthis._findEmptyNodes2(rootMetaObjects[objectId]);\r\n\t\t}\r\n\t}\r\n\r\n\t_findEmptyNodes2(metaObject, countEntities = 0) {\r\n\t\tconst viewer = this.viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst children = metaObject.children;\r\n\t\tconst objectId = metaObject.id;\r\n\t\tconst entity = scene.objects[objectId];\r\n\t\tmetaObject._countEntities = 0;\r\n\t\tif (entity) {\r\n\t\t\tmetaObject._countEntities++;\r\n\t\t}\r\n\t\tif (children) {\r\n\t\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\t\tconst childMetaObject = children[i];\r\n\t\t\t\tchildMetaObject._countEntities = this._findEmptyNodes2(childMetaObject);\r\n\t\t\t\tmetaObject._countEntities += childMetaObject._countEntities;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn metaObject._countEntities;\r\n\t}\r\n\r\n\t_doSortNodes() {\r\n\t\tfor (let i = 0, len = this._rootNodes.length; i < len; i++) {\r\n\t\t\tconst rootNode = this._rootNodes[i];\r\n\t\t\tthis._sortChildren(rootNode);\r\n\t\t}\r\n\t}\r\n\r\n\t_sortChildren(node) {\r\n\t\tconst children = node.children;\r\n\t\tif (!children || children.length === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._hierarchy === \"storeys\" && node.type === \"IfcBuilding\") {\r\n\t\t\t// Assumes that children of an IfcBuilding will always be IfcBuildingStoreys\r\n\t\t\tchildren.sort(this._getSpatialSortFunc());\r\n\t\t} else {\r\n\t\t\tchildren.sort(this._alphaSortFunc);\r\n\t\t}\r\n\t\tfor (let i = 0, len = children.length; i < len; i++) {\r\n\t\t\tconst node = children[i];\r\n\t\t\tthis._sortChildren(node);\r\n\t\t}\r\n\t}\r\n\r\n\t_getSpatialSortFunc() {\r\n\t\t// Creates cached sort func with Viewer in scope\r\n\t\tconst viewer = this.viewer;\r\n\t\tconst scene = viewer.scene;\r\n\t\tconst camera = scene.camera;\r\n\t\tconst metaScene = viewer.metaScene;\r\n\t\treturn (\r\n\t\t\tthis._spatialSortFunc ||\r\n\t\t\t(this._spatialSortFunc = (node1, node2) => {\r\n\t\t\t\tif (!node1.aabb || !node2.aabb) {\r\n\t\t\t\t\t// Sorting on lowest point of the AABB is likely more more robust when objects could overlap storeys\r\n\t\t\t\t\tif (!node1.aabb) {\r\n\t\t\t\t\t\tnode1.aabb = scene.getAABB(metaScene.getObjectIDsInSubtree(node1.objectId));\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!node2.aabb) {\r\n\t\t\t\t\t\tnode2.aabb = scene.getAABB(metaScene.getObjectIDsInSubtree(node2.objectId));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tlet idx = 0;\r\n\t\t\t\tif (camera.xUp) {\r\n\t\t\t\t\tidx = 0;\r\n\t\t\t\t} else if (camera.yUp) {\r\n\t\t\t\t\tidx = 1;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tidx = 2;\r\n\t\t\t\t}\r\n\t\t\t\tif (node1.aabb[idx] > node2.aabb[idx]) {\r\n\t\t\t\t\treturn -1;\r\n\t\t\t\t}\r\n\t\t\t\tif (node1.aabb[idx] < node2.aabb[idx]) {\r\n\t\t\t\t\treturn 1;\r\n\t\t\t\t}\r\n\t\t\t\treturn 0;\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t_alphaSortFunc(node1, node2) {\r\n\t\tconst title1 = node1.title.toUpperCase(); // FIXME: Should be case sensitive?\r\n\t\tconst title2 = node2.title.toUpperCase();\r\n\t\tif (title1 < title2) {\r\n\t\t\treturn -1;\r\n\t\t}\r\n\t\tif (title1 > title2) {\r\n\t\t\treturn 1;\r\n\t\t}\r\n\t\treturn 0;\r\n\t}\r\n\r\n\t// //将所有节点内容添加到html tree里面\r\n\t// _createTrees() {\r\n\t// if (this._rootNodes.length === 0) {\r\n\t// return;\r\n\t// }\r\n\t// const rootNodeElements = this._rootNodes.map((rootNode) => {\r\n\t// return this._createNodeElement(rootNode);\r\n\t// });\r\n\r\n\t// const rootNode = this._renderService.createRootNode();\r\n\t// rootNodeElements.forEach((nodeElement) => {\r\n\t// rootNode.appendChild(nodeElement);\r\n\t// });\r\n\r\n\t// this._containerElement.appendChild(rootNode);\r\n\t// this._rootElement = rootNode;\r\n\t// }\r\n\r\n\t//创建每一个节点项的html部分\r\n\t// _createNodeElement(node) {\r\n\t// const contextmenuHandler = (event) =>{\r\n\t// this.fire(\"contextmenu\", {\r\n\t// event: event,\r\n\t// viewer: this._viewer,\r\n\t// treeViewPlugin: this,\r\n\t// treeViewNode: node\r\n\t// });\r\n\t// event.preventDefault();\r\n\t// };\r\n\t// const onclickHandler = (event) => {\r\n\t// this.fire(\"nodeTitleClicked\", {\r\n\t// event: event,\r\n\t// viewer: this._viewer,\r\n\t// treeViewPlugin: this,\r\n\t// treeViewNode: node\r\n\t// });\r\n\t// event.preventDefault();\r\n\t// };\r\n\r\n\t// return this._renderService.createNodeElement(node, this._switchExpandHandler, this._checkboxChangeHandler, contextmenuHandler, onclickHandler);\r\n\t// }\r\n\r\n\t// _expandSwitchElement(switchElement) {\r\n\t// const expanded = this._renderService.isExpanded(switchElement);\r\n\t// if (expanded) {\r\n\t// return;\r\n\t// }\r\n\r\n\t// const nodeId = this._renderService.getId(switchElement);\r\n\r\n\t// const nodeElements = this._nodeNodes[nodeId].children.map((node) => {\r\n\t// return this._createNodeElement(node);\r\n\t// });\r\n\r\n\t// this._renderService.addChildren(switchElement, nodeElements)\r\n\r\n\t// this._renderService.expand(switchElement, this._switchExpandHandler, this._switchCollapseHandler);\r\n\t// }\r\n\r\n\t// _collapseNode(nodeId) {\r\n\t// const switchElement = this._renderService.getSwitchElement(nodeId);\r\n\t// this._collapseSwitchElement(switchElement);\r\n\t// }\r\n\r\n\t// _collapseSwitchElement(switchElement) {\r\n\t// this._renderService.collapse(switchElement, this._switchExpandHandler, this._switchCollapseHandler);\r\n\t// }\r\n}\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/TreeViewPlugin/TreeViewPlugin.js?");
|
|
2028
2028
|
|
|
2029
2029
|
/***/ }),
|
|
2030
2030
|
|
|
@@ -2154,7 +2154,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2154
2154
|
\********************************************************/
|
|
2155
2155
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2156
2156
|
|
|
2157
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XTCLoaderPlugin: () => (/* binding */ XTCLoaderPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/model/index.js */ \"./src/viewer/scene/model/index.js\");\n/* harmony import */ var _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/metadata/MetaModel.js */ \"./src/viewer/metadata/MetaModel.js\");\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./XTCDefaultDataSource.js */ \"./src/plugins/XTCLoaderPlugin/XTCDefaultDataSource.js\");\n/* harmony import */ var _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/metadata/IFCObjectDefaults.js */ \"./src/viewer/metadata/IFCObjectDefaults.js\");\n/* harmony import */ var _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./parsers/ParserV1.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV1.js\");\n/* harmony import */ var _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./parsers/ParserV2.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV2.js\");\n/* harmony import */ var _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./parsers/ParserV3.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV3.js\");\n/* harmony import */ var _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./parsers/ParserV4.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV4.js\");\n/* harmony import */ var _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./parsers/ParserV5.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV5.js\");\n/* harmony import */ var _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./parsers/ParserV6.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV6.js\");\n/* harmony import */ var _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./parsers/ParserV7.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV7.js\");\n/* harmony import */ var _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./parsers/ParserV8.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV8.js\");\n/* harmony import */ var _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./parsers/ParserV9.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV9.js\");\n/* harmony import */ var _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./parsers/ParserV10.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV10.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst parsers = {};\r\n\r\nparsers[_parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1.version] = _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1;\r\nparsers[_parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2.version] = _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2;\r\nparsers[_parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3.version] = _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3;\r\nparsers[_parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4.version] = _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4;\r\nparsers[_parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5.version] = _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5;\r\nparsers[_parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6.version] = _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6;\r\nparsers[_parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7.version] = _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7;\r\nparsers[_parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8.version] = _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8;\r\nparsers[_parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9.version] = _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9;\r\nparsers[_parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10.version] = _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10;\r\n\r\n/**\r\n * {@link Viewer} plugin that loads models from xeokit's optimized *````.XTC````* format.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter\"><img src=\"http://xeokit.io/img/docs/XTCLoaderPlugin/XTCLoaderPlugin.png\"></a>\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter)]\r\n *\r\n * # Overview\r\n *\r\n * * XTCLoaderPlugin is the most efficient way to load high-detail models into xeokit.\r\n * * An *````.XTC````* file is a single BLOB containing a model, compressed using geometry quantization\r\n * and [pako](https://nodeca.github.io/pako/).\r\n * * Supports double-precision coordinates.\r\n * * Supports compressed textures.\r\n * * Set the position, scale and rotation of each model as you load it.\r\n * * Filter which IFC types get loaded.\r\n * * Configure initial default appearances for IFC types.\r\n * * Set a custom data source for *````.XTC````* and IFC metadata files.\r\n * * Option to load multiple copies of the same model, without object ID clashes.\r\n *\r\n * # Creating *````.XTC````* Files and Metadata\r\n *\r\n * We have several sways to convert your files into XTC. See these tutorials for more info:\r\n *\r\n * * [Converting Models to XTC with convert2xtc](https://www.notion.so/xeokit/Converting-Models-to-XTC-with-convert2xtc-fa567843313f4db8a7d6535e76da9380) - how to convert various file formats (glTF, IFC, CityJSON, LAS/LAZ...) to XTC using our nodejs-based converter.\r\n * * [Converting IFC Models to XTC using 3rd-Party Open Source Tools](https://www.notion.so/xeokit/Converting-IFC-Models-to-XTC-using-3rd-Party-Open-Source-Tools-c373e48bc4094ff5b6e5c5700ff580ee) - how to convert IFC files to XTC using 3rd-party open source CLI tools.\r\n *\r\n * # Scene representation\r\n *\r\n * When loading a model, XTCLoaderPlugin creates an {@link Entity} that represents the model, which\r\n * will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id}\r\n * in {@link Scene#models}. The XTCLoaderPlugin also creates an {@link Entity} for each object within the\r\n * model. Those Entities will have {@link Entity#isObject} set ````true```` and will be registered\r\n * by {@link Entity#id} in {@link Scene#objects}.\r\n *\r\n * # Metadata\r\n *\r\n * Since XTC V8, model metadata is included in the XTC file. If the XTC file has metadata, then loading it creates\r\n * model metadata components within the Viewer, namely a {@link MetaModel} corresponding to the model {@link Entity},\r\n * and a {@link MetaObject} for each object {@link Entity}.\r\n *\r\n * Each {@link MetaObject} has a {@link MetaObject#type}, which indicates the classification of its corresponding\r\n * {@link Entity}. When loading metadata, we can also configure XTCLoaderPlugin with a custom lookup table of initial\r\n * values to set on the properties of each type of {@link Entity}. By default, XTCLoaderPlugin uses its own map of\r\n * default colors and visibilities for IFC element types.\r\n *\r\n * For XTC versions prior to V8, we provided the metadata to XTCLoaderPlugin as an accompanying JSON file to load. We can\r\n * still do that for all XTC versions, and for XTC V8+ it will override any metadata provided within the XTC file.\r\n *\r\n * # Usage\r\n *\r\n * In the example below we'll load the Schependomlaan model from a [.XTC file](https://github.com/xeokit/xeokit-sdk/tree/master/examples/models/xtc/schependomlaan).\r\n *\r\n * This will create a bunch of {@link Entity}s that represents the model and its objects, along with a {@link MetaModel} and {@link MetaObject}s\r\n * that hold their metadata.\r\n *\r\n * Since this model contains IFC types, the XTCLoaderPlugin will set the initial appearance of each object\r\n * {@link Entity} according to its IFC type in {@link XTCLoaderPlugin#objectDefaults}.\r\n *\r\n * Read more about this example in the user guide on [Viewing BIM Models Offline](https://www.notion.so/xeokit/Viewing-an-IFC-Model-with-xeokit-c373e48bc4094ff5b6e5c5700ff580ee).\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_metadata_Schependomlaan)]\r\n *\r\n * ````javascript\r\n * import {Viewer, XTCLoaderPlugin} from \"tctwins-core.es.js\";\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a Viewer,\r\n * // 2. Arrange the camera\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * // 2\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a XTCLoaderPlugin,\r\n * // 2. Load a building model and JSON IFC metadata\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * // 2\r\n * const model = xtcLoader.load({ // Returns an Entity that represents the model\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n *\r\n * model.on(\"loaded\", () => {\r\n *\r\n * //--------------------------------------------------------------------------------------------------------------\r\n * // 1. Find metadata on the third storey\r\n * // 2. Select all the objects in the building's third storey\r\n * // 3. Fit the camera to all the objects on the third storey\r\n * //--------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const metaModel = viewer.metaScene.metaModels[\"myModel\"]; // MetaModel with ID \"myModel\"\r\n * const metaObject\r\n * = viewer.metaScene.metaObjects[\"0u4wgLe6n0ABVaiXyikbkA\"]; // MetaObject with ID \"0u4wgLe6n0ABVaiXyikbkA\"\r\n *\r\n * const name = metaObject.name; // \"01 eerste verdieping\"\r\n * const type = metaObject.type; // \"IfcBuildingStorey\"\r\n * const parent = metaObject.parent; // MetaObject with type \"IfcBuilding\"\r\n * const children = metaObject.children; // Array of child MetaObjects\r\n * const objectId = metaObject.id; // \"0u4wgLe6n0ABVaiXyikbkA\"\r\n * const objectIds = viewer.metaScene.getObjectIDsInSubtree(objectId); // IDs of leaf sub-objects\r\n * const aabb = viewer.scene.getAABB(objectIds); // Axis-aligned boundary of the leaf sub-objects\r\n *\r\n * // 2\r\n * viewer.scene.setObjectsSelected(objectIds, true);\r\n *\r\n * // 3\r\n * viewer.cameraFlight.flyTo(aabb);\r\n * });\r\n *\r\n * // Find the model Entity by ID\r\n * model = viewer.scene.models[\"myModel\"];\r\n *\r\n * // Destroy the model\r\n * model.destroy();\r\n * ````\r\n *\r\n * # Loading XTC files containing textures\r\n *\r\n * XTCLoaderPlugin uses a {@link KTX2TextureTranscoder} to load textures in XTC files (XTC v10+). An XTCLoaderPlugin has its own\r\n * default KTX2TextureTranscoder, configured to load the Basis Codec from the CDN. If we wish, we can override that with our own\r\n * KTX2TextureTranscoder instance that's configured to load the Codec locally.\r\n *\r\n * In the example below, we'll create a {@link Viewer} and add an XTCLoaderPlugin\r\n * configured with a KTX2TextureTranscoder that finds the Codec in our local file system. Then we'll use the\r\n * XTCLoaderPlugin to load an XTC file that contains KTX2 textures, which the plugin will transcode using\r\n * its KTX2TextureTranscoder.\r\n *\r\n * We'll configure our KTX2TextureTranscoder to load the Basis Codec from a local directory. If we were happy with loading the\r\n * Codec from our CDN (ie. our app will always have an Internet connection) then we could just leave out the\r\n * KTX2TextureTranscoder altogether, and let the XTCLoaderPlugin use its internal default KTX2TextureTranscoder, which is configured to\r\n * load the Codec from the CDN. We'll stick with loading our own Codec, in case we want to run our app without an Internet connection.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan\"><img src=\"https://xeokit.github.io/xeokit-sdk/assets/images/xtcWithTextures.png\"></a>\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan)]\r\n *\r\n * ````javascript\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const textureTranscoder = new KTX2TextureTranscoder({\r\n * viewer,\r\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to Basis Universal transcoder\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * textureTranscoder // <<------------- Transcodes KTX2 textures in XTC files\r\n * });\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./HousePlan.xtc\" // <<------ XTC file with KTX2 textures\r\n * });\r\n * ````\r\n *\r\n * # Transforming\r\n *\r\n * We have the option to rotate, scale and translate each *````.XTC````* model as we load it.\r\n *\r\n * This lets us load multiple models, or even multiple copies of the same model, and position them apart from each other.\r\n *\r\n * In the example below, we'll scale our model to half its size, rotate it 90 degrees about its local X-axis, then\r\n * translate it 100 units along its X axis.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Duplex_transform)]\r\n *\r\n * ````javascript\r\n * xtcLoader.load({\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * rotation: [90,0,0],\r\n * scale: [0.5, 0.5, 0.5],\r\n * position: [100, 0, 0]\r\n * });\r\n * ````\r\n *\r\n * # Including and excluding IFC types\r\n *\r\n * We can also load only those objects that have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that represent walls.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_includeTypes)]\r\n *\r\n * ````javascript\r\n * const model2 = xtcLoader.load({\r\n * id: \"myModel2\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * includeTypes: [\"IfcWallStandardCase\"]\r\n * });\r\n * ````\r\n *\r\n * We can also load only those objects that **don't** have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that do not represent empty space.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_excludeTypes)]\r\n *\r\n * ````javascript\r\n * const model3 = xtcLoader.load({\r\n * id: \"myModel3\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * excludeTypes: [\"IfcSpace\"]\r\n * });\r\n * ````\r\n *\r\n * # Configuring initial IFC object appearances\r\n *\r\n * We can specify the custom initial appearance of loaded objects according to their IFC types.\r\n *\r\n * This is useful for things like:\r\n *\r\n * * setting the colors to our objects according to their IFC types,\r\n * * automatically hiding ````IfcSpace```` objects, and\r\n * * ensuring that ````IfcWindow```` objects are always transparent.\r\n * <br>\r\n * In the example below, we'll load a model, while configuring ````IfcSpace```` elements to be always initially invisible,\r\n * and ````IfcWindow```` types to be always translucent blue.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_objectDefaults)]\r\n *\r\n * ````javascript\r\n * const myObjectDefaults = {\r\n *\r\n * IfcSpace: {\r\n * visible: false\r\n * },\r\n * IfcWindow: {\r\n * colorize: [0.337255, 0.303922, 0.870588], // Blue\r\n * opacity: 0.3\r\n * },\r\n *\r\n * //...\r\n *\r\n * DEFAULT: {\r\n * colorize: [0.5, 0.5, 0.5]\r\n * }\r\n * };\r\n *\r\n * const model4 = xtcLoader.load({\r\n * id: \"myModel4\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * objectDefaults: myObjectDefaults // Use our custom initial default states for object Entities\r\n * });\r\n * ````\r\n *\r\n * When we don't customize the appearance of IFC types, as just above, then IfcSpace elements tend to obscure other\r\n * elements, which can be confusing.\r\n *\r\n * It's often helpful to make IfcSpaces transparent and unpickable, like this:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * pickable: false,\r\n * opacity: 0.2\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * Alternatively, we could just make IfcSpaces invisible, which also makes them unpickable:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * visible: false\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * # Configuring a custom data source\r\n *\r\n * By default, XTCLoaderPlugin will load *````.XTC````* files and metadata JSON over HTTP.\r\n *\r\n * In the example below, we'll customize the way XTCLoaderPlugin loads the files by configuring it with our own data source\r\n * object. For simplicity, our custom data source example also uses HTTP, using a couple of xeokit utility functions.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_dataSource)]\r\n *\r\n * ````javascript\r\n * import {utils} from \"tctwins-core.es.js\";\r\n *\r\n * class MyDataSource {\r\n *\r\n * constructor() {\r\n * }\r\n *\r\n * // Gets metamodel JSON\r\n * getMetaModel(metaModelSrc, ok, error) {\r\n * console.log(\"MyDataSource#getMetaModel(\" + metaModelSrc + \", ... )\");\r\n * utils.loadJSON(metaModelSrc,\r\n * (json) => {\r\n * ok(json);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n *\r\n * // Gets the contents of the given .XTC file in an arraybuffer\r\n * getXTC(xTCSrc, ok, error) {\r\n * console.log(\"MyDataSource#getXTC(\" + xTCSrc + \", ... )\");\r\n * utils.loadArraybuffer(xTCSrc,\r\n * (arraybuffer) => {\r\n * ok(arraybuffer);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n * }\r\n *\r\n * const xtcLoader2 = new XTCLoaderPlugin(viewer, {\r\n * dataSource: new MyDataSource()\r\n * });\r\n *\r\n * const model5 = xtcLoader2.load({\r\n * id: \"myModel5\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\"\r\n * });\r\n * ````\r\n *\r\n * # Loading multiple copies of a model, without object ID clashes\r\n *\r\n * Sometimes we need to load two or more instances of the same model, without having clashes\r\n * between the IDs of the equivalent objects in the model instances.\r\n *\r\n * As shown in the example below, we do this by setting {@link XTCLoaderPlugin#globalizeObjectIds} ````true```` before we load our models.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#TreeViewPlugin_Containment_MultipleModels)]\r\n *\r\n * ````javascript\r\n * xtcLoader.globalizeObjectIds = true;\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"model1\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n *\r\n * const model2 = xtcLoader.load({\r\n * id: \"model2\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n * ````\r\n *\r\n * For each {@link Entity} loaded by these two calls, {@link Entity#id} and {@link MetaObject#id} will get prefixed by\r\n * the ID of their model, in order to avoid ID clashes between the two models.\r\n *\r\n * An Entity belonging to the first model will get an ID like this:\r\n *\r\n * ````\r\n * myModel1#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * The equivalent Entity in the second model will get an ID like this:\r\n *\r\n * ````\r\n * myModel2#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * Now, to update the visibility of both of those Entities collectively, using {@link Scene#setObjectsVisible}, we can\r\n * supply just the IFC product ID part to that method:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n * ````\r\n *\r\n * The method, along with {@link Scene#setObjectsXRayed}, {@link Scene#setObjectsHighlighted} etc, will internally expand\r\n * the given ID to refer to the instances of that Entity in both models.\r\n *\r\n * We can also, of course, reference each Entity directly, using its globalized ID:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"myModel1#0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n *````\r\n *\r\n * We can also provide an HTTP URL to the XTC file:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/models/xtc/Schependomlaan.xtc\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * # Loading a model from a manifest of XTC files\r\n *\r\n * The `ifc2gltf` tool from Creoox, which converts IFC files into glTF geometry and JSON metadata files, has the option to\r\n * split its output into multiple pairs of glTF and JSON files, accompanied by a JSON manifest that lists the files.\r\n *\r\n * To integrate with that option, the `convert2xtc` tool, which converts glTF geometry and JSON metadata files into XTC files,\r\n * also has the option to batch-convert the glTF+JSON files in the manifest, in one invocation.\r\n *\r\n * When we use this option, convert2xtc will output a bunch of XTC files, along with a JSON manifest file that lists those XTC files.\r\n *\r\n * Working down the pipeline, the XTCLoaderPlugin has the option batch-load all XTC files listed in that manifest\r\n * into a xeokit Viewer in one load operation, combining the XTC files into a single SceneModel and MetaModel.\r\n *\r\n * You can learn more about this conversion and loading process, with splitting, batch converting and batch loading,\r\n * in [this tutorial](https://www.notion.so/xeokit/Importing-Huge-IFC-Models-as-Multiple-XTC-Files-165fc022e94742cf966ee50003572259).\r\n *\r\n * To show how to use XTCLoaderPlugin to load a manifest of XTC files, let's imagine that we have a set of such XTC files. As\r\n * described in the tutorial, they were converted by `ifc2gltf` from an IFC file into a set of glTF+JSON files, that were\r\n * then converted by convert2xtc into this set of XTC files and a manifest, as shown below.\r\n *\r\n * ````bash\r\n * ./\r\n * ├── model_1.xtc\r\n * ├── model_2.xtc\r\n * ├── model_3.xtc\r\n * ├── model_4..xtc\r\n * └── model.xtc.manifest.json\r\n * ````\r\n *\r\n * The `model.xtc.manifest.json` XTC manifest would look something like this:\r\n *\r\n * ````json\r\n * {\r\n * \"inputFile\": null,\r\n * \"converterApplication\": \"convert2xtc\",\r\n * \"converterApplicationVersion\": \"v1.1.9\",\r\n * \"conversionDate\": \"10-08-2023- 02-05-01\",\r\n * \"outputDir\": null,\r\n * \"xtcFiles\": [\r\n * \"model_1.xtc\",\r\n * \"model_2.xtc\",\r\n * \"model_3.xtc\",\r\n * \"model_4.xtc\"\r\n * ]\r\n * }\r\n * ````\r\n *\r\n * Now, to load all those XTC files into a single SceneModel and MetaModel in one operation, we pass a path to the XTC\r\n * manifest to `XTCLoaderPlugin.load`, as shown in the example below:\r\n *\r\n * ````javascript\r\n * import {\r\n * Viewer,\r\n * XTCLoaderPlugin,\r\n * TreeViewPlugin,\r\n * } from \"tctwins-core.es.js\";\r\n *\r\n * constviewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [26.54, 29.29, 36.20,];\r\n * viewer.scene.camera.look = [-23.51, -8.26, -21.65,];\r\n * viewer.scene.camera.up = [-0.2, 0.89, -0.33,];\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n *\r\n * const metaModel = viewer.metaScene.metaModels[sceneModel.id];\r\n *\r\n * // Then when we need to, we can destroy the SceneModel\r\n * // and MetaModel in one shot, like so:\r\n *\r\n * sceneModel.destroy();\r\n * metaModel.destroy();\r\n * ````\r\n *\r\n * The main advantage here, of splitting IFC files like this within the conversion and import pipeline,\r\n * is to reduce the memory pressure on each of the `ifc2gltf`, `convert2xtc` and XTCLoaderPlugin components.\r\n * They work much reliably (and faster) when processing smaller files (eg. 20MB) than when processing large files (eg. 500MB), where\r\n * they have less trouble allocating the system memory they need for conversion and parsing.\r\n *\r\n * We can also provide an HTTP URL to the manifest:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * We can also provide the manifest as parameter object:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * We can also provide the paths to the XTC files as HTTP URLs:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * @class XTCLoaderPlugin\r\n */\r\nclass XTCLoaderPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t *\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {Object} cfg Plugin configuration.\r\n\t * @param {String} [cfg.id=\"XTCLoader\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {Object} [cfg.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {Object} [cfg.dataSource] A custom data source through which the XTCLoaderPlugin can load model and metadata files. Defaults to an instance of {@link XTCDefaultDataSource}, which loads uover HTTP.\r\n\t * @param {String[]} [cfg.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [cfg.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [cfg.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have a lot of geometry reuse, but may also increase the amount of\r\n\t * browser and GPU memory they require. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\r\n\t * to limit the size of the batched geometry arrays that {@link SceneModel} internally creates for batched geometries.\r\n\t * A low value means less heap allocation/de-allocation while loading batched geometries, but more draw calls and\r\n\t * slower rendering speed. A high value means larger heap allocation/de-allocation while loading, but less draw calls\r\n\t * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\r\n\t * @param {KTX2TextureTranscoder} [cfg.textureTranscoder] Transcoder used internally to transcode KTX2\r\n\t * textures within the XTC. Only required when the XTC is version 10 or later, and contains KTX2 textures.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"XTCLoader\", viewer, cfg);\r\n\r\n\t\tthis._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\r\n\r\n\t\tthis.textureTranscoder = cfg.textureTranscoder;\r\n\t\tthis.dataSource = cfg.dataSource;\r\n\t\tthis.objectDefaults = cfg.objectDefaults;\r\n\t\tthis.includeTypes = cfg.includeTypes;\r\n\t\tthis.excludeTypes = cfg.excludeTypes;\r\n\t\tthis.excludeUnclassifiedObjects = cfg.excludeUnclassifiedObjects;\r\n\t\tthis.reuseGeometries = cfg.reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the ````.xtc```` format versions supported by this XTCLoaderPlugin/\r\n\t * @returns {string[]}\r\n\t */\r\n\tget supportedVersions() {\r\n\t\treturn Object.keys(parsers);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tget textureTranscoder() {\r\n\t\treturn this._textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tset textureTranscoder(textureTranscoder) {\r\n\t\tthis._textureTranscoder = textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tget dataSource() {\r\n\t\treturn this._dataSource;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tset dataSource(value) {\r\n\t\tthis._dataSource = value || new _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__.XTCDefaultDataSource();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tget objectDefaults() {\r\n\t\treturn this._objectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tset objectDefaults(value) {\r\n\t\tthis._objectDefaults = value || _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__.IFCObjectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget includeTypes() {\r\n\t\treturn this._includeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset includeTypes(value) {\r\n\t\tthis._includeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget excludeTypes() {\r\n\t\treturn this._excludeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset excludeTypes(value) {\r\n\t\tthis._excludeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget excludeUnclassifiedObjects() {\r\n\t\treturn this._excludeUnclassifiedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset excludeUnclassifiedObjects(value) {\r\n\t\tthis._excludeUnclassifiedObjects = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget globalizeObjectIds() {\r\n\t\treturn this._globalizeObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Set this ````true```` when you need to load multiple instances of the same model, to avoid ID clashes\r\n\t * between the objects in the different instances.\r\n\t *\r\n\t * When we load a model with this set ````true````, then each {@link Entity#id} and {@link MetaObject#id} will be\r\n\t * prefixed by the ID of the model, ie. ````<modelId>#<objectId>````.\r\n\t *\r\n\t * {@link Entity#originalSystemId} and {@link MetaObject#originalSystemId} will always hold the original, un-prefixed, ID values.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * See the main {@link XTCLoaderPlugin} class documentation for usage info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset globalizeObjectIds(value) {\r\n\t\tthis._globalizeObjectIds = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget reuseGeometries() {\r\n\t\treturn this._reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * Geometry reuse saves memory, but can impact Viewer performance when there are many reused geometries. For\r\n\t * this reason, we can set this ````false```` to disable geometry reuse for models loaded by this XTCLoaderPlugin\r\n\t * (which will then \"expand\" the geometry instances into batches instead).\r\n\t *\r\n\t * The result will be be less WebGL draw calls (which are expensive), at the cost of increased memory footprint.\r\n\t *\r\n\t * See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset reuseGeometries(value) {\r\n\t\tthis._reuseGeometries = value !== false;\r\n\t}\r\n\r\n\t/**\r\n\t * Loads an ````.xtc```` model into this XTCLoaderPlugin's {@link Viewer}.\r\n\t *\r\n\t * Since xeokit/xeokit-sdk 1.9.0, XTCLoaderPlugin has supported XTC 8, which bundles the metamodel\r\n\t * data (eg. an IFC element hierarchy) in the XTC file itself. For XTC 8, we therefore no longer need to\r\n\t * load the metamodel data from a separate accompanying JSON file, as we did with previous XTC versions.\r\n\t * However, if we do choose to specify a separate metamodel JSON file to load (eg. for backward compatibility\r\n\t * in data pipelines), then that metamodel will be loaded and the metamodel in the XTC 8 file will be ignored.\r\n\t *\r\n\t * @param {*} params Loading parameters.\r\n\t * @param {String} [params.id] ID to assign to the root {@link Entity#id}, unique among all components in the Viewer's {@link Scene}, generated automatically by default.\r\n\t * @param {String} [params.src] Path or URL to an *````.xtc````* file, as an alternative to the ````xtc```` parameter.\r\n\t * @param {ArrayBuffer} [params.xtc] The *````.xtc````* file data, as an alternative to the ````src```` parameter.\r\n\t * @param {String} [params.metaModelSrc] Path or URL to an optional metadata file, as an alternative to the ````metaModelData```` parameter.\r\n\t * @param {*} [params.metaModelData] JSON model metadata, as an alternative to the ````metaModelSrc```` parameter.\r\n\t * @param {String} [params.manifestSrc] Path or URL to a JSON manifest file that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {Object} [params.manifest] A JSON manifest object (as an alternative to a path or URL) that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {{String:Object}} [params.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {String[]} [params.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [params.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [params.edges=false] Whether or not xeokit renders the model with edges emphasized.\r\n\t * @param {Number[]} [params.origin=[0,0,0]] The model's World-space double-precision 3D origin. Use this to position the model within xeokit's World coordinate system, using double-precision coordinates.\r\n\t * @param {Number[]} [params.position=[0,0,0]] The model single-precision 3D position, relative to the ````origin```` parameter.\r\n\t * @param {Number[]} [params.scale=[1,1,1]] The model's scale.\r\n\t * @param {Number[]} [params.rotation=[0,0,0]] The model's orientation, given as Euler angles in degrees, for each of the X, Y and Z axis.\r\n\t * @param {Number[]} [params.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] The model's world transform matrix. Overrides the position, scale and rotation parameters. Relative to ````origin````.\r\n\t * @param {Boolean} [params.edges=false] Indicates if the model's edges are initially emphasized.\r\n\t * @param {Boolean} [params.saoEnabled=true] Indicates if Scalable Ambient Obscurance (SAO) is enabled for the model. SAO is configured by the Scene's {@link SAO} component. Only works when {@link SAO#enabled} is also ````true````\r\n\t * @param {Boolean} [params.pbrEnabled=true] Indicates if physically-based rendering (PBR) is enabled for the model. Overrides ````colorTextureEnabled````. Only works when {@link Scene#pbrEnabled} is also ````true````.\r\n\t * @param {Boolean} [params.colorTextureEnabled=true] Indicates if base color texture rendering is enabled for the model. Overridden by ````pbrEnabled````. Only works when {@link Scene#colorTextureEnabled} is also ````true````.\r\n\t * @param {Number} [params.backfaces=false] When we set this ````true````, then we force rendering of backfaces for the model. When\r\n\t * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\r\n\t * Viewer will hide backfaces on watertight meshes, show backfaces on open meshes, and always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\r\n\t * @param {Boolean} [params.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [params.globalizeObjectIds=false] Indicates whether to globalize each {@link Entity#id} and {@link MetaObject#id}, in case you need to prevent ID clashes with other models. See {@link XTCLoaderPlugin#globalizeObjectIds} for more info.\r\n\t * @param {Boolean} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have excessive geometry reuse, but may also increases the amount of\r\n\t * browser and GPU memory used by the model. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\r\n\t * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\r\n\t * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\r\n\t * primitives. Only works while {@link DTX#enabled} is also ````true````.\r\n\t * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}.\r\n\t */\r\n\tload(params = {}) {\r\n\t\tif (params.id && this.viewer.scene.components[params.id]) {\r\n\t\t\tthis.error(\"Component with this ID already exists in viewer: \" + params.id + \" - will autogenerate this ID\");\r\n\t\t\tdelete params.id;\r\n\t\t}\r\n\r\n\t\tif (!params.src && !params.xtc && !params.manifestSrc && !params.manifest) {\r\n\t\t\tthis.error(\"load() param expected: src, xtc, manifestSrc or manifestData\");\r\n\t\t\treturn sceneModel; // Return new empty model\r\n\t\t}\r\n\r\n\t\tconst options = {};\r\n\t\tconst includeTypes = params.includeTypes || this._includeTypes;\r\n\t\tconst excludeTypes = params.excludeTypes || this._excludeTypes;\r\n\t\tconst objectDefaults = params.objectDefaults || this._objectDefaults;\r\n\r\n\t\toptions.reuseGeometries =\r\n\t\t\tparams.reuseGeometries !== null && params.reuseGeometries !== undefined\r\n\t\t\t\t? params.reuseGeometries\r\n\t\t\t\t: this._reuseGeometries !== false;\r\n\r\n\t\tif (includeTypes) {\r\n\t\t\toptions.includeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = includeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.includeTypesMap[includeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (excludeTypes) {\r\n\t\t\toptions.excludeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = excludeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.excludeTypesMap[excludeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (objectDefaults) {\r\n\t\t\toptions.objectDefaults = objectDefaults;\r\n\t\t}\r\n\r\n\t\toptions.excludeUnclassifiedObjects =\r\n\t\t\tparams.excludeUnclassifiedObjects !== undefined\r\n\t\t\t\t? !!params.excludeUnclassifiedObjects\r\n\t\t\t\t: this._excludeUnclassifiedObjects;\r\n\t\toptions.globalizeObjectIds =\r\n\t\t\tparams.globalizeObjectIds !== undefined && params.globalizeObjectIds !== null\r\n\t\t\t\t? !!params.globalizeObjectIds\r\n\t\t\t\t: this._globalizeObjectIds;\r\n\r\n\t\tconst sceneModel = new _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__.SceneModel(\r\n\t\t\tthis.viewer.scene,\r\n\t\t\t_viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.apply(params, {\r\n\t\t\t\tisModel: true,\r\n\t\t\t\ttextureTranscoder: this._textureTranscoder,\r\n\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\r\n\t\t\t\torigin: params.origin,\r\n\t\t\t\tdisableVertexWelding: params.disableVertexWelding || false,\r\n\t\t\t\tdisableIndexRebucketing: params.disableIndexRebucketing || false,\r\n\t\t\t\tdtxEnabled: params.dtxEnabled\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst modelId = sceneModel.id; // In case ID was auto-generated\r\n\r\n\t\tconst metaModel = new _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__.MetaModel({\r\n\t\t\tmetaScene: this.viewer.metaScene,\r\n\t\t\tid: modelId\r\n\t\t});\r\n\r\n\t\tthis.viewer.scene.canvas.spinner.processes++;\r\n\r\n\t\tconst finish = () => {\r\n\t\t\t// this._createDefaultMetaModelIfNeeded(sceneModel, params, options);\r\n\t\t\tsceneModel.finalize();\r\n\t\t\tmetaModel.finalize();\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tsceneModel.once(\"destroyed\", () => {\r\n\t\t\t\tthis.viewer.metaScene.destroyMetaModel(metaModel.id);\r\n\t\t\t});\r\n\t\t\tthis.scheduleTask(() => {\r\n\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tsceneModel.scene.fire(\"modelLoaded\", sceneModel.id); // FIXME: Assumes listeners know order of these two events\r\n\t\t\t\tsceneModel.fire(\"loaded\", true, false); // Don't forget the event, for late subscribers\r\n\t\t\t});\r\n\t\t};\r\n\r\n\t\tconst error = (errMsg) => {\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tthis.error(errMsg);\r\n\t\t\tsceneModel.fire(\"error\", errMsg);\r\n\t\t};\r\n\r\n\t\tlet nextId = 0;\r\n\t\tconst manifestCtx = {\r\n\t\t\tgetNextId: () => {\r\n\t\t\t\treturn `${modelId}.${nextId++}`;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t//模型文件\r\n\t\tif (params.metaModelSrc || params.metaModelData) {\r\n\t\t\tif (params.metaModelSrc) {\r\n\t\t\t\tconst metaModelSrc = params.metaModelSrc;\r\n\r\n\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\tmetaModelSrc,\r\n\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tif (params.src) {\r\n\t\t\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\t\t\tfinish();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(errMsg) => {\r\n\t\t\t\t\t\terror(`load(): Failed to load model metadata for model '${modelId} from '${metaModelSrc}' - ${errMsg}`);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t} else if (params.metaModelData) {\r\n\t\t\t\tmetaModel.loadData(params.metaModelData, {\r\n\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t});\r\n\t\t\t\tif (params.src) {\r\n\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\tfinish();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (params.src) {\r\n\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, metaModel, manifestCtx, finish, error);\r\n\t\t\t} else if (params.xtc) {\r\n\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tfinish();\r\n\t\t\t} else if (params.manifestSrc || params.manifest) {\r\n\t\t\t\tconst baseDir = params.manifestSrc ? getBaseDirectory(params.manifestSrc) : \"\";\r\n\t\t\t\tconst loadJSONs = (metaDataFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= metaDataFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\t\t\t\t`${baseDir}${metaDataFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tconst loadXTCs = (xtcFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= xtcFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getXTC(\r\n\t\t\t\t\t\t\t\t`${baseDir}${xtcFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(arrayBuffer) => {\r\n\t\t\t\t\t\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tif (params.manifest) {\r\n\t\t\t\t\tconst manifestData = params.manifest;\r\n\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._dataSource.getManifest(\r\n\t\t\t\t\t\tparams.manifestSrc,\r\n\t\t\t\t\t\t(manifestData) => {\r\n\t\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\terror\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn sceneModel;\r\n\t}\r\n\r\n\t_loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) {\r\n\t\tthis._dataSource.getXTC(\r\n\t\t\tparams.src,\r\n\t\t\t(arrayBuffer) => {\r\n\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tdone();\r\n\t\t\t},\r\n\t\t\terror\r\n\t\t);\r\n\t}\r\n\r\n\t_parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {\r\n\t\tif (sceneModel.destroyed) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst dataView = new DataView(arrayBuffer);\r\n\t\tconst dataArray = new Uint8Array(arrayBuffer);\r\n\t\tconst xtcVersion = dataView.getUint32(0, true);\r\n\t\tconst parser = parsers[xtcVersion];\r\n\t\tif (!parser) {\r\n\t\t\tthis.error(\r\n\t\t\t\t\"Unsupported .XTC file version: \" +\r\n\t\t\t\t\txtcVersion +\r\n\t\t\t\t\t\" - this XTCLoaderPlugin supports versions \" +\r\n\t\t\t\t\tObject.keys(parsers)\r\n\t\t\t);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.log(\"Loading .xtc V\" + xtcVersion);\r\n\t\tconst numElements = dataView.getUint32(4, true);\r\n\t\tconst elements = [];\r\n\t\tlet byteOffset = (numElements + 2) * 4;\r\n\t\tfor (let i = 0; i < numElements; i++) {\r\n\t\t\tconst elementSize = dataView.getUint32((i + 2) * 4, true);\r\n\t\t\telements.push(dataArray.subarray(byteOffset, byteOffset + elementSize));\r\n\t\t\tbyteOffset += elementSize;\r\n\t\t}\r\n\t\tparser.parse(this.viewer, options, elements, sceneModel, metaModel, manifestCtx);\r\n\t}\r\n\r\n\tloadMetadata(metaModel, deflatedMetadata, done) {\r\n\t\tmetaModel._finalized = false;\r\n\r\n\t\ttry {\r\n\t\t\t{\r\n\t\t\t\tthis._workerInflate(\r\n\t\t\t\t\tmetaModel,\r\n\t\t\t\t\tdeflatedMetadata,\r\n\t\t\t\t\t(worker) => {\r\n\t\t\t\t\t\tworker.terminate();\r\n\t\t\t\t\t\tthis.fire(\"metaloaded\", { result: \"success\", metaModel });\r\n\t\t\t\t\t\tdone();\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(err) => {\r\n\t\t\t\t\t\tthrow err;\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tthis.fire(\"metaloaded\", { result: error, metaModel });\r\n\t\t}\r\n\t}\r\n\r\n\t_workerInflate(metaModel, buffer, done, err) {\r\n\t\tconst plugin = this;\r\n\t\tconst worker = createInlineWorker();\r\n\t\tworker.postMessage({\r\n\t\t\tbuffer\r\n\t\t\t// executionTime: new Date().getTime()\r\n\t\t});\r\n\r\n\t\tworker.onmessage = function (e) {\r\n\t\t\tplugin.fire(\"metaLoading\");\r\n\t\t\tmetaModel.loadData(e.data.metaJson);\r\n\t\t\tmetaModel.finalize();\r\n\t\t\tif (typeof done === \"function\") done(worker);\r\n\t\t\telse worker.terminate();\r\n\t\t};\r\n\t\tworker.onerror = function (e) {\r\n\t\t\tif (typeof err === \"function\") err(e);\r\n\t\t\tworker.terminate();\r\n\t\t};\r\n\t}\r\n\r\n\t// _createDefaultMetaModelIfNeeded(sceneModel, params, options) {\r\n\t//\r\n\t// const metaModelId = sceneModel.id;\r\n\t//\r\n\t// if (!this.viewer.metaScene.metaModels[metaModelId]) {\r\n\t//\r\n\t// const metaModelData = {\r\n\t// metaObjects: []\r\n\t// };\r\n\t//\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: metaModelId,\r\n\t// type: \"default\",\r\n\t// name: metaModelId,\r\n\t// parent: null\r\n\t// });\r\n\t//\r\n\t// const entityList = sceneModel.entityList;\r\n\t//\r\n\t// for (let i = 0, len = entityList.length; i < len; i++) {\r\n\t// const entity = entityList[i];\r\n\t// if (entity.isObject) {\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: entity.id,\r\n\t// type: \"default\",\r\n\t// name: entity.id,\r\n\t// parent: metaModelId\r\n\t// });\r\n\t// }\r\n\t// }\r\n\t//\r\n\t// const src = params.src;\r\n\t//\r\n\t// this.viewer.metaScene.createMetaModel(metaModelId, metaModelData, {\r\n\t//\r\n\t// includeTypes: options.includeTypes,\r\n\t// excludeTypes: options.excludeTypes,\r\n\t// globalizeObjectIds: options.globalizeObjectIds,\r\n\t//\r\n\t// getProperties: async (propertiesId) => {\r\n\t// return await this._dataSource.getProperties(src, propertiesId);\r\n\t// }\r\n\t// });\r\n\t//\r\n\t// sceneModel.once(\"destroyed\", () => {\r\n\t// this.viewer.metaScene.destroyMetaModel(metaModelId);\r\n\t// });\r\n\t// }\r\n\t// }\r\n}\r\n\r\nfunction getBaseDirectory(filePath) {\r\n\tconst pathArray = filePath.split(\"/\");\r\n\tpathArray.pop(); // Remove the file name or the last segment of the path\r\n\treturn pathArray.join(\"/\") + \"/\";\r\n}\r\nfunction createInlineWorker() {\r\n\tconst workerCode = `\r\n self.importScripts('https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako.min.js');\r\n \r\n function inflateMetadata(deflatedData) {\r\n return JSON.parse(self.pako.inflate(deflatedData, { to: \"string\" }));\r\n }\r\n \r\n self.onmessage = function (e) {\r\n console.log(\"start worker:\");\r\n const metaJson = inflateMetadata(e.data.buffer);\r\n\r\n self.postMessage({\r\n metaJson,\r\n time: new Date().getTime()\r\n });\r\n };\r\n `;\r\n\tconst blob = new Blob([workerCode], { type: \"application/javascript\" });\r\n\tconst workerUrl = URL.createObjectURL(blob);\r\n\treturn new Worker(workerUrl);\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XTCLoaderPlugin/XTCLoaderPlugin.js?");
|
|
2157
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ XTCLoaderPlugin: () => (/* binding */ XTCLoaderPlugin)\n/* harmony export */ });\n/* harmony import */ var _viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../viewer/scene/utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../viewer/scene/model/index.js */ \"./src/viewer/scene/model/index.js\");\n/* harmony import */ var _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../viewer/metadata/MetaModel.js */ \"./src/viewer/metadata/MetaModel.js\");\n/* harmony import */ var _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../viewer/Plugin.js */ \"./src/viewer/Plugin.js\");\n/* harmony import */ var _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./XTCDefaultDataSource.js */ \"./src/plugins/XTCLoaderPlugin/XTCDefaultDataSource.js\");\n/* harmony import */ var _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../viewer/metadata/IFCObjectDefaults.js */ \"./src/viewer/metadata/IFCObjectDefaults.js\");\n/* harmony import */ var _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./parsers/ParserV1.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV1.js\");\n/* harmony import */ var _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./parsers/ParserV2.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV2.js\");\n/* harmony import */ var _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./parsers/ParserV3.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV3.js\");\n/* harmony import */ var _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./parsers/ParserV4.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV4.js\");\n/* harmony import */ var _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./parsers/ParserV5.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV5.js\");\n/* harmony import */ var _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./parsers/ParserV6.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV6.js\");\n/* harmony import */ var _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./parsers/ParserV7.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV7.js\");\n/* harmony import */ var _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./parsers/ParserV8.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV8.js\");\n/* harmony import */ var _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./parsers/ParserV9.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV9.js\");\n/* harmony import */ var _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./parsers/ParserV10.js */ \"./src/plugins/XTCLoaderPlugin/parsers/ParserV10.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst parsers = {};\r\n\r\nparsers[_parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1.version] = _parsers_ParserV1_js__WEBPACK_IMPORTED_MODULE_6__.ParserV1;\r\nparsers[_parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2.version] = _parsers_ParserV2_js__WEBPACK_IMPORTED_MODULE_7__.ParserV2;\r\nparsers[_parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3.version] = _parsers_ParserV3_js__WEBPACK_IMPORTED_MODULE_8__.ParserV3;\r\nparsers[_parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4.version] = _parsers_ParserV4_js__WEBPACK_IMPORTED_MODULE_9__.ParserV4;\r\nparsers[_parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5.version] = _parsers_ParserV5_js__WEBPACK_IMPORTED_MODULE_10__.ParserV5;\r\nparsers[_parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6.version] = _parsers_ParserV6_js__WEBPACK_IMPORTED_MODULE_11__.ParserV6;\r\nparsers[_parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7.version] = _parsers_ParserV7_js__WEBPACK_IMPORTED_MODULE_12__.ParserV7;\r\nparsers[_parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8.version] = _parsers_ParserV8_js__WEBPACK_IMPORTED_MODULE_13__.ParserV8;\r\nparsers[_parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9.version] = _parsers_ParserV9_js__WEBPACK_IMPORTED_MODULE_14__.ParserV9;\r\nparsers[_parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10.version] = _parsers_ParserV10_js__WEBPACK_IMPORTED_MODULE_15__.ParserV10;\r\n\r\n/**\r\n * {@link Viewer} plugin that loads models from xeokit's optimized *````.XTC````* format.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter\"><img src=\"http://xeokit.io/img/docs/XTCLoaderPlugin/XTCLoaderPlugin.png\"></a>\r\n *\r\n * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_OTCConferenceCenter)]\r\n *\r\n * # Overview\r\n *\r\n * * XTCLoaderPlugin is the most efficient way to load high-detail models into xeokit.\r\n * * An *````.XTC````* file is a single BLOB containing a model, compressed using geometry quantization\r\n * and [pako](https://nodeca.github.io/pako/).\r\n * * Supports double-precision coordinates.\r\n * * Supports compressed textures.\r\n * * Set the position, scale and rotation of each model as you load it.\r\n * * Filter which IFC types get loaded.\r\n * * Configure initial default appearances for IFC types.\r\n * * Set a custom data source for *````.XTC````* and IFC metadata files.\r\n * * Option to load multiple copies of the same model, without object ID clashes.\r\n *\r\n * # Creating *````.XTC````* Files and Metadata\r\n *\r\n * We have several sways to convert your files into XTC. See these tutorials for more info:\r\n *\r\n * * [Converting Models to XTC with convert2xtc](https://www.notion.so/xeokit/Converting-Models-to-XTC-with-convert2xtc-fa567843313f4db8a7d6535e76da9380) - how to convert various file formats (glTF, IFC, CityJSON, LAS/LAZ...) to XTC using our nodejs-based converter.\r\n * * [Converting IFC Models to XTC using 3rd-Party Open Source Tools](https://www.notion.so/xeokit/Converting-IFC-Models-to-XTC-using-3rd-Party-Open-Source-Tools-c373e48bc4094ff5b6e5c5700ff580ee) - how to convert IFC files to XTC using 3rd-party open source CLI tools.\r\n *\r\n * # Scene representation\r\n *\r\n * When loading a model, XTCLoaderPlugin creates an {@link Entity} that represents the model, which\r\n * will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id}\r\n * in {@link Scene#models}. The XTCLoaderPlugin also creates an {@link Entity} for each object within the\r\n * model. Those Entities will have {@link Entity#isObject} set ````true```` and will be registered\r\n * by {@link Entity#id} in {@link Scene#objects}.\r\n *\r\n * # Metadata\r\n *\r\n * Since XTC V8, model metadata is included in the XTC file. If the XTC file has metadata, then loading it creates\r\n * model metadata components within the Viewer, namely a {@link MetaModel} corresponding to the model {@link Entity},\r\n * and a {@link MetaObject} for each object {@link Entity}.\r\n *\r\n * Each {@link MetaObject} has a {@link MetaObject#type}, which indicates the classification of its corresponding\r\n * {@link Entity}. When loading metadata, we can also configure XTCLoaderPlugin with a custom lookup table of initial\r\n * values to set on the properties of each type of {@link Entity}. By default, XTCLoaderPlugin uses its own map of\r\n * default colors and visibilities for IFC element types.\r\n *\r\n * For XTC versions prior to V8, we provided the metadata to XTCLoaderPlugin as an accompanying JSON file to load. We can\r\n * still do that for all XTC versions, and for XTC V8+ it will override any metadata provided within the XTC file.\r\n *\r\n * # Usage\r\n *\r\n * In the example below we'll load the Schependomlaan model from a [.XTC file](https://github.com/xeokit/xeokit-sdk/tree/master/examples/models/xtc/schependomlaan).\r\n *\r\n * This will create a bunch of {@link Entity}s that represents the model and its objects, along with a {@link MetaModel} and {@link MetaObject}s\r\n * that hold their metadata.\r\n *\r\n * Since this model contains IFC types, the XTCLoaderPlugin will set the initial appearance of each object\r\n * {@link Entity} according to its IFC type in {@link XTCLoaderPlugin#objectDefaults}.\r\n *\r\n * Read more about this example in the user guide on [Viewing BIM Models Offline](https://www.notion.so/xeokit/Viewing-an-IFC-Model-with-xeokit-c373e48bc4094ff5b6e5c5700ff580ee).\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_metadata_Schependomlaan)]\r\n *\r\n * ````javascript\r\n * import {Viewer, XTCLoaderPlugin} from \"tctwins-core.es.js\";\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a Viewer,\r\n * // 2. Arrange the camera\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * // 2\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * //------------------------------------------------------------------------------------------------------------------\r\n * // 1. Create a XTCLoaderPlugin,\r\n * // 2. Load a building model and JSON IFC metadata\r\n * //------------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * // 2\r\n * const model = xtcLoader.load({ // Returns an Entity that represents the model\r\n * id: \"myModel\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\",\r\n * edges: true\r\n * });\r\n *\r\n * model.on(\"loaded\", () => {\r\n *\r\n * //--------------------------------------------------------------------------------------------------------------\r\n * // 1. Find metadata on the third storey\r\n * // 2. Select all the objects in the building's third storey\r\n * // 3. Fit the camera to all the objects on the third storey\r\n * //--------------------------------------------------------------------------------------------------------------\r\n *\r\n * // 1\r\n * const metaModel = viewer.metaScene.metaModels[\"myModel\"]; // MetaModel with ID \"myModel\"\r\n * const metaObject\r\n * = viewer.metaScene.metaObjects[\"0u4wgLe6n0ABVaiXyikbkA\"]; // MetaObject with ID \"0u4wgLe6n0ABVaiXyikbkA\"\r\n *\r\n * const name = metaObject.name; // \"01 eerste verdieping\"\r\n * const type = metaObject.type; // \"IfcBuildingStorey\"\r\n * const parent = metaObject.parent; // MetaObject with type \"IfcBuilding\"\r\n * const children = metaObject.children; // Array of child MetaObjects\r\n * const objectId = metaObject.id; // \"0u4wgLe6n0ABVaiXyikbkA\"\r\n * const objectIds = viewer.metaScene.getObjectIDsInSubtree(objectId); // IDs of leaf sub-objects\r\n * const aabb = viewer.scene.getAABB(objectIds); // Axis-aligned boundary of the leaf sub-objects\r\n *\r\n * // 2\r\n * viewer.scene.setObjectsSelected(objectIds, true);\r\n *\r\n * // 3\r\n * viewer.cameraFlight.flyTo(aabb);\r\n * });\r\n *\r\n * // Find the model Entity by ID\r\n * model = viewer.scene.models[\"myModel\"];\r\n *\r\n * // Destroy the model\r\n * model.destroy();\r\n * ````\r\n *\r\n * # Loading XTC files containing textures\r\n *\r\n * XTCLoaderPlugin uses a {@link KTX2TextureTranscoder} to load textures in XTC files (XTC v10+). An XTCLoaderPlugin has its own\r\n * default KTX2TextureTranscoder, configured to load the Basis Codec from the CDN. If we wish, we can override that with our own\r\n * KTX2TextureTranscoder instance that's configured to load the Codec locally.\r\n *\r\n * In the example below, we'll create a {@link Viewer} and add an XTCLoaderPlugin\r\n * configured with a KTX2TextureTranscoder that finds the Codec in our local file system. Then we'll use the\r\n * XTCLoaderPlugin to load an XTC file that contains KTX2 textures, which the plugin will transcode using\r\n * its KTX2TextureTranscoder.\r\n *\r\n * We'll configure our KTX2TextureTranscoder to load the Basis Codec from a local directory. If we were happy with loading the\r\n * Codec from our CDN (ie. our app will always have an Internet connection) then we could just leave out the\r\n * KTX2TextureTranscoder altogether, and let the XTCLoaderPlugin use its internal default KTX2TextureTranscoder, which is configured to\r\n * load the Codec from the CDN. We'll stick with loading our own Codec, in case we want to run our app without an Internet connection.\r\n *\r\n * <a href=\"https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan\"><img src=\"https://xeokit.github.io/xeokit-sdk/assets/images/xtcWithTextures.png\"></a>\r\n *\r\n * * [[Run this example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Textures_HousePlan)]\r\n *\r\n * ````javascript\r\n * const viewer = new Viewer({\r\n * canvasId: \"myCanvas\",\r\n * transparent: true\r\n * });\r\n *\r\n * viewer.camera.eye = [-2.56, 8.38, 8.27];\r\n * viewer.camera.look = [13.44, 3.31, -14.83];\r\n * viewer.camera.up = [0.10, 0.98, -0.14];\r\n *\r\n * const textureTranscoder = new KTX2TextureTranscoder({\r\n * viewer,\r\n * transcoderPath: \"https://cdn.jsdelivr.net/npm/@xeokit/xeokit-sdk/dist/basis/\" // <------ Path to Basis Universal transcoder\r\n * });\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * textureTranscoder // <<------------- Transcodes KTX2 textures in XTC files\r\n * });\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * src: \"./HousePlan.xtc\" // <<------ XTC file with KTX2 textures\r\n * });\r\n * ````\r\n *\r\n * # Transforming\r\n *\r\n * We have the option to rotate, scale and translate each *````.XTC````* model as we load it.\r\n *\r\n * This lets us load multiple models, or even multiple copies of the same model, and position them apart from each other.\r\n *\r\n * In the example below, we'll scale our model to half its size, rotate it 90 degrees about its local X-axis, then\r\n * translate it 100 units along its X axis.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_Duplex_transform)]\r\n *\r\n * ````javascript\r\n * xtcLoader.load({\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * rotation: [90,0,0],\r\n * scale: [0.5, 0.5, 0.5],\r\n * position: [100, 0, 0]\r\n * });\r\n * ````\r\n *\r\n * # Including and excluding IFC types\r\n *\r\n * We can also load only those objects that have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that represent walls.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_includeTypes)]\r\n *\r\n * ````javascript\r\n * const model2 = xtcLoader.load({\r\n * id: \"myModel2\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * includeTypes: [\"IfcWallStandardCase\"]\r\n * });\r\n * ````\r\n *\r\n * We can also load only those objects that **don't** have the specified IFC types.\r\n *\r\n * In the example below, we'll load only the objects that do not represent empty space.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_excludeTypes)]\r\n *\r\n * ````javascript\r\n * const model3 = xtcLoader.load({\r\n * id: \"myModel3\",\r\n * src: \"./models/xtc/OTCConferenceCenter.xtc\",\r\n * excludeTypes: [\"IfcSpace\"]\r\n * });\r\n * ````\r\n *\r\n * # Configuring initial IFC object appearances\r\n *\r\n * We can specify the custom initial appearance of loaded objects according to their IFC types.\r\n *\r\n * This is useful for things like:\r\n *\r\n * * setting the colors to our objects according to their IFC types,\r\n * * automatically hiding ````IfcSpace```` objects, and\r\n * * ensuring that ````IfcWindow```` objects are always transparent.\r\n * <br>\r\n * In the example below, we'll load a model, while configuring ````IfcSpace```` elements to be always initially invisible,\r\n * and ````IfcWindow```` types to be always translucent blue.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#BIMOffline_XTC_objectDefaults)]\r\n *\r\n * ````javascript\r\n * const myObjectDefaults = {\r\n *\r\n * IfcSpace: {\r\n * visible: false\r\n * },\r\n * IfcWindow: {\r\n * colorize: [0.337255, 0.303922, 0.870588], // Blue\r\n * opacity: 0.3\r\n * },\r\n *\r\n * //...\r\n *\r\n * DEFAULT: {\r\n * colorize: [0.5, 0.5, 0.5]\r\n * }\r\n * };\r\n *\r\n * const model4 = xtcLoader.load({\r\n * id: \"myModel4\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\",\r\n * objectDefaults: myObjectDefaults // Use our custom initial default states for object Entities\r\n * });\r\n * ````\r\n *\r\n * When we don't customize the appearance of IFC types, as just above, then IfcSpace elements tend to obscure other\r\n * elements, which can be confusing.\r\n *\r\n * It's often helpful to make IfcSpaces transparent and unpickable, like this:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * pickable: false,\r\n * opacity: 0.2\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * Alternatively, we could just make IfcSpaces invisible, which also makes them unpickable:\r\n *\r\n * ````javascript\r\n * const xtcLoader = new XTCLoaderPlugin(viewer, {\r\n * objectDefaults: {\r\n * IfcSpace: {\r\n * visible: false\r\n * }\r\n * }\r\n * });\r\n * ````\r\n *\r\n * # Configuring a custom data source\r\n *\r\n * By default, XTCLoaderPlugin will load *````.XTC````* files and metadata JSON over HTTP.\r\n *\r\n * In the example below, we'll customize the way XTCLoaderPlugin loads the files by configuring it with our own data source\r\n * object. For simplicity, our custom data source example also uses HTTP, using a couple of xeokit utility functions.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#loading_XTC_dataSource)]\r\n *\r\n * ````javascript\r\n * import {utils} from \"tctwins-core.es.js\";\r\n *\r\n * class MyDataSource {\r\n *\r\n * constructor() {\r\n * }\r\n *\r\n * // Gets metamodel JSON\r\n * getMetaModel(metaModelSrc, ok, error) {\r\n * console.log(\"MyDataSource#getMetaModel(\" + metaModelSrc + \", ... )\");\r\n * utils.loadJSON(metaModelSrc,\r\n * (json) => {\r\n * ok(json);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n *\r\n * // Gets the contents of the given .XTC file in an arraybuffer\r\n * getXTC(xTCSrc, ok, error) {\r\n * console.log(\"MyDataSource#getXTC(\" + xTCSrc + \", ... )\");\r\n * utils.loadArraybuffer(xTCSrc,\r\n * (arraybuffer) => {\r\n * ok(arraybuffer);\r\n * },\r\n * function (errMsg) {\r\n * error(errMsg);\r\n * });\r\n * }\r\n * }\r\n *\r\n * const xtcLoader2 = new XTCLoaderPlugin(viewer, {\r\n * dataSource: new MyDataSource()\r\n * });\r\n *\r\n * const model5 = xtcLoader2.load({\r\n * id: \"myModel5\",\r\n * src: \"./models/xtc/Duplex.ifc.xtc\"\r\n * });\r\n * ````\r\n *\r\n * # Loading multiple copies of a model, without object ID clashes\r\n *\r\n * Sometimes we need to load two or more instances of the same model, without having clashes\r\n * between the IDs of the equivalent objects in the model instances.\r\n *\r\n * As shown in the example below, we do this by setting {@link XTCLoaderPlugin#globalizeObjectIds} ````true```` before we load our models.\r\n *\r\n * * [[Run example](https://xeokit.github.io/xeokit-sdk/examples/#TreeViewPlugin_Containment_MultipleModels)]\r\n *\r\n * ````javascript\r\n * xtcLoader.globalizeObjectIds = true;\r\n *\r\n * const model = xtcLoader.load({\r\n * id: \"model1\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n *\r\n * const model2 = xtcLoader.load({\r\n * id: \"model2\",\r\n * src: \"./models/xtc/Schependomlaan.xtc\"\r\n * });\r\n * ````\r\n *\r\n * For each {@link Entity} loaded by these two calls, {@link Entity#id} and {@link MetaObject#id} will get prefixed by\r\n * the ID of their model, in order to avoid ID clashes between the two models.\r\n *\r\n * An Entity belonging to the first model will get an ID like this:\r\n *\r\n * ````\r\n * myModel1#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * The equivalent Entity in the second model will get an ID like this:\r\n *\r\n * ````\r\n * myModel2#0BTBFw6f90Nfh9rP1dlXrb\r\n * ````\r\n *\r\n * Now, to update the visibility of both of those Entities collectively, using {@link Scene#setObjectsVisible}, we can\r\n * supply just the IFC product ID part to that method:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n * ````\r\n *\r\n * The method, along with {@link Scene#setObjectsXRayed}, {@link Scene#setObjectsHighlighted} etc, will internally expand\r\n * the given ID to refer to the instances of that Entity in both models.\r\n *\r\n * We can also, of course, reference each Entity directly, using its globalized ID:\r\n *\r\n * ````javascript\r\n * myViewer.scene.setObjectVisibilities(\"myModel1#0BTBFw6f90Nfh9rP1dlXrb\", true);\r\n *````\r\n *\r\n * We can also provide an HTTP URL to the XTC file:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/models/xtc/Schependomlaan.xtc\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * # Loading a model from a manifest of XTC files\r\n *\r\n * The `ifc2gltf` tool from Creoox, which converts IFC files into glTF geometry and JSON metadata files, has the option to\r\n * split its output into multiple pairs of glTF and JSON files, accompanied by a JSON manifest that lists the files.\r\n *\r\n * To integrate with that option, the `convert2xtc` tool, which converts glTF geometry and JSON metadata files into XTC files,\r\n * also has the option to batch-convert the glTF+JSON files in the manifest, in one invocation.\r\n *\r\n * When we use this option, convert2xtc will output a bunch of XTC files, along with a JSON manifest file that lists those XTC files.\r\n *\r\n * Working down the pipeline, the XTCLoaderPlugin has the option batch-load all XTC files listed in that manifest\r\n * into a xeokit Viewer in one load operation, combining the XTC files into a single SceneModel and MetaModel.\r\n *\r\n * You can learn more about this conversion and loading process, with splitting, batch converting and batch loading,\r\n * in [this tutorial](https://www.notion.so/xeokit/Importing-Huge-IFC-Models-as-Multiple-XTC-Files-165fc022e94742cf966ee50003572259).\r\n *\r\n * To show how to use XTCLoaderPlugin to load a manifest of XTC files, let's imagine that we have a set of such XTC files. As\r\n * described in the tutorial, they were converted by `ifc2gltf` from an IFC file into a set of glTF+JSON files, that were\r\n * then converted by convert2xtc into this set of XTC files and a manifest, as shown below.\r\n *\r\n * ````bash\r\n * ./\r\n * ├── model_1.xtc\r\n * ├── model_2.xtc\r\n * ├── model_3.xtc\r\n * ├── model_4..xtc\r\n * └── model.xtc.manifest.json\r\n * ````\r\n *\r\n * The `model.xtc.manifest.json` XTC manifest would look something like this:\r\n *\r\n * ````json\r\n * {\r\n * \"inputFile\": null,\r\n * \"converterApplication\": \"convert2xtc\",\r\n * \"converterApplicationVersion\": \"v1.1.9\",\r\n * \"conversionDate\": \"10-08-2023- 02-05-01\",\r\n * \"outputDir\": null,\r\n * \"xtcFiles\": [\r\n * \"model_1.xtc\",\r\n * \"model_2.xtc\",\r\n * \"model_3.xtc\",\r\n * \"model_4.xtc\"\r\n * ]\r\n * }\r\n * ````\r\n *\r\n * Now, to load all those XTC files into a single SceneModel and MetaModel in one operation, we pass a path to the XTC\r\n * manifest to `XTCLoaderPlugin.load`, as shown in the example below:\r\n *\r\n * ````javascript\r\n * import {\r\n * Viewer,\r\n * XTCLoaderPlugin,\r\n * TreeViewPlugin,\r\n * } from \"tctwins-core.es.js\";\r\n *\r\n * constviewer = new Viewer({\r\n * canvasId: \"myCanvas\"\r\n * });\r\n *\r\n * viewer.scene.camera.eye = [26.54, 29.29, 36.20,];\r\n * viewer.scene.camera.look = [-23.51, -8.26, -21.65,];\r\n * viewer.scene.camera.up = [-0.2, 0.89, -0.33,];\r\n *\r\n * const xtcLoader = new XTCLoaderPlugin(viewer);\r\n *\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n *\r\n * const metaModel = viewer.metaScene.metaModels[sceneModel.id];\r\n *\r\n * // Then when we need to, we can destroy the SceneModel\r\n * // and MetaModel in one shot, like so:\r\n *\r\n * sceneModel.destroy();\r\n * metaModel.destroy();\r\n * ````\r\n *\r\n * The main advantage here, of splitting IFC files like this within the conversion and import pipeline,\r\n * is to reduce the memory pressure on each of the `ifc2gltf`, `convert2xtc` and XTCLoaderPlugin components.\r\n * They work much reliably (and faster) when processing smaller files (eg. 20MB) than when processing large files (eg. 500MB), where\r\n * they have less trouble allocating the system memory they need for conversion and parsing.\r\n *\r\n * We can also provide an HTTP URL to the manifest:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * manifestSrc: \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc.manifest.json\",\r\n * id: \"myModel\",\r\n * });\r\n * ````\r\n *\r\n * We can also provide the manifest as parameter object:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"../../assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * We can also provide the paths to the XTC files as HTTP URLs:\r\n *\r\n * ````javascript\r\n * const sceneModel = xtcLoader.load({\r\n * id: \"myModel\",\r\n * manifest: {\r\n * inputFile: \"assets/models/gltf/Karhumaki/model.glb.manifest.json\",\r\n * converterApplication: \"convert2xtc\",\r\n * converterApplicationVersion: \"v1.1.10\",\r\n * conversionDate\": \"09-11-2023- 18-29-01\",\r\n * xtcFiles: [\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_1.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_2.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_3.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_4.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_5.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_6.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_7.xtc\",\r\n * \"https://xeokit.github.io/xeokit-sdk/assets/models/xtc/v10/split/Karhumaki-Bridge/model_8.xtc\"\r\n * ]\r\n * }\r\n * });\r\n * ````\r\n *\r\n * @class XTCLoaderPlugin\r\n */\r\nclass XTCLoaderPlugin extends _viewer_Plugin_js__WEBPACK_IMPORTED_MODULE_3__.Plugin {\r\n\t/**\r\n\t * @constructor\r\n\t *\r\n\t * @param {Viewer} viewer The Viewer.\r\n\t * @param {Object} cfg Plugin configuration.\r\n\t * @param {String} [cfg.id=\"XTCLoader\"] Optional ID for this plugin, so that we can find it within {@link Viewer#plugins}.\r\n\t * @param {Object} [cfg.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {Object} [cfg.dataSource] A custom data source through which the XTCLoaderPlugin can load model and metadata files. Defaults to an instance of {@link XTCDefaultDataSource}, which loads uover HTTP.\r\n\t * @param {String[]} [cfg.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [cfg.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [cfg.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [cfg.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to internally expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have a lot of geometry reuse, but may also increase the amount of\r\n\t * browser and GPU memory they require. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Number} [cfg.maxGeometryBatchSize=50000000] Maximum geometry batch size, as number of vertices. This is optionally supplied\r\n\t * to limit the size of the batched geometry arrays that {@link SceneModel} internally creates for batched geometries.\r\n\t * A low value means less heap allocation/de-allocation while loading batched geometries, but more draw calls and\r\n\t * slower rendering speed. A high value means larger heap allocation/de-allocation while loading, but less draw calls\r\n\t * and faster rendering speed. It's recommended to keep this somewhere roughly between ````50000```` and ````50000000```.\r\n\t * @param {KTX2TextureTranscoder} [cfg.textureTranscoder] Transcoder used internally to transcode KTX2\r\n\t * textures within the XTC. Only required when the XTC is version 10 or later, and contains KTX2 textures.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(\"XTCLoader\", viewer, cfg);\r\n\r\n\t\tthis._maxGeometryBatchSize = cfg.maxGeometryBatchSize;\r\n\r\n\t\tthis.textureTranscoder = cfg.textureTranscoder;\r\n\t\tthis.dataSource = cfg.dataSource;\r\n\t\tthis.objectDefaults = cfg.objectDefaults;\r\n\t\tthis.includeTypes = cfg.includeTypes;\r\n\t\tthis.excludeTypes = cfg.excludeTypes;\r\n\t\tthis.excludeUnclassifiedObjects = cfg.excludeUnclassifiedObjects;\r\n\t\tthis.reuseGeometries = cfg.reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the ````.xtc```` format versions supported by this XTCLoaderPlugin/\r\n\t * @returns {string[]}\r\n\t */\r\n\tget supportedVersions() {\r\n\t\treturn Object.keys(parsers);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tget textureTranscoder() {\r\n\t\treturn this._textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the texture transcoder.\r\n\t *\r\n\t * @type {TextureTranscoder}\r\n\t */\r\n\tset textureTranscoder(textureTranscoder) {\r\n\t\tthis._textureTranscoder = textureTranscoder;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tget dataSource() {\r\n\t\treturn this._dataSource;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a custom data source through which the XTCLoaderPlugin can load models and metadata.\r\n\t *\r\n\t * Default value is {@link XTCDefaultDataSource}, which loads via HTTP.\r\n\t *\r\n\t * @type {Object}\r\n\t */\r\n\tset dataSource(value) {\r\n\t\tthis._dataSource = value || new _XTCDefaultDataSource_js__WEBPACK_IMPORTED_MODULE_4__.XTCDefaultDataSource();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tget objectDefaults() {\r\n\t\treturn this._objectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets map of initial default states for each loaded {@link Entity} that represents an object.\r\n\t *\r\n\t * Default value is {@link IFCObjectDefaults}.\r\n\t *\r\n\t * @type {{String: Object}}\r\n\t */\r\n\tset objectDefaults(value) {\r\n\t\tthis._objectDefaults = value || _viewer_metadata_IFCObjectDefaults_js__WEBPACK_IMPORTED_MODULE_5__.IFCObjectDefaults;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget includeTypes() {\r\n\t\treturn this._includeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the whitelist of the IFC types loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to only load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset includeTypes(value) {\r\n\t\tthis._includeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget excludeTypes() {\r\n\t\treturn this._excludeTypes;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the blacklist of IFC types that are never loaded by this XTCLoaderPlugin.\r\n\t *\r\n\t * When loading models with metadata, causes this XTCLoaderPlugin to **not** load objects whose types are in this\r\n\t * list. An object's type is indicated by its {@link MetaObject}'s {@link MetaObject#type}.\r\n\t *\r\n\t * Default value is ````undefined````.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tset excludeTypes(value) {\r\n\t\tthis._excludeTypes = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget excludeUnclassifiedObjects() {\r\n\t\treturn this._excludeUnclassifiedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether we load objects that don't have IFC types.\r\n\t *\r\n\t * When loading models with metadata and this is ````true````, XTCLoaderPlugin will not load objects\r\n\t * that don't have IFC types.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset excludeUnclassifiedObjects(value) {\r\n\t\tthis._excludeUnclassifiedObjects = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget globalizeObjectIds() {\r\n\t\treturn this._globalizeObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin globalizes each {@link Entity#id} and {@link MetaObject#id} as it loads a model.\r\n\t *\r\n\t * Set this ````true```` when you need to load multiple instances of the same model, to avoid ID clashes\r\n\t * between the objects in the different instances.\r\n\t *\r\n\t * When we load a model with this set ````true````, then each {@link Entity#id} and {@link MetaObject#id} will be\r\n\t * prefixed by the ID of the model, ie. ````<modelId>#<objectId>````.\r\n\t *\r\n\t * {@link Entity#originalSystemId} and {@link MetaObject#originalSystemId} will always hold the original, un-prefixed, ID values.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * See the main {@link XTCLoaderPlugin} class documentation for usage info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset globalizeObjectIds(value) {\r\n\t\tthis._globalizeObjectIds = !!value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget reuseGeometries() {\r\n\t\treturn this._reuseGeometries;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether XTCLoaderPlugin enables geometry reuse when loading models.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * Geometry reuse saves memory, but can impact Viewer performance when there are many reused geometries. For\r\n\t * this reason, we can set this ````false```` to disable geometry reuse for models loaded by this XTCLoaderPlugin\r\n\t * (which will then \"expand\" the geometry instances into batches instead).\r\n\t *\r\n\t * The result will be be less WebGL draw calls (which are expensive), at the cost of increased memory footprint.\r\n\t *\r\n\t * See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset reuseGeometries(value) {\r\n\t\tthis._reuseGeometries = value !== false;\r\n\t}\r\n\r\n\t/**\r\n\t * Loads an ````.xtc```` model into this XTCLoaderPlugin's {@link Viewer}.\r\n\t *\r\n\t * Since xeokit/xeokit-sdk 1.9.0, XTCLoaderPlugin has supported XTC 8, which bundles the metamodel\r\n\t * data (eg. an IFC element hierarchy) in the XTC file itself. For XTC 8, we therefore no longer need to\r\n\t * load the metamodel data from a separate accompanying JSON file, as we did with previous XTC versions.\r\n\t * However, if we do choose to specify a separate metamodel JSON file to load (eg. for backward compatibility\r\n\t * in data pipelines), then that metamodel will be loaded and the metamodel in the XTC 8 file will be ignored.\r\n\t *\r\n\t * @param {*} params Loading parameters.\r\n\t * @param {String} [params.id] ID to assign to the root {@link Entity#id}, unique among all components in the Viewer's {@link Scene}, generated automatically by default.\r\n\t * @param {String} [params.src] Path or URL to an *````.xtc````* file, as an alternative to the ````xtc```` parameter.\r\n\t * @param {ArrayBuffer} [params.xtc] The *````.xtc````* file data, as an alternative to the ````src```` parameter.\r\n\t * @param {String} [params.metaModelSrc] Path or URL to an optional metadata file, as an alternative to the ````metaModelData```` parameter.\r\n\t * @param {*} [params.metaModelData] JSON model metadata, as an alternative to the ````metaModelSrc```` parameter.\r\n\t * @param {String} [params.manifestSrc] Path or URL to a JSON manifest file that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {Object} [params.manifest] A JSON manifest object (as an alternative to a path or URL) that provides paths to ````.xtc```` files to load as parts of the model. Use this option to load models that have been split into\r\n\t * multiple XTC files. See [tutorial](https://www.notion.so/xeokit/Automatically-Splitting-Large-Models-for-Better-Performance-165fc022e94742cf966ee50003572259) for more info.\r\n\t * @param {{String:Object}} [params.objectDefaults] Map of initial default states for each loaded {@link Entity} that represents an object. Default value is {@link IFCObjectDefaults}.\r\n\t * @param {String[]} [params.includeTypes] When loading metadata, only loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {String[]} [params.excludeTypes] When loading metadata, never loads objects that have {@link MetaObject}s with {@link MetaObject#type} values in this list.\r\n\t * @param {Boolean} [params.edges=false] Whether or not xeokit renders the model with edges emphasized.\r\n\t * @param {Number[]} [params.origin=[0,0,0]] The model's World-space double-precision 3D origin. Use this to position the model within xeokit's World coordinate system, using double-precision coordinates.\r\n\t * @param {Number[]} [params.position=[0,0,0]] The model single-precision 3D position, relative to the ````origin```` parameter.\r\n\t * @param {Number[]} [params.scale=[1,1,1]] The model's scale.\r\n\t * @param {Number[]} [params.rotation=[0,0,0]] The model's orientation, given as Euler angles in degrees, for each of the X, Y and Z axis.\r\n\t * @param {Number[]} [params.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] The model's world transform matrix. Overrides the position, scale and rotation parameters. Relative to ````origin````.\r\n\t * @param {Boolean} [params.edges=false] Indicates if the model's edges are initially emphasized.\r\n\t * @param {Boolean} [params.saoEnabled=true] Indicates if Scalable Ambient Obscurance (SAO) is enabled for the model. SAO is configured by the Scene's {@link SAO} component. Only works when {@link SAO#enabled} is also ````true````\r\n\t * @param {Boolean} [params.pbrEnabled=true] Indicates if physically-based rendering (PBR) is enabled for the model. Overrides ````colorTextureEnabled````. Only works when {@link Scene#pbrEnabled} is also ````true````.\r\n\t * @param {Boolean} [params.colorTextureEnabled=true] Indicates if base color texture rendering is enabled for the model. Overridden by ````pbrEnabled````. Only works when {@link Scene#colorTextureEnabled} is also ````true````.\r\n\t * @param {Number} [params.backfaces=false] When we set this ````true````, then we force rendering of backfaces for the model. When\r\n\t * we leave this ````false````, then we allow the Viewer to decide when to render backfaces. In that case, the\r\n\t * Viewer will hide backfaces on watertight meshes, show backfaces on open meshes, and always show backfaces on meshes when we slice them open with {@link SectionPlane}s.\r\n\t * @param {Boolean} [params.excludeUnclassifiedObjects=false] When loading metadata and this is ````true````, will only load {@link Entity}s that have {@link MetaObject}s (that are not excluded). This is useful when we don't want Entitys in the Scene that are not represented within IFC navigation components, such as {@link TreeViewPlugin}.\r\n\t * @param {Boolean} [params.globalizeObjectIds=false] Indicates whether to globalize each {@link Entity#id} and {@link MetaObject#id}, in case you need to prevent ID clashes with other models. See {@link XTCLoaderPlugin#globalizeObjectIds} for more info.\r\n\t * @param {Boolean} [params.reuseGeometries=true] Indicates whether to enable geometry reuse (````true```` by default) or whether to expand\r\n\t * all geometry instances into batches (````false````), and not use instancing to render them. Setting this ````false```` can significantly\r\n\t * improve Viewer performance for models that have excessive geometry reuse, but may also increases the amount of\r\n\t * browser and GPU memory used by the model. See [#769](https://github.com/xeokit/xeokit-sdk/issues/769) for more info.\r\n\t * @param {Boolean} [params.dtxEnabled=true] When ````true```` (default) use data textures (DTX), where appropriate, to\r\n\t * represent the returned model. Set false to always use vertex buffer objects (VBOs). Note that DTX is only applicable\r\n\t * to non-textured triangle meshes, and that VBOs are always used for meshes that have textures, line segments, or point\r\n\t * primitives. Only works while {@link DTX#enabled} is also ````true````.\r\n\t * @returns {Entity} Entity representing the model, which will have {@link Entity#isModel} set ````true```` and will be registered by {@link Entity#id} in {@link Scene#models}.\r\n\t */\r\n\tload(params = {}) {\r\n\t\tif (params.id && this.viewer.scene.components[params.id]) {\r\n\t\t\tthis.error(\"Component with this ID already exists in viewer: \" + params.id + \" - will autogenerate this ID\");\r\n\t\t\tdelete params.id;\r\n\t\t}\r\n\r\n\t\tif (!params.src && !params.xtc && !params.manifestSrc && !params.manifest) {\r\n\t\t\tthis.error(\"load() param expected: src, xtc, manifestSrc or manifestData\");\r\n\t\t\treturn sceneModel; // Return new empty model\r\n\t\t}\r\n\r\n\t\tconst options = {};\r\n\t\tconst includeTypes = params.includeTypes || this._includeTypes;\r\n\t\tconst excludeTypes = params.excludeTypes || this._excludeTypes;\r\n\t\tconst objectDefaults = params.objectDefaults || this._objectDefaults;\r\n\r\n\t\toptions.reuseGeometries =\r\n\t\t\tparams.reuseGeometries !== null && params.reuseGeometries !== undefined\r\n\t\t\t\t? params.reuseGeometries\r\n\t\t\t\t: this._reuseGeometries !== false;\r\n\r\n\t\tif (includeTypes) {\r\n\t\t\toptions.includeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = includeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.includeTypesMap[includeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (excludeTypes) {\r\n\t\t\toptions.excludeTypesMap = {};\r\n\t\t\tfor (let i = 0, len = excludeTypes.length; i < len; i++) {\r\n\t\t\t\toptions.excludeTypesMap[excludeTypes[i]] = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (objectDefaults) {\r\n\t\t\toptions.objectDefaults = objectDefaults;\r\n\t\t}\r\n\r\n\t\toptions.excludeUnclassifiedObjects =\r\n\t\t\tparams.excludeUnclassifiedObjects !== undefined\r\n\t\t\t\t? !!params.excludeUnclassifiedObjects\r\n\t\t\t\t: this._excludeUnclassifiedObjects;\r\n\t\toptions.globalizeObjectIds =\r\n\t\t\tparams.globalizeObjectIds !== undefined && params.globalizeObjectIds !== null\r\n\t\t\t\t? !!params.globalizeObjectIds\r\n\t\t\t\t: this._globalizeObjectIds;\r\n\r\n\t\tconst sceneModel = new _viewer_scene_model_index_js__WEBPACK_IMPORTED_MODULE_1__.SceneModel(\r\n\t\t\tthis.viewer.scene,\r\n\t\t\t_viewer_scene_utils_js__WEBPACK_IMPORTED_MODULE_0__.utils.apply(params, {\r\n\t\t\t\tisModel: true,\r\n\t\t\t\ttextureTranscoder: this._textureTranscoder,\r\n\t\t\t\tmaxGeometryBatchSize: this._maxGeometryBatchSize,\r\n\t\t\t\torigin: params.origin,\r\n\t\t\t\tdisableVertexWelding: params.disableVertexWelding || false,\r\n\t\t\t\tdisableIndexRebucketing: params.disableIndexRebucketing || false,\r\n\t\t\t\tdtxEnabled: params.dtxEnabled\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tconst modelId = sceneModel.id; // In case ID was auto-generated\r\n\r\n\t\tconst metaModel = new _viewer_metadata_MetaModel_js__WEBPACK_IMPORTED_MODULE_2__.MetaModel({\r\n\t\t\tmetaScene: this.viewer.metaScene,\r\n\t\t\tid: modelId\r\n\t\t});\r\n\r\n\t\tthis.viewer.scene.canvas.spinner.processes++;\r\n\r\n\t\tconst finish = () => {\r\n\t\t\t// this._createDefaultMetaModelIfNeeded(sceneModel, params, options);\r\n\t\t\tsceneModel.finalize();\r\n\t\t\tmetaModel.finalize();\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tsceneModel.once(\"destroyed\", () => {\r\n\t\t\t\tthis.viewer.metaScene.destroyMetaModel(metaModel.id);\r\n\t\t\t});\r\n\t\t\tthis.scheduleTask(() => {\r\n\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tsceneModel.scene.fire(\"modelLoaded\", sceneModel.id); // FIXME: Assumes listeners know order of these two events\r\n\t\t\t\tsceneModel.fire(\"loaded\", true, false); // Don't forget the event, for late subscribers\r\n\t\t\t});\r\n\t\t};\r\n\r\n\t\tconst error = (errMsg) => {\r\n\t\t\tthis.viewer.scene.canvas.spinner.processes--;\r\n\t\t\tthis.error(errMsg);\r\n\t\t\tsceneModel.fire(\"error\", errMsg);\r\n\t\t};\r\n\r\n\t\tlet nextId = 0;\r\n\t\tconst manifestCtx = {\r\n\t\t\tgetNextId: () => {\r\n\t\t\t\treturn `${modelId}.${nextId++}`;\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t//模型文件\r\n\t\tif (params.metaModelSrc || params.metaModelData) {\r\n\t\t\tif (params.metaModelSrc) {\r\n\t\t\t\tconst metaModelSrc = params.metaModelSrc;\r\n\r\n\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\tmetaModelSrc,\r\n\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tif (params.src) {\r\n\t\t\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\t\t\tfinish();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(errMsg) => {\r\n\t\t\t\t\t\terror(`load(): Failed to load model metadata for model '${modelId} from '${metaModelSrc}' - ${errMsg}`);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t} else if (params.metaModelData) {\r\n\t\t\t\tmetaModel.loadData(params.metaModelData, {\r\n\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t});\r\n\t\t\t\tif (params.src) {\r\n\t\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, null, manifestCtx, finish, error);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, null, manifestCtx);\r\n\t\t\t\t\tfinish();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (params.src) {\r\n\t\t\t\tthis._loadModel(params.src, params, options, sceneModel, metaModel, manifestCtx, finish, error);\r\n\t\t\t} else if (params.xtc) {\r\n\t\t\t\tthis._parseModel(params.xtc, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tfinish();\r\n\t\t\t} else if (params.manifestSrc || params.manifest) {\r\n\t\t\t\tconst baseDir = params.manifestSrc ? getBaseDirectory(params.manifestSrc) : \"\";\r\n\t\t\t\tconst loadJSONs = (metaDataFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= metaDataFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getMetaModel(\r\n\t\t\t\t\t\t\t\t`${baseDir}${metaDataFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(metaModelData) => {\r\n\t\t\t\t\t\t\t\t\tmetaModel.loadData(metaModelData, {\r\n\t\t\t\t\t\t\t\t\t\tincludeTypes: includeTypes,\r\n\t\t\t\t\t\t\t\t\t\texcludeTypes: excludeTypes,\r\n\t\t\t\t\t\t\t\t\t\tglobalizeObjectIds: options.globalizeObjectIds\r\n\t\t\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tconst loadXTCs = (xtcFiles, done, error) => {\r\n\t\t\t\t\tlet i = 0;\r\n\t\t\t\t\tconst loadNext = () => {\r\n\t\t\t\t\t\tif (i >= xtcFiles.length) {\r\n\t\t\t\t\t\t\tdone();\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthis._dataSource.getXTC(\r\n\t\t\t\t\t\t\t\t`${baseDir}${xtcFiles[i]}`,\r\n\t\t\t\t\t\t\t\t(arrayBuffer) => {\r\n\t\t\t\t\t\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\t\t\t\tthis.scheduleTask(loadNext, 100);\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t};\r\n\t\t\t\t\tloadNext();\r\n\t\t\t\t};\r\n\t\t\t\tif (params.manifest) {\r\n\t\t\t\t\tconst manifestData = params.manifest;\r\n\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis._dataSource.getManifest(\r\n\t\t\t\t\t\tparams.manifestSrc,\r\n\t\t\t\t\t\t(manifestData) => {\r\n\t\t\t\t\t\t\tif (sceneModel.destroyed) {\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst xtcFiles = manifestData.xtcFiles;\r\n\t\t\t\t\t\t\tif (!xtcFiles || xtcFiles.length === 0) {\r\n\t\t\t\t\t\t\t\terror(`load(): Failed to load model manifest - manifest not valid`);\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tconst metaModelFiles = manifestData.metaModelFiles;\r\n\t\t\t\t\t\t\tif (metaModelFiles) {\r\n\t\t\t\t\t\t\t\tloadJSONs(\r\n\t\t\t\t\t\t\t\t\tmetaModelFiles,\r\n\t\t\t\t\t\t\t\t\t() => {\r\n\t\t\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t\terror\r\n\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tloadXTCs(xtcFiles, finish, error);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\terror\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn sceneModel;\r\n\t}\r\n\r\n\t_loadModel(src, params, options, sceneModel, metaModel, manifestCtx, done, error) {\r\n\t\tthis._dataSource.getXTC(\r\n\t\t\tparams.src,\r\n\t\t\t(arrayBuffer) => {\r\n\t\t\t\tthis._parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx);\r\n\t\t\t\tdone();\r\n\t\t\t},\r\n\t\t\terror\r\n\t\t);\r\n\t}\r\n\r\n\t_parseModel(arrayBuffer, params, options, sceneModel, metaModel, manifestCtx) {\r\n\t\tif (sceneModel.destroyed) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst dataView = new DataView(arrayBuffer);\r\n\t\tconst dataArray = new Uint8Array(arrayBuffer);\r\n\t\tconst xtcVersion = dataView.getUint32(0, true);\r\n\t\tconst parser = parsers[xtcVersion];\r\n\t\tif (!parser) {\r\n\t\t\tthis.error(\r\n\t\t\t\t\"Unsupported .XTC file version: \" +\r\n\t\t\t\t\txtcVersion +\r\n\t\t\t\t\t\" - this XTCLoaderPlugin supports versions \" +\r\n\t\t\t\t\tObject.keys(parsers)\r\n\t\t\t);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.log(\"Loading .xtc V\" + xtcVersion);\r\n\t\tconst numElements = dataView.getUint32(4, true);\r\n\t\tconst elements = [];\r\n\t\tlet byteOffset = (numElements + 2) * 4;\r\n\t\tfor (let i = 0; i < numElements; i++) {\r\n\t\t\tconst elementSize = dataView.getUint32((i + 2) * 4, true);\r\n\t\t\telements.push(dataArray.subarray(byteOffset, byteOffset + elementSize));\r\n\t\t\tbyteOffset += elementSize;\r\n\t\t}\r\n\t\tparser.parse(this.viewer, options, elements, sceneModel, metaModel, manifestCtx);\r\n\t}\r\n\r\n\tloadMetadata(metaModel, deflatedMetadata, done) {\r\n\t\tmetaModel._finalized = false;\r\n\r\n\t\ttry {\r\n\t\t\t{\r\n\t\t\t\tthis._workerInflate(\r\n\t\t\t\t\tmetaModel,\r\n\t\t\t\t\tdeflatedMetadata,\r\n\t\t\t\t\t(worker) => {\r\n\t\t\t\t\t\tworker.terminate();\r\n\t\t\t\t\t\tthis.fire(\"metaLoaded\", { result: \"success\", metaModel });\r\n\t\t\t\t\t\tif (typeof done === \"function\") done();\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(worker, error) => {\r\n\t\t\t\t\t\tworker.terminate();\r\n\t\t\t\t\t\tthis.fire(\"metaLoaded\", { result: \"failed\", message: error, metaModel });\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tthis.fire(\"metaloaded\", { result: error, metaModel });\r\n\t\t}\r\n\t}\r\n\r\n\t_workerInflate(metaModel, buffer, done, err) {\r\n\t\tconst plugin = this;\r\n\t\tconst worker = createInlineWorker();\r\n\t\tworker.postMessage({\r\n\t\t\tbuffer\r\n\t\t\t// executionTime: new Date().getTime()\r\n\t\t});\r\n\r\n\t\tworker.onmessage = function (e) {\r\n\t\t\tplugin.fire(\"metaLoading\", () => {\r\n\t\t\t\tmetaModel.loadData(\r\n\t\t\t\t\te.data.metaJson,\r\n\t\t\t\t\t() => {\r\n\t\t\t\t\t\tmetaModel.finalize();\r\n\t\t\t\t\t\tif (typeof done === \"function\") done(worker);\r\n\t\t\t\t\t\telse worker.terminate();\r\n\t\t\t\t\t},\r\n\t\t\t\t\t(e) => {\r\n\t\t\t\t\t\tif (typeof err === \"function\") err(worker, e);\r\n\t\t\t\t\t}\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t\t};\r\n\t\tworker.onerror = function (e) {\r\n\t\t\tif (typeof err === \"function\") err(worker, e.message);\r\n\t\t\tworker.terminate();\r\n\t\t};\r\n\t}\r\n\r\n\t// _createDefaultMetaModelIfNeeded(sceneModel, params, options) {\r\n\t//\r\n\t// const metaModelId = sceneModel.id;\r\n\t//\r\n\t// if (!this.viewer.metaScene.metaModels[metaModelId]) {\r\n\t//\r\n\t// const metaModelData = {\r\n\t// metaObjects: []\r\n\t// };\r\n\t//\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: metaModelId,\r\n\t// type: \"default\",\r\n\t// name: metaModelId,\r\n\t// parent: null\r\n\t// });\r\n\t//\r\n\t// const entityList = sceneModel.entityList;\r\n\t//\r\n\t// for (let i = 0, len = entityList.length; i < len; i++) {\r\n\t// const entity = entityList[i];\r\n\t// if (entity.isObject) {\r\n\t// metaModelData.metaObjects.push({\r\n\t// id: entity.id,\r\n\t// type: \"default\",\r\n\t// name: entity.id,\r\n\t// parent: metaModelId\r\n\t// });\r\n\t// }\r\n\t// }\r\n\t//\r\n\t// const src = params.src;\r\n\t//\r\n\t// this.viewer.metaScene.createMetaModel(metaModelId, metaModelData, {\r\n\t//\r\n\t// includeTypes: options.includeTypes,\r\n\t// excludeTypes: options.excludeTypes,\r\n\t// globalizeObjectIds: options.globalizeObjectIds,\r\n\t//\r\n\t// getProperties: async (propertiesId) => {\r\n\t// return await this._dataSource.getProperties(src, propertiesId);\r\n\t// }\r\n\t// });\r\n\t//\r\n\t// sceneModel.once(\"destroyed\", () => {\r\n\t// this.viewer.metaScene.destroyMetaModel(metaModelId);\r\n\t// });\r\n\t// }\r\n\t// }\r\n}\r\n\r\nfunction getBaseDirectory(filePath) {\r\n\tconst pathArray = filePath.split(\"/\");\r\n\tpathArray.pop(); // Remove the file name or the last segment of the path\r\n\treturn pathArray.join(\"/\") + \"/\";\r\n}\r\nfunction createInlineWorker() {\r\n\tconst workerCode = `\r\n self.importScripts('https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako.min.js');\r\n \r\n function inflateMetadata(deflatedData) {\r\n return JSON.parse(self.pako.inflate(deflatedData, { to: \"string\" }));\r\n }\r\n \r\n self.onmessage = function (e) {\r\n console.log(\"start worker:\");\r\n const metaJson = inflateMetadata(e.data.buffer);\r\n\r\n self.postMessage({\r\n metaJson,\r\n time: new Date().getTime()\r\n });\r\n };\r\n `;\r\n\tconst blob = new Blob([workerCode], { type: \"application/javascript\" });\r\n\tconst workerUrl = URL.createObjectURL(blob);\r\n\treturn new Worker(workerUrl);\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/plugins/XTCLoaderPlugin/XTCLoaderPlugin.js?");
|
|
2158
2158
|
|
|
2159
2159
|
/***/ }),
|
|
2160
2160
|
|
|
@@ -2404,7 +2404,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2404
2404
|
\******************************************/
|
|
2405
2405
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2406
2406
|
|
|
2407
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MetaModel: () => (/* binding */ MetaModel)\n/* harmony export */ });\n/* harmony import */ var _PropertySet_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PropertySet.js */ \"./src/viewer/metadata/PropertySet.js\");\n/* harmony import */ var _MetaObject_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MetaObject.js */ \"./src/viewer/metadata/MetaObject.js\");\n/* harmony import */ var _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\n\r\n\r\n/**\r\n * @desc Metadata corresponding to an {@link Entity} that represents a model.\r\n *\r\n * An {@link Entity} represents a model when {@link Entity#isModel} is ````true````\r\n *\r\n * A MetaModel corresponds to an {@link Entity} by having the same {@link MetaModel#id} as the {@link Entity#id}.\r\n *\r\n * A MetaModel is created by {@link MetaScene#createMetaModel} and belongs to a {@link MetaScene}.\r\n *\r\n * Each MetaModel is registered by {@link MetaModel#id} in {@link MetaScene#metaModels}.\r\n *\r\n * A {@link MetaModel} represents its object structure with a tree of {@link MetaObject}s, with {@link MetaModel#rootMetaObject} referencing the root {@link MetaObject}.\r\n *\r\n * @class MetaModel\r\n */\r\nclass MetaModel {\r\n\t/**\r\n\t * Creates a new, unfinalized MetaModel.\r\n\t *\r\n\t * * The MetaModel is immediately registered by {@link MetaModel#id} in {@link MetaScene#metaModels}, even though it's not yet populated.\r\n\t * * The MetaModel then needs to be populated with one or more calls to {@link metaModel#loadData}.\r\n\t * * As we populate it, the MetaModel will create {@link MetaObject}s and {@link PropertySet}s in itself, and in the MetaScene.\r\n\t * * When populated, call {@link MetaModel#finalize} to finish it off, which causes MetaScene to fire a \"metaModelCreated\" event.\r\n\t */\r\n\tconstructor(params) {\r\n\t\t/**\r\n\t\t * Globally-unique ID.\r\n\t\t *\r\n\t\t * MetaModels are registered by ID in {@link MetaScene#metaModels}.\r\n\t\t *\r\n\t\t * When this MetaModel corresponds to an {@link Entity} then this ID will match the {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property id\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = params.id;\r\n\r\n\t\t/**\r\n\t\t * The project ID\r\n\t\t * @property projectId\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.projectId = params.projectId;\r\n\r\n\t\t/**\r\n\t\t * The revision ID, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property revisionId\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.revisionId = params.revisionId;\r\n\r\n\t\t/**\r\n\t\t * The model author, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property author\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.author = params.author;\r\n\r\n\t\t/**\r\n\t\t * The date the model was created, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property createdAt\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.createdAt = params.createdAt;\r\n\r\n\t\t/**\r\n\t\t * The application that created the model, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property creatingApplication\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.creatingApplication = params.creatingApplication;\r\n\r\n\t\t/**\r\n\t\t * The model schema version, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property schema\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.schema = params.schema;\r\n\r\n\t\t/**\r\n\t\t * Metadata on the {@link Scene}.\r\n\t\t *\r\n\t\t * @property metaScene\r\n\t\t * @type {MetaScene}\r\n\t\t */\r\n\t\tthis.metaScene = params.metaScene;\r\n\r\n\t\t/**\r\n\t\t * The {@link PropertySet}s in this MetaModel.\r\n\t\t *\r\n\t\t * @property propertySets\r\n\t\t * @type {PropertySet[]}\r\n\t\t */\r\n\t\tthis.propertySets = [];\r\n\r\n\t\t/**\r\n\t\t * The root {@link MetaObject}s in this MetaModel's composition structure hierarchy.\r\n\t\t *\r\n\t\t * @property rootMetaObject\r\n\t\t * @type {MetaObject[]}\r\n\t\t */\r\n\t\tthis.rootMetaObjects = [];\r\n\r\n\t\t/**\r\n\t\t * The {@link MetaObject}s in this MetaModel, each mapped to its ID.\r\n\t\t *\r\n\t\t * @property metaObjects\r\n\t\t * @type {MetaObject[]}\r\n\t\t */\r\n\t\tthis.metaObjects = [];\r\n\r\n\t\tthis.objectCount = 0;\r\n\t\tthis.propertySetCount = 0;\r\n\r\n\t\t/**\r\n\t\t * Connectivity graph.\r\n\t\t * @type {{}}\r\n\t\t */\r\n\t\tthis.graph = params.graph || {};\r\n\r\n\t\tthis.metaScene.metaModels[this.id] = this;\r\n\r\n\t\t/**\r\n\t\t * True when this MetaModel has been finalized.\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis._finalized = false;\r\n\t}\r\n\r\n\tset finalized(finalized) {\r\n\t\tthis._finalized = finalized;\r\n\t}\r\n\r\n\tget finalized() {\r\n\t\treturn this._finalized;\r\n\t}\r\n\r\n\t/**\r\n\t * Backwards compatibility with the model having a single root MetaObject.\r\n\t *\r\n\t * @property rootMetaObject\r\n\t * @type {MetaObject|null}\r\n\t */\r\n\tget rootMetaObject() {\r\n\t\tif (this.rootMetaObjects.length == 1) {\r\n\t\t\treturn this.rootMetaObjects[0];\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\r\n\t/**\r\n\t * Load metamodel data into this MetaModel.\r\n\t * @param metaModelData\r\n\t */\r\n\tloadData(metaModelData, options = {}) {\r\n\t\tif (this._finalized) {\r\n\t\t\tthrow \"MetaScene already finalized - can't add more data\";\r\n\t\t}\r\n\r\n\t\tif (metaModelData.author) this.author = metaModelData.author;\r\n\t\tif (metaModelData.schema) this.schema = metaModelData.schema;\r\n\t\tif (metaModelData.createdAt) this.createdAt = metaModelData.createdAt;\r\n\t\tif (metaModelData.projectId) this.projectId = metaModelData.projectId;\r\n\t\tif (metaModelData.revisionId) this.revisionId = metaModelData.revisionId;\r\n\t\tif (metaModelData.objectCount) this.objectCount = metaModelData.objectCount;\r\n\t\tif (metaModelData.propertySetCount) this.propertySetCount = metaModelData.propertySetCount;\r\n\t\tif (metaModelData.creatingApplication) this.creatingApplication = metaModelData.creatingApplication;\r\n\r\n\t\t// this._globalizeIDs(metaModelData, options);\r\n\r\n\t\tconst metaScene = this.metaScene;\r\n\r\n\t\tif (metaModelData.propertySets) {\r\n\t\t\t// for (let i = 0; i < metaModelData.propertySets.length; i++) {\r\n\t\t\t// \tconst propertySetData = metaModelData.propertySets[i];\r\n\t\t\t// const metaId = propertySetData.id;\r\n\r\n\t\t\tfor (let metaId in metaModelData.propertySets) {\r\n\t\t\t\tconst propertySetData = metaModelData.propertySets[metaId];\r\n\t\t\t\tlet propertySet = new _PropertySet_js__WEBPACK_IMPORTED_MODULE_0__.PropertySet({\r\n\t\t\t\t\tid: propertySetData.id,\r\n\t\t\t\t\toriginalSystemId: propertySetData.originalSystemId || propertySetData.id,\r\n\t\t\t\t\ttype: propertySetData.type,\r\n\t\t\t\t\tname: propertySetData.name,\r\n\t\t\t\t\tproperties: propertySetData.properties\r\n\t\t\t\t});\r\n\t\t\t\tmetaScene.propertySets[metaId] = propertySet;\r\n\t\t\t\t// propertySet.metaModels.push(this);\r\n\t\t\t\tthis.propertySets.push(propertySet);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (metaModelData.metaObjects) {\r\n\t\t\t// for (let i = 0; i < metaModelData.metaObjects.length; i++) {\r\n\t\t\t// \tconst objectData = metaModelData.metaObjects[i];\r\n\t\t\t// \tconst metaId = objectData.id;\r\n\r\n\t\t\tfor (let metaId in metaModelData.metaObjects) {\r\n\t\t\t\tconst objectData = metaModelData.metaObjects[metaId];\r\n\t\t\t\tlet metaObject = new _MetaObject_js__WEBPACK_IMPORTED_MODULE_1__.MetaObject({\r\n\t\t\t\t\tid: metaId,\r\n\t\t\t\t\toriginalSystemId: metaId,\r\n\t\t\t\t\tparentId: objectData.parent,\r\n\t\t\t\t\ttype: objectData.type,\r\n\t\t\t\t\tname: objectData.name,\r\n\t\t\t\t\tpropertySetIds: objectData.propertySetIds,\r\n\t\t\t\t\texternal: objectData.external\r\n\t\t\t\t});\r\n\t\t\t\tmetaObject.children = [];\r\n\t\t\t\tmetaObject.metaModels = [];\r\n\t\t\t\tmetaObject.metaModels.push(this);\r\n\t\t\t\tmetaScene.metaObjects[metaId] = metaObject;\r\n\r\n\t\t\t\tthis.metaObjects.push(metaObject);\r\n\t\t\t\tif (!objectData.parent) {\r\n\t\t\t\t\tthis.rootMetaObjects.push(metaObject);\r\n\t\t\t\t\tmetaScene.rootMetaObjects[metaId] = metaObject;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t_decompressProperties(propertyLookup, properties) {\r\n\t\tfor (let i = 0, len = properties.length; i < len; i++) {\r\n\t\t\tconst property = properties[i];\r\n\t\t\tif (Number.isInteger(property)) {\r\n\t\t\t\tconst lookupProperty = propertyLookup[property];\r\n\t\t\t\tif (lookupProperty) {\r\n\t\t\t\t\tproperties[i] = lookupProperty;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfinalize() {\r\n\t\tif (this._finalized) {\r\n\t\t\tthrow \"MetaScene already finalized - can't re-finalize\";\r\n\t\t}\r\n\r\n\t\t// Re-link MetaScene's entire MetaObject parent/child hierarchy\r\n\r\n\t\tconst metaScene = this.metaScene;\r\n\t\tmetaScene.metaObjectsByType = {};\r\n\r\n\t\tfor (let objectId in metaScene.metaObjects) {\r\n\t\t\tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t\t// if (metaObject.children) {\r\n\t\t\t// \tmetaObject.children = [];\r\n\t\t\t// }\r\n\t\t\tif (metaObject.parentId) {\r\n\t\t\t\tconst parentMetaObject = metaScene.metaObjects[metaObject.parentId];\r\n\t\t\t\tif (parentMetaObject) {\r\n\t\t\t\t\tmetaObject.parent = parentMetaObject;\r\n\t\t\t\t\t(parentMetaObject.children || (parentMetaObject.children = [])).push(metaObject);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Re-link each MetaObject's property sets\r\n\r\n\t\t\tif (metaObject.propertySets) {\r\n\t\t\t\tmetaObject.propertySets = [];\r\n\t\t\t}\r\n\t\t\tif (metaObject.propertySetIds) {\r\n\t\t\t\tfor (let i = 0, len = metaObject.propertySetIds.length; i < len; i++) {\r\n\t\t\t\t\tconst propertySetId = metaObject.propertySetIds[i];\r\n\t\t\t\t\tconst propertySet = metaScene.propertySets[propertySetId];\r\n\t\t\t\t\tmetaObject.propertySets.push(propertySet);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tconst type = metaObject.type;\r\n\t\t\t(metaScene.metaObjectsByType[type] || (metaScene.metaObjectsByType[type] = {}))[objectId] = metaObject;\r\n\t\t}\r\n\r\n\t\t// for (let objectId in metaScene.metaObjects) {\r\n\t\t// \tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t// \tif (metaObject.parentId) {\r\n\t\t// \t\tconst parentMetaObject = metaScene.metaObjects[metaObject.parentId];\r\n\t\t// \t\tif (parentMetaObject) {\r\n\t\t// \t\t\tmetaObject.parent = parentMetaObject;\r\n\t\t// \t\t\t(parentMetaObject.children || (parentMetaObject.children = [])).push(metaObject);\r\n\t\t// \t\t}\r\n\t\t// \t}\r\n\t\t// }\r\n\r\n\t\t// Relink MetaObjects to their MetaModels\r\n\r\n\t\t// for (let objectId in metaScene.metaObjects) {\r\n\t\t// \tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t// \tmetaObject.metaModels = [];\r\n\t\t// }\r\n\r\n\t\t// for (let modelId in metaScene.metaModels) {\r\n\t\t// \tconst metaModel = metaScene.metaModels[modelId];\r\n\t\t// \tfor (let i = 0, len = metaModel.metaObjects.length; i < len; i++) {\r\n\t\t// \t\tconst metaObject = metaModel.metaObjects[i];\r\n\t\t// \t\tmetaObject.metaModels.push(metaModel);\r\n\t\t// \t}\r\n\t\t// }\r\n\r\n\t\t// Rebuild MetaScene's MetaObjects-by-type lookup\r\n\r\n\t\t// metaScene.metaObjectsByType = {};\r\n\t\t// for (let objectId in metaScene.metaObjects) {\r\n\t\t// \tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t// \tconst type = metaObject.type;\r\n\t\t// \t(metaScene.metaObjectsByType[type] || (metaScene.metaObjectsByType[type] = {}))[objectId] = metaObject;\r\n\t\t// }\r\n\r\n\t\tthis._finalized = true;\r\n\r\n\t\tthis.metaScene.fire(\"metaModelCreated\", this.id);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets this MetaModel as JSON.\r\n\t * @returns {{schema: (String|string|*), createdAt: (String|string|*), metaObjects: *[], author: (String|string|*), id: (String|Number|string|number|*), creatingApplication: (String|string|*), projectId: (String|Number|string|number|*), propertySets: *[]}}\r\n\t */\r\n\tgetJSON() {\r\n\t\tconst json = {\r\n\t\t\tid: this.id,\r\n\t\t\tprojectId: this.projectId,\r\n\t\t\tauthor: this.author,\r\n\t\t\tcreatedAt: this.createdAt,\r\n\t\t\tschema: this.schema,\r\n\t\t\tcreatingApplication: this.creatingApplication,\r\n\t\t\tmetaObjects: [],\r\n\t\t\tpropertySets: []\r\n\t\t};\r\n\t\tfor (let i = 0, len = this.metaObjects.length; i < len; i++) {\r\n\t\t\tconst metaObject = this.metaObjects[i];\r\n\t\t\tconst metaObjectCfg = {\r\n\t\t\t\tid: metaObject.id,\r\n\t\t\t\toriginalSystemId: metaObject.originalSystemId,\r\n\t\t\t\textId: metaObject.extId,\r\n\t\t\t\ttype: metaObject.type,\r\n\t\t\t\tname: metaObject.name\r\n\t\t\t};\r\n\t\t\tif (metaObject.parent) {\r\n\t\t\t\tmetaObjectCfg.parent = metaObject.parent.id;\r\n\t\t\t}\r\n\t\t\tif (metaObject.attributes) {\r\n\t\t\t\tmetaObjectCfg.attributes = metaObject.attributes;\r\n\t\t\t}\r\n\t\t\tif (metaObject.propertySetIds) {\r\n\t\t\t\tmetaObjectCfg.propertySetIds = metaObject.propertySetIds;\r\n\t\t\t}\r\n\t\t\tjson.metaObjects.push(metaObjectCfg);\r\n\t\t}\r\n\t\tfor (let i = 0, len = this.propertySets.length; i < len; i++) {\r\n\t\t\tconst propertySet = this.propertySets[i];\r\n\t\t\tconst propertySetCfg = {\r\n\t\t\t\tid: propertySet.id,\r\n\t\t\t\toriginalSystemId: propertySet.originalSystemId,\r\n\t\t\t\textId: propertySet.extId,\r\n\t\t\t\ttype: propertySet.type,\r\n\t\t\t\tname: propertySet.name,\r\n\t\t\t\tpropertyies: []\r\n\t\t\t};\r\n\t\t\tfor (let j = 0, lenj = propertySet.properties.length; j < lenj; j++) {\r\n\t\t\t\tconst property = propertySet.properties[j];\r\n\t\t\t\tconst propertyCfg = {\r\n\t\t\t\t\tid: property.id,\r\n\t\t\t\t\tdescription: property.description,\r\n\t\t\t\t\ttype: property.type,\r\n\t\t\t\t\tname: property.name,\r\n\t\t\t\t\tvalue: property.value,\r\n\t\t\t\t\tvalueType: property.valueType\r\n\t\t\t\t};\r\n\t\t\t\tpropertySetCfg.properties.push(propertyCfg);\r\n\t\t\t}\r\n\t\t\tjson.propertySets.push(propertySetCfg);\r\n\t\t}\r\n\t\treturn json;\r\n\t}\r\n\r\n\t_globalizeIDs(metaModelData, options) {\r\n\t\tconst globalize = !!options.globalizeObjectIds;\r\n\r\n\t\tif (metaModelData.metaObjects) {\r\n\t\t\tfor (let i = 0, len = metaModelData.metaObjects.length; i < len; i++) {\r\n\t\t\t\tconst metaObjectData = metaModelData.metaObjects[i];\r\n\r\n\t\t\t\t// Globalize MetaObject IDs and parent IDs\r\n\r\n\t\t\t\tmetaObjectData.originalSystemId = metaObjectData.id;\r\n\t\t\t\tif (metaObjectData.parent) {\r\n\t\t\t\t\tmetaObjectData.originalParentSystemId = metaObjectData.parent;\r\n\t\t\t\t}\r\n\t\t\t\tif (globalize) {\r\n\t\t\t\t\tmetaObjectData.id = _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, metaObjectData.id);\r\n\t\t\t\t\tif (metaObjectData.parent) {\r\n\t\t\t\t\t\tmetaObjectData.parent = _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, metaObjectData.parent);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Globalize MetaObject property set IDs\r\n\r\n\t\t\t\tif (globalize) {\r\n\t\t\t\t\tconst propertySetIds = metaObjectData.propertySetIds;\r\n\t\t\t\t\tif (propertySetIds) {\r\n\t\t\t\t\t\tconst propertySetGlobalIds = [];\r\n\t\t\t\t\t\tfor (let j = 0, lenj = propertySetIds.length; j < lenj; j++) {\r\n\t\t\t\t\t\t\tpropertySetGlobalIds.push(_scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, propertySetIds[j]));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmetaObjectData.propertySetIds = propertySetGlobalIds;\r\n\t\t\t\t\t\tmetaObjectData.originalSystemPropertySetIds = propertySetIds;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tmetaObjectData.originalSystemPropertySetIds = metaObjectData.propertySetIds;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Globalize global PropertySet IDs\r\n\r\n\t\tif (metaModelData.propertySets) {\r\n\t\t\tfor (let i = 0, len = metaModelData.propertySets.length; i < len; i++) {\r\n\t\t\t\tconst propertySet = metaModelData.propertySets[i];\r\n\t\t\t\tpropertySet.originalSystemId = propertySet.id;\r\n\t\t\t\tif (globalize) {\r\n\t\t\t\t\tpropertySet.id = _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, propertySet.id);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/metadata/MetaModel.js?");
|
|
2407
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MetaModel: () => (/* binding */ MetaModel)\n/* harmony export */ });\n/* harmony import */ var _PropertySet_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PropertySet.js */ \"./src/viewer/metadata/PropertySet.js\");\n/* harmony import */ var _MetaObject_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MetaObject.js */ \"./src/viewer/metadata/MetaObject.js\");\n/* harmony import */ var _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../scene/math/math.js */ \"./src/viewer/scene/math/math.js\");\n\r\n\r\n\r\n\r\n/**\r\n * @desc Metadata corresponding to an {@link Entity} that represents a model.\r\n *\r\n * An {@link Entity} represents a model when {@link Entity#isModel} is ````true````\r\n *\r\n * A MetaModel corresponds to an {@link Entity} by having the same {@link MetaModel#id} as the {@link Entity#id}.\r\n *\r\n * A MetaModel is created by {@link MetaScene#createMetaModel} and belongs to a {@link MetaScene}.\r\n *\r\n * Each MetaModel is registered by {@link MetaModel#id} in {@link MetaScene#metaModels}.\r\n *\r\n * A {@link MetaModel} represents its object structure with a tree of {@link MetaObject}s, with {@link MetaModel#rootMetaObject} referencing the root {@link MetaObject}.\r\n *\r\n * @class MetaModel\r\n */\r\nclass MetaModel {\r\n\t/**\r\n\t * Creates a new, unfinalized MetaModel.\r\n\t *\r\n\t * * The MetaModel is immediately registered by {@link MetaModel#id} in {@link MetaScene#metaModels}, even though it's not yet populated.\r\n\t * * The MetaModel then needs to be populated with one or more calls to {@link metaModel#loadData}.\r\n\t * * As we populate it, the MetaModel will create {@link MetaObject}s and {@link PropertySet}s in itself, and in the MetaScene.\r\n\t * * When populated, call {@link MetaModel#finalize} to finish it off, which causes MetaScene to fire a \"metaModelCreated\" event.\r\n\t */\r\n\tconstructor(params) {\r\n\t\t/**\r\n\t\t * Globally-unique ID.\r\n\t\t *\r\n\t\t * MetaModels are registered by ID in {@link MetaScene#metaModels}.\r\n\t\t *\r\n\t\t * When this MetaModel corresponds to an {@link Entity} then this ID will match the {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property id\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.id = params.id;\r\n\r\n\t\t/**\r\n\t\t * The project ID\r\n\t\t * @property projectId\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.projectId = params.projectId;\r\n\r\n\t\t/**\r\n\t\t * The revision ID, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property revisionId\r\n\t\t * @type {String|Number}\r\n\t\t */\r\n\t\tthis.revisionId = params.revisionId;\r\n\r\n\t\t/**\r\n\t\t * The model author, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property author\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.author = params.author;\r\n\r\n\t\t/**\r\n\t\t * The date the model was created, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property createdAt\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.createdAt = params.createdAt;\r\n\r\n\t\t/**\r\n\t\t * The application that created the model, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property creatingApplication\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.creatingApplication = params.creatingApplication;\r\n\r\n\t\t/**\r\n\t\t * The model schema version, if available.\r\n\t\t *\r\n\t\t * Will be undefined if not available.\r\n\t\t *\r\n\t\t * @property schema\r\n\t\t * @type {String}\r\n\t\t */\r\n\t\tthis.schema = params.schema;\r\n\r\n\t\t/**\r\n\t\t * Metadata on the {@link Scene}.\r\n\t\t *\r\n\t\t * @property metaScene\r\n\t\t * @type {MetaScene}\r\n\t\t */\r\n\t\tthis.metaScene = params.metaScene;\r\n\r\n\t\t/**\r\n\t\t * The {@link PropertySet}s in this MetaModel.\r\n\t\t *\r\n\t\t * @property propertySets\r\n\t\t * @type {PropertySet[]}\r\n\t\t */\r\n\t\tthis.propertySets = [];\r\n\r\n\t\t/**\r\n\t\t * The root {@link MetaObject}s in this MetaModel's composition structure hierarchy.\r\n\t\t *\r\n\t\t * @property rootMetaObject\r\n\t\t * @type {MetaObject[]}\r\n\t\t */\r\n\t\tthis.rootMetaObjects = [];\r\n\r\n\t\t/**\r\n\t\t * The {@link MetaObject}s in this MetaModel, each mapped to its ID.\r\n\t\t *\r\n\t\t * @property metaObjects\r\n\t\t * @type {MetaObject[]}\r\n\t\t */\r\n\t\tthis.metaObjects = [];\r\n\r\n\t\tthis.objectCount = 0;\r\n\t\tthis.propertySetCount = 0;\r\n\r\n\t\t/**\r\n\t\t * Connectivity graph.\r\n\t\t * @type {{}}\r\n\t\t */\r\n\t\tthis.graph = params.graph || {};\r\n\r\n\t\tthis.metaScene.metaModels[this.id] = this;\r\n\r\n\t\t/**\r\n\t\t * True when this MetaModel has been finalized.\r\n\t\t * @type {boolean}\r\n\t\t */\r\n\t\tthis._finalized = false;\r\n\t}\r\n\r\n\tset finalized(finalized) {\r\n\t\tthis._finalized = finalized;\r\n\t}\r\n\r\n\tget finalized() {\r\n\t\treturn this._finalized;\r\n\t}\r\n\r\n\t/**\r\n\t * Backwards compatibility with the model having a single root MetaObject.\r\n\t *\r\n\t * @property rootMetaObject\r\n\t * @type {MetaObject|null}\r\n\t */\r\n\tget rootMetaObject() {\r\n\t\tif (this.rootMetaObjects.length == 1) {\r\n\t\t\treturn this.rootMetaObjects[0];\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\r\n\t/**\r\n\t * Load metamodel data into this MetaModel.\r\n\t * @param metaModelData\r\n\t */\r\n\t// loadData(metaModelData, options = {}) {\r\n\tloadData(metaModelData, done, err) {\r\n\t\tif (this._finalized) {\r\n\t\t\tthrow \"MetaScene already finalized - can't add more data\";\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tif (metaModelData === null) throw \"metaModelData is null!\";\r\n\t\t\t// 使用可选链和空值合并\r\n\t\t\tthis.author = metaModelData.author ?? \"\";\r\n\t\t\tthis.schema = metaModelData.schema ?? \"\";\r\n\t\t\tthis.createdAt = metaModelData.createdAt ?? \"\";\r\n\t\t\tthis.projectId = metaModelData.projectId ?? \"\";\r\n\t\t\tthis.revisionId = metaModelData.revisionId ?? \"\";\r\n\t\t\tthis.objectCount = metaModelData.objectCount ?? \"\";\r\n\t\t\tthis.propertySetCount = metaModelData.propertySetCount ?? \"\";\r\n\t\t\tthis.creatingApplication = metaModelData.creatingApplication ?? \"\";\r\n\r\n\t\t\t// this._globalizeIDs(metaModelData, options);\r\n\r\n\t\t\tconst metaScene = this.metaScene;\r\n\r\n\t\t\tif (metaModelData.propertySets) {\r\n\t\t\t\t// for (let i = 0; i < metaModelData.propertySets.length; i++) {\r\n\t\t\t\t// \tconst propertySetData = metaModelData.propertySets[i];\r\n\t\t\t\t// const metaId = propertySetData.id;\r\n\r\n\t\t\t\tfor (let metaId in metaModelData.propertySets) {\r\n\t\t\t\t\tconst propertySetData = metaModelData.propertySets[metaId];\r\n\t\t\t\t\tlet propertySet = new _PropertySet_js__WEBPACK_IMPORTED_MODULE_0__.PropertySet({\r\n\t\t\t\t\t\tid: propertySetData.id,\r\n\t\t\t\t\t\toriginalSystemId: propertySetData.originalSystemId || propertySetData.id,\r\n\t\t\t\t\t\ttype: propertySetData.type,\r\n\t\t\t\t\t\tname: propertySetData.name,\r\n\t\t\t\t\t\tproperties: propertySetData.properties\r\n\t\t\t\t\t});\r\n\t\t\t\t\tmetaScene.propertySets[metaId] = propertySet;\r\n\t\t\t\t\t// propertySet.metaModels.push(this);\r\n\t\t\t\t\tthis.propertySets.push(propertySet);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (metaModelData.metaObjects) {\r\n\t\t\t\t// for (let i = 0; i < metaModelData.metaObjects.length; i++) {\r\n\t\t\t\t// \tconst objectData = metaModelData.metaObjects[i];\r\n\t\t\t\t// \tconst metaId = objectData.id;\r\n\r\n\t\t\t\tfor (let metaId in metaModelData.metaObjects) {\r\n\t\t\t\t\tconst objectData = metaModelData.metaObjects[metaId];\r\n\t\t\t\t\tlet metaObject = new _MetaObject_js__WEBPACK_IMPORTED_MODULE_1__.MetaObject({\r\n\t\t\t\t\t\tid: metaId,\r\n\t\t\t\t\t\toriginalSystemId: metaId,\r\n\t\t\t\t\t\tparentId: objectData.parent,\r\n\t\t\t\t\t\ttype: objectData.type,\r\n\t\t\t\t\t\tname: objectData.name,\r\n\t\t\t\t\t\tpropertySetIds: objectData.propertySetIds,\r\n\t\t\t\t\t\texternal: objectData.external\r\n\t\t\t\t\t});\r\n\t\t\t\t\tmetaObject.children = [];\r\n\t\t\t\t\tmetaObject.metaModels = [];\r\n\t\t\t\t\tmetaObject.metaModels.push(this);\r\n\t\t\t\t\tmetaScene.metaObjects[metaId] = metaObject;\r\n\r\n\t\t\t\t\tthis.metaObjects.push(metaObject);\r\n\t\t\t\t\tif (!objectData.parent) {\r\n\t\t\t\t\t\tthis.rootMetaObjects.push(metaObject);\r\n\t\t\t\t\t\tmetaScene.rootMetaObjects[metaId] = metaObject;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (typeof done === \"function\") done();\r\n\t\t} catch (error) {\r\n\t\t\tif (typeof err === \"function\") err(error);\r\n\t\t\telse this.log(err);\r\n\t\t}\r\n\t}\r\n\r\n\t_decompressProperties(propertyLookup, properties) {\r\n\t\tfor (let i = 0, len = properties.length; i < len; i++) {\r\n\t\t\tconst property = properties[i];\r\n\t\t\tif (Number.isInteger(property)) {\r\n\t\t\t\tconst lookupProperty = propertyLookup[property];\r\n\t\t\t\tif (lookupProperty) {\r\n\t\t\t\t\tproperties[i] = lookupProperty;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfinalize() {\r\n\t\tif (this._finalized) {\r\n\t\t\tthrow \"MetaScene already finalized - can't re-finalize\";\r\n\t\t}\r\n\r\n\t\t// Re-link MetaScene's entire MetaObject parent/child hierarchy\r\n\r\n\t\tconst metaScene = this.metaScene;\r\n\t\tmetaScene.metaObjectsByType = {};\r\n\r\n\t\tfor (let objectId in metaScene.metaObjects) {\r\n\t\t\tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t\t// if (metaObject.children) {\r\n\t\t\t// \tmetaObject.children = [];\r\n\t\t\t// }\r\n\t\t\tif (metaObject.parentId) {\r\n\t\t\t\tconst parentMetaObject = metaScene.metaObjects[metaObject.parentId];\r\n\t\t\t\tif (parentMetaObject) {\r\n\t\t\t\t\tmetaObject.parent = parentMetaObject;\r\n\t\t\t\t\t(parentMetaObject.children || (parentMetaObject.children = [])).push(metaObject);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Re-link each MetaObject's property sets\r\n\r\n\t\t\tif (metaObject.propertySets) {\r\n\t\t\t\tmetaObject.propertySets = [];\r\n\t\t\t}\r\n\t\t\tif (metaObject.propertySetIds) {\r\n\t\t\t\tfor (let i = 0, len = metaObject.propertySetIds.length; i < len; i++) {\r\n\t\t\t\t\tconst propertySetId = metaObject.propertySetIds[i];\r\n\t\t\t\t\tconst propertySet = metaScene.propertySets[propertySetId];\r\n\t\t\t\t\tmetaObject.propertySets.push(propertySet);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tconst type = metaObject.type;\r\n\t\t\t(metaScene.metaObjectsByType[type] || (metaScene.metaObjectsByType[type] = {}))[objectId] = metaObject;\r\n\t\t}\r\n\r\n\t\t// for (let objectId in metaScene.metaObjects) {\r\n\t\t// \tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t// \tif (metaObject.parentId) {\r\n\t\t// \t\tconst parentMetaObject = metaScene.metaObjects[metaObject.parentId];\r\n\t\t// \t\tif (parentMetaObject) {\r\n\t\t// \t\t\tmetaObject.parent = parentMetaObject;\r\n\t\t// \t\t\t(parentMetaObject.children || (parentMetaObject.children = [])).push(metaObject);\r\n\t\t// \t\t}\r\n\t\t// \t}\r\n\t\t// }\r\n\r\n\t\t// Relink MetaObjects to their MetaModels\r\n\r\n\t\t// for (let objectId in metaScene.metaObjects) {\r\n\t\t// \tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t// \tmetaObject.metaModels = [];\r\n\t\t// }\r\n\r\n\t\t// for (let modelId in metaScene.metaModels) {\r\n\t\t// \tconst metaModel = metaScene.metaModels[modelId];\r\n\t\t// \tfor (let i = 0, len = metaModel.metaObjects.length; i < len; i++) {\r\n\t\t// \t\tconst metaObject = metaModel.metaObjects[i];\r\n\t\t// \t\tmetaObject.metaModels.push(metaModel);\r\n\t\t// \t}\r\n\t\t// }\r\n\r\n\t\t// Rebuild MetaScene's MetaObjects-by-type lookup\r\n\r\n\t\t// metaScene.metaObjectsByType = {};\r\n\t\t// for (let objectId in metaScene.metaObjects) {\r\n\t\t// \tconst metaObject = metaScene.metaObjects[objectId];\r\n\t\t// \tconst type = metaObject.type;\r\n\t\t// \t(metaScene.metaObjectsByType[type] || (metaScene.metaObjectsByType[type] = {}))[objectId] = metaObject;\r\n\t\t// }\r\n\r\n\t\tthis._finalized = true;\r\n\r\n\t\tthis.metaScene.fire(\"metaModelCreated\", this.id);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets this MetaModel as JSON.\r\n\t * @returns {{schema: (String|string|*), createdAt: (String|string|*), metaObjects: *[], author: (String|string|*), id: (String|Number|string|number|*), creatingApplication: (String|string|*), projectId: (String|Number|string|number|*), propertySets: *[]}}\r\n\t */\r\n\tgetJSON() {\r\n\t\tconst json = {\r\n\t\t\tid: this.id,\r\n\t\t\tprojectId: this.projectId,\r\n\t\t\tauthor: this.author,\r\n\t\t\tcreatedAt: this.createdAt,\r\n\t\t\tschema: this.schema,\r\n\t\t\tcreatingApplication: this.creatingApplication,\r\n\t\t\tmetaObjects: [],\r\n\t\t\tpropertySets: []\r\n\t\t};\r\n\t\tfor (let i = 0, len = this.metaObjects.length; i < len; i++) {\r\n\t\t\tconst metaObject = this.metaObjects[i];\r\n\t\t\tconst metaObjectCfg = {\r\n\t\t\t\tid: metaObject.id,\r\n\t\t\t\toriginalSystemId: metaObject.originalSystemId,\r\n\t\t\t\textId: metaObject.extId,\r\n\t\t\t\ttype: metaObject.type,\r\n\t\t\t\tname: metaObject.name\r\n\t\t\t};\r\n\t\t\tif (metaObject.parent) {\r\n\t\t\t\tmetaObjectCfg.parent = metaObject.parent.id;\r\n\t\t\t}\r\n\t\t\tif (metaObject.attributes) {\r\n\t\t\t\tmetaObjectCfg.attributes = metaObject.attributes;\r\n\t\t\t}\r\n\t\t\tif (metaObject.propertySetIds) {\r\n\t\t\t\tmetaObjectCfg.propertySetIds = metaObject.propertySetIds;\r\n\t\t\t}\r\n\t\t\tjson.metaObjects.push(metaObjectCfg);\r\n\t\t}\r\n\t\tfor (let i = 0, len = this.propertySets.length; i < len; i++) {\r\n\t\t\tconst propertySet = this.propertySets[i];\r\n\t\t\tconst propertySetCfg = {\r\n\t\t\t\tid: propertySet.id,\r\n\t\t\t\toriginalSystemId: propertySet.originalSystemId,\r\n\t\t\t\textId: propertySet.extId,\r\n\t\t\t\ttype: propertySet.type,\r\n\t\t\t\tname: propertySet.name,\r\n\t\t\t\tpropertyies: []\r\n\t\t\t};\r\n\t\t\tfor (let j = 0, lenj = propertySet.properties.length; j < lenj; j++) {\r\n\t\t\t\tconst property = propertySet.properties[j];\r\n\t\t\t\tconst propertyCfg = {\r\n\t\t\t\t\tid: property.id,\r\n\t\t\t\t\tdescription: property.description,\r\n\t\t\t\t\ttype: property.type,\r\n\t\t\t\t\tname: property.name,\r\n\t\t\t\t\tvalue: property.value,\r\n\t\t\t\t\tvalueType: property.valueType\r\n\t\t\t\t};\r\n\t\t\t\tpropertySetCfg.properties.push(propertyCfg);\r\n\t\t\t}\r\n\t\t\tjson.propertySets.push(propertySetCfg);\r\n\t\t}\r\n\t\treturn json;\r\n\t}\r\n\r\n\t_globalizeIDs(metaModelData, options) {\r\n\t\tconst globalize = !!options.globalizeObjectIds;\r\n\r\n\t\tif (metaModelData.metaObjects) {\r\n\t\t\tfor (let i = 0, len = metaModelData.metaObjects.length; i < len; i++) {\r\n\t\t\t\tconst metaObjectData = metaModelData.metaObjects[i];\r\n\r\n\t\t\t\t// Globalize MetaObject IDs and parent IDs\r\n\r\n\t\t\t\tmetaObjectData.originalSystemId = metaObjectData.id;\r\n\t\t\t\tif (metaObjectData.parent) {\r\n\t\t\t\t\tmetaObjectData.originalParentSystemId = metaObjectData.parent;\r\n\t\t\t\t}\r\n\t\t\t\tif (globalize) {\r\n\t\t\t\t\tmetaObjectData.id = _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, metaObjectData.id);\r\n\t\t\t\t\tif (metaObjectData.parent) {\r\n\t\t\t\t\t\tmetaObjectData.parent = _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, metaObjectData.parent);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Globalize MetaObject property set IDs\r\n\r\n\t\t\t\tif (globalize) {\r\n\t\t\t\t\tconst propertySetIds = metaObjectData.propertySetIds;\r\n\t\t\t\t\tif (propertySetIds) {\r\n\t\t\t\t\t\tconst propertySetGlobalIds = [];\r\n\t\t\t\t\t\tfor (let j = 0, lenj = propertySetIds.length; j < lenj; j++) {\r\n\t\t\t\t\t\t\tpropertySetGlobalIds.push(_scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, propertySetIds[j]));\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tmetaObjectData.propertySetIds = propertySetGlobalIds;\r\n\t\t\t\t\t\tmetaObjectData.originalSystemPropertySetIds = propertySetIds;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tmetaObjectData.originalSystemPropertySetIds = metaObjectData.propertySetIds;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Globalize global PropertySet IDs\r\n\r\n\t\tif (metaModelData.propertySets) {\r\n\t\t\tfor (let i = 0, len = metaModelData.propertySets.length; i < len; i++) {\r\n\t\t\t\tconst propertySet = metaModelData.propertySets[i];\r\n\t\t\t\tpropertySet.originalSystemId = propertySet.id;\r\n\t\t\t\tif (globalize) {\r\n\t\t\t\t\tpropertySet.id = _scene_math_math_js__WEBPACK_IMPORTED_MODULE_2__.math.globalizeObjectId(this.id, propertySet.id);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/metadata/MetaModel.js?");
|
|
2408
2408
|
|
|
2409
2409
|
/***/ }),
|
|
2410
2410
|
|
|
@@ -2514,7 +2514,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2514
2514
|
\***************************************************************************/
|
|
2515
2515
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2516
2516
|
|
|
2517
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PivotController: () => (/* binding */ PivotController)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _geometry_VBOGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../geometry/VBOGeometry.js */ \"./src/viewer/scene/geometry/VBOGeometry.js\");\n/* harmony import */ var _geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\nconst tempVec3b = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\nconst tempVec4a = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\nconst tempVec4b = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\nconst tempVec4c = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\r\n/** @private */\r\nclass PivotController {\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tconstructor(scene, configs) {\r\n\t\t// Pivot math by: http://www.derschmale.com/\r\n\r\n\t\tthis._scene = scene;\r\n\t\tthis._configs = configs;\r\n\t\tthis._pivotWorldPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._cameraOffset = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._azimuth = 0;\r\n\t\tthis._polar = 0;\r\n\t\tthis._radius = 0;\r\n\t\tthis._pivotPosSet = false; // Initially false, true as soon as _pivotWorldPos has been set to some value\r\n\t\tthis._pivoting = false; // True while pivoting\r\n\t\tthis._shown = false;\r\n\r\n\t\tthis._pivotSphereEnabled = false;\r\n\t\tthis._pivotSphere = null;\r\n\t\tthis._pivotSphereSize = 1;\r\n\t\tthis._pivotSphereGeometry = null;\r\n\t\tthis._pivotSphereMaterial = null;\r\n\t\tthis._rtcCenter = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._rtcPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\tthis._pivotViewPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\tthis._pivotProjPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\tthis._pivotCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tthis._cameraDirty = true;\r\n\r\n\t\tthis._onViewMatrix = this._scene.camera.on(\"viewMatrix\", () => {\r\n\t\t\tthis._cameraDirty = true;\r\n\t\t});\r\n\r\n\t\tthis._onProjMatrix = this._scene.camera.on(\"projMatrix\", () => {\r\n\t\t\tthis._cameraDirty = true;\r\n\t\t});\r\n\r\n\t\tthis._onTick = this._scene.on(\"tick\", () => {\r\n\t\t\tthis.updatePivotElement();\r\n\t\t\tthis.updatePivotSphere();\r\n\t\t});\r\n\t}\r\n\r\n\tcreatePivotSphere() {\r\n\t\tconst currentPos = this.getPivotPos();\r\n\t\tconst cameraPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.decomposeMat4(\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(this._scene.viewer.camera.viewMatrix, _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4()),\r\n\t\t\tcameraPos,\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4(),\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3()\r\n\t\t);\r\n\t\tconst length = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec3(cameraPos, currentPos);\r\n\t\tlet radius = Math.tan(Math.PI / 500) * length * this._pivotSphereSize;\r\n\r\n\t\tif (this._scene.camera.projection == \"ortho\") {\r\n\t\t\tradius /= this._scene.camera.ortho.scale / 2;\r\n\t\t}\r\n\r\n\t\t(0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_5__.worldToRTCPos)(currentPos, this._rtcCenter, this._rtcPos);\r\n\t\tthis._pivotSphereGeometry = new _geometry_VBOGeometry_js__WEBPACK_IMPORTED_MODULE_3__.VBOGeometry(this._scene, (0,_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_4__.buildSphereGeometry)({ radius }));\r\n\t\tthis._pivotSphere = new _mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_2__.Mesh(this._scene, {\r\n\t\t\tgeometry: this._pivotSphereGeometry,\r\n\t\t\tmaterial: this._pivotSphereMaterial,\r\n\t\t\tpickable: false,\r\n\t\t\tposition: this._rtcPos,\r\n\t\t\trtcCenter: this._rtcCenter\r\n\t\t});\r\n\t}\r\n\r\n\tdestroyPivotSphere() {\r\n\t\tif (this._pivotSphere) {\r\n\t\t\tthis._pivotSphere.destroy();\r\n\t\t\tthis._pivotSphere = null;\r\n\t\t}\r\n\t\tif (this._pivotSphereGeometry) {\r\n\t\t\tthis._pivotSphereGeometry.destroy();\r\n\t\t\tthis._pivotSphereGeometry = null;\r\n\t\t}\r\n\t}\r\n\r\n\tupdatePivotElement() {\r\n\t\tconst camera = this._scene.camera;\r\n\t\tconst canvas = this._scene.canvas;\r\n\r\n\t\tif (this._pivoting && this._cameraDirty) {\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint3(camera.viewMatrix, this.getPivotPos(), this._pivotViewPos);\r\n\t\t\tthis._pivotViewPos[3] = 1;\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint4(camera.projMatrix, this._pivotViewPos, this._pivotProjPos);\r\n\r\n\t\t\tconst canvasAABB = canvas.boundary;\r\n\t\t\tconst canvasWidth = canvasAABB[2];\r\n\t\t\tconst canvasHeight = canvasAABB[3];\r\n\r\n\t\t\tthis._pivotCanvasPos[0] = Math.floor(((1 + this._pivotProjPos[0] / this._pivotProjPos[3]) * canvasWidth) / 2);\r\n\t\t\tthis._pivotCanvasPos[1] = Math.floor(((1 - this._pivotProjPos[1] / this._pivotProjPos[3]) * canvasHeight) / 2);\r\n\r\n\t\t\t// data-textures: avoid to do continuous DOM layout calculations\r\n\t\t\tlet canvasBoundingRect = canvas._lastBoundingClientRect;\r\n\r\n\t\t\tconst canvasElem = canvas.canvas;\r\n\r\n\t\t\tcanvasBoundingRect = canvas._lastBoundingClientRect = canvasElem.getBoundingClientRect();\r\n\r\n\t\t\tif (this._pivotElement) {\r\n\t\t\t\tthis._pivotElement.style.left =\r\n\t\t\t\t\tMath.floor(canvasBoundingRect.left + this._pivotCanvasPos[0]) -\r\n\t\t\t\t\tthis._pivotElement.clientWidth / 2 +\r\n\t\t\t\t\twindow.scrollX +\r\n\t\t\t\t\t\"px\";\r\n\t\t\t\tthis._pivotElement.style.top =\r\n\t\t\t\t\tMath.floor(canvasBoundingRect.top + this._pivotCanvasPos[1]) -\r\n\t\t\t\t\tthis._pivotElement.clientHeight / 2 +\r\n\t\t\t\t\twindow.scrollY +\r\n\t\t\t\t\t\"px\";\r\n\t\t\t}\r\n\t\t\tthis._cameraDirty = false;\r\n\t\t}\r\n\t}\r\n\r\n\tupdatePivotSphere() {\r\n\t\tif (this._pivoting && this._pivotSphere) {\r\n\t\t\t(0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_5__.worldToRTCPos)(this.getPivotPos(), this._rtcCenter, this._rtcPos);\r\n\t\t\tif (!_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.compareVec3(this._rtcPos, this._pivotSphere.position)) {\r\n\t\t\t\tthis.destroyPivotSphere();\r\n\t\t\t\tthis.createPivotSphere();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t/**\r\n\t * Sets the HTML DOM element that will represent the pivot position.\r\n\t *\r\n\t * @param pivotElement\r\n\t */\r\n\tsetPivotElement(pivotElement) {\r\n\t\tthis._pivotElement = pivotElement;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a sphere as the representation of the pivot position.\r\n\t *\r\n\t * @param {Object} [cfg] Sphere configuration.\r\n\t * @param {String} [cfg.size=1] Optional size factor of the sphere. Defaults to 1.\r\n\t * @param {String} [cfg.color=Array] Optional maretial color. Defaults to a red.\r\n\t */\r\n\tenablePivotSphere(cfg = {}) {\r\n\t\tthis.destroyPivotSphere();\r\n\t\tthis._pivotSphereEnabled = true;\r\n\t\tif (cfg.size) {\r\n\t\t\tthis._pivotSphereSize = cfg.size;\r\n\t\t}\r\n\t\tconst color = cfg.color || [1, 0, 0];\r\n\t\tthis._pivotSphereMaterial = new _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_1__.PhongMaterial(this._scene, {\r\n\t\t\temissive: color,\r\n\t\t\tambient: color,\r\n\t\t\tspecular: [0, 0, 0],\r\n\t\t\tdiffuse: [0, 0, 0]\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Remove the sphere as the representation of the pivot position.\r\n\t *\r\n\t */\r\n\tdisablePivotSphere() {\r\n\t\tthis.destroyPivotSphere();\r\n\t\tthis._pivotSphereEnabled = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Begins pivoting.\r\n\t */\r\n\tstartPivot() {\r\n\t\tif (this._cameraLookingDownwards()) {\r\n\t\t\tthis._pivoting = false;\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst camera = this._scene.camera;\r\n\r\n\t\tlet lookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lookAtMat4v(camera.eye, camera.look, camera.worldUp);\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint3(lookat, this.getPivotPos(), this._cameraOffset);\r\n\r\n\t\tconst pivotPos = this.getPivotPos();\r\n\t\tthis._cameraOffset[2] += _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec3(camera.eye, pivotPos);\r\n\r\n\t\tlookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(lookat);\r\n\r\n\t\tconst offset = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(lookat, this._cameraOffset);\r\n\t\tconst diff = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.eye, pivotPos, diff);\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(diff, offset);\r\n\r\n\t\tif (camera.zUp) {\r\n\t\t\tconst t = diff[1];\r\n\t\t\tdiff[1] = diff[2];\r\n\t\t\tdiff[2] = t;\r\n\t\t}\r\n\r\n\t\tthis._radius = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(diff);\r\n\t\tthis._polar = Math.acos(diff[1] / this._radius);\r\n\t\tthis._azimuth = Math.atan2(diff[0], diff[2]);\r\n\t\tthis._pivoting = true;\r\n\t}\r\n\r\n\t_cameraLookingDownwards() {\r\n\t\t// Returns true if angle between camera viewing direction and World-space \"up\" axis is too small\r\n\t\tconst camera = this._scene.camera;\r\n\t\tconst forwardAxis = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.look, camera.eye, tempVec3a));\r\n\t\tconst rightAxis = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(forwardAxis, camera.worldUp, tempVec3b);\r\n\t\tlet rightAxisLen = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.sqLenVec3(rightAxis);\r\n\t\treturn rightAxisLen <= 0.0001;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns true if we are currently pivoting.\r\n\t *\r\n\t * @returns {Boolean}\r\n\t */\r\n\tgetPivoting() {\r\n\t\treturn this._pivoting;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a 3D World-space position to pivot about.\r\n\t *\r\n\t * @param {Number[]} worldPos The new World-space pivot position.\r\n\t */\r\n\tsetPivotPos(worldPos) {\r\n\t\tthis._pivotWorldPos.set(worldPos);\r\n\t\tthis._pivotPosSet = true;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the pivot position to the 3D projection of the given 2D canvas coordinates on a sphere centered\r\n\t * at the viewpoint. The radius of the sphere is configured via {@link CameraControl#smartPivot}.\r\n\t *\r\n\t *\r\n\t * @param canvasPos\r\n\t */\r\n\tsetCanvasPivotPos(canvasPos) {\r\n\t\tconst camera = this._scene.camera;\r\n\t\tconst pivotShereRadius = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec3(this._scene.center, camera.eye));\r\n\t\tconst transposedProjectMat = camera.project.transposedMatrix;\r\n\t\tconst Pt3 = transposedProjectMat.subarray(8, 12);\r\n\t\tconst Pt4 = transposedProjectMat.subarray(12);\r\n\t\tconst D = [0, 0, -1.0, 1];\r\n\t\tconst screenZ = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec4(D, Pt3) / _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec4(D, Pt4);\r\n\t\tconst worldPos = tempVec4a;\r\n\t\tcamera.project.unproject(canvasPos, screenZ, tempVec4b, tempVec4c, worldPos);\r\n\t\tconst eyeWorldPosVec = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(worldPos, camera.eye, tempVec3a));\r\n\t\tconst posOnSphere = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(\r\n\t\t\tcamera.eye,\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(eyeWorldPosVec, pivotShereRadius, tempVec3b),\r\n\t\t\ttempVec3c\r\n\t\t);\r\n\t\tthis.setPivotPos(posOnSphere);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the current position we're pivoting about.\r\n\t * @returns {Number[]} The current World-space pivot position.\r\n\t */\r\n\tgetPivotPos() {\r\n\t\treturn this._pivotPosSet ? this._pivotWorldPos : this._scene.camera.look; // Avoid pivoting about [0,0,0] by default\r\n\t}\r\n\r\n\t/**\r\n\t * Continues to pivot.\r\n\t *\r\n\t * @param {Number} yawInc Yaw rotation increment.\r\n\t * @param {Number} pitchInc Pitch rotation increment.\r\n\t */\r\n\tcontinuePivot(yawInc, pitchInc) {\r\n\t\tif (!this._pivoting) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (yawInc === 0 && pitchInc === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst camera = this._scene.camera;\r\n\t\tvar dx = -yawInc;\r\n\t\tconst dy = -pitchInc;\r\n\t\tif (camera.worldUp[2] === 1) {\r\n\t\t\tdx = -dx;\r\n\t\t}\r\n\t\tthis._azimuth += -dx * 0.01;\r\n\t\tthis._polar += dy * 0.01;\r\n\t\tthis._polar = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.clamp(this._polar, 0.001, Math.PI - 0.001);\r\n\t\tconst pos = [\r\n\t\t\tthis._radius * Math.sin(this._polar) * Math.sin(this._azimuth),\r\n\t\t\tthis._radius * Math.cos(this._polar),\r\n\t\t\tthis._radius * Math.sin(this._polar) * Math.cos(this._azimuth)\r\n\t\t];\r\n\t\tif (camera.worldUp[2] === 1) {\r\n\t\t\tconst t = pos[1];\r\n\t\t\tpos[1] = pos[2];\r\n\t\t\tpos[2] = t;\r\n\t\t}\r\n\t\t// Preserve the eye->look distance, since in xeokit \"look\" is the point-of-interest, not the direction vector.\r\n\t\tconst eyeLookLen = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.look, camera.eye, _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3()));\r\n\t\tconst pivotPos = this.getPivotPos();\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(pos, pivotPos);\r\n\t\tlet lookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lookAtMat4v(pos, pivotPos, camera.worldUp);\r\n\t\tlookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(lookat);\r\n\t\tconst offset = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(lookat, this._cameraOffset);\r\n\t\tlookat[12] -= offset[0];\r\n\t\tlookat[13] -= offset[1];\r\n\t\tlookat[14] -= offset[2];\r\n\t\tconst zAxis = [lookat[8], lookat[9], lookat[10]];\r\n\t\tcamera.eye = [lookat[12], lookat[13], lookat[14]];\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.eye, _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(zAxis, eyeLookLen), camera.look);\r\n\t\tcamera.up = [lookat[4], lookat[5], lookat[6]];\r\n\t\tthis.showPivot();\r\n\t}\r\n\r\n\t/**\r\n\t * Shows the pivot position.\r\n\t *\r\n\t * Only works if we set an HTML DOM element to represent the pivot position.\r\n\t */\r\n\tshowPivot() {\r\n\t\tif (this._shown) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._pivotElement) {\r\n\t\t\tthis.updatePivotElement();\r\n\t\t\tthis._pivotElement.style.visibility = \"visible\";\r\n\t\t}\r\n\t\tif (this._pivotSphereEnabled) {\r\n\t\t\tthis.destroyPivotSphere();\r\n\t\t\tthis.createPivotSphere();\r\n\t\t}\r\n\t\tthis._shown = true;\r\n\t}\r\n\r\n\t/**\r\n\t * Hides the pivot position.\r\n\t *\r\n\t * Only works if we set an HTML DOM element to represent the pivot position.\r\n\t */\r\n\thidePivot() {\r\n\t\tif (!this._shown) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._pivotElement) {\r\n\t\t\tthis._pivotElement.style.visibility = \"hidden\";\r\n\t\t}\r\n\t\tif (this._pivotSphereEnabled) {\r\n\t\t\tthis.destroyPivotSphere();\r\n\t\t}\r\n\t\tthis._shown = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Finishes pivoting.\r\n\t */\r\n\tendPivot() {\r\n\t\tthis._pivoting = false;\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tif (this._pivotElement) {\r\n\t\t\tthis._pivotElement.parentNode.removeChild(this._pivotElement);\r\n\t\t}\r\n\t\tthis.destroyPivotSphere();\r\n\t\tthis._scene.camera.off(this._onViewMatrix);\r\n\t\tthis._scene.camera.off(this._onProjMatrix);\r\n\t\tthis._scene.off(this._onTick);\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/controllers/PivotController.js?");
|
|
2517
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PivotController: () => (/* binding */ PivotController)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../mesh/Mesh.js */ \"./src/viewer/scene/mesh/Mesh.js\");\n/* harmony import */ var _geometry_VBOGeometry_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../geometry/VBOGeometry.js */ \"./src/viewer/scene/geometry/VBOGeometry.js\");\n/* harmony import */ var _geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../geometry/builders/buildSphereGeometry.js */ \"./src/viewer/scene/geometry/builders/buildSphereGeometry.js\");\n/* harmony import */ var _math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../math/rtcCoords.js */ \"./src/viewer/scene/math/rtcCoords.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nconst tempVec3a = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\nconst tempVec3b = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\nconst tempVec3c = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\nconst tempVec4a = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\nconst tempVec4b = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\nconst tempVec4c = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\r\n/** @private */\r\nclass PivotController {\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tconstructor(scene, configs) {\r\n\t\t// Pivot math by: http://www.derschmale.com/\r\n\r\n\t\tthis._scene = scene;\r\n\t\tthis._configs = configs;\r\n\t\tthis._pivotWorldPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._cameraOffset = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._azimuth = 0;\r\n\t\tthis._polar = 0;\r\n\t\tthis._radius = 0;\r\n\t\tthis._pivotPosSet = false; // Initially false, true as soon as _pivotWorldPos has been set to some value\r\n\t\tthis._pivoting = false; // True while pivoting\r\n\t\tthis._shown = false;\r\n\r\n\t\tthis._pivotSphereEnabled = false;\r\n\t\tthis._pivotSphere = null;\r\n\t\tthis._pivotSphereSize = 1;\r\n\t\tthis._pivotSphereGeometry = null;\r\n\t\tthis._pivotSphereMaterial = null;\r\n\t\tthis._rtcCenter = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\tthis._rtcPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\tthis._pivotViewPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\tthis._pivotProjPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4();\r\n\t\tthis._pivotCanvasPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec2();\r\n\t\tthis._cameraDirty = true;\r\n\r\n\t\tthis._onViewMatrix = this._scene.camera.on(\"viewMatrix\", () => {\r\n\t\t\tthis._cameraDirty = true;\r\n\t\t});\r\n\r\n\t\tthis._onProjMatrix = this._scene.camera.on(\"projMatrix\", () => {\r\n\t\t\tthis._cameraDirty = true;\r\n\t\t});\r\n\r\n\t\tthis._onTick = this._scene.on(\"tick\", () => {\r\n\t\t\tthis.updatePivotElement();\r\n\t\t\tthis.updatePivotSphere();\r\n\t\t});\r\n\t}\r\n\r\n\tcreatePivotSphere() {\r\n\t\tconst currentPos = this.getPivotPos();\r\n\t\tconst cameraPos = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.decomposeMat4(\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(this._scene.viewer.camera.viewMatrix, _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mat4()),\r\n\t\t\tcameraPos,\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec4(),\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3()\r\n\t\t);\r\n\t\tconst length = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec3(cameraPos, currentPos);\r\n\t\tlet radius = Math.tan(Math.PI / 500) * length * this._pivotSphereSize;\r\n\r\n\t\tif (this._scene.camera.projection == \"ortho\") {\r\n\t\t\tradius /= this._scene.camera.ortho.scale / 2;\r\n\t\t}\r\n\r\n\t\t(0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_5__.worldToRTCPos)(currentPos, this._rtcCenter, this._rtcPos);\r\n\t\tthis._pivotSphereGeometry = new _geometry_VBOGeometry_js__WEBPACK_IMPORTED_MODULE_3__.VBOGeometry(this._scene, (0,_geometry_builders_buildSphereGeometry_js__WEBPACK_IMPORTED_MODULE_4__.buildSphereGeometry)({ radius }));\r\n\t\tthis._pivotSphere = new _mesh_Mesh_js__WEBPACK_IMPORTED_MODULE_2__.Mesh(this._scene, {\r\n\t\t\tgeometry: this._pivotSphereGeometry,\r\n\t\t\tmaterial: this._pivotSphereMaterial,\r\n\t\t\tpickable: false,\r\n\t\t\tposition: this._rtcPos,\r\n\t\t\trtcCenter: this._rtcCenter\r\n\t\t});\r\n\t}\r\n\r\n\tdestroyPivotSphere() {\r\n\t\tif (this._pivotSphere) {\r\n\t\t\tthis._pivotSphere.destroy();\r\n\t\t\tthis._pivotSphere = null;\r\n\t\t}\r\n\t\tif (this._pivotSphereGeometry) {\r\n\t\t\tthis._pivotSphereGeometry.destroy();\r\n\t\t\tthis._pivotSphereGeometry = null;\r\n\t\t}\r\n\t}\r\n\r\n\tupdatePivotElement() {\r\n\t\tconst camera = this._scene.camera;\r\n\t\tconst canvas = this._scene.canvas;\r\n\r\n\t\tif (this._pivoting && this._cameraDirty) {\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint3(camera.viewMatrix, this.getPivotPos(), this._pivotViewPos);\r\n\t\t\tthis._pivotViewPos[3] = 1;\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint4(camera.projMatrix, this._pivotViewPos, this._pivotProjPos);\r\n\r\n\t\t\tconst canvasAABB = canvas.boundary;\r\n\t\t\tconst canvasWidth = canvasAABB[2];\r\n\t\t\tconst canvasHeight = canvasAABB[3];\r\n\r\n\t\t\tthis._pivotCanvasPos[0] = Math.floor(((1 + this._pivotProjPos[0] / this._pivotProjPos[3]) * canvasWidth) / 2);\r\n\t\t\tthis._pivotCanvasPos[1] = Math.floor(((1 - this._pivotProjPos[1] / this._pivotProjPos[3]) * canvasHeight) / 2);\r\n\r\n\t\t\t// data-textures: avoid to do continuous DOM layout calculations\r\n\t\t\tlet canvasBoundingRect = canvas._lastBoundingClientRect;\r\n\r\n\t\t\tconst canvasElem = canvas.canvas;\r\n\r\n\t\t\tcanvasBoundingRect = canvas._lastBoundingClientRect = canvasElem.getBoundingClientRect();\r\n\r\n\t\t\tif (this._pivotElement) {\r\n\t\t\t\tthis._pivotElement.style.left =\r\n\t\t\t\t\tMath.floor(canvasBoundingRect.left + this._pivotCanvasPos[0]) -\r\n\t\t\t\t\tthis._pivotElement.clientWidth / 2 +\r\n\t\t\t\t\twindow.scrollX +\r\n\t\t\t\t\t\"px\";\r\n\t\t\t\tthis._pivotElement.style.top =\r\n\t\t\t\t\tMath.floor(canvasBoundingRect.top + this._pivotCanvasPos[1]) -\r\n\t\t\t\t\tthis._pivotElement.clientHeight / 2 +\r\n\t\t\t\t\twindow.scrollY +\r\n\t\t\t\t\t\"px\";\r\n\t\t\t}\r\n\t\t\tthis._cameraDirty = false;\r\n\t\t}\r\n\t}\r\n\r\n\tupdatePivotSphere() {\r\n\t\tif (this._pivoting && this._pivotSphere) {\r\n\t\t\t(0,_math_rtcCoords_js__WEBPACK_IMPORTED_MODULE_5__.worldToRTCPos)(this.getPivotPos(), this._rtcCenter, this._rtcPos);\r\n\t\t\tif (!_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.compareVec3(this._rtcPos, this._pivotSphere.position)) {\r\n\t\t\t\tthis.destroyPivotSphere();\r\n\t\t\t\tthis.createPivotSphere();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t/**\r\n\t * Sets the HTML DOM element that will represent the pivot position.\r\n\t *\r\n\t * @param pivotElement\r\n\t */\r\n\tsetPivotElement(pivotElement) {\r\n\t\tthis._pivotElement = pivotElement;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a sphere as the representation of the pivot position.\r\n\t *\r\n\t * @param {Object} [cfg] Sphere configuration.\r\n\t * @param {String} [cfg.size=1] Optional size factor of the sphere. Defaults to 1.\r\n\t * @param {String} [cfg.color=Array] Optional maretial color. Defaults to a red.\r\n\t */\r\n\tenablePivotSphere(cfg = {}) {\r\n\t\tthis.destroyPivotSphere();\r\n\t\tthis._pivotSphereEnabled = true;\r\n\t\tif (cfg.size) {\r\n\t\t\tthis._pivotSphereSize = cfg.size;\r\n\t\t}\r\n\t\tconst color = cfg.color || [1, 0, 0];\r\n\t\tthis._pivotSphereMaterial = new _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_1__.PhongMaterial(this._scene, {\r\n\t\t\temissive: color,\r\n\t\t\tambient: color,\r\n\t\t\tspecular: [0, 0, 0],\r\n\t\t\tdiffuse: [0, 0, 0]\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Remove the sphere as the representation of the pivot position.\r\n\t *\r\n\t */\r\n\tdisablePivotSphere() {\r\n\t\tthis.destroyPivotSphere();\r\n\t\tthis._pivotSphereEnabled = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Begins pivoting.\r\n\t */\r\n\tstartPivot() {\r\n\t\tif (this._cameraLookingDownwards()) {\r\n\t\t\tthis._pivoting = false;\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst camera = this._scene.camera;\r\n\r\n\t\tlet lookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lookAtMat4v(camera.eye, camera.look, camera.worldUp);\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformPoint3(lookat, this.getPivotPos(), this._cameraOffset);\r\n\r\n\t\tconst pivotPos = this.getPivotPos();\r\n\t\tthis._cameraOffset[2] += _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec3(camera.eye, pivotPos);\r\n\r\n\t\tlookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(lookat);\r\n\r\n\t\tconst offset = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(lookat, this._cameraOffset);\r\n\t\tconst diff = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3();\r\n\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.eye, pivotPos, diff);\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(diff, offset);\r\n\r\n\t\tif (camera.zUp) {\r\n\t\t\tconst t = diff[1];\r\n\t\t\tdiff[1] = diff[2];\r\n\t\t\tdiff[2] = t;\r\n\t\t}\r\n\r\n\t\tthis._radius = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(diff);\r\n\t\tthis._polar = Math.acos(diff[1] / this._radius);\r\n\t\tthis._azimuth = Math.atan2(diff[0], diff[2]);\r\n\t\tthis._pivoting = true;\r\n\t}\r\n\r\n\t_cameraLookingDownwards() {\r\n\t\t// Returns true if angle between camera viewing direction and World-space \"up\" axis is too small\r\n\t\tconst camera = this._scene.camera;\r\n\t\tconst forwardAxis = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.look, camera.eye, tempVec3a));\r\n\t\tconst rightAxis = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.cross3Vec3(forwardAxis, camera.worldUp, tempVec3b);\r\n\t\tlet rightAxisLen = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.sqLenVec3(rightAxis);\r\n\t\treturn rightAxisLen <= 0.0001;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns true if we are currently pivoting.\r\n\t *\r\n\t * @returns {Boolean}\r\n\t */\r\n\tgetPivoting() {\r\n\t\treturn this._pivoting;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a 3D World-space position to pivot about.\r\n\t *\r\n\t * @param {Number[]} worldPos The new World-space pivot position.\r\n\t */\r\n\tsetPivotPos(worldPos) {\r\n\t\tif (!!this._pivotWorldPos) this._pivotWorldPos.set(worldPos);\r\n\t\tthis._pivotPosSet = true;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the pivot position to the 3D projection of the given 2D canvas coordinates on a sphere centered\r\n\t * at the viewpoint. The radius of the sphere is configured via {@link CameraControl#smartPivot}.\r\n\t *\r\n\t *\r\n\t * @param canvasPos\r\n\t */\r\n\tsetCanvasPivotPos(canvasPos) {\r\n\t\tconst camera = this._scene.camera;\r\n\t\tconst pivotShereRadius = Math.abs(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.distVec3(this._scene.center, camera.eye));\r\n\t\tconst transposedProjectMat = camera.project.transposedMatrix;\r\n\t\tconst Pt3 = transposedProjectMat.subarray(8, 12);\r\n\t\tconst Pt4 = transposedProjectMat.subarray(12);\r\n\t\tconst D = [0, 0, -1.0, 1];\r\n\t\tconst screenZ = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec4(D, Pt3) / _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.dotVec4(D, Pt4);\r\n\t\tconst worldPos = tempVec4a;\r\n\t\tcamera.project.unproject(canvasPos, screenZ, tempVec4b, tempVec4c, worldPos);\r\n\t\tconst eyeWorldPosVec = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.normalizeVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(worldPos, camera.eye, tempVec3a));\r\n\t\tconst posOnSphere = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(\r\n\t\t\tcamera.eye,\r\n\t\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(eyeWorldPosVec, pivotShereRadius, tempVec3b),\r\n\t\t\ttempVec3c\r\n\t\t);\r\n\t\tthis.setPivotPos(posOnSphere);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the current position we're pivoting about.\r\n\t * @returns {Number[]} The current World-space pivot position.\r\n\t */\r\n\tgetPivotPos() {\r\n\t\treturn this._pivotPosSet ? this._pivotWorldPos : this._scene.camera.look; // Avoid pivoting about [0,0,0] by default\r\n\t}\r\n\r\n\t/**\r\n\t * Continues to pivot.\r\n\t *\r\n\t * @param {Number} yawInc Yaw rotation increment.\r\n\t * @param {Number} pitchInc Pitch rotation increment.\r\n\t */\r\n\tcontinuePivot(yawInc, pitchInc) {\r\n\t\tif (!this._pivoting) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (yawInc === 0 && pitchInc === 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst camera = this._scene.camera;\r\n\t\tvar dx = -yawInc;\r\n\t\tconst dy = -pitchInc;\r\n\t\tif (camera.worldUp[2] === 1) {\r\n\t\t\tdx = -dx;\r\n\t\t}\r\n\t\tthis._azimuth += -dx * 0.01;\r\n\t\tthis._polar += dy * 0.01;\r\n\t\tthis._polar = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.clamp(this._polar, 0.001, Math.PI - 0.001);\r\n\t\tconst pos = [\r\n\t\t\tthis._radius * Math.sin(this._polar) * Math.sin(this._azimuth),\r\n\t\t\tthis._radius * Math.cos(this._polar),\r\n\t\t\tthis._radius * Math.sin(this._polar) * Math.cos(this._azimuth)\r\n\t\t];\r\n\t\tif (camera.worldUp[2] === 1) {\r\n\t\t\tconst t = pos[1];\r\n\t\t\tpos[1] = pos[2];\r\n\t\t\tpos[2] = t;\r\n\t\t}\r\n\t\t// Preserve the eye->look distance, since in xeokit \"look\" is the point-of-interest, not the direction vector.\r\n\t\tconst eyeLookLen = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lenVec3(_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.look, camera.eye, _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3()));\r\n\t\tconst pivotPos = this.getPivotPos();\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.addVec3(pos, pivotPos);\r\n\t\tlet lookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.lookAtMat4v(pos, pivotPos, camera.worldUp);\r\n\t\tlookat = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.inverseMat4(lookat);\r\n\t\tconst offset = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.transformVec3(lookat, this._cameraOffset);\r\n\t\tlookat[12] -= offset[0];\r\n\t\tlookat[13] -= offset[1];\r\n\t\tlookat[14] -= offset[2];\r\n\t\tconst zAxis = [lookat[8], lookat[9], lookat[10]];\r\n\t\tcamera.eye = [lookat[12], lookat[13], lookat[14]];\r\n\t\t_math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.subVec3(camera.eye, _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.mulVec3Scalar(zAxis, eyeLookLen), camera.look);\r\n\t\tcamera.up = [lookat[4], lookat[5], lookat[6]];\r\n\t\tthis.showPivot();\r\n\t}\r\n\r\n\t/**\r\n\t * Shows the pivot position.\r\n\t *\r\n\t * Only works if we set an HTML DOM element to represent the pivot position.\r\n\t */\r\n\tshowPivot() {\r\n\t\tif (this._shown) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._pivotElement) {\r\n\t\t\tthis.updatePivotElement();\r\n\t\t\tthis._pivotElement.style.visibility = \"visible\";\r\n\t\t}\r\n\t\tif (this._pivotSphereEnabled) {\r\n\t\t\tthis.destroyPivotSphere();\r\n\t\t\tthis.createPivotSphere();\r\n\t\t}\r\n\t\tthis._shown = true;\r\n\t}\r\n\r\n\t/**\r\n\t * Hides the pivot position.\r\n\t *\r\n\t * Only works if we set an HTML DOM element to represent the pivot position.\r\n\t */\r\n\thidePivot() {\r\n\t\tif (!this._shown) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (this._pivotElement) {\r\n\t\t\tthis._pivotElement.style.visibility = \"hidden\";\r\n\t\t}\r\n\t\tif (this._pivotSphereEnabled) {\r\n\t\t\tthis.destroyPivotSphere();\r\n\t\t}\r\n\t\tthis._shown = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Finishes pivoting.\r\n\t */\r\n\tendPivot() {\r\n\t\tthis._pivoting = false;\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tif (this._pivotElement) {\r\n\t\t\tthis._pivotElement.parentNode.removeChild(this._pivotElement);\r\n\t\t}\r\n\t\tthis.destroyPivotSphere();\r\n\t\tthis._scene.camera.off(this._onViewMatrix);\r\n\t\tthis._scene.camera.off(this._onProjMatrix);\r\n\t\tthis._scene.off(this._onTick);\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/CameraControl/lib/controllers/PivotController.js?");
|
|
2518
2518
|
|
|
2519
2519
|
/***/ }),
|
|
2520
2520
|
|
|
@@ -2734,7 +2734,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2734
2734
|
\*******************************************/
|
|
2735
2735
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2736
2736
|
|
|
2737
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Canvas: () => (/* binding */ Canvas)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _Spinner_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Spinner.js */ \"./src/viewer/scene/canvas/Spinner.js\");\n\r\n\r\n\r\n\r\nconst WEBGL_CONTEXT_NAMES = [\"webgl2\", \"experimental-webgl\", \"webkit-3d\", \"moz-webgl\", \"moz-glweb20\"];\r\n\r\n/**\r\n * @desc Manages its {@link Scene}'s HTML canvas.\r\n *\r\n * * Provides the HTML canvas element in {@link Canvas#canvas}.\r\n * * Has a {@link Spinner}, provided at {@link Canvas#spinner}, which manages the loading progress indicator.\r\n */\r\nclass Canvas extends _Component_js__WEBPACK_IMPORTED_MODULE_1__.Component {\r\n\t/**\r\n\t * @constructor\r\n\t * @private\r\n\t */\r\n\tconstructor(owner, cfg = {}) {\r\n\t\tsuper(owner, cfg);\r\n\t\tthis._backgroundColor = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([\r\n\t\t\tcfg.backgroundColor ? cfg.backgroundColor[0] : 1,\r\n\t\t\tcfg.backgroundColor ? cfg.backgroundColor[1] : 1,\r\n\t\t\tcfg.backgroundColor ? cfg.backgroundColor[2] : 1\r\n\t\t]);\r\n\t\tthis._backgroundColorFromAmbientLight = !!cfg.backgroundColorFromAmbientLight;\r\n\r\n\t\tthis.parent = owner;\r\n\t\tif (cfg.canvas)\r\n\t\t\t/**\r\n\t\t\t * The HTML canvas.\r\n\t\t\t *\r\n\t\t\t * @property canvas\r\n\t\t\t * @type {HTMLCanvasElement}\r\n\t\t\t * @final\r\n\t\t\t */\r\n\t\t\tthis.canvas = cfg.canvas;\r\n\t\telse this._createCanvas();\r\n\r\n\t\t/**\r\n\t\t * The WebGL rendering context.\r\n\t\t *\r\n\t\t * @property gl\r\n\t\t * @type {WebGLRenderingContext}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.gl = null;\r\n\r\n\t\t/**\r\n\t\t * True when WebGL 2 support is enabled.\r\n\t\t *\r\n\t\t * @property webgl2\r\n\t\t * @type {Boolean}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.webgl2 = false; // Will set true in _initWebGL if WebGL is requested and we succeed in getting it.\r\n\r\n\t\t/**\r\n\t\t * Indicates if this Canvas is transparent.\r\n\t\t *\r\n\t\t * @property transparent\r\n\t\t * @type {Boolean}\r\n\t\t * @default {false}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.transparent = !!cfg.transparent;\r\n\r\n\t\t/**\r\n\t\t * Attributes for the WebGL context\r\n\t\t *\r\n\t\t * @type {{}|*}\r\n\t\t */\r\n\t\tthis.contextAttr = cfg.contextAttr || {};\r\n\t\tthis.contextAttr.alpha = this.transparent;\r\n\r\n\t\tthis.contextAttr.preserveDrawingBuffer = !!this.contextAttr.preserveDrawingBuffer;\r\n\t\tthis.contextAttr.stencil = false;\r\n\t\tthis.contextAttr.premultipliedAlpha = !!this.contextAttr.premultipliedAlpha; // False by default: https://github.com/xeokit/xeokit-sdk/issues/251\r\n\t\tthis.contextAttr.antialias = this.contextAttr.antialias !== false;\r\n\r\n\t\t// If the canvas uses css styles to specify the sizes make sure the basic\r\n\t\t// width and height attributes match or the WebGL context will use 300 x 150\r\n\r\n\t\tthis.resolutionScale = cfg.resolutionScale;\r\n\r\n\t\tthis.canvas.width = Math.round(this.canvas.clientWidth * this._resolutionScale);\r\n\t\tthis.canvas.height = Math.round(this.canvas.clientHeight * this._resolutionScale);\r\n\r\n\t\t/**\r\n\t\t * Boundary of the Canvas in absolute browser window coordinates.\r\n\t\t *\r\n\t\t * ### Usage:\r\n\t\t *\r\n\t\t * ````javascript\r\n\t\t * var boundary = myScene.canvas.boundary;\r\n\t\t *\r\n\t\t * var xmin = boundary[0];\r\n\t\t * var ymin = boundary[1];\r\n\t\t * var width = boundary[2];\r\n\t\t * var height = boundary[3];\r\n\t\t * ````\r\n\t\t *\r\n\t\t * @property boundary\r\n\t\t * @type {Number[]}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.boundary = [this.canvas.left, this.canvas.offsetTop, this.canvas.clientWidth, this.canvas.clientHeight];\r\n\r\n\t\t// Get WebGL context\r\n\t\tthis._initWebGL();\r\n\r\n\t\t// Bind context loss and recovery handlers\r\n\r\n\t\tconst self = this;\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"webglcontextlost\",\r\n\t\t\t(this._webglcontextlostListener = function (event) {\r\n\t\t\t\tconsole.time(\"webglcontextrestored\");\r\n\t\t\t\tself.scene._webglContextLost();\r\n\t\t\t\t/**\r\n\t\t\t\t * Fired whenever the WebGL context has been lost\r\n\t\t\t\t * @event webglcontextlost\r\n\t\t\t\t */\r\n\t\t\t\tself.fire(\"webglcontextlost\");\r\n\t\t\t\tevent.preventDefault();\r\n\t\t\t}),\r\n\t\t\tfalse\r\n\t\t);\r\n\r\n\t\tthis.canvas.addEventListener(\r\n\t\t\t\"webglcontextrestored\",\r\n\t\t\t(this._webglcontextrestoredListener = function (event) {\r\n\t\t\t\tself._initWebGL();\r\n\t\t\t\tif (self.gl) {\r\n\t\t\t\t\tself.scene._webglContextRestored(self.gl);\r\n\t\t\t\t\t/**\r\n\t\t\t\t\t * Fired whenever the WebGL context has been restored again after having previously being lost\r\n\t\t\t\t\t * @event webglContextRestored\r\n\t\t\t\t\t * @param value The WebGL context object\r\n\t\t\t\t\t */\r\n\t\t\t\t\tself.fire(\"webglcontextrestored\", self.gl);\r\n\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t}\r\n\t\t\t\tconsole.timeEnd(\"webglcontextrestored\");\r\n\t\t\t}),\r\n\t\t\tfalse\r\n\t\t);\r\n\r\n\t\t// Attach to resize events on the canvas\r\n\t\tthis._dirtyBoundary = true; // make sure we publish the 1st boundary event\r\n\r\n\t\tconst resizeObserver = new ResizeObserver((entries) => {\r\n\t\t\tfor (const entry of entries) {\r\n\t\t\t\tif (entry.contentBoxSize) {\r\n\t\t\t\t\tthis._dirtyBoundary = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tresizeObserver.observe(this.canvas);\r\n\r\n\t\t// Publish canvas size and position changes on each scene tick\r\n\t\tthis._tick = this.scene.on(\"tick\", () => {\r\n\t\t\t// Only publish if the canvas bounds changed\r\n\t\t\tif (!this._dirtyBoundary) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tthis._dirtyBoundary = false;\r\n\r\n\t\t\t// Set the real size of the canvas (the drawable w*h)\r\n\t\t\tself.canvas.width = Math.round(self.canvas.clientWidth * self._resolutionScale);\r\n\t\t\tself.canvas.height = Math.round(self.canvas.clientHeight * self._resolutionScale);\r\n\r\n\t\t\t// Publish the boundary change\r\n\t\t\tself.boundary[0] = self.canvas.offsetLeft;\r\n\t\t\tself.boundary[1] = self.canvas.offsetTop;\r\n\t\t\tself.boundary[2] = self.canvas.clientWidth;\r\n\t\t\tself.boundary[3] = self.canvas.clientHeight;\r\n\r\n\t\t\tself.fire(\"boundary\", self.boundary);\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t * @type {Spinner}\r\n\t\t */\r\n\t\tthis._spinner = new _Spinner_js__WEBPACK_IMPORTED_MODULE_2__.Spinner(this.scene, {\r\n\t\t\tcanvas: this.canvas,\r\n\t\t\telementId: cfg.spinnerElementId\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * 设置是否需要改变canvas\r\n\t * @param {boolean} change\r\n\t */\r\n\tset dirtyBoundary(change) {\r\n\t\tthis._dirtyBoundary = change;\r\n\t}\r\n\r\n\t/**\r\n @private\r\n */\r\n\tget type() {\r\n\t\treturn \"Canvas\";\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether the canvas clear color will be derived from {@link AmbientLight} or {@link Canvas#backgroundColor}\r\n\t * when {@link Canvas#transparent} is ```true```.\r\n\t *\r\n\t * When {@link Canvas#transparent} is ```true``` and this is ````true````, then the canvas clear color will\r\n\t * be taken from the {@link Scene}'s ambient light color.\r\n\t *\r\n\t * When {@link Canvas#transparent} is ```true``` and this is ````false````, then the canvas clear color will\r\n\t * be taken from {@link Canvas#backgroundColor}.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget backgroundColorFromAmbientLight() {\r\n\t\treturn this._backgroundColorFromAmbientLight;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets if the canvas background color is derived from an {@link AmbientLight}.\r\n\t *\r\n\t * This only has effect when the canvas is not transparent. When not enabled, the background color\r\n\t * will be the canvas element's HTML/CSS background color.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset backgroundColorFromAmbientLight(backgroundColorFromAmbientLight) {\r\n\t\tthis._backgroundColorFromAmbientLight = backgroundColorFromAmbientLight !== false;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the canvas clear color.\r\n\t *\r\n\t * Default value is ````[1, 1, 1]````.\r\n\t *\r\n\t * @type {Number[]}\r\n\t */\r\n\tget backgroundColor() {\r\n\t\treturn this._backgroundColor;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the canvas clear color.\r\n\t *\r\n\t * Default value is ````[1, 1, 1]````.\r\n\t *\r\n\t * @type {Number[]}\r\n\t */\r\n\tset backgroundColor(value) {\r\n\t\tif (value) {\r\n\t\t\tthis._backgroundColor[0] = value[0];\r\n\t\t\tthis._backgroundColor[1] = value[1];\r\n\t\t\tthis._backgroundColor[2] = value[2];\r\n\t\t} else {\r\n\t\t\tthis._backgroundColor[0] = 1.0;\r\n\t\t\tthis._backgroundColor[1] = 1.0;\r\n\t\t\tthis._backgroundColor[2] = 1.0;\r\n\t\t}\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the scale of the canvas back buffer relative to the CSS-defined size of the canvas.\r\n\t *\r\n\t * This is a common way to trade off rendering quality for speed. If the canvas size is defined in CSS, then\r\n\t * setting this to a value between ````[0..1]```` (eg ````0.5````) will render into a smaller back buffer, giving\r\n\t * a performance boost.\r\n\t *\r\n\t * @returns {*|number} The resolution scale.\r\n\t */\r\n\tget resolutionScale() {\r\n\t\treturn this._resolutionScale;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the scale of the canvas back buffer relative to the CSS-defined size of the canvas.\r\n\t *\r\n\t * This is a common way to trade off rendering quality for speed. If the canvas size is defined in CSS, then\r\n\t * setting this to a value between ````[0..1]```` (eg ````0.5````) will render into a smaller back buffer, giving\r\n\t * a performance boost.\r\n\t *\r\n\t * @param {*|number} resolutionScale The resolution scale.\r\n\t */\r\n\tset resolutionScale(resolutionScale) {\r\n\t\tresolutionScale = resolutionScale || 1.0;\r\n\t\tif (resolutionScale === this._resolutionScale) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._resolutionScale = resolutionScale;\r\n\t\tconst canvas = this.canvas;\r\n\t\tcanvas.width = Math.round(canvas.clientWidth * this._resolutionScale);\r\n\t\tcanvas.height = Math.round(canvas.clientHeight * this._resolutionScale);\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * The busy {@link Spinner} for this Canvas.\r\n\t *\r\n\t * @property spinner\r\n\t * @type Spinner\r\n\t * @final\r\n\t */\r\n\tget spinner() {\r\n\t\treturn this._spinner;\r\n\t}\r\n\r\n\t/**\r\n\t * Creates a default canvas in the DOM.\r\n\t * @private\r\n\t */\r\n\t_createCanvas() {\r\n\t\tconst canvasId = \"tctwins-canvas-\" + _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.createUUID();\r\n\t\tconst div = document.createElement(\"div\");\r\n\r\n\t\tconst style = div.style;\r\n\t\tstyle.height = \"100%\";\r\n\t\tstyle.width = \"100%\";\r\n\t\tstyle.padding = \"0\";\r\n\t\tstyle.margin = \"0\";\r\n\t\tstyle.background = \"rgba(0,0,0,0);\";\r\n\t\tstyle.float = \"left\";\r\n\t\tstyle.left = \"0\";\r\n\t\tstyle.top = \"0\";\r\n\t\tstyle.position = \"absolute\";\r\n\t\tstyle.opacity = \"1.0\";\r\n\t\tstyle[\"z-index\"] = \"-10000\";\r\n\r\n\t\tdiv.innerHTML +=\r\n\t\t\t'<canvas id=\"' + canvasId + '\" style=\"width: 100%; height: 100%; float: left; margin: 0; padding: 0;\"></canvas>';\r\n\r\n\t\tthis.parent.viewer.container.appendChild(div);\r\n\t\tthis.canvas = document.getElementById(canvasId);\r\n\t}\r\n\r\n\t_getElementXY(e) {\r\n\t\tlet x = 0,\r\n\t\t\ty = 0;\r\n\t\twhile (e) {\r\n\t\t\tx += e.offsetLeft - e.scrollLeft;\r\n\t\t\ty += e.offsetTop - e.scrollTop;\r\n\t\t\te = e.offsetParent;\r\n\t\t}\r\n\t\treturn { x: x, y: y };\r\n\t}\r\n\r\n\t/**\r\n\t * Initialises the WebGL context\r\n\t * @private\r\n\t */\r\n\t_initWebGL() {\r\n\t\t// Default context attribute values\r\n\r\n\t\tif (!this.gl) {\r\n\t\t\tfor (let i = 0; !this.gl && i < WEBGL_CONTEXT_NAMES.length; i++) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tthis.gl = this.canvas.getContext(WEBGL_CONTEXT_NAMES[i], this.contextAttr);\r\n\t\t\t\t} catch (e) {\r\n\t\t\t\t\t// Try with next context name\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!this.gl) {\r\n\t\t\tthis.error(\"Failed to get a WebGL context\");\r\n\r\n\t\t\t/**\r\n\t\t\t * Fired whenever the canvas failed to get a WebGL context, which probably means that WebGL\r\n\t\t\t * is either unsupported or has been disabled.\r\n\t\t\t * @event webglContextFailed\r\n\t\t\t */\r\n\t\t\tthis.fire(\"webglContextFailed\", true, true);\r\n\t\t}\r\n\r\n\t\t// data-textures: avoid to re-bind same texture\r\n\t\t{\r\n\t\t\tconst gl = this.gl;\r\n\r\n\t\t\tlet lastTextureUnit = \"__\";\r\n\r\n\t\t\tlet originalActiveTexture = gl.activeTexture;\r\n\r\n\t\t\tgl.activeTexture = function (arg1) {\r\n\t\t\t\tif (lastTextureUnit === arg1) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlastTextureUnit = arg1;\r\n\r\n\t\t\t\toriginalActiveTexture.call(this, arg1);\r\n\t\t\t};\r\n\r\n\t\t\tlet lastBindTexture = {};\r\n\r\n\t\t\tlet originalBindTexture = gl.bindTexture;\r\n\r\n\t\t\tlet avoidedRebinds = 0;\r\n\r\n\t\t\tgl.bindTexture = function (arg1, arg2) {\r\n\t\t\t\tif (lastBindTexture[lastTextureUnit] === arg2) {\r\n\t\t\t\t\tavoidedRebinds++;\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlastBindTexture[lastTextureUnit] = arg2;\r\n\r\n\t\t\t\toriginalBindTexture.call(this, arg1, arg2);\r\n\t\t\t};\r\n\r\n\t\t\t// setInterval (\r\n\t\t\t// () => {\r\n\t\t\t// console.log (`${avoidedRebinds} avoided texture binds/sec`);\r\n\t\t\t// avoidedRebinds = 0;\r\n\t\t\t// },\r\n\t\t\t// 1000\r\n\t\t\t// );\r\n\t\t}\r\n\r\n\t\tif (this.gl) {\r\n\t\t\t// Setup extension (if necessary) and hints for fragment shader derivative functions\r\n\t\t\tif (this.webgl2) {\r\n\t\t\t\tthis.gl.hint(this.gl.FRAGMENT_SHADER_DERIVATIVE_HINT, this.gl.FASTEST);\r\n\r\n\t\t\t\t// data-textures: not using standard-derivatives\r\n\t\t\t\tif (!(this.gl instanceof WebGL2RenderingContext)) {\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t * @deprecated\r\n\t */\r\n\tgetSnapshot(params) {\r\n\t\tthrow \"Canvas#getSnapshot() has been replaced by Viewer#getSnapshot() - use that method instead.\";\r\n\t}\r\n\r\n\t/**\r\n\t * Reads colors of pixels from the last rendered frame.\r\n\t *\r\n\t * Call this method like this:\r\n\t *\r\n\t * ````JavaScript\r\n\t *\r\n\t * // Ignore transparent pixels (default is false)\r\n\t * var opaqueOnly = true;\r\n\t *\r\n\t * var colors = new Float32Array(8);\r\n\t *\r\n\t * viewer.scene.canvas.readPixels([ 100, 22, 12, 33 ], colors, 2, opaqueOnly);\r\n\t * ````\r\n\t *\r\n\t * Then the r,g,b components of the colors will be set to the colors at those pixels.\r\n\t *\r\n\t * @param {Number[]} pixels\r\n\t * @param {Number[]} colors\r\n\t * @param {Number} size\r\n\t * @param {Boolean} opaqueOnly\r\n\t */\r\n\treadPixels(pixels, colors, size, opaqueOnly) {\r\n\t\treturn this.scene._renderer.readPixels(pixels, colors, size, opaqueOnly);\r\n\t}\r\n\r\n\t/**\r\n\t * Simulates lost WebGL context.\r\n\t */\r\n\tloseWebGLContext() {\r\n\t\tif (this.canvas.loseContext) {\r\n\t\t\tthis.canvas.loseContext();\r\n\t\t}\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tthis.scene.off(this._tick);\r\n\t\tif (this._spinner) {\r\n\t\t\tthis._spinner.destroy();\r\n\t\t\tthis._spinner = null;\r\n\t\t}\r\n\t\t// Memory leak avoidance\r\n\t\tthis.canvas.removeEventListener(\"webglcontextlost\", this._webglcontextlostListener);\r\n\t\tthis.canvas.removeEventListener(\"webglcontextrestored\", this._webglcontextrestoredListener);\r\n\t\tif (this.gl != null) {\r\n\t\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\r\n\t\t\tthis.gl = null;\r\n\t\t}\r\n\t\tsuper.destroy();\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/canvas/Canvas.js?");
|
|
2737
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Canvas: () => (/* binding */ Canvas)\n/* harmony export */ });\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _Spinner_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Spinner.js */ \"./src/viewer/scene/canvas/Spinner.js\");\n\n\n\n\nconst WEBGL_CONTEXT_NAMES = [\"webgl2\", \"experimental-webgl\", \"webkit-3d\", \"moz-webgl\", \"moz-glweb20\"];\n\n/**\n * @desc Manages its {@link Scene}'s HTML canvas.\n *\n * * Provides the HTML canvas element in {@link Canvas#canvas}.\n * * Has a {@link Spinner}, provided at {@link Canvas#spinner}, which manages the loading progress indicator.\n */\nclass Canvas extends _Component_js__WEBPACK_IMPORTED_MODULE_1__.Component {\n\t/**\n\t * @constructor\n\t * @private\n\t */\n\tconstructor(owner, cfg = {}) {\n\t\tsuper(owner, cfg);\n\t\tthis._backgroundColor = _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.vec3([\n\t\t\tcfg.backgroundColor ? cfg.backgroundColor[0] : 1,\n\t\t\tcfg.backgroundColor ? cfg.backgroundColor[1] : 1,\n\t\t\tcfg.backgroundColor ? cfg.backgroundColor[2] : 1\n\t\t]);\n\t\tthis._backgroundColorFromAmbientLight = !!cfg.backgroundColorFromAmbientLight;\n\n\t\tthis.parent = owner;\n\t\tif (cfg.canvas)\n\t\t\t/**\n\t\t\t * The HTML canvas.\n\t\t\t *\n\t\t\t * @property canvas\n\t\t\t * @type {HTMLCanvasElement}\n\t\t\t * @final\n\t\t\t */\n\t\t\tthis.canvas = cfg.canvas;\n\t\telse this._createCanvas();\n\n\t\t/**\n\t\t * The WebGL rendering context.\n\t\t *\n\t\t * @property gl\n\t\t * @type {WebGLRenderingContext}\n\t\t * @final\n\t\t */\n\t\tthis.gl = null;\n\n\t\t/**\n\t\t * True when WebGL 2 support is enabled.\n\t\t *\n\t\t * @property webgl2\n\t\t * @type {Boolean}\n\t\t * @final\n\t\t */\n\t\tthis.webgl2 = false; // Will set true in _initWebGL if WebGL is requested and we succeed in getting it.\n\n\t\t/**\n\t\t * Indicates if this Canvas is transparent.\n\t\t *\n\t\t * @property transparent\n\t\t * @type {Boolean}\n\t\t * @default {false}\n\t\t * @final\n\t\t */\n\t\tthis.transparent = !!cfg.transparent;\n\n\t\t/**\n\t\t * Attributes for the WebGL context\n\t\t *\n\t\t * @type {{}|*}\n\t\t */\n\t\tthis.contextAttr = cfg.contextAttr || {};\n\t\tthis.contextAttr.alpha = this.transparent;\n\n\t\tthis.contextAttr.preserveDrawingBuffer = !!this.contextAttr.preserveDrawingBuffer;\n\t\tthis.contextAttr.stencil = false;\n\t\tthis.contextAttr.premultipliedAlpha = !!this.contextAttr.premultipliedAlpha; // False by default: https://github.com/xeokit/xeokit-sdk/issues/251\n\t\tthis.contextAttr.antialias = this.contextAttr.antialias !== false;\n\n\t\t// If the canvas uses css styles to specify the sizes make sure the basic\n\t\t// width and height attributes match or the WebGL context will use 300 x 150\n\n\t\tthis.resolutionScale = cfg.resolutionScale;\n\n\t\tthis.canvas.width = Math.round(this.canvas.clientWidth * this._resolutionScale);\n\t\tthis.canvas.height = Math.round(this.canvas.clientHeight * this._resolutionScale);\n\n\t\t/**\n\t\t * Boundary of the Canvas in absolute browser window coordinates.\n\t\t *\n\t\t * ### Usage:\n\t\t *\n\t\t * ````javascript\n\t\t * var boundary = myScene.canvas.boundary;\n\t\t *\n\t\t * var xmin = boundary[0];\n\t\t * var ymin = boundary[1];\n\t\t * var width = boundary[2];\n\t\t * var height = boundary[3];\n\t\t * ````\n\t\t *\n\t\t * @property boundary\n\t\t * @type {Number[]}\n\t\t * @final\n\t\t */\n\t\tthis.boundary = [this.canvas.left, this.canvas.offsetTop, this.canvas.clientWidth, this.canvas.clientHeight];\n\n\t\t// Get WebGL context\n\t\tthis._initWebGL();\n\n\t\t// Bind context loss and recovery handlers\n\n\t\tconst self = this;\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"webglcontextlost\",\n\t\t\t(this._webglcontextlostListener = function (event) {\n\t\t\t\tconsole.time(\"webglcontextrestored\");\n\t\t\t\tself.scene._webglContextLost();\n\t\t\t\t/**\n\t\t\t\t * Fired whenever the WebGL context has been lost\n\t\t\t\t * @event webglcontextlost\n\t\t\t\t */\n\t\t\t\tself.fire(\"webglcontextlost\");\n\t\t\t\tevent.preventDefault();\n\t\t\t}),\n\t\t\tfalse\n\t\t);\n\n\t\tthis.canvas.addEventListener(\n\t\t\t\"webglcontextrestored\",\n\t\t\t(this._webglcontextrestoredListener = function (event) {\n\t\t\t\tself._initWebGL();\n\t\t\t\tif (self.gl) {\n\t\t\t\t\tself.scene._webglContextRestored(self.gl);\n\t\t\t\t\t/**\n\t\t\t\t\t * Fired whenever the WebGL context has been restored again after having previously being lost\n\t\t\t\t\t * @event webglContextRestored\n\t\t\t\t\t * @param value The WebGL context object\n\t\t\t\t\t */\n\t\t\t\t\tself.fire(\"webglcontextrestored\", self.gl);\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t\tconsole.timeEnd(\"webglcontextrestored\");\n\t\t\t}),\n\t\t\tfalse\n\t\t);\n\n\t\t// Attach to resize events on the canvas\n\t\tthis._dirtyBoundary = true; // make sure we publish the 1st boundary event\n\n\t\tconst resizeObserver = new ResizeObserver((entries) => {\n\t\t\tfor (const entry of entries) {\n\t\t\t\tif (entry.contentBoxSize) {\n\t\t\t\t\tthis._dirtyBoundary = true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tresizeObserver.observe(this.canvas);\n\n\t\t// Publish canvas size and position changes on each scene tick\n\t\tthis._tick = this.scene.on(\"tick\", () => {\n\t\t\t// Only publish if the canvas bounds changed\n\t\t\tif (!this._dirtyBoundary) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._dirtyBoundary = false;\n\n\t\t\t// Set the real size of the canvas (the drawable w*h)\n\t\t\tself.canvas.width = Math.round(self.canvas.clientWidth * self._resolutionScale);\n\t\t\tself.canvas.height = Math.round(self.canvas.clientHeight * self._resolutionScale);\n\n\t\t\t// Publish the boundary change\n\t\t\tself.boundary[0] = self.canvas.offsetLeft;\n\t\t\tself.boundary[1] = self.canvas.offsetTop;\n\t\t\tself.boundary[2] = self.canvas.clientWidth;\n\t\t\tself.boundary[3] = self.canvas.clientHeight;\n\n\t\t\tself.fire(\"boundary\", self.boundary);\n\t\t});\n\n\t\t/**\n\t\t * @type {Spinner}\n\t\t */\n\t\tthis._spinner = new _Spinner_js__WEBPACK_IMPORTED_MODULE_2__.Spinner(this.scene, {\n\t\t\tcanvas: this.canvas,\n\t\t\telementId: cfg.spinnerElementId\n\t\t});\n\t}\n\n\t/**\n\t * 设置是否需要改变canvas\n\t * @param {boolean} change\n\t */\n\tset dirtyBoundary(change) {\n\t\tthis._dirtyBoundary = change;\n\t}\n\n\t/**\n @private\n */\n\tget type() {\n\t\treturn \"Canvas\";\n\t}\n\n\t/**\n\t * Gets whether the canvas clear color will be derived from {@link AmbientLight} or {@link Canvas#backgroundColor}\n\t * when {@link Canvas#transparent} is ```true```.\n\t *\n\t * When {@link Canvas#transparent} is ```true``` and this is ````true````, then the canvas clear color will\n\t * be taken from the {@link Scene}'s ambient light color.\n\t *\n\t * When {@link Canvas#transparent} is ```true``` and this is ````false````, then the canvas clear color will\n\t * be taken from {@link Canvas#backgroundColor}.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget backgroundColorFromAmbientLight() {\n\t\treturn this._backgroundColorFromAmbientLight;\n\t}\n\n\t/**\n\t * Sets if the canvas background color is derived from an {@link AmbientLight}.\n\t *\n\t * This only has effect when the canvas is not transparent. When not enabled, the background color\n\t * will be the canvas element's HTML/CSS background color.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset backgroundColorFromAmbientLight(backgroundColorFromAmbientLight) {\n\t\tthis._backgroundColorFromAmbientLight = backgroundColorFromAmbientLight !== false;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the canvas clear color.\n\t *\n\t * Default value is ````[1, 1, 1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget backgroundColor() {\n\t\treturn this._backgroundColor;\n\t}\n\n\t/**\n\t * Sets the canvas clear color.\n\t *\n\t * Default value is ````[1, 1, 1]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tset backgroundColor(value) {\n\t\tif (value) {\n\t\t\tthis._backgroundColor[0] = value[0];\n\t\t\tthis._backgroundColor[1] = value[1];\n\t\t\tthis._backgroundColor[2] = value[2];\n\t\t} else {\n\t\t\tthis._backgroundColor[0] = 1.0;\n\t\t\tthis._backgroundColor[1] = 1.0;\n\t\t\tthis._backgroundColor[2] = 1.0;\n\t\t}\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the scale of the canvas back buffer relative to the CSS-defined size of the canvas.\n\t *\n\t * This is a common way to trade off rendering quality for speed. If the canvas size is defined in CSS, then\n\t * setting this to a value between ````[0..1]```` (eg ````0.5````) will render into a smaller back buffer, giving\n\t * a performance boost.\n\t *\n\t * @returns {*|number} The resolution scale.\n\t */\n\tget resolutionScale() {\n\t\treturn this._resolutionScale;\n\t}\n\n\t/**\n\t * Sets the scale of the canvas back buffer relative to the CSS-defined size of the canvas.\n\t *\n\t * This is a common way to trade off rendering quality for speed. If the canvas size is defined in CSS, then\n\t * setting this to a value between ````[0..1]```` (eg ````0.5````) will render into a smaller back buffer, giving\n\t * a performance boost.\n\t *\n\t * @param {*|number} resolutionScale The resolution scale.\n\t */\n\tset resolutionScale(resolutionScale) {\n\t\tresolutionScale = resolutionScale || 1.0;\n\t\tif (resolutionScale === this._resolutionScale) {\n\t\t\treturn;\n\t\t}\n\t\tthis._resolutionScale = resolutionScale;\n\t\tconst canvas = this.canvas;\n\t\tcanvas.width = Math.round(canvas.clientWidth * this._resolutionScale);\n\t\tcanvas.height = Math.round(canvas.clientHeight * this._resolutionScale);\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * The busy {@link Spinner} for this Canvas.\n\t *\n\t * @property spinner\n\t * @type Spinner\n\t * @final\n\t */\n\tget spinner() {\n\t\treturn this._spinner;\n\t}\n\n\t/**\n\t * Creates a default canvas in the DOM.\n\t * @private\n\t */\n\t_createCanvas() {\n\t\tconst canvasId = \"tctwins-canvas-\" + _math_math_js__WEBPACK_IMPORTED_MODULE_0__.math.createUUID();\n\t\tconst div = document.createElement(\"div\");\n\n\t\tconst style = div.style;\n\t\tstyle.height = \"100%\";\n\t\tstyle.width = \"100%\";\n\t\tstyle.padding = \"0\";\n\t\tstyle.margin = \"0\";\n\t\tstyle.background = \"rgba(0,0,0,0);\";\n\t\tstyle.float = \"left\";\n\t\tstyle.left = \"0\";\n\t\tstyle.top = \"0\";\n\t\tstyle.position = \"absolute\";\n\t\tstyle.opacity = \"1.0\";\n\t\tstyle[\"z-index\"] = \"-10000\";\n\n\t\tdiv.innerHTML +=\n\t\t\t'<canvas id=\"' + canvasId + '\" style=\"width: 100%; height: 100%; float: left; margin: 0; padding: 0;\"></canvas>';\n\n\t\tthis.parent.viewer.container.appendChild(div);\n\t\tthis.canvas = document.getElementById(canvasId);\n\t}\n\n\t_getElementXY(e) {\n\t\tlet x = 0,\n\t\t\ty = 0;\n\t\twhile (e) {\n\t\t\tx += e.offsetLeft - e.scrollLeft;\n\t\t\ty += e.offsetTop - e.scrollTop;\n\t\t\te = e.offsetParent;\n\t\t}\n\t\treturn { x: x, y: y };\n\t}\n\n\t/**\n\t * Initialises the WebGL context\n\t * @private\n\t */\n\t_initWebGL() {\n\t\t// Default context attribute values\n\n\t\tif (!this.gl) {\n\t\t\tfor (let i = 0; !this.gl && i < WEBGL_CONTEXT_NAMES.length; i++) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.gl = this.canvas.getContext(WEBGL_CONTEXT_NAMES[i], this.contextAttr);\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Try with next context name\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!this.gl) {\n\t\t\tthis.error(\"Failed to get a WebGL context\");\n\n\t\t\t/**\n\t\t\t * Fired whenever the canvas failed to get a WebGL context, which probably means that WebGL\n\t\t\t * is either unsupported or has been disabled.\n\t\t\t * @event webglContextFailed\n\t\t\t */\n\t\t\tthis.fire(\"webglContextFailed\", true, true);\n\t\t}\n\n\t\t// data-textures: avoid to re-bind same texture\n\t\t{\n\t\t\tconst gl = this.gl;\n\n\t\t\tlet lastTextureUnit = \"__\";\n\n\t\t\tlet originalActiveTexture = gl.activeTexture;\n\n\t\t\tgl.activeTexture = function (arg1) {\n\t\t\t\tif (lastTextureUnit === arg1) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlastTextureUnit = arg1;\n\n\t\t\t\toriginalActiveTexture.call(this, arg1);\n\t\t\t};\n\n\t\t\tlet lastBindTexture = {};\n\n\t\t\tlet originalBindTexture = gl.bindTexture;\n\n\t\t\tlet avoidedRebinds = 0;\n\n\t\t\tgl.bindTexture = function (arg1, arg2) {\n\t\t\t\tif (lastBindTexture[lastTextureUnit] === arg2) {\n\t\t\t\t\tavoidedRebinds++;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlastBindTexture[lastTextureUnit] = arg2;\n\n\t\t\t\toriginalBindTexture.call(this, arg1, arg2);\n\t\t\t};\n\n\t\t\t// setInterval (\n\t\t\t// () => {\n\t\t\t// console.log (`${avoidedRebinds} avoided texture binds/sec`);\n\t\t\t// avoidedRebinds = 0;\n\t\t\t// },\n\t\t\t// 1000\n\t\t\t// );\n\t\t}\n\n\t\tif (this.gl) {\n\t\t\t// Setup extension (if necessary) and hints for fragment shader derivative functions\n\t\t\tif (this.webgl2) {\n\t\t\t\tthis.gl.hint(this.gl.FRAGMENT_SHADER_DERIVATIVE_HINT, this.gl.FASTEST);\n\n\t\t\t\t// data-textures: not using standard-derivatives\n\t\t\t\tif (!(this.gl instanceof WebGL2RenderingContext)) {\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t * @deprecated\n\t */\n\tgetSnapshot(params) {\n\t\tthrow \"Canvas#getSnapshot() has been replaced by Viewer#getSnapshot() - use that method instead.\";\n\t}\n\n\t/**\n\t * Reads colors of pixels from the last rendered frame.\n\t *\n\t * Call this method like this:\n\t *\n\t * ````JavaScript\n\t *\n\t * // Ignore transparent pixels (default is false)\n\t * var opaqueOnly = true;\n\t *\n\t * var colors = new Float32Array(8);\n\t *\n\t * viewer.scene.canvas.readPixels([ 100, 22, 12, 33 ], colors, 2, opaqueOnly);\n\t * ````\n\t *\n\t * Then the r,g,b components of the colors will be set to the colors at those pixels.\n\t *\n\t * @param {Number[]} pixels\n\t * @param {Number[]} colors\n\t * @param {Number} size\n\t * @param {Boolean} opaqueOnly\n\t */\n\treadPixels(pixels, colors, size, opaqueOnly) {\n\t\treturn this.scene._renderer.readPixels(pixels, colors, size, opaqueOnly);\n\t}\n\n\t/**\n\t * Simulates lost WebGL context.\n\t */\n\tloseWebGLContext() {\n\t\tif (this.canvas.loseContext) {\n\t\t\tthis.canvas.loseContext();\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.scene.off(this._tick);\n\t\tif (this._spinner) {\n\t\t\tthis._spinner.destroy();\n\t\t\tthis._spinner = null;\n\t\t}\n\t\t// Memory leak avoidance\n\t\tthis.canvas.removeEventListener(\"webglcontextlost\", this._webglcontextlostListener);\n\t\tthis.canvas.removeEventListener(\"webglcontextrestored\", this._webglcontextrestoredListener);\n\t\tif (this.gl != null) {\n\t\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n\t\t\tthis.gl = null;\n\t\t}\n\t\tsuper.destroy();\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/canvas/Canvas.js?");
|
|
2738
2738
|
|
|
2739
2739
|
/***/ }),
|
|
2740
2740
|
|
|
@@ -2744,7 +2744,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
2744
2744
|
\********************************************/
|
|
2745
2745
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
2746
2746
|
|
|
2747
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Spinner: () => (/* binding */ Spinner)\n/* harmony export */ });\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n\r\n\r\nconst defaultCSS =\r\n\t\".sk-fading-circle {\\\r\n background: transparent;\\\r\n margin: 20px auto;\\\r\n width: 50px;\\\r\n height:50px;\\\r\n position: relative;\\\r\n }\\\r\n .sk-fading-circle .sk-circle {\\\r\n width: 120%;\\\r\n height: 120%;\\\r\n position: absolute;\\\r\n left: 0;\\\r\n top: 0;\\\r\n }\\\r\n .sk-fading-circle .sk-circle:before {\\\r\n content: '';\\\r\n display: block;\\\r\n margin: 0 auto;\\\r\n width: 15%;\\\r\n height: 15%;\\\r\n background-color: #ff8800;\\\r\n border-radius: 100%;\\\r\n -webkit-animation: sk-circleFadeDelay 1.2s infinite ease-in-out both;\\\r\n animation: sk-circleFadeDelay 1.2s infinite ease-in-out both;\\\r\n }\\\r\n .sk-fading-circle .sk-circle2 {\\\r\n -webkit-transform: rotate(30deg);\\\r\n -ms-transform: rotate(30deg);\\\r\n transform: rotate(30deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle3 {\\\r\n -webkit-transform: rotate(60deg);\\\r\n -ms-transform: rotate(60deg);\\\r\n transform: rotate(60deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle4 {\\\r\n -webkit-transform: rotate(90deg);\\\r\n -ms-transform: rotate(90deg);\\\r\n transform: rotate(90deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle5 {\\\r\n -webkit-transform: rotate(120deg);\\\r\n -ms-transform: rotate(120deg);\\\r\n transform: rotate(120deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle6 {\\\r\n -webkit-transform: rotate(150deg);\\\r\n -ms-transform: rotate(150deg);\\\r\n transform: rotate(150deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle7 {\\\r\n -webkit-transform: rotate(180deg);\\\r\n -ms-transform: rotate(180deg);\\\r\n transform: rotate(180deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle8 {\\\r\n -webkit-transform: rotate(210deg);\\\r\n -ms-transform: rotate(210deg);\\\r\n transform: rotate(210deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle9 {\\\r\n -webkit-transform: rotate(240deg);\\\r\n -ms-transform: rotate(240deg);\\\r\n transform: rotate(240deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle10 {\\\r\n -webkit-transform: rotate(270deg);\\\r\n -ms-transform: rotate(270deg);\\\r\n transform: rotate(270deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle11 {\\\r\n -webkit-transform: rotate(300deg);\\\r\n -ms-transform: rotate(300deg);\\\r\n transform: rotate(300deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle12 {\\\r\n -webkit-transform: rotate(330deg);\\\r\n -ms-transform: rotate(330deg);\\\r\n transform: rotate(330deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle2:before {\\\r\n -webkit-animation-delay: -1.1s;\\\r\n animation-delay: -1.1s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle3:before {\\\r\n -webkit-animation-delay: -1s;\\\r\n animation-delay: -1s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle4:before {\\\r\n -webkit-animation-delay: -0.9s;\\\r\n animation-delay: -0.9s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle5:before {\\\r\n -webkit-animation-delay: -0.8s;\\\r\n animation-delay: -0.8s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle6:before {\\\r\n -webkit-animation-delay: -0.7s;\\\r\n animation-delay: -0.7s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle7:before {\\\r\n -webkit-animation-delay: -0.6s;\\\r\n animation-delay: -0.6s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle8:before {\\\r\n -webkit-animation-delay: -0.5s;\\\r\n animation-delay: -0.5s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle9:before {\\\r\n -webkit-animation-delay: -0.4s;\\\r\n animation-delay: -0.4s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle10:before {\\\r\n -webkit-animation-delay: -0.3s;\\\r\n animation-delay: -0.3s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle11:before {\\\r\n -webkit-animation-delay: -0.2s;\\\r\n animation-delay: -0.2s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle12:before {\\\r\n -webkit-animation-delay: -0.1s;\\\r\n animation-delay: -0.1s;\\\r\n }\\\r\n @-webkit-keyframes sk-circleFadeDelay {\\\r\n 0%, 39%, 100% { opacity: 0; }\\\r\n 40% { opacity: 1; }\\\r\n }\\\r\n @keyframes sk-circleFadeDelay {\\\r\n 0%, 39%, 100% { opacity: 0; }\\\r\n 40% { opacity: 1; }\\\r\n }\";\r\n\r\n/**\r\n * @desc Displays a progress animation at the center of its {@link Canvas} while things are loading or otherwise busy.\r\n *\r\n *\r\n * * Located at {@link Canvas#spinner}.\r\n * * Automatically shown while things are loading, however may also be shown by application code wanting to indicate busyness.\r\n * * {@link Spinner#processes} holds the count of active processes. As a process starts, it increments {@link Spinner#processes}, then decrements it on completion or failure.\r\n * * A Spinner is only visible while {@link Spinner#processes} is greater than zero.\r\n *\r\n * ````javascript\r\n * var spinner = viewer.scene.canvas.spinner;\r\n *\r\n * // Increment count of busy processes represented by the spinner;\r\n * // assuming the count was zero, this now shows the spinner\r\n * spinner.processes++;\r\n *\r\n * // Increment the count again, by some other process; spinner already visible, now requires two decrements\r\n * // before it becomes invisible again\r\n * spinner.processes++;\r\n *\r\n * // Decrement the count; count still greater than zero, so spinner remains visible\r\n * spinner.process--;\r\n *\r\n * // Decrement the count; count now zero, so spinner becomes invisible\r\n * spinner.process--;\r\n * ````\r\n */\r\nclass Spinner extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\r\n\t/**\r\n @private\r\n */\r\n\tget type() {\r\n\t\treturn \"Spinner\";\r\n\t}\r\n\r\n\t/**\r\n @private\r\n */\r\n\tconstructor(owner, cfg = {}) {\r\n\t\tsuper(owner, cfg);\r\n\r\n\t\tthis._canvas = cfg.canvas;\r\n\t\tthis._element = null;\r\n\t\tthis._isCustom = false; // True when the element is custom HTML\r\n\r\n\t\tif (cfg.elementId) {\r\n\t\t\t// Custom spinner element supplied\r\n\t\t\tthis._element = document.getElementById(cfg.elementId);\r\n\t\t\tif (!this._element) {\r\n\t\t\t\tthis.error(\r\n\t\t\t\t\t\"Can't find given Spinner HTML element: '\" + cfg.elementId + \"' - will automatically create default element\"\r\n\t\t\t\t);\r\n\t\t\t} else {\r\n\t\t\t\tthis._adjustPosition();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!this._element) {\r\n\t\t\tthis._createDefaultSpinner();\r\n\t\t}\r\n\r\n\t\tthis.processes = 0;\r\n\t}\r\n\r\n\t/** @private */\r\n\t_createDefaultSpinner() {\r\n\t\tthis._injectDefaultCSS();\r\n\t\tconst element = document.createElement(\"div\");\r\n\t\tconst style = element.style;\r\n\t\tstyle[\"z-index\"] = \"9000\";\r\n\t\tstyle.position = \"absolute\";\r\n\t\telement.innerHTML =\r\n\t\t\t'<div class=\"sk-fading-circle\">\\\r\n <div class=\"sk-circle1 sk-circle\"></div>\\\r\n <div class=\"sk-circle2 sk-circle\"></div>\\\r\n <div class=\"sk-circle3 sk-circle\"></div>\\\r\n <div class=\"sk-circle4 sk-circle\"></div>\\\r\n <div class=\"sk-circle5 sk-circle\"></div>\\\r\n <div class=\"sk-circle6 sk-circle\"></div>\\\r\n <div class=\"sk-circle7 sk-circle\"></div>\\\r\n <div class=\"sk-circle8 sk-circle\"></div>\\\r\n <div class=\"sk-circle9 sk-circle\"></div>\\\r\n <div class=\"sk-circle10 sk-circle\"></div>\\\r\n <div class=\"sk-circle11 sk-circle\"></div>\\\r\n <div class=\"sk-circle12 sk-circle\"></div>\\\r\n </div>';\r\n\t\telement.setAttribute(\"class\", \"loading-circle\");\r\n\t\tif (this._canvas.parentElement) this._canvas.parentElement.appendChild(element);\r\n\t\telse {\r\n\t\t\tconst viewer = document.getElementById(\"myViewer\");\r\n\t\t\tviewer.appendChild(element);\r\n\t\t}\r\n\t\tthis._element = element;\r\n\t\tthis._isCustom = false;\r\n\t\tthis._adjustPosition();\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\t_injectDefaultCSS() {\r\n\t\tconst elementId = \"tctwins-spinner-css\";\r\n\t\tif (document.getElementById(elementId)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst defaultCSSNode = document.createElement(\"style\");\r\n\t\tdefaultCSSNode.innerHTML = defaultCSS;\r\n\t\tdefaultCSSNode.id = elementId;\r\n\t\tif (this._canvas.parentElement) this._canvas.parentElement.appendChild(defaultCSSNode);\r\n\t\telse {\r\n\t\t\tconst viewer = document.getElementById(\"myViewer\");\r\n\t\t\tviewer.appendChild(defaultCSSNode);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\t_adjustPosition() {\r\n\t\t// (Re)positions spinner DIV over the center of the canvas - called by Canvas\r\n\t\tif (this._isCustom) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst canvas = this._canvas;\r\n\t\tconst element = this._element;\r\n\t\tconst style = element.style;\r\n\t\tstyle[\"left\"] = canvas.offsetLeft + canvas.clientWidth * 0.5 - element.clientWidth * 0.5 + \"px\";\r\n\t\tstyle[\"top\"] = canvas.offsetTop + canvas.clientHeight * 0.5 - element.clientHeight * 0.5 + \"px\";\r\n\t}\r\n\r\n\t/**\r\n * Sets the number of processes this Spinner represents.\r\n *\r\n * The Spinner is visible while this property is greater than zero.\r\n *\r\n * Increment this property whenever you commence some process during which you want the Spinner to be visible, then decrement it again when the process is complete.\r\n *\r\n * Clamps to zero if you attempt to set to to a negative value.\r\n *\r\n * Fires a {@link Spinner#processes:event} event on change.\r\n\r\n * Default value is ````0````.\r\n *\r\n * @param {Number} value New processes count.\r\n */\r\n\tset processes(value) {\r\n\t\tvalue = value || 0;\r\n\t\tif (this._processes === value) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (value < 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst prevValue = this._processes;\r\n\t\tthis._processes = value;\r\n\t\tconst element = this._element;\r\n\t\tif (element) {\r\n\t\t\telement.style[\"visibility\"] = this._processes > 0 ? \"visible\" : \"hidden\";\r\n\t\t}\r\n\t\t/**\r\n Fired whenever this Spinner's {@link Spinner#visible} property changes.\r\n\r\n @event processes\r\n @param value The property's new value\r\n */\r\n\t\tthis.fire(\"processes\", this._processes);\r\n\t\tif (this._processes === 0 && this._processes !== prevValue) {\r\n\t\t\t/**\r\n Fired whenever this Spinner's {@link Spinner#visible} property becomes zero.\r\n\r\n @event zeroProcesses\r\n */\r\n\t\t\tthis.fire(\"zeroProcesses\", this._processes);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of processes this Spinner represents.\r\n\t *\r\n\t * The Spinner is visible while this property is greater than zero.\r\n\t *\r\n\t * @returns {Number} Current processes count.\r\n\t */\r\n\tget processes() {\r\n\t\treturn this._processes;\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tif (this._element && !this._isCustom) {\r\n\t\t\tthis._element.parentNode.removeChild(this._element);\r\n\t\t\tthis._element = null;\r\n\t\t}\r\n\t\tconst styleElement = document.getElementById(\"tctwins-spinner-css\");\r\n\t\tif (styleElement) {\r\n\t\t\tstyleElement.parentNode.removeChild(styleElement);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/canvas/Spinner.js?");
|
|
2747
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Spinner: () => (/* binding */ Spinner)\n/* harmony export */ });\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n\r\n\r\nconst defaultCSS =\r\n\t\".sk-fading-circle {\\\r\n background: transparent;\\\r\n margin: 20px auto;\\\r\n width: 50px;\\\r\n height:50px;\\\r\n position: relative;\\\r\n }\\\r\n .sk-fading-circle .sk-circle {\\\r\n width: 120%;\\\r\n height: 120%;\\\r\n position: absolute;\\\r\n left: 0;\\\r\n top: 0;\\\r\n }\\\r\n .sk-fading-circle .sk-circle:before {\\\r\n content: '';\\\r\n display: block;\\\r\n margin: 0 auto;\\\r\n width: 15%;\\\r\n height: 15%;\\\r\n background-color: #66abdd;\\\r\n border-radius: 100%;\\\r\n -webkit-animation: sk-circleFadeDelay 1.2s infinite ease-in-out both;\\\r\n animation: sk-circleFadeDelay 1.2s infinite ease-in-out both;\\\r\n }\\\r\n .sk-fading-circle .sk-circle2 {\\\r\n -webkit-transform: rotate(30deg);\\\r\n -ms-transform: rotate(30deg);\\\r\n transform: rotate(30deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle3 {\\\r\n -webkit-transform: rotate(60deg);\\\r\n -ms-transform: rotate(60deg);\\\r\n transform: rotate(60deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle4 {\\\r\n -webkit-transform: rotate(90deg);\\\r\n -ms-transform: rotate(90deg);\\\r\n transform: rotate(90deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle5 {\\\r\n -webkit-transform: rotate(120deg);\\\r\n -ms-transform: rotate(120deg);\\\r\n transform: rotate(120deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle6 {\\\r\n -webkit-transform: rotate(150deg);\\\r\n -ms-transform: rotate(150deg);\\\r\n transform: rotate(150deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle7 {\\\r\n -webkit-transform: rotate(180deg);\\\r\n -ms-transform: rotate(180deg);\\\r\n transform: rotate(180deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle8 {\\\r\n -webkit-transform: rotate(210deg);\\\r\n -ms-transform: rotate(210deg);\\\r\n transform: rotate(210deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle9 {\\\r\n -webkit-transform: rotate(240deg);\\\r\n -ms-transform: rotate(240deg);\\\r\n transform: rotate(240deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle10 {\\\r\n -webkit-transform: rotate(270deg);\\\r\n -ms-transform: rotate(270deg);\\\r\n transform: rotate(270deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle11 {\\\r\n -webkit-transform: rotate(300deg);\\\r\n -ms-transform: rotate(300deg);\\\r\n transform: rotate(300deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle12 {\\\r\n -webkit-transform: rotate(330deg);\\\r\n -ms-transform: rotate(330deg);\\\r\n transform: rotate(330deg);\\\r\n }\\\r\n .sk-fading-circle .sk-circle2:before {\\\r\n -webkit-animation-delay: -1.1s;\\\r\n animation-delay: -1.1s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle3:before {\\\r\n -webkit-animation-delay: -1s;\\\r\n animation-delay: -1s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle4:before {\\\r\n -webkit-animation-delay: -0.9s;\\\r\n animation-delay: -0.9s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle5:before {\\\r\n -webkit-animation-delay: -0.8s;\\\r\n animation-delay: -0.8s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle6:before {\\\r\n -webkit-animation-delay: -0.7s;\\\r\n animation-delay: -0.7s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle7:before {\\\r\n -webkit-animation-delay: -0.6s;\\\r\n animation-delay: -0.6s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle8:before {\\\r\n -webkit-animation-delay: -0.5s;\\\r\n animation-delay: -0.5s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle9:before {\\\r\n -webkit-animation-delay: -0.4s;\\\r\n animation-delay: -0.4s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle10:before {\\\r\n -webkit-animation-delay: -0.3s;\\\r\n animation-delay: -0.3s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle11:before {\\\r\n -webkit-animation-delay: -0.2s;\\\r\n animation-delay: -0.2s;\\\r\n }\\\r\n .sk-fading-circle .sk-circle12:before {\\\r\n -webkit-animation-delay: -0.1s;\\\r\n animation-delay: -0.1s;\\\r\n }\\\r\n @-webkit-keyframes sk-circleFadeDelay {\\\r\n 0%, 39%, 100% { opacity: 0; }\\\r\n 40% { opacity: 1; }\\\r\n }\\\r\n @keyframes sk-circleFadeDelay {\\\r\n 0%, 39%, 100% { opacity: 0; }\\\r\n 40% { opacity: 1; }\\\r\n }\";\r\n\r\n/**\r\n * @desc Displays a progress animation at the center of its {@link Canvas} while things are loading or otherwise busy.\r\n *\r\n *\r\n * * Located at {@link Canvas#spinner}.\r\n * * Automatically shown while things are loading, however may also be shown by application code wanting to indicate busyness.\r\n * * {@link Spinner#processes} holds the count of active processes. As a process starts, it increments {@link Spinner#processes}, then decrements it on completion or failure.\r\n * * A Spinner is only visible while {@link Spinner#processes} is greater than zero.\r\n *\r\n * ````javascript\r\n * var spinner = viewer.scene.canvas.spinner;\r\n *\r\n * // Increment count of busy processes represented by the spinner;\r\n * // assuming the count was zero, this now shows the spinner\r\n * spinner.processes++;\r\n *\r\n * // Increment the count again, by some other process; spinner already visible, now requires two decrements\r\n * // before it becomes invisible again\r\n * spinner.processes++;\r\n *\r\n * // Decrement the count; count still greater than zero, so spinner remains visible\r\n * spinner.process--;\r\n *\r\n * // Decrement the count; count now zero, so spinner becomes invisible\r\n * spinner.process--;\r\n * ````\r\n */\r\nclass Spinner extends _Component_js__WEBPACK_IMPORTED_MODULE_0__.Component {\r\n\t/**\r\n @private\r\n */\r\n\tget type() {\r\n\t\treturn \"Spinner\";\r\n\t}\r\n\r\n\t/**\r\n @private\r\n */\r\n\tconstructor(owner, cfg = {}) {\r\n\t\tsuper(owner, cfg);\r\n\r\n\t\tthis._canvas = cfg.canvas;\r\n\t\tthis._element = null;\r\n\t\tthis._isCustom = false; // True when the element is custom HTML\r\n\r\n\t\tif (cfg.elementId) {\r\n\t\t\t// Custom spinner element supplied\r\n\t\t\tthis._element = document.getElementById(cfg.elementId);\r\n\t\t\tif (!this._element) {\r\n\t\t\t\tthis._createDefaultSpinner(cfg.elementId);\r\n\t\t\t} else {\r\n\t\t\t\tthis._adjustPosition();\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthis._createDefaultSpinner(\"engine_spinner\");\r\n\t\t}\r\n\r\n\t\tthis.processes = 0;\r\n\t}\r\n\r\n\tget visible() {\r\n\t\treturn this._element.style[\"visibility\"] === \"visible\";\r\n\t}\r\n\r\n\tset visible(visible) {\r\n\t\tvisible ? (this._element.style[\"visibility\"] = \"visible\") : (this._element.style[\"visibility\"] = \"hidden\");\r\n\t}\r\n\r\n\t/** @private */\r\n\t_createDefaultSpinner(elementId) {\r\n\t\tconsole.log(\"_createDefaultSpinner\");\r\n\t\tthis._injectDefaultCSS();\r\n\t\tconst element = document.createElement(\"div\");\r\n\t\telement.setAttribute(\"id\", elementId);\r\n\t\tconst style = element.style;\r\n\t\tstyle[\"z-index\"] = \"9000\";\r\n\t\tstyle.position = \"absolute\";\r\n\t\telement.innerHTML =\r\n\t\t\t'<div class=\"sk-fading-circle\">\\\r\n <div class=\"sk-circle1 sk-circle\"></div>\\\r\n <div class=\"sk-circle2 sk-circle\"></div>\\\r\n <div class=\"sk-circle3 sk-circle\"></div>\\\r\n <div class=\"sk-circle4 sk-circle\"></div>\\\r\n <div class=\"sk-circle5 sk-circle\"></div>\\\r\n <div class=\"sk-circle6 sk-circle\"></div>\\\r\n <div class=\"sk-circle7 sk-circle\"></div>\\\r\n <div class=\"sk-circle8 sk-circle\"></div>\\\r\n <div class=\"sk-circle9 sk-circle\"></div>\\\r\n <div class=\"sk-circle10 sk-circle\"></div>\\\r\n <div class=\"sk-circle11 sk-circle\"></div>\\\r\n <div class=\"sk-circle12 sk-circle\"></div>\\\r\n </div>';\r\n\t\telement.setAttribute(\"class\", \"loading-circle\");\r\n\t\tif (this._canvas.parentElement) this._canvas.parentElement.appendChild(element);\r\n\t\telse {\r\n\t\t\tconst viewer = document.getElementById(\"myViewer\");\r\n\t\t\tviewer.appendChild(element);\r\n\t\t}\r\n\t\tthis._element = element;\r\n\t\tthis._isCustom = false;\r\n\t\tthis._adjustPosition();\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\t_injectDefaultCSS() {\r\n\t\tconst elementId = \"tctwins-spinner-css\";\r\n\t\tif (document.getElementById(elementId)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst defaultCSSNode = document.createElement(\"style\");\r\n\t\tdefaultCSSNode.innerHTML = defaultCSS;\r\n\t\tdefaultCSSNode.id = elementId;\r\n\t\tif (this._canvas.parentElement) this._canvas.parentElement.appendChild(defaultCSSNode);\r\n\t\telse {\r\n\t\t\tconst viewer = document.getElementById(\"myViewer\");\r\n\t\t\tviewer.appendChild(defaultCSSNode);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\t_adjustPosition() {\r\n\t\t// (Re)positions spinner DIV over the center of the canvas - called by Canvas\r\n\t\tif (this._isCustom) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst canvas = this._canvas;\r\n\t\tconst element = this._element;\r\n\t\tconst style = element.style;\r\n\t\tstyle[\"left\"] = canvas.offsetLeft + canvas.clientWidth * 0.5 - element.clientWidth * 0.5 + \"px\";\r\n\t\tstyle[\"top\"] = canvas.offsetTop + canvas.clientHeight * 0.5 - element.clientHeight * 0.5 + \"px\";\r\n\t}\r\n\r\n\t/**\r\n * Sets the number of processes this Spinner represents.\r\n *\r\n * The Spinner is visible while this property is greater than zero.\r\n *\r\n * Increment this property whenever you commence some process during which you want the Spinner to be visible, then decrement it again when the process is complete.\r\n *\r\n * Clamps to zero if you attempt to set to to a negative value.\r\n *\r\n * Fires a {@link Spinner#processes:event} event on change.\r\n\r\n * Default value is ````0````.\r\n *\r\n * @param {Number} value New processes count.\r\n */\r\n\tset processes(value) {\r\n\t\tvalue = value || 0;\r\n\t\tif (this._processes === value) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (value < 0) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tconst prevValue = this._processes;\r\n\t\tthis._processes = value;\r\n\t\tconst element = this._element;\r\n\t\tif (element) {\r\n\t\t\telement.style[\"visibility\"] = this._processes > 0 ? \"visible\" : \"hidden\";\r\n\t\t}\r\n\t\t/**\r\n Fired whenever this Spinner's {@link Spinner#visible} property changes.\r\n\r\n @event processes\r\n @param value The property's new value\r\n */\r\n\t\tthis.fire(\"processes\", this._processes);\r\n\t\tif (this._processes === 0 && this._processes !== prevValue) {\r\n\t\t\t/**\r\n Fired whenever this Spinner's {@link Spinner#visible} property becomes zero.\r\n\r\n @event zeroProcesses\r\n */\r\n\t\t\tthis.fire(\"zeroProcesses\", this._processes);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of processes this Spinner represents.\r\n\t *\r\n\t * The Spinner is visible while this property is greater than zero.\r\n\t *\r\n\t * @returns {Number} Current processes count.\r\n\t */\r\n\tget processes() {\r\n\t\treturn this._processes;\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tif (this._element && !this._isCustom) {\r\n\t\t\tthis._element.parentNode.removeChild(this._element);\r\n\t\t\tthis._element = null;\r\n\t\t}\r\n\t\tconst styleElement = document.getElementById(\"tctwins-spinner-css\");\r\n\t\tif (styleElement) {\r\n\t\t\tstyleElement.parentNode.removeChild(styleElement);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/canvas/Spinner.js?");
|
|
2748
2748
|
|
|
2749
2749
|
/***/ }),
|
|
2750
2750
|
|
|
@@ -4804,7 +4804,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
|
|
|
4804
4804
|
\*****************************************/
|
|
4805
4805
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
4806
4806
|
|
|
4807
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Scene: () => (/* binding */ Scene)\n/* harmony export */ });\n/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../core.js */ \"./src/viewer/scene/core.js\");\n/* harmony import */ var _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lod/LOD.js */ \"./src/viewer/scene/lod/LOD.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../canvas/Canvas.js */ \"./src/viewer/scene/canvas/Canvas.js\");\n/* harmony import */ var _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../webgl/Renderer.js */ \"./src/viewer/scene/webgl/Renderer.js\");\n/* harmony import */ var _input_Input_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../input/Input.js */ \"./src/viewer/scene/input/Input.js\");\n/* harmony import */ var _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../viewport/Viewport.js */ \"./src/viewer/scene/viewport/Viewport.js\");\n/* harmony import */ var _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../camera/Camera.js */ \"./src/viewer/scene/camera/Camera.js\");\n/* harmony import */ var _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../lights/AmbientLight.js */ \"./src/viewer/scene/lights/AmbientLight.js\");\n/* harmony import */ var _geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../geometry/builders/buildBoxGeometry.js */ \"./src/viewer/scene/geometry/builders/buildBoxGeometry.js\");\n/* harmony import */ var _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../materials/EdgeMaterial.js */ \"./src/viewer/scene/materials/EdgeMaterial.js\");\n/* harmony import */ var _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../metriqs/Metriqs.js */ \"./src/viewer/scene/metriqs/Metriqs.js\");\n/* harmony import */ var _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../postfx/SAO.js */ \"./src/viewer/scene/postfx/SAO.js\");\n/* harmony import */ var _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../materials/PointsMaterial.js */ \"./src/viewer/scene/materials/PointsMaterial.js\");\n/* harmony import */ var _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../materials/LinesMaterial.js */ \"./src/viewer/scene/materials/LinesMaterial.js\");\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n// Enables runtime check for redundant calls to object state update methods, eg. Scene#_objectVisibilityUpdated\r\nconst ASSERT_OBJECT_STATE_UPDATE = false;\r\n\r\n// Cached vars to avoid garbage collection\r\n\r\nfunction getEntityIDMap(scene, entityIds) {\r\n\tconst map = {};\r\n\tlet entityId;\r\n\tlet entity;\r\n\tfor (let i = 0, len = entityIds.length; i < len; i++) {\r\n\t\tentityId = entityIds[i];\r\n\t\tentity = scene.components[entityId];\r\n\t\tif (!entity) {\r\n\t\t\tscene.warn(\"pick(): Component not found: \" + entityId);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (!entity.isEntity) {\r\n\t\t\tscene.warn(\"pick(): Component is not an Entity: \" + entityId);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tmap[entityId] = true;\r\n\t}\r\n\treturn map;\r\n}\r\n\r\n/**\r\n * Fired whenever a debug message is logged on a component within this Scene.\r\n * @event log\r\n * @param {String} value The debug message\r\n */\r\n\r\n/**\r\n * Fired whenever an error is logged on a component within this Scene.\r\n * @event error\r\n * @param {String} value The error message\r\n */\r\n\r\n/**\r\n * Fired whenever a warning is logged on a component within this Scene.\r\n * @event warn\r\n * @param {String} value The warning message\r\n */\r\n\r\n/**\r\n * @desc Contains the components that comprise a 3D scene.\r\n *\r\n * * A {@link Viewer} has a single Scene, which it provides in {@link Viewer#scene}.\r\n * * Plugins like {@link AxisGizmoPlugin} also have their own private Scenes.\r\n * * Each Scene has a corresponding {@link MetaScene}, which the Viewer provides in {@link Viewer#metaScene}.\r\n *\r\n * ## Getting a Viewer's Scene\r\n *\r\n * ````javascript\r\n * var scene = viewer.scene;\r\n * ````\r\n *\r\n * ## Creating and accessing Scene components\r\n *\r\n * As a brief introduction to creating Scene components, we'll create a {@link Mesh} that has a\r\n * {@link buildTorusGeometry} and a {@link PhongMaterial}:\r\n *\r\n * ````javascript\r\n * var teapotMesh = new Mesh(scene, {\r\n * id: \"myMesh\", // <<---------- ID automatically generated if not provided\r\n * geometry: new TorusGeometry(scene),\r\n * material: new PhongMaterial(scene, {\r\n * id: \"myMaterial\",\r\n * diffuse: [0.2, 0.2, 1.0]\r\n * })\r\n * });\r\n *\r\n * teapotMesh.scene.camera.eye = [45, 45, 45];\r\n * ````\r\n *\r\n * Find components by ID in their Scene's {@link Scene#components} map:\r\n *\r\n * ````javascript\r\n * var teapotMesh = scene.components[\"myMesh\"];\r\n * teapotMesh.visible = false;\r\n *\r\n * var teapotMaterial = scene.components[\"myMaterial\"];\r\n * teapotMaterial.diffuse = [1,0,0]; // Change to red\r\n * ````\r\n *\r\n * A Scene also has a map of component instances for each {@link Component} subtype:\r\n *\r\n * ````javascript\r\n * var meshes = scene.types[\"Mesh\"];\r\n * var teapotMesh = meshes[\"myMesh\"];\r\n * teapotMesh.xrayed = true;\r\n *\r\n * var phongMaterials = scene.types[\"PhongMaterial\"];\r\n * var teapotMaterial = phongMaterials[\"myMaterial\"];\r\n * teapotMaterial.diffuse = [0,1,0]; // Change to green\r\n * ````\r\n *\r\n * See {@link Node}, {@link Node} and {@link Model} for how to create and access more sophisticated content.\r\n *\r\n * ## Controlling the camera\r\n *\r\n * Use the Scene's {@link Camera} to control the current viewpoint and projection:\r\n *\r\n * ````javascript\r\n * var camera = myScene.camera;\r\n *\r\n * camera.eye = [-10,0,0];\r\n * camera.look = [-10,0,0];\r\n * camera.up = [0,1,0];\r\n *\r\n * camera.projection = \"perspective\";\r\n * camera.perspective.fov = 45;\r\n * //...\r\n * ````\r\n *\r\n * ## Managing the canvas\r\n *\r\n * The Scene's {@link Canvas} component provides various conveniences relevant to the WebGL canvas, such\r\n * as firing resize events etc:\r\n *\r\n * ````javascript\r\n * var canvas = scene.canvas;\r\n *\r\n * canvas.on(\"boundary\", function(boundary) {\r\n * //...\r\n * });\r\n * ````\r\n *\r\n * ## Picking\r\n *\r\n * Use {@link Scene#pick} to pick and raycast entites.\r\n *\r\n * For example, to pick a point on the surface of the closest entity at the given canvas coordinates:\r\n *\r\n * ````javascript\r\n * var pickResult = scene.pick({\r\n * pickSurface: true,\r\n * canvasPos: [23, 131]\r\n * });\r\n *\r\n * if (pickResult) { // Picked an entity\r\n *\r\n * var entity = pickResult.entity;\r\n *\r\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\r\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Mesh's Geometry's indices array\r\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\r\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\r\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\r\n * var viewPos = pickResult. ; // Float64Array containing the picked View-space position on the triangle\r\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\r\n * var normal = pickResult.normal; // Float64Array containing the interpolated normal vector at the picked position on the triangle\r\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\r\n * }\r\n * ````\r\n *\r\n * ## Pick masking\r\n *\r\n * We can use {@link Scene#pick}'s ````includeEntities```` and ````excludeEntities```` options to mask which {@link Mesh}es we attempt to pick.\r\n *\r\n * This is useful for picking through things, to pick only the Entities of interest.\r\n *\r\n * To pick only Entities ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through any other Entities that are\r\n * in the way, as if they weren't there:\r\n *\r\n * ````javascript\r\n * var pickResult = scene.pick({\r\n * canvasPos: [23, 131],\r\n * includeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\r\n * });\r\n *\r\n * if (pickResult) {\r\n * // Entity will always be either \"gearbox#77.0\" or \"gearbox#79.0\"\r\n * var entity = pickResult.entity;\r\n * }\r\n * ````\r\n *\r\n * To pick any pickable Entity, except for ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through those\r\n * Entities if they happen to be in the way:\r\n *\r\n * ````javascript\r\n * var pickResult = scene.pick({\r\n * canvasPos: [23, 131],\r\n * excludeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\r\n * });\r\n *\r\n * if (pickResult) {\r\n * // Entity will never be \"gearbox#77.0\" or \"gearbox#79.0\"\r\n * var entity = pickResult.entity;\r\n * }\r\n * ````\r\n *\r\n * See {@link Scene#pick} for more info on picking.\r\n *\r\n * ## Querying and tracking boundaries\r\n *\r\n * Getting a Scene's World-space axis-aligned boundary (AABB):\r\n *\r\n * ````javascript\r\n * var aabb = scene.aabb; // [xmin, ymin, zmin, xmax, ymax, zmax]\r\n * ````\r\n *\r\n * Subscribing to updates to the AABB, which occur whenever {@link Entity}s are transformed, their\r\n * {@link ReadableGeometry}s have been updated, or the {@link Camera} has moved:\r\n *\r\n * ````javascript\r\n * scene.on(\"boundary\", function() {\r\n * var aabb = scene.aabb;\r\n * });\r\n * ````\r\n *\r\n * Getting the AABB of the {@link Entity}s with the given IDs:\r\n *\r\n * ````JavaScript\r\n * scene.getAABB(); // Gets collective boundary of all Entities in the scene\r\n * scene.getAABB(\"saw\"); // Gets boundary of an Object\r\n * scene.getAABB([\"saw\", \"gearbox\"]); // Gets collective boundary of two Objects\r\n * ````\r\n *\r\n * See {@link Scene#getAABB} and {@link Entity} for more info on querying and tracking boundaries.\r\n *\r\n * ## Managing the viewport\r\n *\r\n * The Scene's {@link Viewport} component manages the WebGL viewport:\r\n *\r\n * ````javascript\r\n * var viewport = scene.viewport\r\n * viewport.boundary = [0, 0, 500, 400];;\r\n * ````\r\n *\r\n * ## Controlling rendering\r\n *\r\n * You can configure a Scene to perform multiple \"passes\" (renders) per frame. This is useful when we want to render the\r\n * scene to multiple viewports, such as for stereo effects.\r\n *\r\n * In the example, below, we'll configure the Scene to render twice on each frame, each time to different viewport. We'll do this\r\n * with a callback that intercepts the Scene before each render and sets its {@link Viewport} to a\r\n * different portion of the canvas. By default, the Scene will clear the canvas only before the first render, allowing the\r\n * two views to be shown on the canvas at the same time.\r\n *\r\n * ````Javascript\r\n * var viewport = scene.viewport;\r\n *\r\n * // Configure Scene to render twice for each frame\r\n * scene.passes = 2; // Default is 1\r\n * scene.clearEachPass = false; // Default is false\r\n *\r\n * // Render to a separate viewport on each render\r\n *\r\n * var viewport = scene.viewport;\r\n * viewport.autoBoundary = false;\r\n *\r\n * scene.on(\"rendering\", function (e) {\r\n * switch (e.pass) {\r\n * case 0:\r\n * viewport.boundary = [0, 0, 200, 200]; // xmin, ymin, width, height\r\n * break;\r\n *\r\n * case 1:\r\n * viewport.boundary = [200, 0, 200, 200];\r\n * break;\r\n * }\r\n * });\r\n *\r\n * // We can also intercept the Scene after each render,\r\n * // (though we're not using this for anything here)\r\n * scene.on(\"rendered\", function (e) {\r\n * switch (e.pass) {\r\n * case 0:\r\n * break;\r\n *\r\n * case 1:\r\n * break;\r\n * }\r\n * });\r\n * ````\r\n *\r\n * ## Gamma correction\r\n *\r\n * Within its shaders, xeokit performs shading calculations in linear space.\r\n *\r\n * By default, the Scene expects color textures (eg. {@link PhongMaterial#diffuseMap},\r\n * {@link MetallicMaterial#baseColorMap} and {@link SpecularMaterial#diffuseMap}) to\r\n * be in pre-multipled gamma space, so will convert those to linear space before they are used in shaders. Other textures are\r\n * always expected to be in linear space.\r\n *\r\n * By default, the Scene will also gamma-correct its rendered output.\r\n *\r\n * You can configure the Scene to expect all those color textures to be linear space, so that it does not gamma-correct them:\r\n *\r\n * ````javascript\r\n * scene.gammaInput = false;\r\n * ````\r\n *\r\n * You would still need to gamma-correct the output, though, if it's going straight to the canvas, so normally we would\r\n * leave that enabled:\r\n *\r\n * ````javascript\r\n * scene.gammaOutput = true;\r\n * ````\r\n *\r\n * See {@link Texture} for more information on texture encoding and gamma.\r\n *\r\n * @class Scene\r\n */\r\nclass Scene extends _Component_js__WEBPACK_IMPORTED_MODULE_4__.Component {\r\n\t/**\r\n @private\r\n */\r\n\tget type() {\r\n\t\treturn \"Scene\";\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t * @constructor\r\n\t * @param {Viewer} viewer The Viewer this Scene belongs to.\r\n\t * @param {Object} cfg Scene configuration.\r\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\r\n\t * @param {HTMLElement} [cfg.keyboardEventsElement] Optional reference to HTML element on which key events should be handled. Defaults to the HTML Document.\r\n\t * @param {number} [cfg.numCachedSectionPlanes=0] Enhances the efficiency of SectionPlane creation by proactively allocating Viewer resources for a specified quantity\r\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\r\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\r\n\t * responsiveness. It is important to consider that each SectionPlane imposes rendering performance, so it is recommended to set this value to a quantity that aligns with\r\n\t * your expected usage.\r\n\t * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.\r\n\t */\r\n\tconstructor(viewer, cfg = {}) {\r\n\t\tsuper(null, cfg);\r\n\r\n\t\tconst canvas = cfg.canvasElement || document.getElementById(cfg.canvasId);\r\n\r\n\t\tif (!(canvas instanceof HTMLCanvasElement)) {\r\n\t\t\tthrow \"Mandatory config expected: valid canvasId or canvasElement\";\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * @type {{[key: string]: {wrapperFunc: Function, tickSubId: string}}}\r\n\t\t */\r\n\t\tthis._tickifiedFunctions = {};\r\n\r\n\t\tthis._transparent = !!cfg.transparent;\r\n\t\tconst alphaDepthMask = !!cfg.alphaDepthMask;\r\n\t\tthis._edgesEnabled = !!cfg.edgesEnabled;\r\n\r\n\t\tthis._aabbDirty = true;\r\n\r\n\t\t/**\r\n\t\t * The {@link Viewer} this Scene belongs to.\r\n\t\t * @type {Viewer}\r\n\t\t */\r\n\t\tthis.viewer = viewer;\r\n\r\n\t\t/** Decremented each frame, triggers occlusion test for occludable {@link Marker}s when zero.\r\n\t\t * @private\r\n\t\t * @type {number}\r\n\t\t */\r\n\t\tthis.occlusionTestCountdown = 0;\r\n\r\n\t\t/**\r\n The number of models currently loading.\r\n\r\n @property loading\r\n @final\r\n @type {Number}\r\n */\r\n\t\tthis.loading = 0;\r\n\r\n\t\t/**\r\n The epoch time (in milliseconds since 1970) when this Scene was instantiated.\r\n\r\n @property timeCreated\r\n @final\r\n @type {Number}\r\n */\r\n\t\tthis.startTime = new Date().getTime();\r\n\r\n\t\t/**\r\n\t\t * Map of {@link Entity}s that represent models.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isModel} is ````true````.\r\n\t\t *\r\n\t\t * @property models\r\n\t\t * @final\r\n\t\t * @type {{String:Entity}}\r\n\t\t */\r\n\t\tthis.models = {};\r\n\r\n\t\t/**\r\n\t\t * Map of {@link Entity}s that represents objects.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isObject} is ````true````.\r\n\t\t *\r\n\t\t * @property objects\r\n\t\t * @final\r\n\t\t * @type {{String:Entity}}\r\n\t\t */\r\n\t\tthis.objects = {};\r\n\t\tthis._numObjects = 0;\r\n\r\n\t\t/**\r\n\t\t * Map of currently visible {@link Entity}s that represent objects.\r\n\t\t *\r\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is visible when {@link Entity#visible} is true.\r\n\t\t *\r\n\t\t * @property visibleObjects\r\n\t\t * @final\r\n\t\t * @type {{String:Object}}\r\n\t\t */\r\n\t\tthis.visibleObjects = {};\r\n\t\tthis._numVisibleObjects = 0;\r\n\r\n\t\t/**\r\n\t\t * Map of currently xrayed {@link Entity}s that represent objects.\r\n\t\t *\r\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is xrayed when {@link Entity#xrayed} is true.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property xrayedObjects\r\n\t\t * @final\r\n\t\t * @type {{String:Object}}\r\n\t\t */\r\n\t\tthis.xrayedObjects = {};\r\n\t\tthis._numXRayedObjects = 0;\r\n\r\n\t\t/**\r\n\t\t * Map of currently highlighted {@link Entity}s that represent objects.\r\n\t\t *\r\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true```` is true, and is highlighted when {@link Entity#highlighted} is true.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property highlightedObjects\r\n\t\t * @final\r\n\t\t * @type {{String:Object}}\r\n\t\t */\r\n\t\tthis.highlightedObjects = {};\r\n\t\tthis._numHighlightedObjects = 0;\r\n\r\n\t\t/**\r\n\t\t * Map of currently selected {@link Entity}s that represent objects.\r\n\t\t *\r\n\t\t * An Entity represents an object if {@link Entity#isObject} is true, and is selected while {@link Entity#selected} is true.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property selectedObjects\r\n\t\t * @final\r\n\t\t * @type {{String:Object}}\r\n\t\t */\r\n\t\tthis.selectedObjects = {};\r\n\t\tthis._numSelectedObjects = 0;\r\n\r\n\t\t/**\r\n\t\t * Map of currently colorized {@link Entity}s that represent objects.\r\n\t\t *\r\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property colorizedObjects\r\n\t\t * @final\r\n\t\t * @type {{String:Object}}\r\n\t\t */\r\n\t\tthis.colorizedObjects = {};\r\n\t\tthis._numColorizedObjects = 0;\r\n\r\n\t\t/**\r\n\t\t * Map of {@link Entity}s that represent objects whose opacity was updated.\r\n\t\t *\r\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property opacityObjects\r\n\t\t * @final\r\n\t\t * @type {{String:Object}}\r\n\t\t */\r\n\t\tthis.opacityObjects = {};\r\n\t\tthis._numOpacityObjects = 0;\r\n\r\n\t\t/**\r\n\t\t * Map of {@link Entity}s that represent objects whose {@link Entity#offset}s were updated.\r\n\t\t *\r\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\r\n\t\t *\r\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\r\n\t\t *\r\n\t\t * @property offsetObjects\r\n\t\t * @final\r\n\t\t * @type {{String:Object}}\r\n\t\t */\r\n\t\tthis.offsetObjects = {};\r\n\t\tthis._numOffsetObjects = 0;\r\n\r\n\t\t// Cached ID arrays, lazy-rebuilt as needed when stale after map updates\r\n\r\n\t\t/**\r\n Lazy-regenerated ID lists.\r\n */\r\n\t\tthis._modelIds = null;\r\n\t\tthis._objectIds = null;\r\n\t\tthis._visibleObjectIds = null;\r\n\t\tthis._xrayedObjectIds = null;\r\n\t\tthis._highlightedObjectIds = null;\r\n\t\tthis._selectedObjectIds = null;\r\n\t\tthis._colorizedObjectIds = null;\r\n\t\tthis._opacityObjectIds = null;\r\n\t\tthis._offsetObjectIds = null;\r\n\r\n\t\tthis._collidables = {}; // Components that contribute to the Scene AABB\r\n\t\tthis._compilables = {}; // Components that require shader compilation\r\n\r\n\t\tthis._needRecompile = false;\r\n\r\n\t\t/**\r\n\t\t * For each {@link Component} type, a map of IDs to {@link Component} instances of that type.\r\n\t\t *\r\n\t\t * @type {{String:{String:Component}}}\r\n\t\t */\r\n\t\tthis.types = {};\r\n\r\n\t\t/**\r\n\t\t * The {@link Component}s within this Scene, each mapped to its {@link Component#id}.\r\n\t\t *\r\n\t\t * *@type {{String:Component}}\r\n\t\t */\r\n\t\tthis.components = {};\r\n\r\n\t\t/**\r\n\t\t * The {@link SectionPlane}s in this Scene, each mapped to its {@link SectionPlane#id}.\r\n\t\t *\r\n\t\t * @type {{String:SectionPlane}}\r\n\t\t */\r\n\t\tthis.sectionPlanes = {};\r\n\r\n\t\t/**\r\n\t\t * The {@link Light}s in this Scene, each mapped to its {@link Light#id}.\r\n\t\t *\r\n\t\t * @type {{String:Light}}\r\n\t\t */\r\n\t\tthis.lights = {};\r\n\r\n\t\t/**\r\n\t\t * The {@link LightMap}s in this Scene, each mapped to its {@link LightMap#id}.\r\n\t\t *\r\n\t\t * @type {{String:LightMap}}\r\n\t\t */\r\n\t\tthis.lightMaps = {};\r\n\r\n\t\t/**\r\n\t\t * The {@link ReflectionMap}s in this Scene, each mapped to its {@link ReflectionMap#id}.\r\n\t\t *\r\n\t\t * @type {{String:ReflectionMap}}\r\n\t\t */\r\n\t\tthis.reflectionMaps = {};\r\n\r\n\t\t/**\r\n\t\t * The {@link Bitmap}s in this Scene, each mapped to its {@link Bitmap#id}.\r\n\t\t *\r\n\t\t * @type {{String:Bitmap}}\r\n\t\t */\r\n\t\tthis.bitmaps = {};\r\n\r\n\t\t/**\r\n\t\t * The {@link LineSet}s in this Scene, each mapped to its {@link LineSet#id}.\r\n\t\t *\r\n\t\t * @type {{String:LineSet}}\r\n\t\t */\r\n\t\tthis.lineSets = {};\r\n\r\n\t\t/**\r\n\t\t * The real world offset for this Scene\r\n\t\t *\r\n\t\t * @type {Number[]}\r\n\t\t */\r\n\t\tthis.realWorldOffset = cfg.realWorldOffset || new Float64Array([0, 0, 0]);\r\n\r\n\t\t/**\r\n\t\t * Manages the HTML5 canvas for this Scene.\r\n\t\t *\r\n\t\t * @type {Canvas}\r\n\t\t */\r\n\t\tthis.canvas = new _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__.Canvas(this, {\r\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\r\n\t\t\tcanvas: canvas,\r\n\t\t\tspinnerElementId: cfg.spinnerElementId,\r\n\t\t\ttransparent: this._transparent,\r\n\t\t\twebgl2: cfg.webgl2 !== false,\r\n\t\t\tcontextAttr: cfg.contextAttr || {},\r\n\t\t\tbackgroundColor: cfg.backgroundColor,\r\n\t\t\tbackgroundColorFromAmbientLight: cfg.backgroundColorFromAmbientLight,\r\n\t\t\tpremultipliedAlpha: cfg.premultipliedAlpha\r\n\t\t});\r\n\r\n\t\tthis.canvas.on(\"boundary\", () => {\r\n\t\t\tthis.glRedraw();\r\n\t\t});\r\n\r\n\t\tthis.canvas.on(\"webglContextFailed\", () => {\r\n\t\t\talert(\"xeokit failed to find WebGL!\");\r\n\t\t});\r\n\r\n\t\tthis._renderer = new _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__.Renderer(this, {\r\n\t\t\ttransparent: this._transparent,\r\n\t\t\talphaDepthMask: alphaDepthMask,\r\n\t\t\tedgesEnabled: this._edgesEnabled\r\n\t\t});\r\n\r\n\t\tthis._sectionPlanesState = new (function () {\r\n\t\t\tthis.sectionPlanes = [];\r\n\r\n\t\t\tthis.clippingCaps = false;\r\n\r\n\t\t\tthis._numCachedSectionPlanes = 0;\r\n\r\n\t\t\tlet hash = null;\r\n\r\n\t\t\tthis.getHash = function () {\r\n\t\t\t\tif (hash) {\r\n\t\t\t\t\treturn hash;\r\n\t\t\t\t}\r\n\t\t\t\tconst numAllocatedSectionPlanes = this.getNumAllocatedSectionPlanes();\r\n\t\t\t\tconst sectionPlanes = this.sectionPlanes;\r\n\t\t\t\tif (numAllocatedSectionPlanes === 0) {\r\n\t\t\t\t\treturn (this.hash = \";\");\r\n\t\t\t\t}\r\n\t\t\t\tlet sectionPlane;\r\n\r\n\t\t\t\tconst hashParts = [];\r\n\t\t\t\tfor (let i = 0, len = numAllocatedSectionPlanes; i < len; i++) {\r\n\t\t\t\t\tsectionPlane = sectionPlanes[i];\r\n\t\t\t\t\thashParts.push(\"cp\");\r\n\t\t\t\t}\r\n\t\t\t\thashParts.push(\";\");\r\n\t\t\t\thash = hashParts.join(\"\");\r\n\t\t\t\treturn hash;\r\n\t\t\t};\r\n\r\n\t\t\tthis.addSectionPlane = function (sectionPlane) {\r\n\t\t\t\tthis.sectionPlanes.push(sectionPlane);\r\n\t\t\t\thash = null;\r\n\t\t\t};\r\n\r\n\t\t\tthis.removeSectionPlane = function (sectionPlane) {\r\n\t\t\t\tfor (let i = 0, len = this.sectionPlanes.length; i < len; i++) {\r\n\t\t\t\t\tif (this.sectionPlanes[i].id === sectionPlane.id) {\r\n\t\t\t\t\t\tthis.sectionPlanes.splice(i, 1);\r\n\t\t\t\t\t\thash = null;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\tthis.setNumCachedSectionPlanes = function (numCachedSectionPlanes) {\r\n\t\t\t\tthis._numCachedSectionPlanes = numCachedSectionPlanes;\r\n\t\t\t\thash = null;\r\n\t\t\t};\r\n\r\n\t\t\tthis.getNumCachedSectionPlanes = function () {\r\n\t\t\t\treturn this._numCachedSectionPlanes;\r\n\t\t\t};\r\n\r\n\t\t\tthis.getNumAllocatedSectionPlanes = function () {\r\n\t\t\t\tconst num = this.sectionPlanes.length;\r\n\t\t\t\treturn num > this._numCachedSectionPlanes ? num : this._numCachedSectionPlanes;\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(cfg.numCachedSectionPlanes || 0);\r\n\r\n\t\tthis._lightsState = new (function () {\r\n\t\t\tconst DEFAULT_AMBIENT = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 0]);\r\n\t\t\tconst ambientColorIntensity = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4();\r\n\r\n\t\t\tthis.lights = [];\r\n\t\t\tthis.reflectionMaps = [];\r\n\t\t\tthis.lightMaps = [];\r\n\r\n\t\t\tlet hash = null;\r\n\t\t\tlet ambientLight = null;\r\n\r\n\t\t\tthis.getHash = function () {\r\n\t\t\t\tif (hash) {\r\n\t\t\t\t\treturn hash;\r\n\t\t\t\t}\r\n\t\t\t\tconst hashParts = [];\r\n\t\t\t\tconst lights = this.lights;\r\n\t\t\t\tlet light;\r\n\t\t\t\tfor (let i = 0, len = lights.length; i < len; i++) {\r\n\t\t\t\t\tlight = lights[i];\r\n\t\t\t\t\thashParts.push(\"/\");\r\n\t\t\t\t\thashParts.push(light.type);\r\n\t\t\t\t\thashParts.push(light.space === \"world\" ? \"w\" : \"v\");\r\n\t\t\t\t\tif (light.castsShadow) {\r\n\t\t\t\t\t\thashParts.push(\"sh\");\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (this.lightMaps.length > 0) {\r\n\t\t\t\t\thashParts.push(\"/lm\");\r\n\t\t\t\t}\r\n\t\t\t\tif (this.reflectionMaps.length > 0) {\r\n\t\t\t\t\thashParts.push(\"/rm\");\r\n\t\t\t\t}\r\n\t\t\t\thashParts.push(\";\");\r\n\t\t\t\thash = hashParts.join(\"\");\r\n\t\t\t\treturn hash;\r\n\t\t\t};\r\n\r\n\t\t\tthis.addLight = function (state) {\r\n\t\t\t\tthis.lights.push(state);\r\n\t\t\t\tambientLight = null;\r\n\t\t\t\thash = null;\r\n\t\t\t};\r\n\r\n\t\t\tthis.removeLight = function (state) {\r\n\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\r\n\t\t\t\t\tconst light = this.lights[i];\r\n\t\t\t\t\tif (light.id === state.id) {\r\n\t\t\t\t\t\tthis.lights.splice(i, 1);\r\n\t\t\t\t\t\tif (ambientLight && ambientLight.id === state.id) {\r\n\t\t\t\t\t\t\tambientLight = null;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\thash = null;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\tthis.addReflectionMap = function (state) {\r\n\t\t\t\tthis.reflectionMaps.push(state);\r\n\t\t\t\thash = null;\r\n\t\t\t};\r\n\r\n\t\t\tthis.removeReflectionMap = function (state) {\r\n\t\t\t\tfor (let i = 0, len = this.reflectionMaps.length; i < len; i++) {\r\n\t\t\t\t\tif (this.reflectionMaps[i].id === state.id) {\r\n\t\t\t\t\t\tthis.reflectionMaps.splice(i, 1);\r\n\t\t\t\t\t\thash = null;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\tthis.addLightMap = function (state) {\r\n\t\t\t\tthis.lightMaps.push(state);\r\n\t\t\t\thash = null;\r\n\t\t\t};\r\n\r\n\t\t\tthis.removeLightMap = function (state) {\r\n\t\t\t\tfor (let i = 0, len = this.lightMaps.length; i < len; i++) {\r\n\t\t\t\t\tif (this.lightMaps[i].id === state.id) {\r\n\t\t\t\t\t\tthis.lightMaps.splice(i, 1);\r\n\t\t\t\t\t\thash = null;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\tthis.getAmbientColorAndIntensity = function () {\r\n\t\t\t\tif (!ambientLight) {\r\n\t\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\r\n\t\t\t\t\t\tconst light = this.lights[i];\r\n\t\t\t\t\t\tif (light.type === \"ambient\") {\r\n\t\t\t\t\t\t\tambientLight = light;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (ambientLight) {\r\n\t\t\t\t\tconst color = ambientLight.color;\r\n\t\t\t\t\tconst intensity = ambientLight.intensity;\r\n\t\t\t\t\tambientColorIntensity[0] = color[0];\r\n\t\t\t\t\tambientColorIntensity[1] = color[1];\r\n\t\t\t\t\tambientColorIntensity[2] = color[2];\r\n\t\t\t\t\tambientColorIntensity[3] = intensity;\r\n\t\t\t\t\treturn ambientColorIntensity;\r\n\t\t\t\t} else {\r\n\t\t\t\t\treturn DEFAULT_AMBIENT;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t})();\r\n\r\n\t\t/**\r\n\t\t * Publishes input events that occur on this Scene's canvas.\r\n\t\t * @property input\r\n\t\t * @type {Input}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.input = new _input_Input_js__WEBPACK_IMPORTED_MODULE_7__.Input(this, {\r\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\r\n\t\t\telement: this.canvas.canvas,\r\n\t\t\tkeyboardEventsElement: cfg.keyboardEventsElement\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t * Configures this Scene's units of measurement and coordinate mapping between Real-space and World-space 3D coordinate systems.\r\n\t\t *\r\n\t\t * @property metrics\r\n\t\t * @type {Metrics}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.metrics = new _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__.Metrics(this, {\r\n\t\t\tunits: cfg.units,\r\n\t\t\tscale: cfg.scale,\r\n\t\t\torigin: cfg.origin\r\n\t\t});\r\n\r\n\t\t/** Configures Scalable Ambient Obscurance (SAO) for this Scene.\r\n\t\t * @type {SAO}\r\n\t\t * @final\r\n\t\t */\r\n\t\tthis.sao = new _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__.SAO(this, {\r\n\t\t\tenabled: cfg.saoEnabled\r\n\t\t});\r\n\r\n\t\tthis.ticksPerRender = cfg.ticksPerRender;\r\n\t\tthis.ticksPerOcclusionTest = cfg.ticksPerOcclusionTest;\r\n\t\tthis.passes = cfg.passes;\r\n\t\tthis.clearEachPass = cfg.clearEachPass;\r\n\t\tthis.gammaInput = cfg.gammaInput;\r\n\t\tthis.gammaOutput = cfg.gammaOutput;\r\n\t\tthis.gammaFactor = cfg.gammaFactor;\r\n\r\n\t\tthis._entityOffsetsEnabled = !!cfg.entityOffsetsEnabled;\r\n\t\tthis._logarithmicDepthBufferEnabled = !!cfg.logarithmicDepthBufferEnabled;\r\n\r\n\t\tthis._dtxEnabled = cfg.dtxEnabled !== false;\r\n\t\tthis._pbrEnabled = !!cfg.pbrEnabled;\r\n\t\tthis._colorTextureEnabled = cfg.colorTextureEnabled !== false;\r\n\t\tthis._dtxEnabled = !!cfg.dtxEnabled;\r\n\t\tthis._lodEnabled = cfg.lodEnabled !== false;\r\n\r\n\t\t// Register Scene on xeokit\r\n\t\t// Do this BEFORE we add components below\r\n\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core._addScene(this);\r\n\r\n\t\tthis._initDefaults();\r\n\r\n\t\t// Global components\r\n\r\n\t\tthis._viewport = new _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__.Viewport(this, {\r\n\t\t\tid: \"default.viewport\",\r\n\t\t\tautoBoundary: true,\r\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\r\n\t\t});\r\n\r\n\t\tthis._camera = new _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__.Camera(this, {\r\n\t\t\tid: \"default.camera\",\r\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\r\n\t\t});\r\n\r\n\t\t// Default lights\r\n\r\n\t\tnew _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__.AmbientLight(this, {\r\n\t\t\tcolor: [1.0, 1.0, 1.0],\r\n\t\t\tintensity: 0.7\r\n\t\t});\r\n\r\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\r\n\t\t\tdir: [0.8, -0.5, -0.5],\r\n\t\t\tcolor: [0.67, 0.67, 1.0],\r\n\t\t\tintensity: 0.7,\r\n\t\t\tspace: \"world\"\r\n\t\t});\r\n\r\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\r\n\t\t\tdir: [-0.8, -1.0, 0.5],\r\n\t\t\tcolor: [1, 1, 0.9],\r\n\t\t\tintensity: 0.9,\r\n\t\t\tspace: \"world\"\r\n\t\t});\r\n\r\n\t\tthis._camera.on(\"dirty\", () => {\r\n\t\t\tthis._renderer.imageDirty();\r\n\t\t});\r\n\r\n\t\tthis._lod = new _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__.LOD(this, {\r\n\t\t\tenabled: this._lodEnabled,\r\n\t\t\ttargetFPS: 30\r\n\t\t});\r\n\t}\r\n\r\n\t_initDefaults() {\r\n\t\t// Call this Scene's property accessors to lazy-init their properties\r\n\r\n\t\tlet dummy; // Keeps Codacy happy\r\n\r\n\t\tdummy = this.geometry;\r\n\t\tdummy = this.material;\r\n\t\tdummy = this.xrayMaterial;\r\n\t\tdummy = this.edgeMaterial;\r\n\t\tdummy = this.selectedMaterial;\r\n\t\tdummy = this.highlightMaterial;\r\n\t}\r\n\r\n\t_addComponent(component) {\r\n\t\tif (component.id) {\r\n\t\t\t// Manual ID\r\n\t\t\tif (this.components[component.id]) {\r\n\t\t\t\tthis.error(\r\n\t\t\t\t\t\"Component \" +\r\n\t\t\t\t\t\t_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.inQuotes(component.id) +\r\n\t\t\t\t\t\t\" already exists in Scene - ignoring ID, will randomly-generate instead\"\r\n\t\t\t\t);\r\n\t\t\t\tcomponent.id = null;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!component.id) {\r\n\t\t\t// Auto ID\r\n\t\t\tif (window.nextID === undefined) {\r\n\t\t\t\twindow.nextID = 0;\r\n\t\t\t}\r\n\t\t\t//component.id = math.createUUID();\r\n\t\t\tcomponent.id = \"__\" + window.nextID++;\r\n\t\t\twhile (this.components[component.id]) {\r\n\t\t\t\tcomponent.id = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.createUUID();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.components[component.id] = component;\r\n\r\n\t\t// Register for class type\r\n\t\tconst type = component.type;\r\n\t\tlet types = this.types[component.type];\r\n\t\tif (!types) {\r\n\t\t\ttypes = this.types[type] = {};\r\n\t\t}\r\n\t\ttypes[component.id] = component;\r\n\r\n\t\tif (component.compile) {\r\n\t\t\tthis._compilables[component.id] = component;\r\n\t\t}\r\n\t\tif (component.isDrawable) {\r\n\t\t\tthis._renderer.addDrawable(component.id, component);\r\n\t\t\tthis._collidables[component.id] = component;\r\n\t\t}\r\n\t}\r\n\r\n\t_removeComponent(component) {\r\n\t\tvar id = component.id;\r\n\t\tvar type = component.type;\r\n\t\tdelete this.components[id];\r\n\t\t// Unregister for types\r\n\t\tconst types = this.types[type];\r\n\t\tif (types) {\r\n\t\t\tdelete types[id];\r\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isEmptyObject(types)) {\r\n\t\t\t\tdelete this.types[type];\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (component.compile) {\r\n\t\t\tdelete this._compilables[component.id];\r\n\t\t}\r\n\t\tif (component.isDrawable) {\r\n\t\t\tthis._renderer.removeDrawable(component.id);\r\n\t\t\tdelete this._collidables[component.id];\r\n\t\t}\r\n\t}\r\n\r\n\t// Methods below are called by various component types to register themselves on their\r\n\t// Scene. Violates Hollywood Principle, where we could just filter on type in _addComponent,\r\n\t// but this is faster than checking the type of each component in such a filter.\r\n\r\n\t_sectionPlaneCreated(sectionPlane) {\r\n\t\tthis.sectionPlanes[sectionPlane.id] = sectionPlane;\r\n\t\tthis.scene._sectionPlanesState.addSectionPlane(sectionPlane._state);\r\n\t\tthis.scene.fire(\"sectionPlaneCreated\", sectionPlane, true /* Don't retain event */);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_bitmapCreated(bitmap) {\r\n\t\tthis.bitmaps[bitmap.id] = bitmap;\r\n\t\tthis.scene.fire(\"bitmapCreated\", bitmap, true /* Don't retain event */);\r\n\t}\r\n\r\n\t_lineSetCreated(lineSet) {\r\n\t\tthis.lineSets[lineSet.id] = lineSet;\r\n\t\tthis.scene.fire(\"lineSetCreated\", lineSet, true /* Don't retain event */);\r\n\t}\r\n\r\n\t_lightCreated(light) {\r\n\t\tthis.lights[light.id] = light;\r\n\t\tthis.scene._lightsState.addLight(light._state);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_lightMapCreated(lightMap) {\r\n\t\tthis.lightMaps[lightMap.id] = lightMap;\r\n\t\tthis.scene._lightsState.addLightMap(lightMap._state);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_reflectionMapCreated(reflectionMap) {\r\n\t\tthis.reflectionMaps[reflectionMap.id] = reflectionMap;\r\n\t\tthis.scene._lightsState.addReflectionMap(reflectionMap._state);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_sectionPlaneDestroyed(sectionPlane) {\r\n\t\tdelete this.sectionPlanes[sectionPlane.id];\r\n\t\tthis.scene._sectionPlanesState.removeSectionPlane(sectionPlane._state);\r\n\t\tthis.scene.fire(\"sectionPlaneDestroyed\", sectionPlane, true /* Don't retain event */);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_bitmapDestroyed(bitmap) {\r\n\t\tdelete this.bitmaps[bitmap.id];\r\n\t\tthis.scene.fire(\"bitmapDestroyed\", bitmap, true /* Don't retain event */);\r\n\t}\r\n\r\n\t_lineSetDestroyed(lineSet) {\r\n\t\tdelete this.lineSets[lineSet.id];\r\n\t\tthis.scene.fire(\"lineSetDestroyed\", lineSet, true /* Don't retain event */);\r\n\t}\r\n\r\n\t_lightDestroyed(light) {\r\n\t\tdelete this.lights[light.id];\r\n\t\tthis.scene._lightsState.removeLight(light._state);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_lightMapDestroyed(lightMap) {\r\n\t\tdelete this.lightMaps[lightMap.id];\r\n\t\tthis.scene._lightsState.removeLightMap(lightMap._state);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_reflectionMapDestroyed(reflectionMap) {\r\n\t\tdelete this.reflectionMaps[reflectionMap.id];\r\n\t\tthis.scene._lightsState.removeReflectionMap(reflectionMap._state);\r\n\t\tthis._needRecompile = true;\r\n\t}\r\n\r\n\t_registerModel(entity) {\r\n\t\tthis.models[entity.id] = entity;\r\n\t\tthis._modelIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_deregisterModel(entity) {\r\n\t\tconst modelId = entity.id;\r\n\t\tdelete this.models[modelId];\r\n\t\tthis._modelIds = null; // Lazy regenerate\r\n\t\tthis.fire(\"modelUnloaded\", modelId);\r\n\t}\r\n\r\n\t_registerObject(entity) {\r\n\t\tthis.objects[entity.id] = entity;\r\n\t\tthis._numObjects++;\r\n\t\tthis._objectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_deregisterObject(entity) {\r\n\t\tdelete this.objects[entity.id];\r\n\t\tthis._numObjects--;\r\n\t\tthis._objectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_objectVisibilityUpdated(entity, notify = true) {\r\n\t\tif (entity.visible) {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.visibleObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=true)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis.visibleObjects[entity.id] = entity;\r\n\t\t\tthis._numVisibleObjects++;\r\n\t\t} else {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.visibleObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=false)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tdelete this.visibleObjects[entity.id];\r\n\t\t\tthis._numVisibleObjects--;\r\n\t\t}\r\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\r\n\t\tif (notify) {\r\n\t\t\tthis.fire(\"objectVisibility\", entity, true);\r\n\t\t}\r\n\t}\r\n\r\n\t_deRegisterVisibleObject(entity) {\r\n\t\tdelete this.visibleObjects[entity.id];\r\n\t\tthis._numVisibleObjects--;\r\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_objectXRayedUpdated(entity, notify = true) {\r\n\t\tif (entity.xrayed) {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.xrayedObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=true)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis.xrayedObjects[entity.id] = entity;\r\n\t\t\tthis._numXRayedObjects++;\r\n\t\t} else {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.xrayedObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=false)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tdelete this.xrayedObjects[entity.id];\r\n\t\t\tthis._numXRayedObjects--;\r\n\t\t}\r\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\r\n\t\tif (notify) {\r\n\t\t\tthis.fire(\"objectXRayed\", entity, true);\r\n\t\t}\r\n\t}\r\n\r\n\t_deRegisterXRayedObject(entity) {\r\n\t\tdelete this.xrayedObjects[entity.id];\r\n\t\tthis._numXRayedObjects--;\r\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_objectHighlightedUpdated(entity) {\r\n\t\tif (entity.highlighted) {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.highlightedObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=true)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis.highlightedObjects[entity.id] = entity;\r\n\t\t\tthis._numHighlightedObjects++;\r\n\t\t} else {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.highlightedObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=false)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tdelete this.highlightedObjects[entity.id];\r\n\t\t\tthis._numHighlightedObjects--;\r\n\t\t}\r\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_deRegisterHighlightedObject(entity) {\r\n\t\tdelete this.highlightedObjects[entity.id];\r\n\t\tthis._numHighlightedObjects--;\r\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_objectSelectedUpdated(entity, notify = true) {\r\n\t\tif (entity.selected) {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.selectedObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object select update (selected=true)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis.selectedObjects[entity.id] = entity;\r\n\t\t\tthis._numSelectedObjects++;\r\n\t\t} else {\r\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.selectedObjects[entity.id]) {\r\n\t\t\t\tconsole.error(\"Redundant object select update (selected=false)\");\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tdelete this.selectedObjects[entity.id];\r\n\t\t\tthis._numSelectedObjects--;\r\n\t\t}\r\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\r\n\t\tif (notify) {\r\n\t\t\tthis.fire(\"objectSelected\", entity, true);\r\n\t\t}\r\n\t}\r\n\r\n\t_deRegisterSelectedObject(entity) {\r\n\t\tdelete this.selectedObjects[entity.id];\r\n\t\tthis._numSelectedObjects--;\r\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_objectColorizeUpdated(entity, colorized) {\r\n\t\tif (colorized) {\r\n\t\t\tthis.colorizedObjects[entity.id] = entity;\r\n\t\t\tthis._numColorizedObjects++;\r\n\t\t} else {\r\n\t\t\tdelete this.colorizedObjects[entity.id];\r\n\t\t\tthis._numColorizedObjects--;\r\n\t\t}\r\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_deRegisterColorizedObject(entity) {\r\n\t\tdelete this.colorizedObjects[entity.id];\r\n\t\tthis._numColorizedObjects--;\r\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_objectOpacityUpdated(entity, opacityUpdated) {\r\n\t\tif (opacityUpdated) {\r\n\t\t\tthis.opacityObjects[entity.id] = entity;\r\n\t\t\tthis._numOpacityObjects++;\r\n\t\t} else {\r\n\t\t\tdelete this.opacityObjects[entity.id];\r\n\t\t\tthis._numOpacityObjects--;\r\n\t\t}\r\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_deRegisterOpacityObject(entity) {\r\n\t\tdelete this.opacityObjects[entity.id];\r\n\t\tthis._numOpacityObjects--;\r\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_objectOffsetUpdated(entity, offset) {\r\n\t\tif (!offset || (offset[0] === 0 && offset[1] === 0 && offset[2] === 0)) {\r\n\t\t\tthis.offsetObjects[entity.id] = entity;\r\n\t\t\tthis._numOffsetObjects++;\r\n\t\t} else {\r\n\t\t\tdelete this.offsetObjects[entity.id];\r\n\t\t\tthis._numOffsetObjects--;\r\n\t\t}\r\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_deRegisterOffsetObject(entity) {\r\n\t\tdelete this.offsetObjects[entity.id];\r\n\t\tthis._numOffsetObjects--;\r\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\r\n\t}\r\n\r\n\t_webglContextLost() {\r\n\t\t// this.loading++;\r\n\t\tthis.canvas.spinner.processes++;\r\n\t\tfor (const id in this.components) {\r\n\t\t\tif (this.components.hasOwnProperty(id)) {\r\n\t\t\t\tconst component = this.components[id];\r\n\t\t\t\tif (component._webglContextLost) {\r\n\t\t\t\t\tcomponent._webglContextLost();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis._renderer.webglContextLost();\r\n\t}\r\n\r\n\t_webglContextRestored() {\r\n\t\tconst gl = this.canvas.gl;\r\n\t\tfor (const id in this.components) {\r\n\t\t\tif (this.components.hasOwnProperty(id)) {\r\n\t\t\t\tconst component = this.components[id];\r\n\t\t\t\tif (component._webglContextRestored) {\r\n\t\t\t\t\tcomponent._webglContextRestored(gl);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis._renderer.webglContextRestored(gl);\r\n\t\t//this.loading--;\r\n\t\tthis.canvas.spinner.processes--;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the capabilities of this Scene.\r\n\t *\r\n\t * @private\r\n\t * @returns {{astcSupported: boolean, etc1Supported: boolean, pvrtcSupported: boolean, etc2Supported: boolean, dxtSupported: boolean, bptcSupported: boolean}}\r\n\t */\r\n\tget capabilities() {\r\n\t\treturn this._renderer.capabilities;\r\n\t}\r\n\r\n\t/**\r\n\t * Whether {@link Entity#offset} is enabled.\r\n\t *\r\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\r\n\t *\r\n\t * @returns {Boolean} True if {@link Entity#offset} is enabled.\r\n\t */\r\n\tget entityOffsetsEnabled() {\r\n\t\treturn this._entityOffsetsEnabled;\r\n\t}\r\n\r\n\t/**\r\n\t * Whether precision surface picking is enabled.\r\n\t *\r\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\r\n\t *\r\n\t * The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.\r\n\t *\r\n\t * Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer.\r\n\t *\r\n\t * @returns {Boolean} True if precision picking is enabled.\r\n\t */\r\n\tget pickSurfacePrecisionEnabled() {\r\n\t\treturn false; // Removed\r\n\t}\r\n\r\n\t/**\r\n\t * Whether logarithmic depth buffer is enabled.\r\n\t *\r\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\r\n\t *\r\n\t * @returns {Boolean} True if logarithmic depth buffer is enabled.\r\n\t */\r\n\tget logarithmicDepthBufferEnabled() {\r\n\t\treturn this._logarithmicDepthBufferEnabled;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\r\n\t *\r\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\r\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\r\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\r\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\r\n\t * your expected usage.\r\n\t *\r\n\t * Default is ````0````.\r\n\t */\r\n\tset numCachedSectionPlanes(numCachedSectionPlanes) {\r\n\t\tnumCachedSectionPlanes = numCachedSectionPlanes || 0;\r\n\t\tif (this._sectionPlanesState.getNumCachedSectionPlanes() !== numCachedSectionPlanes) {\r\n\t\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(numCachedSectionPlanes);\r\n\t\t\tthis._needRecompile = true;\r\n\t\t\tthis.glRedraw();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\r\n\t *\r\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\r\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\r\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\r\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\r\n\t * your expected usage.\r\n\t *\r\n\t * Default is ````0````.\r\n\t *\r\n\t * @returns {number} The number of {@link SectionPlane}s for which this Scene pre-caches resources.\r\n\t */\r\n\tget numCachedSectionPlanes() {\r\n\t\treturn this._sectionPlanesState.getNumCachedSectionPlanes();\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether physically-based rendering is enabled.\r\n\t *\r\n\t * Default is ````false````.\r\n\t */\r\n\tset pbrEnabled(pbrEnabled) {\r\n\t\tthis._pbrEnabled = !!pbrEnabled;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether physically-based rendering is enabled.\r\n\t *\r\n\t * Default is ````false````.\r\n\t *\r\n\t * @returns {Boolean} True if quality rendering is enabled.\r\n\t */\r\n\tget pbrEnabled() {\r\n\t\treturn this._pbrEnabled;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether data texture scene representation (DTX) is enabled for the {@link Scene}.\r\n\t *\r\n\t * Even when enabled, DTX will only work if supported.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset dtxEnabled(value) {\r\n\t\tvalue = !!value;\r\n\t\tif (this._dtxEnabled === value) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._dtxEnabled = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether data texture-based scene representation (DTX) is enabled for the {@link Scene}.\r\n\t *\r\n\t * Even when enabled, DTX will only apply if supported.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget dtxEnabled() {\r\n\t\treturn this._dtxEnabled;\r\n\t}\r\n\r\n\t/**\r\n\t * set showedges enable\r\n\t * @param {boolean} edgesEnabled\r\n\t */\r\n\tset edgesEnabled(edgesEnabled) {\r\n\t\tedgesEnabled = !!edgesEnabled;\r\n\t\tif (this._edgesEnabled === edgesEnabled) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._edgesEnabled = edgesEnabled;\r\n\t\tthis._renderer.setEdgesEnabled(edgesEnabled);\r\n\t}\r\n\r\n\t/**\r\n\t * @param {boolean} trans\r\n\t */\r\n\tget edgesEnabled() {\r\n\t\treturn this._edgesEnabled;\r\n\t}\r\n\r\n\t/**\r\n\t * set whether transparent of canvas background\r\n\t * @param {boolean} trans\r\n\t */\r\n\tset backgroundTransparent(trans) {\r\n\t\ttrans = !!trans;\r\n\t\t// if (this._transparent == trans) {\r\n\t\t// return;\r\n\t\t// }\r\n\t\tthis._transparent = trans;\r\n\t\tthis._renderer.setTransparentEnabled(trans);\r\n\t}\r\n\r\n\t/**\r\n\t * @returns {boolean} backgroundTransparent\r\n\t */\r\n\tget backgroundTransparent() {\r\n\t\treturn this._transparent;\r\n\t}\r\n\r\n\t/**\r\n\t * set background color\r\n\t * @param {[]} color\r\n\t */\r\n\tset backgroundColor(color) {\r\n\t\tthis.canvas.backgroundColor = color;\r\n\t\tthis._renderer.render({ force: true });\r\n\t}\r\n\r\n\t/**\r\n\t * return backgroundColor\r\n\t * @returns {boolean} backgroundColor\r\n\t */\r\n\tget backgroundColor() {\r\n\t\treturn this.canvas.backgroundColor();\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether basic color texture rendering is enabled.\r\n\t *\r\n\t * Default is ````true````.\r\n\t *\r\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\r\n\t */\r\n\tset colorTextureEnabled(colorTextureEnabled) {\r\n\t\tthis._colorTextureEnabled = !!colorTextureEnabled;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether basic color texture rendering is enabled.\r\n\t *\r\n\t * Default is ````true````.\r\n\t *\r\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\r\n\t */\r\n\tget colorTextureEnabled() {\r\n\t\treturn this._colorTextureEnabled;\r\n\t}\r\n\r\n\t/**\r\n\t * Performs an occlusion test on all {@link Marker}s in this {@link Scene}.\r\n\t *\r\n\t * Sets each {@link Marker#visible} ````true```` if the Marker is currently not occluded by any opaque {@link Entity}s\r\n\t * in the Scene, or ````false```` if an Entity is occluding it.\r\n\t */\r\n\tdoOcclusionTest() {\r\n\t\tif (this._needRecompile) {\r\n\t\t\tthis._recompile();\r\n\t\t\tthis._needRecompile = false;\r\n\t\t}\r\n\t\tthis._renderer.doOcclusionTest();\r\n\t}\r\n\r\n\t/**\r\n\t * Renders a single frame of this Scene.\r\n\t *\r\n\t * The Scene will periodically render itself after any updates, but you can call this method to force a render\r\n\t * if required.\r\n\t *\r\n\t * @param {Boolean} [forceRender=false] Forces a render when true, otherwise only renders if something has changed in this Scene\r\n\t * since the last render.\r\n\t */\r\n\trender(forceRender) {\r\n\t\tif (forceRender) {\r\n\t\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.runTasks();\r\n\t\t}\r\n\r\n\t\tconst renderEvent = {\r\n\t\t\tsceneId: null,\r\n\t\t\tpass: 0\r\n\t\t};\r\n\r\n\t\tif (this._needRecompile) {\r\n\t\t\tthis._recompile();\r\n\t\t\tthis._renderer.imageDirty();\r\n\t\t\tthis._needRecompile = false;\r\n\t\t}\r\n\r\n\t\tif (!forceRender && !this._renderer.needsRender()) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\trenderEvent.sceneId = this.id;\r\n\r\n\t\tconst passes = this._passes;\r\n\t\tconst clearEachPass = this._clearEachPass;\r\n\t\tlet pass;\r\n\t\tlet clear;\r\n\r\n\t\tfor (pass = 0; pass < passes; pass++) {\r\n\t\t\trenderEvent.pass = pass;\r\n\r\n\t\t\t/**\r\n\t\t\t * Fired when about to render a frame for a Scene.\r\n\t\t\t *\r\n\t\t\t * @event rendering\r\n\t\t\t * @param {String} sceneID The ID of this Scene.\r\n\t\t\t * @param {Number} pass Index of the pass we are about to render (see {@link Scene#passes}).\r\n\t\t\t */\r\n\t\t\tthis.fire(\"rendering\", renderEvent, true);\r\n\r\n\t\t\tclear = clearEachPass || pass === 0;\r\n\r\n\t\t\tthis._renderer.render({ pass: pass, clear: clear, force: forceRender });\r\n\r\n\t\t\t/**\r\n\t\t\t * Fired when we have just rendered a frame for a Scene.\r\n\t\t\t *\r\n\t\t\t * @event rendering\r\n\t\t\t * @param {String} sceneID The ID of this Scene.\r\n\t\t\t * @param {Number} pass Index of the pass we rendered (see {@link Scene#passes}).\r\n\t\t\t */\r\n\t\t\tthis.fire(\"rendered\", renderEvent, true);\r\n\t\t}\r\n\r\n\t\tthis._saveAmbientColor();\r\n\t}\r\n\r\n\t/**\r\n\t * @private\r\n\t */\r\n\tcompile() {\r\n\t\tif (this._needRecompile) {\r\n\t\t\tthis._recompile();\r\n\t\t\tthis._renderer.imageDirty();\r\n\t\t\tthis._needRecompile = false;\r\n\t\t}\r\n\t}\r\n\r\n\t_recompile() {\r\n\t\tfor (const id in this._compilables) {\r\n\t\t\tif (this._compilables.hasOwnProperty(id)) {\r\n\t\t\t\tthis._compilables[id].compile();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis._renderer.shadowsDirty();\r\n\t\tthis.fire(\"compile\", this, true);\r\n\t}\r\n\r\n\t_saveAmbientColor() {\r\n\t\tconst canvas = this.canvas;\r\n\t\tif (!canvas.transparent && !canvas.backgroundImage && !canvas.backgroundColor) {\r\n\t\t\tconst ambientColorIntensity = this._lightsState.getAmbientColorAndIntensity();\r\n\t\t\tif (\r\n\t\t\t\t!this._lastAmbientColor ||\r\n\t\t\t\tthis._lastAmbientColor[0] !== ambientColorIntensity[0] ||\r\n\t\t\t\tthis._lastAmbientColor[1] !== ambientColorIntensity[1] ||\r\n\t\t\t\tthis._lastAmbientColor[2] !== ambientColorIntensity[2] ||\r\n\t\t\t\tthis._lastAmbientColor[3] !== ambientColorIntensity[3]\r\n\t\t\t) {\r\n\t\t\t\tcanvas.backgroundColor = ambientColorIntensity;\r\n\t\t\t\tif (!this._lastAmbientColor) {\r\n\t\t\t\t\tthis._lastAmbientColor = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 1]);\r\n\t\t\t\t}\r\n\t\t\t\tthis._lastAmbientColor.set(ambientColorIntensity);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthis._lastAmbientColor = null;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#models}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget modelIds() {\r\n\t\tif (!this._modelIds) {\r\n\t\t\tthis._modelIds = Object.keys(this.models);\r\n\t\t}\r\n\t\treturn this._modelIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of {@link Entity}s in {@link Scene#objects}.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget numObjects() {\r\n\t\treturn this._numObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#objects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget objectIds() {\r\n\t\tif (!this._objectIds) {\r\n\t\t\tthis._objectIds = Object.keys(this.objects);\r\n\t\t}\r\n\t\treturn this._objectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of {@link Entity}s in {@link Scene#visibleObjects}.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget numVisibleObjects() {\r\n\t\treturn this._numVisibleObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#visibleObjects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget visibleObjectIds() {\r\n\t\tif (!this._visibleObjectIds) {\r\n\t\t\tthis._visibleObjectIds = Object.keys(this.visibleObjects);\r\n\t\t}\r\n\t\treturn this._visibleObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of {@link Entity}s in {@link Scene#xrayedObjects}.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget numXRayedObjects() {\r\n\t\treturn this._numXRayedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#xrayedObjects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget xrayedObjectIds() {\r\n\t\tif (!this._xrayedObjectIds) {\r\n\t\t\tthis._xrayedObjectIds = Object.keys(this.xrayedObjects);\r\n\t\t}\r\n\t\treturn this._xrayedObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of {@link Entity}s in {@link Scene#highlightedObjects}.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget numHighlightedObjects() {\r\n\t\treturn this._numHighlightedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#highlightedObjects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget highlightedObjectIds() {\r\n\t\tif (!this._highlightedObjectIds) {\r\n\t\t\tthis._highlightedObjectIds = Object.keys(this.highlightedObjects);\r\n\t\t}\r\n\t\treturn this._highlightedObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of {@link Entity}s in {@link Scene#selectedObjects}.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget numSelectedObjects() {\r\n\t\treturn this._numSelectedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#selectedObjects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget selectedObjectIds() {\r\n\t\tif (!this._selectedObjectIds) {\r\n\t\t\tthis._selectedObjectIds = Object.keys(this.selectedObjects);\r\n\t\t}\r\n\t\treturn this._selectedObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of {@link Entity}s in {@link Scene#colorizedObjects}.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget numColorizedObjects() {\r\n\t\treturn this._numColorizedObjects;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#colorizedObjects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget colorizedObjectIds() {\r\n\t\tif (!this._colorizedObjectIds) {\r\n\t\t\tthis._colorizedObjectIds = Object.keys(this.colorizedObjects);\r\n\t\t}\r\n\t\treturn this._colorizedObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#opacityObjects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget opacityObjectIds() {\r\n\t\tif (!this._opacityObjectIds) {\r\n\t\t\tthis._opacityObjectIds = Object.keys(this.opacityObjects);\r\n\t\t}\r\n\t\treturn this._opacityObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#offsetObjects}.\r\n\t *\r\n\t * @type {String[]}\r\n\t */\r\n\tget offsetObjectIds() {\r\n\t\tif (!this._offsetObjectIds) {\r\n\t\t\tthis._offsetObjectIds = Object.keys(this.offsetObjects);\r\n\t\t}\r\n\t\treturn this._offsetObjectIds;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the number of \"ticks\" that happen between each render or this Scene.\r\n\t *\r\n\t * Default value is ````1````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tset ticksPerRender(value) {\r\n\t\tif (value === undefined || value === null) {\r\n\t\t\tvalue = 1;\r\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\r\n\t\t\tthis.error(\"Unsupported value for 'ticksPerRender': '\" + value + \"' - should be an integer greater than zero.\");\r\n\t\t\tvalue = 1;\r\n\t\t}\r\n\t\tif (value === this._ticksPerRender) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._ticksPerRender = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of \"ticks\" that happen between each render or this Scene.\r\n\t *\r\n\t * Default value is ````1````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget ticksPerRender() {\r\n\t\treturn this._ticksPerRender;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the number of \"ticks\" that happen between occlusion testing for {@link Marker}s.\r\n\t *\r\n\t * Default value is ````20````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tset ticksPerOcclusionTest(value) {\r\n\t\tif (value === undefined || value === null) {\r\n\t\t\tvalue = 20;\r\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\r\n\t\t\tthis.error(\r\n\t\t\t\t\"Unsupported value for 'ticksPerOcclusionTest': '\" + value + \"' - should be an integer greater than zero.\"\r\n\t\t\t);\r\n\t\t\tvalue = 20;\r\n\t\t}\r\n\t\tif (value === this._ticksPerOcclusionTest) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._ticksPerOcclusionTest = value;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of \"ticks\" that happen between each render of this Scene.\r\n\t *\r\n\t * Default value is ````1````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget ticksPerOcclusionTest() {\r\n\t\treturn this._ticksPerOcclusionTest;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the number of times this Scene renders per frame.\r\n\t *\r\n\t * Default value is ````1````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tset passes(value) {\r\n\t\tif (value === undefined || value === null) {\r\n\t\t\tvalue = 1;\r\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\r\n\t\t\tthis.error(\"Unsupported value for 'passes': '\" + value + \"' - should be an integer greater than zero.\");\r\n\t\t\tvalue = 1;\r\n\t\t}\r\n\t\tif (value === this._passes) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._passes = value;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the number of times this Scene renders per frame.\r\n\t *\r\n\t * Default value is ````1````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget passes() {\r\n\t\treturn this._passes;\r\n\t}\r\n\r\n\t/**\r\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset clearEachPass(value) {\r\n\t\tvalue = !!value;\r\n\t\tif (value === this._clearEachPass) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._clearEachPass = value;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget clearEachPass() {\r\n\t\treturn this._clearEachPass;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset gammaInput(value) {\r\n\t\tvalue = value !== false;\r\n\t\tif (value === this._renderer.gammaInput) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._renderer.gammaInput = value;\r\n\t\tthis._needRecompile = true;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget gammaInput() {\r\n\t\treturn this._renderer.gammaInput;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets whether or not to render pixels with pre-multiplied gama.\r\n\t *\r\n\t * Default value is ````false````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tset gammaOutput(value) {\r\n\t\tvalue = !!value;\r\n\t\tif (value === this._renderer.gammaOutput) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._renderer.gammaOutput = value;\r\n\t\tthis._needRecompile = true;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets whether or not to render pixels with pre-multiplied gama.\r\n\t *\r\n\t * Default value is ````true````.\r\n\t *\r\n\t * @type {Boolean}\r\n\t */\r\n\tget gammaOutput() {\r\n\t\treturn this._renderer.gammaOutput;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the gamma factor to use when {@link Scene#gammaOutput} is set true.\r\n\t *\r\n\t * Default value is ````2.2````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tset gammaFactor(value) {\r\n\t\tvalue = value === undefined || value === null ? 2.2 : value;\r\n\t\tif (value === this._renderer.gammaFactor) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis._renderer.gammaFactor = value;\r\n\t\tthis.glRedraw();\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the gamma factor to use when {@link Scene#gammaOutput} is set true.\r\n\t *\r\n\t * Default value is ````2.2````.\r\n\t *\r\n\t * @type {Number}\r\n\t */\r\n\tget gammaFactor() {\r\n\t\treturn this._renderer.gammaFactor;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the default {@link Geometry} for this Scene, which is a {@link ReadableGeometry} with a unit-sized box shape.\r\n\t *\r\n\t * Has {@link ReadableGeometry#id} set to \"default.geometry\".\r\n\t *\r\n\t * {@link Mesh}s in this Scene have {@link Mesh#geometry} set to this {@link ReadableGeometry} by default.\r\n\t *\r\n\t * @type {ReadableGeometry}\r\n\t */\r\n\tget geometry() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.geometry\"] ||\r\n\t\t\t(0,_geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__.buildBoxGeometry)(_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__.ReadableGeometry, this, {\r\n\t\t\t\tid: \"default.geometry\",\r\n\t\t\t\tdontClear: true\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the default {@link Material} for this Scene, which is a {@link PhongMaterial}.\r\n\t *\r\n\t * Has {@link PhongMaterial#id} set to \"default.material\".\r\n\t *\r\n\t * {@link Mesh}s in this Scene have {@link Mesh#material} set to this {@link PhongMaterial} by default.\r\n\t *\r\n\t * @type {PhongMaterial}\r\n\t */\r\n\tget material() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.material\"] ||\r\n\t\t\tnew _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__.PhongMaterial(this, {\r\n\t\t\t\tid: \"default.material\",\r\n\t\t\t\temissive: [0.4, 0.4, 0.4], // Visible by default on geometry without normals\r\n\t\t\t\tdontClear: true\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the default xraying {@link EmphasisMaterial} for this Scene.\r\n\t *\r\n\t * Has {@link EmphasisMaterial#id} set to \"default.xrayMaterial\".\r\n\t *\r\n\t * {@link Mesh}s in this Scene have {@link Mesh#xrayMaterial} set to this {@link EmphasisMaterial} by default.\r\n\t *\r\n\t * {@link Mesh}s are xrayed while {@link Mesh#xrayed} is ````true````.\r\n\t *\r\n\t * @type {EmphasisMaterial}\r\n\t */\r\n\tget xrayMaterial() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.xrayMaterial\"] ||\r\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\r\n\t\t\t\tid: \"default.xrayMaterial\",\r\n\t\t\t\tpreset: \"sepia\",\r\n\t\t\t\tdontClear: true\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the default highlight {@link EmphasisMaterial} for this Scene.\r\n\t *\r\n\t * Has {@link EmphasisMaterial#id} set to \"default.highlightMaterial\".\r\n\t *\r\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\r\n\t *\r\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\r\n\t *\r\n\t * @type {EmphasisMaterial}\r\n\t */\r\n\tget highlightMaterial() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.highlightMaterial\"] ||\r\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\r\n\t\t\t\tid: \"default.highlightMaterial\",\r\n\t\t\t\tpreset: \"yellowHighlight\",\r\n\t\t\t\tfillAlpha: 0.1,\r\n\t\t\t\tfillColor: [0.7, 0.9, 0.9],\r\n\t\t\t\tdontClear: false,\r\n\t\t\t\tedges: false,\r\n\t\t\t\tglowThrough: false\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the default selection {@link EmphasisMaterial} for this Scene.\r\n\t *\r\n\t * Has {@link EmphasisMaterial#id} set to \"default.selectedMaterial\".\r\n\t *\r\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\r\n\t *\r\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\r\n\t *\r\n\t * @type {EmphasisMaterial}\r\n\t */\r\n\tget selectedMaterial() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.selectedMaterial\"] ||\r\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\r\n\t\t\t\tid: \"default.selectedMaterial\",\r\n\t\t\t\tpreset: \"greenSelected\",\r\n\t\t\t\tdontClear: true\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the default {@link EdgeMaterial} for this Scene.\r\n\t *\r\n\t * Has {@link EdgeMaterial#id} set to \"default.edgeMaterial\".\r\n\t *\r\n\t * {@link Mesh}s in this Scene have {@link Mesh#edgeMaterial} set to this {@link EdgeMaterial} by default.\r\n\t *\r\n\t * {@link Mesh}s have their edges emphasized while {@link Mesh#edges} is ````true````.\r\n\t *\r\n\t * @type {EdgeMaterial}\r\n\t */\r\n\tget edgeMaterial() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.edgeMaterial\"] ||\r\n\t\t\tnew _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__.EdgeMaterial(this, {\r\n\t\t\t\tid: \"default.edgeMaterial\",\r\n\t\t\t\tpreset: \"default\",\r\n\t\t\t\tedgeColor: [0.0, 0.0, 0.0],\r\n\t\t\t\tedgeAlpha: 1.0,\r\n\t\t\t\tedgeWidth: 1,\r\n\t\t\t\tdontClear: true\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link PointsMaterial} for this Scene.\r\n\t *\r\n\t * @type {PointsMaterial}\r\n\t */\r\n\tget pointsMaterial() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.pointsMaterial\"] ||\r\n\t\t\tnew _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__.PointsMaterial(this, {\r\n\t\t\t\tid: \"default.pointsMaterial\",\r\n\t\t\t\tpreset: \"default\",\r\n\t\t\t\tdontClear: true\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link LinesMaterial} for this Scene.\r\n\t *\r\n\t * @type {LinesMaterial}\r\n\t */\r\n\tget linesMaterial() {\r\n\t\treturn (\r\n\t\t\tthis.components[\"default.linesMaterial\"] ||\r\n\t\t\tnew _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__.LinesMaterial(this, {\r\n\t\t\t\tid: \"default.linesMaterial\",\r\n\t\t\t\tpreset: \"default\",\r\n\t\t\t\tdontClear: true\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link Viewport} for this Scene.\r\n\t *\r\n\t * @type Viewport\r\n\t */\r\n\tget viewport() {\r\n\t\treturn this._viewport;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the {@link Camera} for this Scene.\r\n\t *\r\n\t * @type {Camera}\r\n\t */\r\n\tget camera() {\r\n\t\treturn this._camera;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the World-space 3D center of this Scene.\r\n\t *\r\n\t *@type {Number[]}\r\n\t */\r\n\tget center() {\r\n\t\tif (this._aabbDirty || !this._center) {\r\n\t\t\tif (!this._center || !this._center) {\r\n\t\t\t\tthis._center = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec3();\r\n\t\t\t}\r\n\t\t\tconst aabb = this.aabb;\r\n\t\t\tthis._center[0] = (aabb[0] + aabb[3]) / 2;\r\n\t\t\tthis._center[1] = (aabb[1] + aabb[4]) / 2;\r\n\t\t\tthis._center[2] = (aabb[2] + aabb[5]) / 2;\r\n\t\t}\r\n\t\treturn this._center;\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the World-space axis-aligned 3D boundary (AABB) of this Scene.\r\n\t *\r\n\t * The AABB is represented by a six-element Float64Array containing the min/max extents of the axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\r\n\t *\r\n\t * When the Scene has no content, will be ````[-100,-100,-100,100,100,100]````.\r\n\t *\r\n\t * @type {Number[]}\r\n\t */\r\n\tget aabb() {\r\n\t\tif (this._aabbDirty) {\r\n\t\t\tif (!this._aabb) {\r\n\t\t\t\tthis._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\r\n\t\t\t}\r\n\t\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\r\n\t\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\r\n\t\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\r\n\t\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\r\n\t\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\r\n\t\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\r\n\t\t\tlet aabb;\r\n\t\t\tconst collidables = this._collidables;\r\n\t\t\tlet collidable;\r\n\t\t\tlet valid = false;\r\n\t\t\tfor (const collidableId in collidables) {\r\n\t\t\t\tif (collidables.hasOwnProperty(collidableId)) {\r\n\t\t\t\t\tcollidable = collidables[collidableId];\r\n\t\t\t\t\tif (collidable.collidable === false) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\taabb = collidable.aabb;\r\n\t\t\t\t\tif (aabb[0] < xmin) {\r\n\t\t\t\t\t\txmin = aabb[0];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (aabb[1] < ymin) {\r\n\t\t\t\t\t\tymin = aabb[1];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (aabb[2] < zmin) {\r\n\t\t\t\t\t\tzmin = aabb[2];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (aabb[3] > xmax) {\r\n\t\t\t\t\t\txmax = aabb[3];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (aabb[4] > ymax) {\r\n\t\t\t\t\t\tymax = aabb[4];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (aabb[5] > zmax) {\r\n\t\t\t\t\t\tzmax = aabb[5];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tvalid = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!valid) {\r\n\t\t\t\txmin = -100;\r\n\t\t\t\tymin = -100;\r\n\t\t\t\tzmin = -100;\r\n\t\t\t\txmax = 100;\r\n\t\t\t\tymax = 100;\r\n\t\t\t\tzmax = 100;\r\n\t\t\t}\r\n\t\t\tthis._aabb[0] = xmin;\r\n\t\t\tthis._aabb[1] = ymin;\r\n\t\t\tthis._aabb[2] = zmin;\r\n\t\t\tthis._aabb[3] = xmax;\r\n\t\t\tthis._aabb[4] = ymax;\r\n\t\t\tthis._aabb[5] = zmax;\r\n\t\t\tthis._aabbDirty = false;\r\n\t\t}\r\n\t\treturn this._aabb;\r\n\t}\r\n\r\n\t_setAABBDirty() {\r\n\t\t//if (!this._aabbDirty) {\r\n\t\tthis._aabbDirty = true;\r\n\t\tthis.fire(\"boundary\");\r\n\t\t// }\r\n\t}\r\n\r\n\t/**\r\n * Attempts to pick an {@link Entity} in this Scene.\r\n *\r\n * Ignores {@link Entity}s with {@link Entity#pickable} set ````false````.\r\n *\r\n * When an {@link Entity} is picked, fires a \"pick\" event on the {@link Entity} with the pick result as parameters.\r\n *\r\n * Picking the {@link Entity} at the given canvas coordinates:\r\n\r\n * ````javascript\r\n * var pickResult = scene.pick({\r\n * canvasPos: [23, 131]\r\n * });\r\n *\r\n * if (pickResult) { // Picked an Entity\r\n * var entity = pickResult.entity;\r\n * }\r\n * ````\r\n *\r\n * Picking, with a ray cast through the canvas, hits an {@link Entity}:\r\n *\r\n * ````javascript\r\n * var pickResult = scene.pick({\r\n * pickSurface: true,\r\n * canvasPos: [23, 131]\r\n * });\r\n *\r\n * if (pickResult) { // Picked an Entity\r\n *\r\n * var entity = pickResult.entity;\r\n *\r\n * if (pickResult.primitive === \"triangle\") {\r\n *\r\n * // Picked a triangle on the entity surface\r\n *\r\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\r\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\r\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\r\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\r\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\r\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\r\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\r\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\r\n *\r\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\r\n *\r\n * // Picked a point and normal on the entity surface\r\n *\r\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\r\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\r\n * }\r\n * }\r\n * ````\r\n *\r\n * Picking the {@link Entity} that intersects an arbitrarily-aligned World-space ray:\r\n *\r\n * ````javascript\r\n * var pickResult = scene.pick({\r\n * pickSurface: true, // Picking with arbitrarily-positioned ray\r\n * origin: [0,0,-5], // Ray origin\r\n * direction: [0,0,1] // Ray direction\r\n * });\r\n *\r\n * if (pickResult) { // Picked an Entity with the ray\r\n *\r\n * var entity = pickResult.entity;\r\n *\r\n * if (pickResult.primitive == \"triangle\") {\r\n *\r\n * // Picked a triangle on the entity surface\r\n *\r\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\r\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\r\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\r\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\r\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\r\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\r\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\r\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\r\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\r\n * var origin = pickResult.origin; // Float64Array containing the World-space ray origin\r\n * var direction = pickResult.direction; // Float64Array containing the World-space ray direction\r\n *\r\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\r\n *\r\n * // Picked a point and normal on the entity surface\r\n *\r\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\r\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\r\n * }\r\n * }\r\n * ````\r\n *\r\n * @param {*} params Picking parameters.\r\n * @param {Boolean} [params.pickSurface=false] Whether to find the picked position on the surface of the Entity.\r\n * @param {Boolean} [params.pickSurfacePrecision=false] When picking an Entity surface position, indicates whether or not we want full-precision {@link PickResult#worldPos}. Only works when {@link Scene#pickSurfacePrecisionEnabled} is ````true````. If pick succeeds, the returned {@link PickResult} will have {@link PickResult#precision} set ````true````, to indicate that it contains full-precision surface pick results.\r\n * @param {Boolean} [params.pickSurfaceNormal=false] Whether to find the picked normal on the surface of the Entity. Only works if ````pickSurface```` is given.\r\n * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\r\n * @param {Number[]} [params.origin] World-space ray origin when ray-picking. Ignored when canvasPos given.\r\n * @param {Number[]} [params.direction] World-space ray direction when ray-picking. Also indicates the length of the ray. Ignored when canvasPos given.\r\n * @param {Number[]} [params.matrix] 4x4 transformation matrix to define the World-space ray origin and direction, as an alternative to ````origin```` and ````direction````.\r\n * @param {String[]} [params.includeEntities] IDs of {@link Entity}s to restrict picking to. When given, ignores {@link Entity}s whose IDs are not in this list.\r\n * @param {String[]} [params.excludeEntities] IDs of {@link Entity}s to ignore. When given, will pick *through* these {@link Entity}s, as if they were not there.\r\n * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\r\n * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\r\n * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\r\n * @param {PickResult} [pickResult] Holds the results of the pick attempt. Will use the Scene's singleton PickResult if you don't supply your own.\r\n * @returns {PickResult} Holds results of the pick attempt, returned when an {@link Entity} is picked, else null. See method comments for description.\r\n */\r\n\tpick(params, pickResult) {\r\n\t\tif (this.canvas.boundary[2] === 0 || this.canvas.boundary[3] === 0) {\r\n\t\t\tthis.error(\"Picking not allowed while canvas has zero width or height\");\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tparams = params || {};\r\n\r\n\t\tparams.pickSurface = params.pickSurface || params.rayPick; // Backwards compatibility\r\n\r\n\t\tif (!params.canvasPos && !params.matrix && (!params.origin || !params.direction)) {\r\n\t\t\tthis.warn(\"picking without canvasPos, matrix, or ray origin and direction\");\r\n\t\t}\r\n\r\n\t\tconst includeEntities = params.includeEntities || params.include; // Backwards compat\r\n\t\tif (includeEntities) {\r\n\t\t\tparams.includeEntityIds = getEntityIDMap(this, includeEntities);\r\n\t\t}\r\n\r\n\t\tconst excludeEntities = params.excludeEntities || params.exclude; // Backwards compat\r\n\t\tif (excludeEntities) {\r\n\t\t\tparams.excludeEntityIds = getEntityIDMap(this, excludeEntities);\r\n\t\t}\r\n\r\n\t\tif (this._needRecompile) {\r\n\t\t\tthis._recompile();\r\n\t\t\tthis._renderer.imageDirty();\r\n\t\t\tthis._needRecompile = false;\r\n\t\t}\r\n\r\n\t\tif (params.snapToEdge || params.snapToVertex) {\r\n\t\t\tpickResult = this._renderer.snapPick(\r\n\t\t\t\tparams.canvasPos,\r\n\t\t\t\tparams.snapRadius || 30,\r\n\t\t\t\tparams.snapToVertex,\r\n\t\t\t\tparams.snapToEdge,\r\n\t\t\t\tpickResult\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\tpickResult = this._renderer.pick(params, pickResult);\r\n\t\t}\r\n\r\n\t\tif (pickResult) {\r\n\t\t\tif (pickResult.entity && pickResult.entity.fire) {\r\n\t\t\t\tpickResult.entity.fire(\"picked\", pickResult); // TODO: SceneModelEntity doesn't fire events\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn pickResult;\r\n\t}\r\n\r\n\t/**\r\n\t * @param {Object} params Picking parameters.\r\n\t * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\r\n\t * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\r\n\t * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\r\n\t * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\r\n\t * @deprecated\r\n\t */\r\n\tsnapPick(params) {\r\n\t\tif (undefined === this._warnSnapPickDeprecated) {\r\n\t\t\tthis._warnSnapPickDeprecated = true;\r\n\t\t\tthis.warn(\"Scene.snapPick() is deprecated since v2.4.2 - use Scene.pick() instead\");\r\n\t\t}\r\n\t\treturn this._renderer.snapPick(params.canvasPos, params.snapRadius || 30, params.snapToVertex, params.snapToEdge);\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys all non-default {@link Component}s in this Scene.\r\n\t */\r\n\tclear() {\r\n\t\tvar component;\r\n\t\tfor (const id in this.components) {\r\n\t\t\tif (this.components.hasOwnProperty(id)) {\r\n\t\t\t\tcomponent = this.components[id];\r\n\t\t\t\tif (!component._dontClear) {\r\n\t\t\t\t\t// Don't destroy components like Camera, Input, Viewport etc.\r\n\t\t\t\t\tcomponent.destroy();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys all {@link Light}s in this Scene..\r\n\t */\r\n\tclearLights() {\r\n\t\tconst ids = Object.keys(this.lights);\r\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\r\n\t\t\tthis.lights[ids[i]].destroy();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys all {@link SectionPlane}s in this Scene.\r\n\t */\r\n\tclearSectionPlanes() {\r\n\t\tconst ids = Object.keys(this.sectionPlanes);\r\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\r\n\t\t\tthis.sectionPlanes[ids[i]].destroy();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys all {@link Line}s in this Scene.\r\n\t */\r\n\tclearBitmaps() {\r\n\t\tconst ids = Object.keys(this.bitmaps);\r\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\r\n\t\t\tthis.bitmaps[ids[i]].destroy();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys all {@link Line}s in this Scene.\r\n\t */\r\n\tclearLines() {\r\n\t\tconst ids = Object.keys(this.lineSets);\r\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\r\n\t\t\tthis.lineSets[ids[i]].destroy();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the collective axis-aligned boundary (AABB) of a batch of {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * Each {@link Entity} on which {@link Entity#isObject} is registered by {@link Entity#id} in {@link Scene#visibleObjects}.\r\n\t *\r\n\t * Each {@link Entity} is only included in the AABB when {@link Entity#collidable} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @returns {[Number, Number, Number, Number, Number, Number]} An axis-aligned World-space bounding box, given as elements ````[xmin, ymin, zmin, xmax, ymax, zmax]````.\r\n\t */\r\n\tgetAABB(ids) {\r\n\t\tif (ids === undefined) {\r\n\t\t\treturn this.aabb;\r\n\t\t}\r\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\r\n\t\t\tconst entity = this.objects[ids];\r\n\t\t\tif (entity && entity.aabb) {\r\n\t\t\t\t// A Component subclass with an AABB\r\n\t\t\t\treturn entity.aabb;\r\n\t\t\t}\r\n\t\t\tids = [ids]; // Must be an entity type\r\n\t\t}\r\n\t\tif (ids.length === 0) {\r\n\t\t\treturn this.aabb;\r\n\t\t}\r\n\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\r\n\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\r\n\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\r\n\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\r\n\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\r\n\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\r\n\t\tlet valid;\r\n\t\tthis.withObjects(ids, (entity) => {\r\n\t\t\tif (entity.collidable) {\r\n\t\t\t\tconst aabb = entity.aabb;\r\n\t\t\t\tif (aabb[0] < xmin) {\r\n\t\t\t\t\txmin = aabb[0];\r\n\t\t\t\t}\r\n\t\t\t\tif (aabb[1] < ymin) {\r\n\t\t\t\t\tymin = aabb[1];\r\n\t\t\t\t}\r\n\t\t\t\tif (aabb[2] < zmin) {\r\n\t\t\t\t\tzmin = aabb[2];\r\n\t\t\t\t}\r\n\t\t\t\tif (aabb[3] > xmax) {\r\n\t\t\t\t\txmax = aabb[3];\r\n\t\t\t\t}\r\n\t\t\t\tif (aabb[4] > ymax) {\r\n\t\t\t\t\tymax = aabb[4];\r\n\t\t\t\t}\r\n\t\t\t\tif (aabb[5] > zmax) {\r\n\t\t\t\t\tzmax = aabb[5];\r\n\t\t\t\t}\r\n\t\t\t\tvalid = true;\r\n\t\t\t}\r\n\t\t});\r\n\t\tif (valid) {\r\n\t\t\tconst aabb2 = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\r\n\t\t\taabb2[0] = xmin;\r\n\t\t\taabb2[1] = ymin;\r\n\t\t\taabb2[2] = zmin;\r\n\t\t\taabb2[3] = xmax;\r\n\t\t\taabb2[4] = ymax;\r\n\t\t\taabb2[5] = zmax;\r\n\t\t\treturn aabb2;\r\n\t\t} else {\r\n\t\t\treturn this.aabb; // Scene AABB\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#visible} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#visible} are ````true```` is\r\n\t * registered by {@link Entity#id} in {@link Scene#visibleObjects}.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} visible Whether or not to set visible.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsVisible(ids, visible) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.visible !== visible;\r\n\t\t\tentity.visible = visible;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#collidable} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} collidable Whether or not to set collidable.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsCollidable(ids, collidable) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.collidable !== collidable;\r\n\t\t\tentity.collidable = collidable;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#culled} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} culled Whether or not to cull.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsCulled(ids, culled) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.culled !== culled;\r\n\t\t\tentity.culled = culled;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#selected} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#selected} are ````true```` is\r\n\t * registered by {@link Entity#id} in {@link Scene#selectedObjects}.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} selected Whether or not to select.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsSelected(ids, selected) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.selected !== selected;\r\n\t\t\tentity.selected = selected;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#highlighted} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#highlighted} are ````true```` is\r\n\t * registered by {@link Entity#id} in {@link Scene#highlightedObjects}.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} highlighted Whether or not to highlight.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsHighlighted(ids, highlighted) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.highlighted !== highlighted;\r\n\t\t\tentity.highlighted = highlighted;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#xrayed} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} xrayed Whether or not to xray.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsXRayed(ids, xrayed) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.xrayed !== xrayed;\r\n\t\t\tentity.xrayed = xrayed;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#edges} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} edges Whether or not to show edges.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsEdges(ids, edges) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.edges !== edges;\r\n\t\t\tentity.edges = edges;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#colorize} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Number[]} [colorize=(1,1,1)] RGB colorize factors, multiplied by the rendered pixel colors.\r\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsColorized(ids, colorize) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tentity.colorize = colorize;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#opacity} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Number} [opacity=1.0] Opacity factor, multiplied by the rendered pixel alphas.\r\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsOpacity(ids, opacity) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.opacity !== opacity;\r\n\t\t\tentity.opacity = opacity;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#pickable} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Boolean} pickable Whether or not to set pickable.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\tsetObjectsPickable(ids, pickable) {\r\n\t\treturn this.withObjects(ids, (entity) => {\r\n\t\t\tconst changed = entity.pickable !== pickable;\r\n\t\t\tentity.pickable = pickable;\r\n\t\t\treturn changed;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Batch-updates {@link Entity#offset} on {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Number[]} [offset] 3D offset vector.\r\n\t */\r\n\tsetObjectsOffset(ids, offset) {\r\n\t\tthis.withObjects(ids, (entity) => {\r\n\t\t\tentity.offset = offset;\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Iterates with a callback over {@link Entity}s that represent objects.\r\n\t *\r\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\r\n\t *\r\n\t * @param {String[]} ids Array of {@link Entity#id} values.\r\n\t * @param {Function} callback Callback to execute on eacn {@link Entity}.\r\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\r\n\t */\r\n\twithObjects(ids, callback) {\r\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\r\n\t\t\tids = [ids];\r\n\t\t}\r\n\t\tlet changed = false;\r\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\r\n\t\t\tconst id = ids[i];\r\n\t\t\tlet entity = this.objects[id];\r\n\t\t\tif (entity) {\r\n\t\t\t\tchanged = callback(entity) || changed;\r\n\t\t\t} else {\r\n\t\t\t\tconst modelIds = this.modelIds;\r\n\t\t\t\tfor (let i = 0, len = modelIds.length; i < len; i++) {\r\n\t\t\t\t\tconst modelId = modelIds[i];\r\n\t\t\t\t\tconst globalObjectId = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.globalizeObjectId(modelId, id);\r\n\t\t\t\t\tentity = this.objects[globalObjectId];\r\n\t\t\t\t\tif (entity) {\r\n\t\t\t\t\t\tchanged = callback(entity) || changed;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn changed;\r\n\t}\r\n\r\n\t/**\r\n\t * This method will \"tickify\" the provided `cb` function.\r\n\t *\r\n\t * This means, the function will be wrapped so:\r\n\t *\r\n\t * - it runs time-aligned to scene ticks\r\n\t * - it runs maximum once per scene-tick\r\n\t *\r\n\t * @param {Function} cb The function to tickify\r\n\t * @returns {Function}\r\n\t */\r\n\ttickify(cb) {\r\n\t\tconst cbString = cb.toString();\r\n\r\n\t\t/**\r\n\t\t * Check if the function is already tickified, and if so return the cached one.\r\n\t\t */\r\n\t\tif (cbString in this._tickifiedFunctions) {\r\n\t\t\treturn this._tickifiedFunctions[cbString].wrapperFunc;\r\n\t\t}\r\n\r\n\t\tlet alreadyRun = 0;\r\n\t\tlet needToRun = 0;\r\n\r\n\t\tlet lastArgs;\r\n\r\n\t\t/**\r\n\t\t * The provided `cb` function is replaced with a \"set-dirty\" function\r\n\t\t *\r\n\t\t * @type {Function}\r\n\t\t */\r\n\t\tconst wrapperFunc = function (...args) {\r\n\t\t\tlastArgs = args;\r\n\t\t\tneedToRun++;\r\n\t\t};\r\n\r\n\t\t/**\r\n\t\t * An each scene tick, if the \"dirty-flag\" is set, run the `cb` function.\r\n\t\t *\r\n\t\t * This will make it run time-aligned to the scene tick.\r\n\t\t */\r\n\t\tconst tickSubId = this.on(\"tick\", () => {\r\n\t\t\tconst tmp = needToRun;\r\n\t\t\tif (tmp > alreadyRun) {\r\n\t\t\t\talreadyRun = tmp;\r\n\t\t\t\tcb(...lastArgs);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\t/**\r\n\t\t * And, store the list of subscribers.\r\n\t\t */\r\n\t\tthis._tickifiedFunctions[cbString] = { tickSubId, wrapperFunc };\r\n\r\n\t\treturn wrapperFunc;\r\n\t}\r\n\r\n\t/**\r\n\t * Destroys this Scene.\r\n\t */\r\n\tdestroy(callback) {\r\n\t\tsuper.destroy();\r\n\t\tfor (const id in this.components) {\r\n\t\t\tif (this.components.hasOwnProperty(id)) {\r\n\t\t\t\tthis.components[id].destroy();\r\n\t\t\t}\r\n\t\t}\r\n\t\t// this.canvas.destroy(); // canvas是scene的其中一个component,所有以不必再destroy\r\n\r\n\t\t// Memory leak prevention\r\n\t\tthis.components = null;\r\n\t\tthis.models = null;\r\n\t\tthis.objects = null;\r\n\t\tthis.visibleObjects = null;\r\n\t\tthis.xrayedObjects = null;\r\n\t\tthis.highlightedObjects = null;\r\n\t\tthis.selectedObjects = null;\r\n\t\tthis.colorizedObjects = null;\r\n\t\tthis.opacityObjects = null;\r\n\t\tthis.sectionPlanes = null;\r\n\t\tthis.lights = null;\r\n\t\tthis.lightMaps = null;\r\n\t\tthis.reflectionMaps = null;\r\n\t\tthis._objectIds = null;\r\n\t\tthis._visibleObjectIds = null;\r\n\t\tthis._xrayedObjectIds = null;\r\n\t\tthis._highlightedObjectIds = null;\r\n\t\tthis._selectedObjectIds = null;\r\n\t\tthis._colorizedObjectIds = null;\r\n\t\tthis.types = null;\r\n\t\tthis._renderer = null;\r\n\t\tthis.input = null;\r\n\t\tthis._viewport = null;\r\n\t\tthis._camera = null;\r\n\t\tthis.canvas = null;\r\n\t\tif (typeof callback === \"function\") {\r\n\t\t\tcallback();\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/scene/Scene.js?");
|
|
4807
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Scene: () => (/* binding */ Scene)\n/* harmony export */ });\n/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../core.js */ \"./src/viewer/scene/core.js\");\n/* harmony import */ var _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../lod/LOD.js */ \"./src/viewer/scene/lod/LOD.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils.js */ \"./src/viewer/scene/utils.js\");\n/* harmony import */ var _math_math_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../math/math.js */ \"./src/viewer/scene/math/math.js\");\n/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Component.js */ \"./src/viewer/scene/Component.js\");\n/* harmony import */ var _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../canvas/Canvas.js */ \"./src/viewer/scene/canvas/Canvas.js\");\n/* harmony import */ var _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../webgl/Renderer.js */ \"./src/viewer/scene/webgl/Renderer.js\");\n/* harmony import */ var _input_Input_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../input/Input.js */ \"./src/viewer/scene/input/Input.js\");\n/* harmony import */ var _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../viewport/Viewport.js */ \"./src/viewer/scene/viewport/Viewport.js\");\n/* harmony import */ var _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../camera/Camera.js */ \"./src/viewer/scene/camera/Camera.js\");\n/* harmony import */ var _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../lights/DirLight.js */ \"./src/viewer/scene/lights/DirLight.js\");\n/* harmony import */ var _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../lights/AmbientLight.js */ \"./src/viewer/scene/lights/AmbientLight.js\");\n/* harmony import */ var _geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../geometry/ReadableGeometry.js */ \"./src/viewer/scene/geometry/ReadableGeometry.js\");\n/* harmony import */ var _geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../geometry/builders/buildBoxGeometry.js */ \"./src/viewer/scene/geometry/builders/buildBoxGeometry.js\");\n/* harmony import */ var _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../materials/PhongMaterial.js */ \"./src/viewer/scene/materials/PhongMaterial.js\");\n/* harmony import */ var _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../materials/EmphasisMaterial.js */ \"./src/viewer/scene/materials/EmphasisMaterial.js\");\n/* harmony import */ var _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../materials/EdgeMaterial.js */ \"./src/viewer/scene/materials/EdgeMaterial.js\");\n/* harmony import */ var _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../metriqs/Metriqs.js */ \"./src/viewer/scene/metriqs/Metriqs.js\");\n/* harmony import */ var _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../postfx/SAO.js */ \"./src/viewer/scene/postfx/SAO.js\");\n/* harmony import */ var _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../materials/PointsMaterial.js */ \"./src/viewer/scene/materials/PointsMaterial.js\");\n/* harmony import */ var _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../materials/LinesMaterial.js */ \"./src/viewer/scene/materials/LinesMaterial.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// Enables runtime check for redundant calls to object state update methods, eg. Scene#_objectVisibilityUpdated\nconst ASSERT_OBJECT_STATE_UPDATE = false;\n\n// Cached vars to avoid garbage collection\n\nfunction getEntityIDMap(scene, entityIds) {\n\tconst map = {};\n\tlet entityId;\n\tlet entity;\n\tfor (let i = 0, len = entityIds.length; i < len; i++) {\n\t\tentityId = entityIds[i];\n\t\tentity = scene.components[entityId];\n\t\tif (!entity) {\n\t\t\tscene.warn(\"pick(): Component not found: \" + entityId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!entity.isEntity) {\n\t\t\tscene.warn(\"pick(): Component is not an Entity: \" + entityId);\n\t\t\tcontinue;\n\t\t}\n\t\tmap[entityId] = true;\n\t}\n\treturn map;\n}\n\n/**\n * Fired whenever a debug message is logged on a component within this Scene.\n * @event log\n * @param {String} value The debug message\n */\n\n/**\n * Fired whenever an error is logged on a component within this Scene.\n * @event error\n * @param {String} value The error message\n */\n\n/**\n * Fired whenever a warning is logged on a component within this Scene.\n * @event warn\n * @param {String} value The warning message\n */\n\n/**\n * @desc Contains the components that comprise a 3D scene.\n *\n * * A {@link Viewer} has a single Scene, which it provides in {@link Viewer#scene}.\n * * Plugins like {@link AxisGizmoPlugin} also have their own private Scenes.\n * * Each Scene has a corresponding {@link MetaScene}, which the Viewer provides in {@link Viewer#metaScene}.\n *\n * ## Getting a Viewer's Scene\n *\n * ````javascript\n * var scene = viewer.scene;\n * ````\n *\n * ## Creating and accessing Scene components\n *\n * As a brief introduction to creating Scene components, we'll create a {@link Mesh} that has a\n * {@link buildTorusGeometry} and a {@link PhongMaterial}:\n *\n * ````javascript\n * var teapotMesh = new Mesh(scene, {\n * id: \"myMesh\", // <<---------- ID automatically generated if not provided\n * geometry: new TorusGeometry(scene),\n * material: new PhongMaterial(scene, {\n * id: \"myMaterial\",\n * diffuse: [0.2, 0.2, 1.0]\n * })\n * });\n *\n * teapotMesh.scene.camera.eye = [45, 45, 45];\n * ````\n *\n * Find components by ID in their Scene's {@link Scene#components} map:\n *\n * ````javascript\n * var teapotMesh = scene.components[\"myMesh\"];\n * teapotMesh.visible = false;\n *\n * var teapotMaterial = scene.components[\"myMaterial\"];\n * teapotMaterial.diffuse = [1,0,0]; // Change to red\n * ````\n *\n * A Scene also has a map of component instances for each {@link Component} subtype:\n *\n * ````javascript\n * var meshes = scene.types[\"Mesh\"];\n * var teapotMesh = meshes[\"myMesh\"];\n * teapotMesh.xrayed = true;\n *\n * var phongMaterials = scene.types[\"PhongMaterial\"];\n * var teapotMaterial = phongMaterials[\"myMaterial\"];\n * teapotMaterial.diffuse = [0,1,0]; // Change to green\n * ````\n *\n * See {@link Node}, {@link Node} and {@link Model} for how to create and access more sophisticated content.\n *\n * ## Controlling the camera\n *\n * Use the Scene's {@link Camera} to control the current viewpoint and projection:\n *\n * ````javascript\n * var camera = myScene.camera;\n *\n * camera.eye = [-10,0,0];\n * camera.look = [-10,0,0];\n * camera.up = [0,1,0];\n *\n * camera.projection = \"perspective\";\n * camera.perspective.fov = 45;\n * //...\n * ````\n *\n * ## Managing the canvas\n *\n * The Scene's {@link Canvas} component provides various conveniences relevant to the WebGL canvas, such\n * as firing resize events etc:\n *\n * ````javascript\n * var canvas = scene.canvas;\n *\n * canvas.on(\"boundary\", function(boundary) {\n * //...\n * });\n * ````\n *\n * ## Picking\n *\n * Use {@link Scene#pick} to pick and raycast entites.\n *\n * For example, to pick a point on the surface of the closest entity at the given canvas coordinates:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true,\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an entity\n *\n * var entity = pickResult.entity;\n *\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Mesh's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult. ; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var normal = pickResult.normal; // Float64Array containing the interpolated normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n * }\n * ````\n *\n * ## Pick masking\n *\n * We can use {@link Scene#pick}'s ````includeEntities```` and ````excludeEntities```` options to mask which {@link Mesh}es we attempt to pick.\n *\n * This is useful for picking through things, to pick only the Entities of interest.\n *\n * To pick only Entities ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through any other Entities that are\n * in the way, as if they weren't there:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131],\n * includeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\n * });\n *\n * if (pickResult) {\n * // Entity will always be either \"gearbox#77.0\" or \"gearbox#79.0\"\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * To pick any pickable Entity, except for ````\"gearbox#77.0\"```` and ````\"gearbox#79.0\"````, picking through those\n * Entities if they happen to be in the way:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131],\n * excludeEntities: [\"gearbox#77.0\", \"gearbox#79.0\"]\n * });\n *\n * if (pickResult) {\n * // Entity will never be \"gearbox#77.0\" or \"gearbox#79.0\"\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * See {@link Scene#pick} for more info on picking.\n *\n * ## Querying and tracking boundaries\n *\n * Getting a Scene's World-space axis-aligned boundary (AABB):\n *\n * ````javascript\n * var aabb = scene.aabb; // [xmin, ymin, zmin, xmax, ymax, zmax]\n * ````\n *\n * Subscribing to updates to the AABB, which occur whenever {@link Entity}s are transformed, their\n * {@link ReadableGeometry}s have been updated, or the {@link Camera} has moved:\n *\n * ````javascript\n * scene.on(\"boundary\", function() {\n * var aabb = scene.aabb;\n * });\n * ````\n *\n * Getting the AABB of the {@link Entity}s with the given IDs:\n *\n * ````JavaScript\n * scene.getAABB(); // Gets collective boundary of all Entities in the scene\n * scene.getAABB(\"saw\"); // Gets boundary of an Object\n * scene.getAABB([\"saw\", \"gearbox\"]); // Gets collective boundary of two Objects\n * ````\n *\n * See {@link Scene#getAABB} and {@link Entity} for more info on querying and tracking boundaries.\n *\n * ## Managing the viewport\n *\n * The Scene's {@link Viewport} component manages the WebGL viewport:\n *\n * ````javascript\n * var viewport = scene.viewport\n * viewport.boundary = [0, 0, 500, 400];;\n * ````\n *\n * ## Controlling rendering\n *\n * You can configure a Scene to perform multiple \"passes\" (renders) per frame. This is useful when we want to render the\n * scene to multiple viewports, such as for stereo effects.\n *\n * In the example, below, we'll configure the Scene to render twice on each frame, each time to different viewport. We'll do this\n * with a callback that intercepts the Scene before each render and sets its {@link Viewport} to a\n * different portion of the canvas. By default, the Scene will clear the canvas only before the first render, allowing the\n * two views to be shown on the canvas at the same time.\n *\n * ````Javascript\n * var viewport = scene.viewport;\n *\n * // Configure Scene to render twice for each frame\n * scene.passes = 2; // Default is 1\n * scene.clearEachPass = false; // Default is false\n *\n * // Render to a separate viewport on each render\n *\n * var viewport = scene.viewport;\n * viewport.autoBoundary = false;\n *\n * scene.on(\"rendering\", function (e) {\n * switch (e.pass) {\n * case 0:\n * viewport.boundary = [0, 0, 200, 200]; // xmin, ymin, width, height\n * break;\n *\n * case 1:\n * viewport.boundary = [200, 0, 200, 200];\n * break;\n * }\n * });\n *\n * // We can also intercept the Scene after each render,\n * // (though we're not using this for anything here)\n * scene.on(\"rendered\", function (e) {\n * switch (e.pass) {\n * case 0:\n * break;\n *\n * case 1:\n * break;\n * }\n * });\n * ````\n *\n * ## Gamma correction\n *\n * Within its shaders, xeokit performs shading calculations in linear space.\n *\n * By default, the Scene expects color textures (eg. {@link PhongMaterial#diffuseMap},\n * {@link MetallicMaterial#baseColorMap} and {@link SpecularMaterial#diffuseMap}) to\n * be in pre-multipled gamma space, so will convert those to linear space before they are used in shaders. Other textures are\n * always expected to be in linear space.\n *\n * By default, the Scene will also gamma-correct its rendered output.\n *\n * You can configure the Scene to expect all those color textures to be linear space, so that it does not gamma-correct them:\n *\n * ````javascript\n * scene.gammaInput = false;\n * ````\n *\n * You would still need to gamma-correct the output, though, if it's going straight to the canvas, so normally we would\n * leave that enabled:\n *\n * ````javascript\n * scene.gammaOutput = true;\n * ````\n *\n * See {@link Texture} for more information on texture encoding and gamma.\n *\n * @class Scene\n */\nclass Scene extends _Component_js__WEBPACK_IMPORTED_MODULE_4__.Component {\n\t/**\n @private\n */\n\tget type() {\n\t\treturn \"Scene\";\n\t}\n\n\t/**\n\t * @private\n\t * @constructor\n\t * @param {Viewer} viewer The Viewer this Scene belongs to.\n\t * @param {Object} cfg Scene configuration.\n\t * @param {String} [cfg.canvasId] ID of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasElement is mandatory. When both values are given, the element reference is always preferred to the ID.\n\t * @param {HTMLCanvasElement} [cfg.canvasElement] Reference of an existing HTML canvas for the {@link Scene#canvas} - either this or canvasId is mandatory. When both values are given, the element reference is always preferred to the ID.\n\t * @param {HTMLElement} [cfg.keyboardEventsElement] Optional reference to HTML element on which key events should be handled. Defaults to the HTML Document.\n\t * @param {number} [cfg.numCachedSectionPlanes=0] Enhances the efficiency of SectionPlane creation by proactively allocating Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane imposes rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t * @throws {String} Throws an exception when both canvasId or canvasElement are missing or they aren't pointing to a valid HTMLCanvasElement.\n\t */\n\tconstructor(viewer, cfg = {}) {\n\t\tsuper(null, cfg);\n\n\t\tconst canvas = cfg.canvasElement || document.getElementById(cfg.canvasId);\n\n\t\tif (!(canvas instanceof HTMLCanvasElement)) {\n\t\t\tthrow \"Mandatory config expected: valid canvasId or canvasElement\";\n\t\t}\n\n\t\t/**\n\t\t * @type {{[key: string]: {wrapperFunc: Function, tickSubId: string}}}\n\t\t */\n\t\tthis._tickifiedFunctions = {};\n\n\t\tthis._transparent = !!cfg.transparent;\n\t\tconst alphaDepthMask = !!cfg.alphaDepthMask;\n\t\tthis._edgesEnabled = !!cfg.edgesEnabled;\n\n\t\tthis._aabbDirty = true;\n\n\t\t/**\n\t\t * The {@link Viewer} this Scene belongs to.\n\t\t * @type {Viewer}\n\t\t */\n\t\tthis.viewer = viewer;\n\n\t\t/** Decremented each frame, triggers occlusion test for occludable {@link Marker}s when zero.\n\t\t * @private\n\t\t * @type {number}\n\t\t */\n\t\tthis.occlusionTestCountdown = 0;\n\n\t\t/**\n The number of models currently loading.\n\n @property loading\n @final\n @type {Number}\n */\n\t\tthis.loading = 0;\n\n\t\t/**\n The epoch time (in milliseconds since 1970) when this Scene was instantiated.\n\n @property timeCreated\n @final\n @type {Number}\n */\n\t\tthis.startTime = new Date().getTime();\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represent models.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isModel} is ````true````.\n\t\t *\n\t\t * @property models\n\t\t * @final\n\t\t * @type {{String:Entity}}\n\t\t */\n\t\tthis.models = {};\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represents objects.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id} when {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * @property objects\n\t\t * @final\n\t\t * @type {{String:Entity}}\n\t\t */\n\t\tthis.objects = {};\n\t\tthis._numObjects = 0;\n\n\t\t/**\n\t\t * Map of currently visible {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is visible when {@link Entity#visible} is true.\n\t\t *\n\t\t * @property visibleObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.visibleObjects = {};\n\t\tthis._numVisibleObjects = 0;\n\n\t\t/**\n\t\t * Map of currently xrayed {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````, and is xrayed when {@link Entity#xrayed} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property xrayedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.xrayedObjects = {};\n\t\tthis._numXRayedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently highlighted {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true```` is true, and is highlighted when {@link Entity#highlighted} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property highlightedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.highlightedObjects = {};\n\t\tthis._numHighlightedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently selected {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is true, and is selected while {@link Entity#selected} is true.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property selectedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.selectedObjects = {};\n\t\tthis._numSelectedObjects = 0;\n\n\t\t/**\n\t\t * Map of currently colorized {@link Entity}s that represent objects.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property colorizedObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.colorizedObjects = {};\n\t\tthis._numColorizedObjects = 0;\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represent objects whose opacity was updated.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property opacityObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.opacityObjects = {};\n\t\tthis._numOpacityObjects = 0;\n\n\t\t/**\n\t\t * Map of {@link Entity}s that represent objects whose {@link Entity#offset}s were updated.\n\t\t *\n\t\t * An Entity represents an object if {@link Entity#isObject} is ````true````.\n\t\t *\n\t\t * Each {@link Entity} is mapped here by {@link Entity#id}.\n\t\t *\n\t\t * @property offsetObjects\n\t\t * @final\n\t\t * @type {{String:Object}}\n\t\t */\n\t\tthis.offsetObjects = {};\n\t\tthis._numOffsetObjects = 0;\n\n\t\t// Cached ID arrays, lazy-rebuilt as needed when stale after map updates\n\n\t\t/**\n Lazy-regenerated ID lists.\n */\n\t\tthis._modelIds = null;\n\t\tthis._objectIds = null;\n\t\tthis._visibleObjectIds = null;\n\t\tthis._xrayedObjectIds = null;\n\t\tthis._highlightedObjectIds = null;\n\t\tthis._selectedObjectIds = null;\n\t\tthis._colorizedObjectIds = null;\n\t\tthis._opacityObjectIds = null;\n\t\tthis._offsetObjectIds = null;\n\n\t\tthis._collidables = {}; // Components that contribute to the Scene AABB\n\t\tthis._compilables = {}; // Components that require shader compilation\n\n\t\tthis._needRecompile = false;\n\n\t\t/**\n\t\t * For each {@link Component} type, a map of IDs to {@link Component} instances of that type.\n\t\t *\n\t\t * @type {{String:{String:Component}}}\n\t\t */\n\t\tthis.types = {};\n\n\t\t/**\n\t\t * The {@link Component}s within this Scene, each mapped to its {@link Component#id}.\n\t\t *\n\t\t * *@type {{String:Component}}\n\t\t */\n\t\tthis.components = {};\n\n\t\t/**\n\t\t * The {@link SectionPlane}s in this Scene, each mapped to its {@link SectionPlane#id}.\n\t\t *\n\t\t * @type {{String:SectionPlane}}\n\t\t */\n\t\tthis.sectionPlanes = {};\n\n\t\t/**\n\t\t * The {@link Light}s in this Scene, each mapped to its {@link Light#id}.\n\t\t *\n\t\t * @type {{String:Light}}\n\t\t */\n\t\tthis.lights = {};\n\n\t\t/**\n\t\t * The {@link LightMap}s in this Scene, each mapped to its {@link LightMap#id}.\n\t\t *\n\t\t * @type {{String:LightMap}}\n\t\t */\n\t\tthis.lightMaps = {};\n\n\t\t/**\n\t\t * The {@link ReflectionMap}s in this Scene, each mapped to its {@link ReflectionMap#id}.\n\t\t *\n\t\t * @type {{String:ReflectionMap}}\n\t\t */\n\t\tthis.reflectionMaps = {};\n\n\t\t/**\n\t\t * The {@link Bitmap}s in this Scene, each mapped to its {@link Bitmap#id}.\n\t\t *\n\t\t * @type {{String:Bitmap}}\n\t\t */\n\t\tthis.bitmaps = {};\n\n\t\t/**\n\t\t * The {@link LineSet}s in this Scene, each mapped to its {@link LineSet#id}.\n\t\t *\n\t\t * @type {{String:LineSet}}\n\t\t */\n\t\tthis.lineSets = {};\n\n\t\t/**\n\t\t * The real world offset for this Scene\n\t\t *\n\t\t * @type {Number[]}\n\t\t */\n\t\tthis.realWorldOffset = cfg.realWorldOffset || new Float64Array([0, 0, 0]);\n\n\t\t/**\n\t\t * Manages the HTML5 canvas for this Scene.\n\t\t *\n\t\t * @type {Canvas}\n\t\t */\n\t\tthis.canvas = new _canvas_Canvas_js__WEBPACK_IMPORTED_MODULE_5__.Canvas(this, {\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\n\t\t\tcanvas: canvas,\n\t\t\tspinnerElementId: cfg.spinnerElementId,\n\t\t\ttransparent: this._transparent,\n\t\t\twebgl2: cfg.webgl2 !== false,\n\t\t\tcontextAttr: cfg.contextAttr || {},\n\t\t\tbackgroundColor: cfg.backgroundColor,\n\t\t\tbackgroundColorFromAmbientLight: cfg.backgroundColorFromAmbientLight,\n\t\t\tpremultipliedAlpha: cfg.premultipliedAlpha\n\t\t});\n\n\t\tthis.canvas.on(\"boundary\", () => {\n\t\t\tthis.glRedraw();\n\t\t});\n\n\t\tthis.canvas.on(\"webglContextFailed\", () => {\n\t\t\talert(\"xeokit failed to find WebGL!\");\n\t\t});\n\n\t\tthis._renderer = new _webgl_Renderer_js__WEBPACK_IMPORTED_MODULE_6__.Renderer(this, {\n\t\t\ttransparent: this._transparent,\n\t\t\talphaDepthMask: alphaDepthMask,\n\t\t\tedgesEnabled: this._edgesEnabled\n\t\t});\n\n\t\tthis._sectionPlanesState = new (function () {\n\t\t\tthis.sectionPlanes = [];\n\n\t\t\tthis.clippingCaps = false;\n\n\t\t\tthis._numCachedSectionPlanes = 0;\n\n\t\t\tlet hash = null;\n\n\t\t\tthis.getHash = function () {\n\t\t\t\tif (hash) {\n\t\t\t\t\treturn hash;\n\t\t\t\t}\n\t\t\t\tconst numAllocatedSectionPlanes = this.getNumAllocatedSectionPlanes();\n\t\t\t\tconst sectionPlanes = this.sectionPlanes;\n\t\t\t\tif (numAllocatedSectionPlanes === 0) {\n\t\t\t\t\treturn (this.hash = \";\");\n\t\t\t\t}\n\t\t\t\tlet sectionPlane;\n\n\t\t\t\tconst hashParts = [];\n\t\t\t\tfor (let i = 0, len = numAllocatedSectionPlanes; i < len; i++) {\n\t\t\t\t\tsectionPlane = sectionPlanes[i];\n\t\t\t\t\thashParts.push(\"cp\");\n\t\t\t\t}\n\t\t\t\thashParts.push(\";\");\n\t\t\t\thash = hashParts.join(\"\");\n\t\t\t\treturn hash;\n\t\t\t};\n\n\t\t\tthis.addSectionPlane = function (sectionPlane) {\n\t\t\t\tthis.sectionPlanes.push(sectionPlane);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeSectionPlane = function (sectionPlane) {\n\t\t\t\tfor (let i = 0, len = this.sectionPlanes.length; i < len; i++) {\n\t\t\t\t\tif (this.sectionPlanes[i].id === sectionPlane.id) {\n\t\t\t\t\t\tthis.sectionPlanes.splice(i, 1);\n\t\t\t\t\t\thash = null;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.setNumCachedSectionPlanes = function (numCachedSectionPlanes) {\n\t\t\t\tthis._numCachedSectionPlanes = numCachedSectionPlanes;\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.getNumCachedSectionPlanes = function () {\n\t\t\t\treturn this._numCachedSectionPlanes;\n\t\t\t};\n\n\t\t\tthis.getNumAllocatedSectionPlanes = function () {\n\t\t\t\tconst num = this.sectionPlanes.length;\n\t\t\t\treturn num > this._numCachedSectionPlanes ? num : this._numCachedSectionPlanes;\n\t\t\t};\n\t\t})();\n\n\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(cfg.numCachedSectionPlanes || 0);\n\n\t\tthis._lightsState = new (function () {\n\t\t\tconst DEFAULT_AMBIENT = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 0]);\n\t\t\tconst ambientColorIntensity = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4();\n\n\t\t\tthis.lights = [];\n\t\t\tthis.reflectionMaps = [];\n\t\t\tthis.lightMaps = [];\n\n\t\t\tlet hash = null;\n\t\t\tlet ambientLight = null;\n\n\t\t\tthis.getHash = function () {\n\t\t\t\tif (hash) {\n\t\t\t\t\treturn hash;\n\t\t\t\t}\n\t\t\t\tconst hashParts = [];\n\t\t\t\tconst lights = this.lights;\n\t\t\t\tlet light;\n\t\t\t\tfor (let i = 0, len = lights.length; i < len; i++) {\n\t\t\t\t\tlight = lights[i];\n\t\t\t\t\thashParts.push(\"/\");\n\t\t\t\t\thashParts.push(light.type);\n\t\t\t\t\thashParts.push(light.space === \"world\" ? \"w\" : \"v\");\n\t\t\t\t\tif (light.castsShadow) {\n\t\t\t\t\t\thashParts.push(\"sh\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (this.lightMaps.length > 0) {\n\t\t\t\t\thashParts.push(\"/lm\");\n\t\t\t\t}\n\t\t\t\tif (this.reflectionMaps.length > 0) {\n\t\t\t\t\thashParts.push(\"/rm\");\n\t\t\t\t}\n\t\t\t\thashParts.push(\";\");\n\t\t\t\thash = hashParts.join(\"\");\n\t\t\t\treturn hash;\n\t\t\t};\n\n\t\t\tthis.addLight = function (state) {\n\t\t\t\tthis.lights.push(state);\n\t\t\t\tambientLight = null;\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeLight = function (state) {\n\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\n\t\t\t\t\tconst light = this.lights[i];\n\t\t\t\t\tif (light.id === state.id) {\n\t\t\t\t\t\tthis.lights.splice(i, 1);\n\t\t\t\t\t\tif (ambientLight && ambientLight.id === state.id) {\n\t\t\t\t\t\t\tambientLight = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\thash = null;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addReflectionMap = function (state) {\n\t\t\t\tthis.reflectionMaps.push(state);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeReflectionMap = function (state) {\n\t\t\t\tfor (let i = 0, len = this.reflectionMaps.length; i < len; i++) {\n\t\t\t\t\tif (this.reflectionMaps[i].id === state.id) {\n\t\t\t\t\t\tthis.reflectionMaps.splice(i, 1);\n\t\t\t\t\t\thash = null;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.addLightMap = function (state) {\n\t\t\t\tthis.lightMaps.push(state);\n\t\t\t\thash = null;\n\t\t\t};\n\n\t\t\tthis.removeLightMap = function (state) {\n\t\t\t\tfor (let i = 0, len = this.lightMaps.length; i < len; i++) {\n\t\t\t\t\tif (this.lightMaps[i].id === state.id) {\n\t\t\t\t\t\tthis.lightMaps.splice(i, 1);\n\t\t\t\t\t\thash = null;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.getAmbientColorAndIntensity = function () {\n\t\t\t\tif (!ambientLight) {\n\t\t\t\t\tfor (let i = 0, len = this.lights.length; i < len; i++) {\n\t\t\t\t\t\tconst light = this.lights[i];\n\t\t\t\t\t\tif (light.type === \"ambient\") {\n\t\t\t\t\t\t\tambientLight = light;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (ambientLight) {\n\t\t\t\t\tconst color = ambientLight.color;\n\t\t\t\t\tconst intensity = ambientLight.intensity;\n\t\t\t\t\tambientColorIntensity[0] = color[0];\n\t\t\t\t\tambientColorIntensity[1] = color[1];\n\t\t\t\t\tambientColorIntensity[2] = color[2];\n\t\t\t\t\tambientColorIntensity[3] = intensity;\n\t\t\t\t\treturn ambientColorIntensity;\n\t\t\t\t} else {\n\t\t\t\t\treturn DEFAULT_AMBIENT;\n\t\t\t\t}\n\t\t\t};\n\t\t})();\n\n\t\t/**\n\t\t * Publishes input events that occur on this Scene's canvas.\n\t\t * @property input\n\t\t * @type {Input}\n\t\t * @final\n\t\t */\n\t\tthis.input = new _input_Input_js__WEBPACK_IMPORTED_MODULE_7__.Input(this, {\n\t\t\tdontClear: true, // Never destroy this component with Scene#clear();\n\t\t\telement: this.canvas.canvas,\n\t\t\tkeyboardEventsElement: cfg.keyboardEventsElement\n\t\t});\n\n\t\t/**\n\t\t * Configures this Scene's units of measurement and coordinate mapping between Real-space and World-space 3D coordinate systems.\n\t\t *\n\t\t * @property metrics\n\t\t * @type {Metrics}\n\t\t * @final\n\t\t */\n\t\tthis.metrics = new _metriqs_Metriqs_js__WEBPACK_IMPORTED_MODULE_17__.Metrics(this, {\n\t\t\tunits: cfg.units,\n\t\t\tscale: cfg.scale,\n\t\t\torigin: cfg.origin\n\t\t});\n\n\t\t/** Configures Scalable Ambient Obscurance (SAO) for this Scene.\n\t\t * @type {SAO}\n\t\t * @final\n\t\t */\n\t\tthis.sao = new _postfx_SAO_js__WEBPACK_IMPORTED_MODULE_18__.SAO(this, {\n\t\t\tenabled: cfg.saoEnabled\n\t\t});\n\n\t\tthis.ticksPerRender = cfg.ticksPerRender;\n\t\tthis.ticksPerOcclusionTest = cfg.ticksPerOcclusionTest;\n\t\tthis.passes = cfg.passes;\n\t\tthis.clearEachPass = cfg.clearEachPass;\n\t\tthis.gammaInput = cfg.gammaInput;\n\t\tthis.gammaOutput = cfg.gammaOutput;\n\t\tthis.gammaFactor = cfg.gammaFactor;\n\n\t\tthis._entityOffsetsEnabled = !!cfg.entityOffsetsEnabled;\n\t\tthis._logarithmicDepthBufferEnabled = !!cfg.logarithmicDepthBufferEnabled;\n\n\t\tthis._dtxEnabled = cfg.dtxEnabled !== false;\n\t\tthis._pbrEnabled = !!cfg.pbrEnabled;\n\t\tthis._colorTextureEnabled = cfg.colorTextureEnabled !== false;\n\t\tthis._dtxEnabled = !!cfg.dtxEnabled;\n\t\tthis._lodEnabled = cfg.lodEnabled !== false;\n\n\t\t// Register Scene on xeokit\n\t\t// Do this BEFORE we add components below\n\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core._addScene(this);\n\n\t\tthis._initDefaults();\n\n\t\t// Global components\n\n\t\tthis._viewport = new _viewport_Viewport_js__WEBPACK_IMPORTED_MODULE_8__.Viewport(this, {\n\t\t\tid: \"default.viewport\",\n\t\t\tautoBoundary: true,\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\n\t\t});\n\n\t\tthis._camera = new _camera_Camera_js__WEBPACK_IMPORTED_MODULE_9__.Camera(this, {\n\t\t\tid: \"default.camera\",\n\t\t\tdontClear: true // Never destroy this component with Scene#clear();\n\t\t});\n\n\t\t// Default lights\n\n\t\tnew _lights_AmbientLight_js__WEBPACK_IMPORTED_MODULE_11__.AmbientLight(this, {\n\t\t\tcolor: [1.0, 1.0, 1.0],\n\t\t\tintensity: 0.7\n\t\t});\n\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\n\t\t\tdir: [0.8, -0.5, -0.5],\n\t\t\tcolor: [0.67, 0.67, 1.0],\n\t\t\tintensity: 0.7,\n\t\t\tspace: \"world\"\n\t\t});\n\n\t\tnew _lights_DirLight_js__WEBPACK_IMPORTED_MODULE_10__.DirLight(this, {\n\t\t\tdir: [-0.8, -1.0, 0.5],\n\t\t\tcolor: [1, 1, 0.9],\n\t\t\tintensity: 0.9,\n\t\t\tspace: \"world\"\n\t\t});\n\n\t\tthis._camera.on(\"dirty\", () => {\n\t\t\tthis._renderer.imageDirty();\n\t\t});\n\n\t\tthis._lod = new _lod_LOD_js__WEBPACK_IMPORTED_MODULE_1__.LOD(this, {\n\t\t\tenabled: this._lodEnabled,\n\t\t\ttargetFPS: 30\n\t\t});\n\t}\n\n\t_initDefaults() {\n\t\t// Call this Scene's property accessors to lazy-init their properties\n\n\t\tlet dummy; // Keeps Codacy happy\n\n\t\tdummy = this.geometry;\n\t\tdummy = this.material;\n\t\tdummy = this.xrayMaterial;\n\t\tdummy = this.edgeMaterial;\n\t\tdummy = this.selectedMaterial;\n\t\tdummy = this.highlightMaterial;\n\t}\n\n\t_addComponent(component) {\n\t\tif (component.id) {\n\t\t\t// Manual ID\n\t\t\tif (this.components[component.id]) {\n\t\t\t\tthis.error(\n\t\t\t\t\t\"Component \" +\n\t\t\t\t\t\t_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.inQuotes(component.id) +\n\t\t\t\t\t\t\" already exists in Scene - ignoring ID, will randomly-generate instead\"\n\t\t\t\t);\n\t\t\t\tcomponent.id = null;\n\t\t\t}\n\t\t}\n\t\tif (!component.id) {\n\t\t\t// Auto ID\n\t\t\tif (window.nextID === undefined) {\n\t\t\t\twindow.nextID = 0;\n\t\t\t}\n\t\t\t//component.id = math.createUUID();\n\t\t\tcomponent.id = \"__\" + window.nextID++;\n\t\t\twhile (this.components[component.id]) {\n\t\t\t\tcomponent.id = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.createUUID();\n\t\t\t}\n\t\t}\n\t\tthis.components[component.id] = component;\n\n\t\t// Register for class type\n\t\tconst type = component.type;\n\t\tlet types = this.types[component.type];\n\t\tif (!types) {\n\t\t\ttypes = this.types[type] = {};\n\t\t}\n\t\ttypes[component.id] = component;\n\n\t\tif (component.compile) {\n\t\t\tthis._compilables[component.id] = component;\n\t\t}\n\t\tif (component.isDrawable) {\n\t\t\tthis._renderer.addDrawable(component.id, component);\n\t\t\tthis._collidables[component.id] = component;\n\t\t}\n\t}\n\n\t_removeComponent(component) {\n\t\tvar id = component.id;\n\t\tvar type = component.type;\n\t\tdelete this.components[id];\n\t\t// Unregister for types\n\t\tconst types = this.types[type];\n\t\tif (types) {\n\t\t\tdelete types[id];\n\t\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isEmptyObject(types)) {\n\t\t\t\tdelete this.types[type];\n\t\t\t}\n\t\t}\n\t\tif (component.compile) {\n\t\t\tdelete this._compilables[component.id];\n\t\t}\n\t\tif (component.isDrawable) {\n\t\t\tthis._renderer.removeDrawable(component.id);\n\t\t\tdelete this._collidables[component.id];\n\t\t}\n\t}\n\n\t// Methods below are called by various component types to register themselves on their\n\t// Scene. Violates Hollywood Principle, where we could just filter on type in _addComponent,\n\t// but this is faster than checking the type of each component in such a filter.\n\n\t_sectionPlaneCreated(sectionPlane) {\n\t\tthis.sectionPlanes[sectionPlane.id] = sectionPlane;\n\t\tthis.scene._sectionPlanesState.addSectionPlane(sectionPlane._state);\n\t\tthis.scene.fire(\"sectionPlaneCreated\", sectionPlane, true /* Don't retain event */);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_bitmapCreated(bitmap) {\n\t\tthis.bitmaps[bitmap.id] = bitmap;\n\t\tthis.scene.fire(\"bitmapCreated\", bitmap, true /* Don't retain event */);\n\t}\n\n\t_lineSetCreated(lineSet) {\n\t\tthis.lineSets[lineSet.id] = lineSet;\n\t\tthis.scene.fire(\"lineSetCreated\", lineSet, true /* Don't retain event */);\n\t}\n\n\t_lightCreated(light) {\n\t\tthis.lights[light.id] = light;\n\t\tthis.scene._lightsState.addLight(light._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_lightMapCreated(lightMap) {\n\t\tthis.lightMaps[lightMap.id] = lightMap;\n\t\tthis.scene._lightsState.addLightMap(lightMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_reflectionMapCreated(reflectionMap) {\n\t\tthis.reflectionMaps[reflectionMap.id] = reflectionMap;\n\t\tthis.scene._lightsState.addReflectionMap(reflectionMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_sectionPlaneDestroyed(sectionPlane) {\n\t\tdelete this.sectionPlanes[sectionPlane.id];\n\t\tthis.scene._sectionPlanesState.removeSectionPlane(sectionPlane._state);\n\t\tthis.scene.fire(\"sectionPlaneDestroyed\", sectionPlane, true /* Don't retain event */);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_bitmapDestroyed(bitmap) {\n\t\tdelete this.bitmaps[bitmap.id];\n\t\tthis.scene.fire(\"bitmapDestroyed\", bitmap, true /* Don't retain event */);\n\t}\n\n\t_lineSetDestroyed(lineSet) {\n\t\tdelete this.lineSets[lineSet.id];\n\t\tthis.scene.fire(\"lineSetDestroyed\", lineSet, true /* Don't retain event */);\n\t}\n\n\t_lightDestroyed(light) {\n\t\tdelete this.lights[light.id];\n\t\tthis.scene._lightsState.removeLight(light._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_lightMapDestroyed(lightMap) {\n\t\tdelete this.lightMaps[lightMap.id];\n\t\tthis.scene._lightsState.removeLightMap(lightMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_reflectionMapDestroyed(reflectionMap) {\n\t\tdelete this.reflectionMaps[reflectionMap.id];\n\t\tthis.scene._lightsState.removeReflectionMap(reflectionMap._state);\n\t\tthis._needRecompile = true;\n\t}\n\n\t_registerModel(entity) {\n\t\tthis.models[entity.id] = entity;\n\t\tthis._modelIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterModel(entity) {\n\t\tconst modelId = entity.id;\n\t\tdelete this.models[modelId];\n\t\tthis._modelIds = null; // Lazy regenerate\n\t\tthis.fire(\"modelUnloaded\", modelId);\n\t}\n\n\t_registerObject(entity) {\n\t\tthis.objects[entity.id] = entity;\n\t\tthis._numObjects++;\n\t\tthis._objectIds = null; // Lazy regenerate\n\t}\n\n\t_deregisterObject(entity) {\n\t\tdelete this.objects[entity.id];\n\t\tthis._numObjects--;\n\t\tthis._objectIds = null; // Lazy regenerate\n\t}\n\n\t_objectVisibilityUpdated(entity, notify = true) {\n\t\tif (entity.visible) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.visibleObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.visibleObjects[entity.id] = entity;\n\t\t\tthis._numVisibleObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.visibleObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object visibility update (visible=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.visibleObjects[entity.id];\n\t\t\tthis._numVisibleObjects--;\n\t\t}\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectVisibility\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterVisibleObject(entity) {\n\t\tdelete this.visibleObjects[entity.id];\n\t\tthis._numVisibleObjects--;\n\t\tthis._visibleObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectXRayedUpdated(entity, notify = true) {\n\t\tif (entity.xrayed) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.xrayedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.xrayedObjects[entity.id] = entity;\n\t\t\tthis._numXRayedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.xrayedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object xray update (xrayed=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.xrayedObjects[entity.id];\n\t\t\tthis._numXRayedObjects--;\n\t\t}\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectXRayed\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterXRayedObject(entity) {\n\t\tdelete this.xrayedObjects[entity.id];\n\t\tthis._numXRayedObjects--;\n\t\tthis._xrayedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectHighlightedUpdated(entity) {\n\t\tif (entity.highlighted) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.highlightedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.highlightedObjects[entity.id] = entity;\n\t\t\tthis._numHighlightedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.highlightedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object highlight update (highlighted=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.highlightedObjects[entity.id];\n\t\t\tthis._numHighlightedObjects--;\n\t\t}\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterHighlightedObject(entity) {\n\t\tdelete this.highlightedObjects[entity.id];\n\t\tthis._numHighlightedObjects--;\n\t\tthis._highlightedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectSelectedUpdated(entity, notify = true) {\n\t\tif (entity.selected) {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && this.selectedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object select update (selected=true)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.selectedObjects[entity.id] = entity;\n\t\t\tthis._numSelectedObjects++;\n\t\t} else {\n\t\t\tif (ASSERT_OBJECT_STATE_UPDATE && !this.selectedObjects[entity.id]) {\n\t\t\t\tconsole.error(\"Redundant object select update (selected=false)\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdelete this.selectedObjects[entity.id];\n\t\t\tthis._numSelectedObjects--;\n\t\t}\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\n\t\tif (notify) {\n\t\t\tthis.fire(\"objectSelected\", entity, true);\n\t\t}\n\t}\n\n\t_deRegisterSelectedObject(entity) {\n\t\tdelete this.selectedObjects[entity.id];\n\t\tthis._numSelectedObjects--;\n\t\tthis._selectedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectColorizeUpdated(entity, colorized) {\n\t\tif (colorized) {\n\t\t\tthis.colorizedObjects[entity.id] = entity;\n\t\t\tthis._numColorizedObjects++;\n\t\t} else {\n\t\t\tdelete this.colorizedObjects[entity.id];\n\t\t\tthis._numColorizedObjects--;\n\t\t}\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterColorizedObject(entity) {\n\t\tdelete this.colorizedObjects[entity.id];\n\t\tthis._numColorizedObjects--;\n\t\tthis._colorizedObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectOpacityUpdated(entity, opacityUpdated) {\n\t\tif (opacityUpdated) {\n\t\t\tthis.opacityObjects[entity.id] = entity;\n\t\t\tthis._numOpacityObjects++;\n\t\t} else {\n\t\t\tdelete this.opacityObjects[entity.id];\n\t\t\tthis._numOpacityObjects--;\n\t\t}\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterOpacityObject(entity) {\n\t\tdelete this.opacityObjects[entity.id];\n\t\tthis._numOpacityObjects--;\n\t\tthis._opacityObjectIds = null; // Lazy regenerate\n\t}\n\n\t_objectOffsetUpdated(entity, offset) {\n\t\tif (!offset || (offset[0] === 0 && offset[1] === 0 && offset[2] === 0)) {\n\t\t\tthis.offsetObjects[entity.id] = entity;\n\t\t\tthis._numOffsetObjects++;\n\t\t} else {\n\t\t\tdelete this.offsetObjects[entity.id];\n\t\t\tthis._numOffsetObjects--;\n\t\t}\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\n\t}\n\n\t_deRegisterOffsetObject(entity) {\n\t\tdelete this.offsetObjects[entity.id];\n\t\tthis._numOffsetObjects--;\n\t\tthis._offsetObjectIds = null; // Lazy regenerate\n\t}\n\n\t_webglContextLost() {\n\t\t// this.loading++;\n\t\tthis.canvas.spinner.processes++;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tconst component = this.components[id];\n\t\t\t\tif (component._webglContextLost) {\n\t\t\t\t\tcomponent._webglContextLost();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._renderer.webglContextLost();\n\t}\n\n\t_webglContextRestored() {\n\t\tconst gl = this.canvas.gl;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tconst component = this.components[id];\n\t\t\t\tif (component._webglContextRestored) {\n\t\t\t\t\tcomponent._webglContextRestored(gl);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._renderer.webglContextRestored(gl);\n\t\t//this.loading--;\n\t\tthis.canvas.spinner.processes--;\n\t}\n\n\t/**\n\t * Returns the capabilities of this Scene.\n\t *\n\t * @private\n\t * @returns {{astcSupported: boolean, etc1Supported: boolean, pvrtcSupported: boolean, etc2Supported: boolean, dxtSupported: boolean, bptcSupported: boolean}}\n\t */\n\tget capabilities() {\n\t\treturn this._renderer.capabilities;\n\t}\n\n\t/**\n\t * Whether {@link Entity#offset} is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * @returns {Boolean} True if {@link Entity#offset} is enabled.\n\t */\n\tget entityOffsetsEnabled() {\n\t\treturn this._entityOffsetsEnabled;\n\t}\n\n\t/**\n\t * Whether precision surface picking is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * The ````pickSurfacePrecision```` option for ````Scene#pick```` only works if this is set ````true````.\n\t *\n\t * Note that when ````true````, this configuration will increase the amount of browser memory used by the Viewer.\n\t *\n\t * @returns {Boolean} True if precision picking is enabled.\n\t */\n\tget pickSurfacePrecisionEnabled() {\n\t\treturn false; // Removed\n\t}\n\n\t/**\n\t * Whether logarithmic depth buffer is enabled.\n\t *\n\t * This is set via the {@link Viewer} constructor and is ````false```` by default.\n\t *\n\t * @returns {Boolean} True if logarithmic depth buffer is enabled.\n\t */\n\tget logarithmicDepthBufferEnabled() {\n\t\treturn this._logarithmicDepthBufferEnabled;\n\t}\n\n\t/**\n\t * Sets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t *\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t *\n\t * Default is ````0````.\n\t */\n\tset numCachedSectionPlanes(numCachedSectionPlanes) {\n\t\tnumCachedSectionPlanes = numCachedSectionPlanes || 0;\n\t\tif (this._sectionPlanesState.getNumCachedSectionPlanes() !== numCachedSectionPlanes) {\n\t\t\tthis._sectionPlanesState.setNumCachedSectionPlanes(numCachedSectionPlanes);\n\t\t\tthis._needRecompile = true;\n\t\t\tthis.glRedraw();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t *\n\t * This property enhances the efficiency of SectionPlane creation by proactively allocating and caching Viewer resources for a specified quantity\n\t * of SectionPlanes. Introducing this parameter streamlines the initial creation speed of SectionPlanes, particularly up to the designated quantity. This parameter internally\n\t * configures renderer logic for the specified number of SectionPlanes, eliminating the need for setting up logic with each SectionPlane creation and thereby enhancing\n\t * responsiveness. It is important to consider that each SectionPlane impacts rendering performance, so it is recommended to set this value to a quantity that aligns with\n\t * your expected usage.\n\t *\n\t * Default is ````0````.\n\t *\n\t * @returns {number} The number of {@link SectionPlane}s for which this Scene pre-caches resources.\n\t */\n\tget numCachedSectionPlanes() {\n\t\treturn this._sectionPlanesState.getNumCachedSectionPlanes();\n\t}\n\n\t/**\n\t * Sets whether physically-based rendering is enabled.\n\t *\n\t * Default is ````false````.\n\t */\n\tset pbrEnabled(pbrEnabled) {\n\t\tthis._pbrEnabled = !!pbrEnabled;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether physically-based rendering is enabled.\n\t *\n\t * Default is ````false````.\n\t *\n\t * @returns {Boolean} True if quality rendering is enabled.\n\t */\n\tget pbrEnabled() {\n\t\treturn this._pbrEnabled;\n\t}\n\n\t/**\n\t * Sets whether data texture scene representation (DTX) is enabled for the {@link Scene}.\n\t *\n\t * Even when enabled, DTX will only work if supported.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset dtxEnabled(value) {\n\t\tvalue = !!value;\n\t\tif (this._dtxEnabled === value) {\n\t\t\treturn;\n\t\t}\n\t\tthis._dtxEnabled = value;\n\t}\n\n\t/**\n\t * Gets whether data texture-based scene representation (DTX) is enabled for the {@link Scene}.\n\t *\n\t * Even when enabled, DTX will only apply if supported.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget dtxEnabled() {\n\t\treturn this._dtxEnabled;\n\t}\n\n\t/**\n\t * set showedges enable\n\t * @param {boolean} edgesEnabled\n\t */\n\tset edgesEnabled(edgesEnabled) {\n\t\tedgesEnabled = !!edgesEnabled;\n\t\tif (this._edgesEnabled === edgesEnabled) {\n\t\t\treturn;\n\t\t}\n\t\tthis._edgesEnabled = edgesEnabled;\n\t\tthis._renderer.setEdgesEnabled(edgesEnabled);\n\t}\n\n\t/**\n\t * @param {boolean} trans\n\t */\n\tget edgesEnabled() {\n\t\treturn this._edgesEnabled;\n\t}\n\n\t/**\n\t * set whether transparent of canvas background\n\t * @param {boolean} trans\n\t */\n\tset backgroundTransparent(trans) {\n\t\ttrans = !!trans;\n\t\t// if (this._transparent == trans) {\n\t\t// return;\n\t\t// }\n\t\tthis._transparent = trans;\n\t\tthis._renderer.setTransparentEnabled(trans);\n\t}\n\n\t/**\n\t * @returns {boolean} backgroundTransparent\n\t */\n\tget backgroundTransparent() {\n\t\treturn this._transparent;\n\t}\n\n\t/**\n\t * set background color\n\t * @param {[]} color\n\t */\n\tset backgroundColor(color) {\n\t\tthis.canvas.backgroundColor = color;\n\t\tthis._renderer.render({ force: true });\n\t}\n\n\t/**\n\t * return backgroundColor\n\t * @returns {boolean} backgroundColor\n\t */\n\tget backgroundColor() {\n\t\treturn this.canvas.backgroundColor();\n\t}\n\n\t/**\n\t * Sets whether basic color texture rendering is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\n\t */\n\tset colorTextureEnabled(colorTextureEnabled) {\n\t\tthis._colorTextureEnabled = !!colorTextureEnabled;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether basic color texture rendering is enabled.\n\t *\n\t * Default is ````true````.\n\t *\n\t * @returns {Boolean} True if basic color texture rendering is enabled.\n\t */\n\tget colorTextureEnabled() {\n\t\treturn this._colorTextureEnabled;\n\t}\n\n\t/**\n\t * Performs an occlusion test on all {@link Marker}s in this {@link Scene}.\n\t *\n\t * Sets each {@link Marker#visible} ````true```` if the Marker is currently not occluded by any opaque {@link Entity}s\n\t * in the Scene, or ````false```` if an Entity is occluding it.\n\t */\n\tdoOcclusionTest() {\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\t\tthis._renderer.doOcclusionTest();\n\t}\n\n\t/**\n\t * Renders a single frame of this Scene.\n\t *\n\t * The Scene will periodically render itself after any updates, but you can call this method to force a render\n\t * if required.\n\t *\n\t * @param {Boolean} [forceRender=false] Forces a render when true, otherwise only renders if something has changed in this Scene\n\t * since the last render.\n\t */\n\trender(forceRender) {\n\t\tif (forceRender) {\n\t\t\t_core_js__WEBPACK_IMPORTED_MODULE_0__.core.runTasks();\n\t\t}\n\n\t\tconst renderEvent = {\n\t\t\tsceneId: null,\n\t\t\tpass: 0\n\t\t};\n\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\n\t\tif (!forceRender && !this._renderer.needsRender()) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderEvent.sceneId = this.id;\n\n\t\tconst passes = this._passes;\n\t\tconst clearEachPass = this._clearEachPass;\n\t\tlet pass;\n\t\tlet clear;\n\n\t\tfor (pass = 0; pass < passes; pass++) {\n\t\t\trenderEvent.pass = pass;\n\n\t\t\t/**\n\t\t\t * Fired when about to render a frame for a Scene.\n\t\t\t *\n\t\t\t * @event rendering\n\t\t\t * @param {String} sceneID The ID of this Scene.\n\t\t\t * @param {Number} pass Index of the pass we are about to render (see {@link Scene#passes}).\n\t\t\t */\n\t\t\tthis.fire(\"rendering\", renderEvent, true);\n\n\t\t\tclear = clearEachPass || pass === 0;\n\n\t\t\tthis._renderer.render({ pass: pass, clear: clear, force: forceRender });\n\n\t\t\t/**\n\t\t\t * Fired when we have just rendered a frame for a Scene.\n\t\t\t *\n\t\t\t * @event rendering\n\t\t\t * @param {String} sceneID The ID of this Scene.\n\t\t\t * @param {Number} pass Index of the pass we rendered (see {@link Scene#passes}).\n\t\t\t */\n\t\t\tthis.fire(\"rendered\", renderEvent, true);\n\t\t}\n\n\t\tthis._saveAmbientColor();\n\t}\n\n\t/**\n\t * @private\n\t */\n\tcompile() {\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\t}\n\n\t_recompile() {\n\t\tfor (const id in this._compilables) {\n\t\t\tif (this._compilables.hasOwnProperty(id)) {\n\t\t\t\tthis._compilables[id].compile();\n\t\t\t}\n\t\t}\n\t\tthis._renderer.shadowsDirty();\n\t\tthis.fire(\"compile\", this, true);\n\t}\n\n\t_saveAmbientColor() {\n\t\tconst canvas = this.canvas;\n\t\tif (!canvas.transparent && !canvas.backgroundImage && !canvas.backgroundColor) {\n\t\t\tconst ambientColorIntensity = this._lightsState.getAmbientColorAndIntensity();\n\t\t\tif (\n\t\t\t\t!this._lastAmbientColor ||\n\t\t\t\tthis._lastAmbientColor[0] !== ambientColorIntensity[0] ||\n\t\t\t\tthis._lastAmbientColor[1] !== ambientColorIntensity[1] ||\n\t\t\t\tthis._lastAmbientColor[2] !== ambientColorIntensity[2] ||\n\t\t\t\tthis._lastAmbientColor[3] !== ambientColorIntensity[3]\n\t\t\t) {\n\t\t\t\tcanvas.backgroundColor = ambientColorIntensity;\n\t\t\t\tif (!this._lastAmbientColor) {\n\t\t\t\t\tthis._lastAmbientColor = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec4([0, 0, 0, 1]);\n\t\t\t\t}\n\t\t\t\tthis._lastAmbientColor.set(ambientColorIntensity);\n\t\t\t}\n\t\t} else {\n\t\t\tthis._lastAmbientColor = null;\n\t\t}\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#models}.\n\t *\n\t * @type {String[]}\n\t */\n\tget modelIds() {\n\t\tif (!this._modelIds) {\n\t\t\tthis._modelIds = Object.keys(this.models);\n\t\t}\n\t\treturn this._modelIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#objects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numObjects() {\n\t\treturn this._numObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#objects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget objectIds() {\n\t\tif (!this._objectIds) {\n\t\t\tthis._objectIds = Object.keys(this.objects);\n\t\t}\n\t\treturn this._objectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#visibleObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numVisibleObjects() {\n\t\treturn this._numVisibleObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#visibleObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget visibleObjectIds() {\n\t\tif (!this._visibleObjectIds) {\n\t\t\tthis._visibleObjectIds = Object.keys(this.visibleObjects);\n\t\t}\n\t\treturn this._visibleObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#xrayedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numXRayedObjects() {\n\t\treturn this._numXRayedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#xrayedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget xrayedObjectIds() {\n\t\tif (!this._xrayedObjectIds) {\n\t\t\tthis._xrayedObjectIds = Object.keys(this.xrayedObjects);\n\t\t}\n\t\treturn this._xrayedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#highlightedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numHighlightedObjects() {\n\t\treturn this._numHighlightedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#highlightedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget highlightedObjectIds() {\n\t\tif (!this._highlightedObjectIds) {\n\t\t\tthis._highlightedObjectIds = Object.keys(this.highlightedObjects);\n\t\t}\n\t\treturn this._highlightedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#selectedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numSelectedObjects() {\n\t\treturn this._numSelectedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#selectedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget selectedObjectIds() {\n\t\tif (!this._selectedObjectIds) {\n\t\t\tthis._selectedObjectIds = Object.keys(this.selectedObjects);\n\t\t}\n\t\treturn this._selectedObjectIds;\n\t}\n\n\t/**\n\t * Gets the number of {@link Entity}s in {@link Scene#colorizedObjects}.\n\t *\n\t * @type {Number}\n\t */\n\tget numColorizedObjects() {\n\t\treturn this._numColorizedObjects;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#colorizedObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget colorizedObjectIds() {\n\t\tif (!this._colorizedObjectIds) {\n\t\t\tthis._colorizedObjectIds = Object.keys(this.colorizedObjects);\n\t\t}\n\t\treturn this._colorizedObjectIds;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#opacityObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget opacityObjectIds() {\n\t\tif (!this._opacityObjectIds) {\n\t\t\tthis._opacityObjectIds = Object.keys(this.opacityObjects);\n\t\t}\n\t\treturn this._opacityObjectIds;\n\t}\n\n\t/**\n\t * Gets the IDs of the {@link Entity}s in {@link Scene#offsetObjects}.\n\t *\n\t * @type {String[]}\n\t */\n\tget offsetObjectIds() {\n\t\tif (!this._offsetObjectIds) {\n\t\t\tthis._offsetObjectIds = Object.keys(this.offsetObjects);\n\t\t}\n\t\treturn this._offsetObjectIds;\n\t}\n\n\t/**\n\t * Sets the number of \"ticks\" that happen between each render or this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tset ticksPerRender(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 1;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\"Unsupported value for 'ticksPerRender': '\" + value + \"' - should be an integer greater than zero.\");\n\t\t\tvalue = 1;\n\t\t}\n\t\tif (value === this._ticksPerRender) {\n\t\t\treturn;\n\t\t}\n\t\tthis._ticksPerRender = value;\n\t}\n\n\t/**\n\t * Gets the number of \"ticks\" that happen between each render or this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget ticksPerRender() {\n\t\treturn this._ticksPerRender;\n\t}\n\n\t/**\n\t * Sets the number of \"ticks\" that happen between occlusion testing for {@link Marker}s.\n\t *\n\t * Default value is ````20````.\n\t *\n\t * @type {Number}\n\t */\n\tset ticksPerOcclusionTest(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 20;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\n\t\t\t\t\"Unsupported value for 'ticksPerOcclusionTest': '\" + value + \"' - should be an integer greater than zero.\"\n\t\t\t);\n\t\t\tvalue = 20;\n\t\t}\n\t\tif (value === this._ticksPerOcclusionTest) {\n\t\t\treturn;\n\t\t}\n\t\tthis._ticksPerOcclusionTest = value;\n\t}\n\n\t/**\n\t * Gets the number of \"ticks\" that happen between each render of this Scene.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget ticksPerOcclusionTest() {\n\t\treturn this._ticksPerOcclusionTest;\n\t}\n\n\t/**\n\t * Sets the number of times this Scene renders per frame.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tset passes(value) {\n\t\tif (value === undefined || value === null) {\n\t\t\tvalue = 1;\n\t\t} else if (!_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isNumeric(value) || value <= 0) {\n\t\t\tthis.error(\"Unsupported value for 'passes': '\" + value + \"' - should be an integer greater than zero.\");\n\t\t\tvalue = 1;\n\t\t}\n\t\tif (value === this._passes) {\n\t\t\treturn;\n\t\t}\n\t\tthis._passes = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the number of times this Scene renders per frame.\n\t *\n\t * Default value is ````1````.\n\t *\n\t * @type {Number}\n\t */\n\tget passes() {\n\t\treturn this._passes;\n\t}\n\n\t/**\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset clearEachPass(value) {\n\t\tvalue = !!value;\n\t\tif (value === this._clearEachPass) {\n\t\t\treturn;\n\t\t}\n\t\tthis._clearEachPass = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * When {@link Scene#passes} is greater than ````1````, indicates whether or not to clear the canvas before each pass (````true````) or just before the first pass (````false````).\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget clearEachPass() {\n\t\treturn this._clearEachPass;\n\t}\n\n\t/**\n\t * Sets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset gammaInput(value) {\n\t\tvalue = value !== false;\n\t\tif (value === this._renderer.gammaInput) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaInput = value;\n\t\tthis._needRecompile = true;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether or not {@link Scene} should expect all {@link Texture}s and colors to have pre-multiplied gamma.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget gammaInput() {\n\t\treturn this._renderer.gammaInput;\n\t}\n\n\t/**\n\t * Sets whether or not to render pixels with pre-multiplied gama.\n\t *\n\t * Default value is ````false````.\n\t *\n\t * @type {Boolean}\n\t */\n\tset gammaOutput(value) {\n\t\tvalue = !!value;\n\t\tif (value === this._renderer.gammaOutput) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaOutput = value;\n\t\tthis._needRecompile = true;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets whether or not to render pixels with pre-multiplied gama.\n\t *\n\t * Default value is ````true````.\n\t *\n\t * @type {Boolean}\n\t */\n\tget gammaOutput() {\n\t\treturn this._renderer.gammaOutput;\n\t}\n\n\t/**\n\t * Sets the gamma factor to use when {@link Scene#gammaOutput} is set true.\n\t *\n\t * Default value is ````2.2````.\n\t *\n\t * @type {Number}\n\t */\n\tset gammaFactor(value) {\n\t\tvalue = value === undefined || value === null ? 2.2 : value;\n\t\tif (value === this._renderer.gammaFactor) {\n\t\t\treturn;\n\t\t}\n\t\tthis._renderer.gammaFactor = value;\n\t\tthis.glRedraw();\n\t}\n\n\t/**\n\t * Gets the gamma factor to use when {@link Scene#gammaOutput} is set true.\n\t *\n\t * Default value is ````2.2````.\n\t *\n\t * @type {Number}\n\t */\n\tget gammaFactor() {\n\t\treturn this._renderer.gammaFactor;\n\t}\n\n\t/**\n\t * Gets the default {@link Geometry} for this Scene, which is a {@link ReadableGeometry} with a unit-sized box shape.\n\t *\n\t * Has {@link ReadableGeometry#id} set to \"default.geometry\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#geometry} set to this {@link ReadableGeometry} by default.\n\t *\n\t * @type {ReadableGeometry}\n\t */\n\tget geometry() {\n\t\treturn (\n\t\t\tthis.components[\"default.geometry\"] ||\n\t\t\t(0,_geometry_builders_buildBoxGeometry_js__WEBPACK_IMPORTED_MODULE_13__.buildBoxGeometry)(_geometry_ReadableGeometry_js__WEBPACK_IMPORTED_MODULE_12__.ReadableGeometry, this, {\n\t\t\t\tid: \"default.geometry\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default {@link Material} for this Scene, which is a {@link PhongMaterial}.\n\t *\n\t * Has {@link PhongMaterial#id} set to \"default.material\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#material} set to this {@link PhongMaterial} by default.\n\t *\n\t * @type {PhongMaterial}\n\t */\n\tget material() {\n\t\treturn (\n\t\t\tthis.components[\"default.material\"] ||\n\t\t\tnew _materials_PhongMaterial_js__WEBPACK_IMPORTED_MODULE_14__.PhongMaterial(this, {\n\t\t\t\tid: \"default.material\",\n\t\t\t\temissive: [0.4, 0.4, 0.4], // Visible by default on geometry without normals\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default xraying {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.xrayMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#xrayMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are xrayed while {@link Mesh#xrayed} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget xrayMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.xrayMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.xrayMaterial\",\n\t\t\t\tpreset: \"sepia\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default highlight {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.highlightMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget highlightMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.highlightMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.highlightMaterial\",\n\t\t\t\tpreset: \"yellowHighlight\",\n\t\t\t\tfillAlpha: 0.1,\n\t\t\t\tfillColor: [0.7, 0.9, 0.9],\n\t\t\t\tdontClear: false,\n\t\t\t\tedges: false,\n\t\t\t\tglowThrough: false\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default selection {@link EmphasisMaterial} for this Scene.\n\t *\n\t * Has {@link EmphasisMaterial#id} set to \"default.selectedMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#highlightMaterial} set to this {@link EmphasisMaterial} by default.\n\t *\n\t * {@link Mesh}s are highlighted while {@link Mesh#highlighted} is ````true````.\n\t *\n\t * @type {EmphasisMaterial}\n\t */\n\tget selectedMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.selectedMaterial\"] ||\n\t\t\tnew _materials_EmphasisMaterial_js__WEBPACK_IMPORTED_MODULE_15__.EmphasisMaterial(this, {\n\t\t\t\tid: \"default.selectedMaterial\",\n\t\t\t\tpreset: \"greenSelected\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the default {@link EdgeMaterial} for this Scene.\n\t *\n\t * Has {@link EdgeMaterial#id} set to \"default.edgeMaterial\".\n\t *\n\t * {@link Mesh}s in this Scene have {@link Mesh#edgeMaterial} set to this {@link EdgeMaterial} by default.\n\t *\n\t * {@link Mesh}s have their edges emphasized while {@link Mesh#edges} is ````true````.\n\t *\n\t * @type {EdgeMaterial}\n\t */\n\tget edgeMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.edgeMaterial\"] ||\n\t\t\tnew _materials_EdgeMaterial_js__WEBPACK_IMPORTED_MODULE_16__.EdgeMaterial(this, {\n\t\t\t\tid: \"default.edgeMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tedgeColor: [0.0, 0.0, 0.0],\n\t\t\t\tedgeAlpha: 1.0,\n\t\t\t\tedgeWidth: 1,\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link PointsMaterial} for this Scene.\n\t *\n\t * @type {PointsMaterial}\n\t */\n\tget pointsMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.pointsMaterial\"] ||\n\t\t\tnew _materials_PointsMaterial_js__WEBPACK_IMPORTED_MODULE_19__.PointsMaterial(this, {\n\t\t\t\tid: \"default.pointsMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link LinesMaterial} for this Scene.\n\t *\n\t * @type {LinesMaterial}\n\t */\n\tget linesMaterial() {\n\t\treturn (\n\t\t\tthis.components[\"default.linesMaterial\"] ||\n\t\t\tnew _materials_LinesMaterial_js__WEBPACK_IMPORTED_MODULE_20__.LinesMaterial(this, {\n\t\t\t\tid: \"default.linesMaterial\",\n\t\t\t\tpreset: \"default\",\n\t\t\t\tdontClear: true\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Gets the {@link Viewport} for this Scene.\n\t *\n\t * @type Viewport\n\t */\n\tget viewport() {\n\t\treturn this._viewport;\n\t}\n\n\t/**\n\t * Gets the {@link Camera} for this Scene.\n\t *\n\t * @type {Camera}\n\t */\n\tget camera() {\n\t\treturn this._camera;\n\t}\n\n\t/**\n\t * Gets the World-space 3D center of this Scene.\n\t *\n\t *@type {Number[]}\n\t */\n\tget center() {\n\t\tif (this._aabbDirty || !this._center) {\n\t\t\tif (!this._center || !this._center) {\n\t\t\t\tthis._center = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.vec3();\n\t\t\t}\n\t\t\tconst aabb = this.aabb;\n\t\t\tthis._center[0] = (aabb[0] + aabb[3]) / 2;\n\t\t\tthis._center[1] = (aabb[1] + aabb[4]) / 2;\n\t\t\tthis._center[2] = (aabb[2] + aabb[5]) / 2;\n\t\t}\n\t\treturn this._center;\n\t}\n\n\t/**\n\t * Gets the World-space axis-aligned 3D boundary (AABB) of this Scene.\n\t *\n\t * The AABB is represented by a six-element Float64Array containing the min/max extents of the axis-aligned volume, ie. ````[xmin, ymin,zmin,xmax,ymax, zmax]````.\n\t *\n\t * When the Scene has no content, will be ````[-100,-100,-100,100,100,100]````.\n\t *\n\t * @type {Number[]}\n\t */\n\tget aabb() {\n\t\tif (this._aabbDirty) {\n\t\t\tif (!this._aabb) {\n\t\t\t\tthis._aabb = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\n\t\t\t}\n\t\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\t\tlet aabb;\n\t\t\tconst collidables = this._collidables;\n\t\t\tlet collidable;\n\t\t\tlet valid = false;\n\t\t\tfor (const collidableId in collidables) {\n\t\t\t\tif (collidables.hasOwnProperty(collidableId)) {\n\t\t\t\t\tcollidable = collidables[collidableId];\n\t\t\t\t\tif (collidable.collidable === false) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\taabb = collidable.aabb;\n\t\t\t\t\tif (aabb[0] < xmin) {\n\t\t\t\t\t\txmin = aabb[0];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[1] < ymin) {\n\t\t\t\t\t\tymin = aabb[1];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[2] < zmin) {\n\t\t\t\t\t\tzmin = aabb[2];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[3] > xmax) {\n\t\t\t\t\t\txmax = aabb[3];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[4] > ymax) {\n\t\t\t\t\t\tymax = aabb[4];\n\t\t\t\t\t}\n\t\t\t\t\tif (aabb[5] > zmax) {\n\t\t\t\t\t\tzmax = aabb[5];\n\t\t\t\t\t}\n\t\t\t\t\tvalid = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!valid) {\n\t\t\t\txmin = -100;\n\t\t\t\tymin = -100;\n\t\t\t\tzmin = -100;\n\t\t\t\txmax = 100;\n\t\t\t\tymax = 100;\n\t\t\t\tzmax = 100;\n\t\t\t}\n\t\t\tthis._aabb[0] = xmin;\n\t\t\tthis._aabb[1] = ymin;\n\t\t\tthis._aabb[2] = zmin;\n\t\t\tthis._aabb[3] = xmax;\n\t\t\tthis._aabb[4] = ymax;\n\t\t\tthis._aabb[5] = zmax;\n\t\t\tthis._aabbDirty = false;\n\t\t}\n\t\treturn this._aabb;\n\t}\n\n\t_setAABBDirty() {\n\t\t//if (!this._aabbDirty) {\n\t\tthis._aabbDirty = true;\n\t\tthis.fire(\"boundary\");\n\t\t// }\n\t}\n\n\t/**\n * Attempts to pick an {@link Entity} in this Scene.\n *\n * Ignores {@link Entity}s with {@link Entity#pickable} set ````false````.\n *\n * When an {@link Entity} is picked, fires a \"pick\" event on the {@link Entity} with the pick result as parameters.\n *\n * Picking the {@link Entity} at the given canvas coordinates:\n\n * ````javascript\n * var pickResult = scene.pick({\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an Entity\n * var entity = pickResult.entity;\n * }\n * ````\n *\n * Picking, with a ray cast through the canvas, hits an {@link Entity}:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true,\n * canvasPos: [23, 131]\n * });\n *\n * if (pickResult) { // Picked an Entity\n *\n * var entity = pickResult.entity;\n *\n * if (pickResult.primitive === \"triangle\") {\n *\n * // Picked a triangle on the entity surface\n *\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n *\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\n *\n * // Picked a point and normal on the entity surface\n *\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\n * }\n * }\n * ````\n *\n * Picking the {@link Entity} that intersects an arbitrarily-aligned World-space ray:\n *\n * ````javascript\n * var pickResult = scene.pick({\n * pickSurface: true, // Picking with arbitrarily-positioned ray\n * origin: [0,0,-5], // Ray origin\n * direction: [0,0,1] // Ray direction\n * });\n *\n * if (pickResult) { // Picked an Entity with the ray\n *\n * var entity = pickResult.entity;\n *\n * if (pickResult.primitive == \"triangle\") {\n *\n * // Picked a triangle on the entity surface\n *\n * var primitive = pickResult.primitive; // Type of primitive that was picked, usually \"triangles\"\n * var primIndex = pickResult.primIndex; // Position of triangle's first index in the picked Entity's Geometry's indices array\n * var indices = pickResult.indices; // UInt32Array containing the triangle's vertex indices\n * var localPos = pickResult.localPos; // Float64Array containing the picked Local-space position on the triangle\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the triangle\n * var viewPos = pickResult.viewPos; // Float64Array containing the picked View-space position on the triangle\n * var bary = pickResult.bary; // Float64Array containing the picked barycentric position within the triangle\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the interpolated World-space normal vector at the picked position on the triangle\n * var uv = pickResult.uv; // Float64Array containing the interpolated UV coordinates at the picked position on the triangle\n * var origin = pickResult.origin; // Float64Array containing the World-space ray origin\n * var direction = pickResult.direction; // Float64Array containing the World-space ray direction\n *\n * } else if (pickResult.worldPos && pickResult.worldNormal) {\n *\n * // Picked a point and normal on the entity surface\n *\n * var worldPos = pickResult.worldPos; // Float64Array containing the picked World-space position on the Entity surface\n * var worldNormal = pickResult.worldNormal; // Float64Array containing the picked World-space normal vector on the Entity Surface\n * }\n * }\n * ````\n *\n * @param {*} params Picking parameters.\n * @param {Boolean} [params.pickSurface=false] Whether to find the picked position on the surface of the Entity.\n * @param {Boolean} [params.pickSurfacePrecision=false] When picking an Entity surface position, indicates whether or not we want full-precision {@link PickResult#worldPos}. Only works when {@link Scene#pickSurfacePrecisionEnabled} is ````true````. If pick succeeds, the returned {@link PickResult} will have {@link PickResult#precision} set ````true````, to indicate that it contains full-precision surface pick results.\n * @param {Boolean} [params.pickSurfaceNormal=false] Whether to find the picked normal on the surface of the Entity. Only works if ````pickSurface```` is given.\n * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\n * @param {Number[]} [params.origin] World-space ray origin when ray-picking. Ignored when canvasPos given.\n * @param {Number[]} [params.direction] World-space ray direction when ray-picking. Also indicates the length of the ray. Ignored when canvasPos given.\n * @param {Number[]} [params.matrix] 4x4 transformation matrix to define the World-space ray origin and direction, as an alternative to ````origin```` and ````direction````.\n * @param {String[]} [params.includeEntities] IDs of {@link Entity}s to restrict picking to. When given, ignores {@link Entity}s whose IDs are not in this list.\n * @param {String[]} [params.excludeEntities] IDs of {@link Entity}s to ignore. When given, will pick *through* these {@link Entity}s, as if they were not there.\n * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\n * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\n * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\n * @param {PickResult} [pickResult] Holds the results of the pick attempt. Will use the Scene's singleton PickResult if you don't supply your own.\n * @returns {PickResult} Holds results of the pick attempt, returned when an {@link Entity} is picked, else null. See method comments for description.\n */\n\tpick(params, pickResult) {\n\t\tif (this.canvas.boundary[2] === 0 || this.canvas.boundary[3] === 0) {\n\t\t\tthis.error(\"Picking not allowed while canvas has zero width or height\");\n\t\t\treturn null;\n\t\t}\n\n\t\tparams = params || {};\n\n\t\tparams.pickSurface = params.pickSurface || params.rayPick; // Backwards compatibility\n\n\t\tif (!params.canvasPos && !params.matrix && (!params.origin || !params.direction)) {\n\t\t\tthis.warn(\"picking without canvasPos, matrix, or ray origin and direction\");\n\t\t}\n\n\t\tconst includeEntities = params.includeEntities || params.include; // Backwards compat\n\t\tif (includeEntities) {\n\t\t\tparams.includeEntityIds = getEntityIDMap(this, includeEntities);\n\t\t}\n\n\t\tconst excludeEntities = params.excludeEntities || params.exclude; // Backwards compat\n\t\tif (excludeEntities) {\n\t\t\tparams.excludeEntityIds = getEntityIDMap(this, excludeEntities);\n\t\t}\n\n\t\tif (this._needRecompile) {\n\t\t\tthis._recompile();\n\t\t\tthis._renderer.imageDirty();\n\t\t\tthis._needRecompile = false;\n\t\t}\n\n\t\tif (params.snapToEdge || params.snapToVertex) {\n\t\t\tpickResult = this._renderer.snapPick(\n\t\t\t\tparams.canvasPos,\n\t\t\t\tparams.snapRadius || 30,\n\t\t\t\tparams.snapToVertex,\n\t\t\t\tparams.snapToEdge,\n\t\t\t\tpickResult\n\t\t\t);\n\t\t} else {\n\t\t\tpickResult = this._renderer.pick(params, pickResult);\n\t\t}\n\n\t\tif (pickResult) {\n\t\t\tif (pickResult.entity && pickResult.entity.fire) {\n\t\t\t\tpickResult.entity.fire(\"picked\", pickResult); // TODO: SceneModelEntity doesn't fire events\n\t\t\t}\n\t\t}\n\n\t\treturn pickResult;\n\t}\n\n\t/**\n\t * @param {Object} params Picking parameters.\n\t * @param {Number[]} [params.canvasPos] Canvas-space coordinates. When ray-picking, this will override the **origin** and ** direction** parameters and will cause the ray to be fired through the canvas at this position, directly along the negative View-space Z-axis.\n\t * @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels\n\t * @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.\n\t * @param {boolean} [params.snapToEdge=true] Whether to snap to edge.\n\t * @deprecated\n\t */\n\tsnapPick(params) {\n\t\tif (undefined === this._warnSnapPickDeprecated) {\n\t\t\tthis._warnSnapPickDeprecated = true;\n\t\t\tthis.warn(\"Scene.snapPick() is deprecated since v2.4.2 - use Scene.pick() instead\");\n\t\t}\n\t\treturn this._renderer.snapPick(params.canvasPos, params.snapRadius || 30, params.snapToVertex, params.snapToEdge);\n\t}\n\n\t/**\n\t * Destroys all non-default {@link Component}s in this Scene.\n\t */\n\tclear() {\n\t\tvar component;\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tcomponent = this.components[id];\n\t\t\t\tif (!component._dontClear) {\n\t\t\t\t\t// Don't destroy components like Camera, Input, Viewport etc.\n\t\t\t\t\tcomponent.destroy();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Light}s in this Scene..\n\t */\n\tclearLights() {\n\t\tconst ids = Object.keys(this.lights);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.lights[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link SectionPlane}s in this Scene.\n\t */\n\tclearSectionPlanes() {\n\t\tconst ids = Object.keys(this.sectionPlanes);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.sectionPlanes[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Line}s in this Scene.\n\t */\n\tclearBitmaps() {\n\t\tconst ids = Object.keys(this.bitmaps);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.bitmaps[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Destroys all {@link Line}s in this Scene.\n\t */\n\tclearLines() {\n\t\tconst ids = Object.keys(this.lineSets);\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tthis.lineSets[ids[i]].destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Gets the collective axis-aligned boundary (AABB) of a batch of {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which {@link Entity#isObject} is registered by {@link Entity#id} in {@link Scene#visibleObjects}.\n\t *\n\t * Each {@link Entity} is only included in the AABB when {@link Entity#collidable} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @returns {[Number, Number, Number, Number, Number, Number]} An axis-aligned World-space bounding box, given as elements ````[xmin, ymin, zmin, xmax, ymax, zmax]````.\n\t */\n\tgetAABB(ids) {\n\t\tif (ids === undefined) {\n\t\t\treturn this.aabb;\n\t\t}\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\n\t\t\tconst entity = this.objects[ids];\n\t\t\tif (entity && entity.aabb) {\n\t\t\t\t// A Component subclass with an AABB\n\t\t\t\treturn entity.aabb;\n\t\t\t}\n\t\t\tids = [ids]; // Must be an entity type\n\t\t}\n\t\tif (ids.length === 0) {\n\t\t\treturn this.aabb;\n\t\t}\n\t\tlet xmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet ymin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet zmin = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MAX_DOUBLE;\n\t\tlet xmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet ymax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet zmax = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.MIN_DOUBLE;\n\t\tlet valid;\n\t\tthis.withObjects(ids, (entity) => {\n\t\t\tif (entity.collidable) {\n\t\t\t\tconst aabb = entity.aabb;\n\t\t\t\tif (aabb[0] < xmin) {\n\t\t\t\t\txmin = aabb[0];\n\t\t\t\t}\n\t\t\t\tif (aabb[1] < ymin) {\n\t\t\t\t\tymin = aabb[1];\n\t\t\t\t}\n\t\t\t\tif (aabb[2] < zmin) {\n\t\t\t\t\tzmin = aabb[2];\n\t\t\t\t}\n\t\t\t\tif (aabb[3] > xmax) {\n\t\t\t\t\txmax = aabb[3];\n\t\t\t\t}\n\t\t\t\tif (aabb[4] > ymax) {\n\t\t\t\t\tymax = aabb[4];\n\t\t\t\t}\n\t\t\t\tif (aabb[5] > zmax) {\n\t\t\t\t\tzmax = aabb[5];\n\t\t\t\t}\n\t\t\t\tvalid = true;\n\t\t\t}\n\t\t});\n\t\tif (valid) {\n\t\t\tconst aabb2 = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.AABB3();\n\t\t\taabb2[0] = xmin;\n\t\t\taabb2[1] = ymin;\n\t\t\taabb2[2] = zmin;\n\t\t\taabb2[3] = xmax;\n\t\t\taabb2[4] = ymax;\n\t\t\taabb2[5] = zmax;\n\t\t\treturn aabb2;\n\t\t} else {\n\t\t\treturn this.aabb; // Scene AABB\n\t\t}\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#visible} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#visible} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#visibleObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} visible Whether or not to set visible.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsVisible(ids, visible) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.visible !== visible;\n\t\t\tentity.visible = visible;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#collidable} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} collidable Whether or not to set collidable.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsCollidable(ids, collidable) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.collidable !== collidable;\n\t\t\tentity.collidable = collidable;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#culled} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} culled Whether or not to cull.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsCulled(ids, culled) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.culled !== culled;\n\t\t\tentity.culled = culled;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#selected} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#selected} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#selectedObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} selected Whether or not to select.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsSelected(ids, selected) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.selected !== selected;\n\t\t\tentity.selected = selected;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#highlighted} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * Each {@link Entity} on which both {@link Entity#isObject} and {@link Entity#highlighted} are ````true```` is\n\t * registered by {@link Entity#id} in {@link Scene#highlightedObjects}.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} highlighted Whether or not to highlight.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsHighlighted(ids, highlighted) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.highlighted !== highlighted;\n\t\t\tentity.highlighted = highlighted;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#xrayed} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} xrayed Whether or not to xray.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsXRayed(ids, xrayed) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.xrayed !== xrayed;\n\t\t\tentity.xrayed = xrayed;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#edges} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} edges Whether or not to show edges.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsEdges(ids, edges) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.edges !== edges;\n\t\t\tentity.edges = edges;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#colorize} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number[]} [colorize=(1,1,1)] RGB colorize factors, multiplied by the rendered pixel colors.\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsColorized(ids, colorize) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tentity.colorize = colorize;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#opacity} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number} [opacity=1.0] Opacity factor, multiplied by the rendered pixel alphas.\n\t * @returns {Boolean} True if any {@link Entity}s changed opacity, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsOpacity(ids, opacity) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.opacity !== opacity;\n\t\t\tentity.opacity = opacity;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#pickable} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Boolean} pickable Whether or not to set pickable.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\tsetObjectsPickable(ids, pickable) {\n\t\treturn this.withObjects(ids, (entity) => {\n\t\t\tconst changed = entity.pickable !== pickable;\n\t\t\tentity.pickable = pickable;\n\t\t\treturn changed;\n\t\t});\n\t}\n\n\t/**\n\t * Batch-updates {@link Entity#offset} on {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Number[]} [offset] 3D offset vector.\n\t */\n\tsetObjectsOffset(ids, offset) {\n\t\tthis.withObjects(ids, (entity) => {\n\t\t\tentity.offset = offset;\n\t\t});\n\t}\n\n\t/**\n\t * Iterates with a callback over {@link Entity}s that represent objects.\n\t *\n\t * An {@link Entity} represents an object when {@link Entity#isObject} is ````true````.\n\t *\n\t * @param {String[]} ids Array of {@link Entity#id} values.\n\t * @param {Function} callback Callback to execute on eacn {@link Entity}.\n\t * @returns {Boolean} True if any {@link Entity}s were updated, else false if all updates were redundant and not applied.\n\t */\n\twithObjects(ids, callback) {\n\t\tif (_utils_js__WEBPACK_IMPORTED_MODULE_2__.utils.isString(ids)) {\n\t\t\tids = [ids];\n\t\t}\n\t\tlet changed = false;\n\t\tfor (let i = 0, len = ids.length; i < len; i++) {\n\t\t\tconst id = ids[i];\n\t\t\tlet entity = this.objects[id];\n\t\t\tif (entity) {\n\t\t\t\tchanged = callback(entity) || changed;\n\t\t\t} else {\n\t\t\t\tconst modelIds = this.modelIds;\n\t\t\t\tfor (let i = 0, len = modelIds.length; i < len; i++) {\n\t\t\t\t\tconst modelId = modelIds[i];\n\t\t\t\t\tconst globalObjectId = _math_math_js__WEBPACK_IMPORTED_MODULE_3__.math.globalizeObjectId(modelId, id);\n\t\t\t\t\tentity = this.objects[globalObjectId];\n\t\t\t\t\tif (entity) {\n\t\t\t\t\t\tchanged = callback(entity) || changed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn changed;\n\t}\n\n\t/**\n\t * This method will \"tickify\" the provided `cb` function.\n\t *\n\t * This means, the function will be wrapped so:\n\t *\n\t * - it runs time-aligned to scene ticks\n\t * - it runs maximum once per scene-tick\n\t *\n\t * @param {Function} cb The function to tickify\n\t * @returns {Function}\n\t */\n\ttickify(cb) {\n\t\tconst cbString = cb.toString();\n\n\t\t/**\n\t\t * Check if the function is already tickified, and if so return the cached one.\n\t\t */\n\t\tif (cbString in this._tickifiedFunctions) {\n\t\t\treturn this._tickifiedFunctions[cbString].wrapperFunc;\n\t\t}\n\n\t\tlet alreadyRun = 0;\n\t\tlet needToRun = 0;\n\n\t\tlet lastArgs;\n\n\t\t/**\n\t\t * The provided `cb` function is replaced with a \"set-dirty\" function\n\t\t *\n\t\t * @type {Function}\n\t\t */\n\t\tconst wrapperFunc = function (...args) {\n\t\t\tlastArgs = args;\n\t\t\tneedToRun++;\n\t\t};\n\n\t\t/**\n\t\t * An each scene tick, if the \"dirty-flag\" is set, run the `cb` function.\n\t\t *\n\t\t * This will make it run time-aligned to the scene tick.\n\t\t */\n\t\tconst tickSubId = this.on(\"tick\", () => {\n\t\t\tconst tmp = needToRun;\n\t\t\tif (tmp > alreadyRun) {\n\t\t\t\talreadyRun = tmp;\n\t\t\t\tcb(...lastArgs);\n\t\t\t}\n\t\t});\n\n\t\t/**\n\t\t * And, store the list of subscribers.\n\t\t */\n\t\tthis._tickifiedFunctions[cbString] = { tickSubId, wrapperFunc };\n\n\t\treturn wrapperFunc;\n\t}\n\n\t/**\n\t * Destroys this Scene.\n\t */\n\tdestroy(callback) {\n\t\tsuper.destroy();\n\t\tfor (const id in this.components) {\n\t\t\tif (this.components.hasOwnProperty(id)) {\n\t\t\t\tthis.components[id].destroy();\n\t\t\t}\n\t\t}\n\t\t// this.canvas.destroy(); // canvas是scene的其中一个component,所有以不必再destroy\n\n\t\t// Memory leak prevention\n\t\tthis.components = null;\n\t\tthis.models = null;\n\t\tthis.objects = null;\n\t\tthis.visibleObjects = null;\n\t\tthis.xrayedObjects = null;\n\t\tthis.highlightedObjects = null;\n\t\tthis.selectedObjects = null;\n\t\tthis.colorizedObjects = null;\n\t\tthis.opacityObjects = null;\n\t\tthis.sectionPlanes = null;\n\t\tthis.lights = null;\n\t\tthis.lightMaps = null;\n\t\tthis.reflectionMaps = null;\n\t\tthis._objectIds = null;\n\t\tthis._visibleObjectIds = null;\n\t\tthis._xrayedObjectIds = null;\n\t\tthis._highlightedObjectIds = null;\n\t\tthis._selectedObjectIds = null;\n\t\tthis._colorizedObjectIds = null;\n\t\tthis.types = null;\n\t\tthis._renderer = null;\n\t\tthis.input = null;\n\t\tthis._viewport = null;\n\t\tthis._camera = null;\n\t\tthis.canvas = null;\n\t\tif (typeof callback === \"function\") {\n\t\t\tcallback();\n\t\t}\n\t}\n}\n\n\n\n\n//# sourceURL=webpack://@xtctwins/tctwins-core/./src/viewer/scene/scene/Scene.js?");
|
|
4808
4808
|
|
|
4809
4809
|
/***/ }),
|
|
4810
4810
|
|