@xtctwins/tctwins-core 1.0.31 → 1.0.32
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.
|
@@ -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.author) this.author = metaModelData.author;\r\n\t\t\tif (metaModelData.schema) this.schema = metaModelData.schema;\r\n\t\t\tif (metaModelData.createdAt) this.createdAt = metaModelData.createdAt;\r\n\t\t\tif (metaModelData.projectId) this.projectId = metaModelData.projectId;\r\n\t\t\tif (metaModelData.revisionId) this.revisionId = metaModelData.revisionId;\r\n\t\t\tif (metaModelData.objectCount) this.objectCount = metaModelData.objectCount;\r\n\t\t\tif (metaModelData.propertySetCount) this.propertySetCount = metaModelData.propertySetCount;\r\n\t\t\tif (metaModelData.creatingApplication) this.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
|
|
|
@@ -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
|
|