@collabdt/core 0.0.42 → 0.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/components/Toolbar.d.ts.map +1 -1
- package/dist/core/components/Toolbar.js.map +1 -1
- package/dist/core/components/ToolbarBody.js.map +1 -1
- package/dist/core/components/TopNavigationBar.js.map +1 -1
- package/dist/core/components/authentication/ForgotPassword.js.map +1 -1
- package/dist/core/components/authentication/Signin.js.map +1 -1
- package/dist/core/components/authentication/Signup.js.map +1 -1
- package/dist/core/components/settings/src/OrganizationSkeleton.js.map +1 -1
- package/dist/core/components/settings/src/SettingsSkeleton.js.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.js.map +1 -1
- package/dist/core/components/ui/DataTable.d.ts.map +1 -1
- package/dist/core/components/ui/DataTable.js +7 -0
- package/dist/core/components/ui/DataTable.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileItemComponent.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileItemComponent.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileMarker.d.ts +5 -2
- package/dist/core/components/ui/FilesManager/src/FileMarker.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/FileMarker.js +84 -21
- package/dist/core/components/ui/FilesManager/src/FileMarker.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/convertIfcToFragmentsFile.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/convertIfcToFragmentsFile.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadHandler.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadHandler.js.map +1 -1
- package/dist/core/components/ui/Icons/IfcIcon.d.ts.map +1 -1
- package/dist/core/components/ui/Icons/IfcIcon.js.map +1 -1
- package/dist/core/components/ui/InfoSidebar/index.d.ts.map +1 -1
- package/dist/core/components/ui/InfoSidebar/index.js.map +1 -1
- package/dist/core/components/ui/Navbar.d.ts.map +1 -1
- package/dist/core/components/ui/Navbar.js.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
- package/dist/core/components/ui/ShareFeature/ShareToolSubmenu.d.ts.map +1 -1
- package/dist/core/components/ui/ShareFeature/ShareToolSubmenu.js.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js +2 -2
- package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js +2 -2
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js.map +1 -1
- package/dist/core/components/viewers/Viewer.d.ts.map +1 -1
- package/dist/core/components/viewers/Viewer.js +5 -1
- package/dist/core/components/viewers/Viewer.js.map +1 -1
- package/dist/core/components/viewers/bim/BimToolbar.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/BimToolbar.js.map +1 -1
- package/dist/core/components/viewers/bim/BimViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/BimViewer.js +14 -5
- package/dist/core/components/viewers/bim/BimViewer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimLoadingState/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimLoadingState/index.js +6 -0
- package/dist/core/components/viewers/bim/src/BimLoadingState/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +168 -39
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts +14 -37
- package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/DXFLoader/index.js +31 -318
- package/dist/core/components/viewers/bim/src/DXFLoader/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts +66 -7
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.js +253 -21
- package/dist/core/components/viewers/bim/src/FloorplanTool/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/ModelManager/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/ModelManager/index.js +9 -0
- package/dist/core/components/viewers/bim/src/ModelManager/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/SimpleBimViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/SimpleBimViewer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts +3 -2
- package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.js.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js +3 -4
- package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +40 -18
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts +2 -5
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js +45 -59
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts +10 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js +25 -73
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts +7 -3
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js +42 -78
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js +52 -75
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts +15 -3
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js +165 -105
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js.map +1 -1
- package/dist/core/components/viewers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/index.js.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.js +1 -0
- package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/DatasetManager/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/DatasetManager/index.js +4 -3
- package/dist/core/components/viewers/map/datasets/DatasetManager/index.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/RowActions.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/RowActions.js +148 -0
- package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/index.js +32 -15
- package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts +4 -0
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js +43 -0
- package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js +39 -3
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts +1 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.js +2 -1
- package/dist/core/components/viewers/map/datasets/src/minioDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts +47 -0
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.js +114 -0
- package/dist/core/components/viewers/map/datasets/src/publishedTiles.js.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts +49 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts.map +1 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.js +100 -0
- package/dist/core/components/viewers/map/datasets/src/wmsTime.js.map +1 -0
- package/dist/core/components/viewers/map/src/Geocoder.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/Geocoder.js +9 -9
- package/dist/core/components/viewers/map/src/Geocoder.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +25 -43
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js +19 -2
- package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts +9 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js +28 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js +1 -16
- package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js +31 -2
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts +21 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js +111 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js +77 -2
- package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js +10 -3
- package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoder.d.ts +6 -2
- package/dist/core/components/viewers/map/utils/geocoder.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoder.js +10 -62
- package/dist/core/components/viewers/map/utils/geocoder.js.map +1 -1
- package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts +5 -0
- package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/adapters.js +192 -0
- package/dist/core/components/viewers/map/utils/geocoding/adapters.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.d.ts +6 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.js +14 -0
- package/dist/core/components/viewers/map/utils/geocoding/config.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.d.ts +8 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.js +44 -0
- package/dist/core/components/viewers/map/utils/geocoding/index.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts +6 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.js +39 -0
- package/dist/core/components/viewers/map/utils/geocoding/osm.js.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts +8 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts.map +1 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.js +35 -0
- package/dist/core/components/viewers/map/utils/geocoding/pelias.js.map +1 -0
- package/dist/core/components/viewers/pointcloud/PointCloudToolbar.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/PointCloudToolbar.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/PointCloudViewer.js +1 -3
- package/dist/core/components/viewers/pointcloud/PointCloudViewer.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +2 -3
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js +8 -2
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js +9 -9
- package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js.map +1 -1
- package/dist/core/hooks/provider.js.map +1 -1
- package/dist/core/plugins/host/provider.d.ts.map +1 -1
- package/dist/core/plugins/host/provider.js.map +1 -1
- package/dist/core/store/AppConfig/context.d.ts.map +1 -1
- package/dist/core/store/AppConfig/context.js.map +1 -1
- package/dist/core/store/BIM/context.d.ts.map +1 -1
- package/dist/core/store/BIM/context.js.map +1 -1
- package/dist/core/store/BIM/reducer.d.ts +0 -1
- package/dist/core/store/BIM/reducer.d.ts.map +1 -1
- package/dist/core/store/BIM/reducer.js +0 -4
- package/dist/core/store/BIM/reducer.js.map +1 -1
- package/dist/core/store/Buildings/context.d.ts.map +1 -1
- package/dist/core/store/Buildings/context.js.map +1 -1
- package/dist/core/store/Content/context.d.ts.map +1 -1
- package/dist/core/store/Content/context.js.map +1 -1
- package/dist/core/store/Datasets/context.d.ts.map +1 -1
- package/dist/core/store/Datasets/context.js +2 -1
- package/dist/core/store/Datasets/context.js.map +1 -1
- package/dist/core/store/Datasets/reducer.d.ts +2 -0
- package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
- package/dist/core/store/Datasets/reducer.js +9 -4
- package/dist/core/store/Datasets/reducer.js.map +1 -1
- package/dist/core/store/Files/context.d.ts.map +1 -1
- package/dist/core/store/Files/context.js.map +1 -1
- package/dist/core/store/Map/context.d.ts.map +1 -1
- package/dist/core/store/Map/context.js.map +1 -1
- package/dist/core/store/Menus/context.d.ts.map +1 -1
- package/dist/core/store/Menus/context.js.map +1 -1
- package/dist/core/store/Permissions/context.d.ts.map +1 -1
- package/dist/core/store/Permissions/context.js.map +1 -1
- package/dist/core/store/PointCloud/context.d.ts.map +1 -1
- package/dist/core/store/PointCloud/context.js.map +1 -1
- package/dist/core/store/Tools/context.d.ts.map +1 -1
- package/dist/core/store/Tools/context.js.map +1 -1
- package/dist/core/types/datasetTypes.d.ts +8 -1
- package/dist/core/types/datasetTypes.d.ts.map +1 -1
- package/dist/core/types/dbTypes.d.ts +13 -13
- package/dist/core/types/dbTypes.d.ts.map +1 -1
- package/dist/core/types/dbTypes.js +13 -13
- package/dist/core/types/dbTypes.js.map +1 -1
- package/dist/core/types/index.d.ts +1 -1
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js.map +1 -1
- package/dist/core/utils/imageUtils.js +1 -1
- package/dist/core/utils/imageUtils.js.map +1 -1
- package/package.json +4 -3
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts +0 -3
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts.map +0 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js +0 -173
- package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js.map +0 -1
|
@@ -53,8 +53,26 @@ const _FloorplanTool = class _FloorplanTool extends OBC.Component {
|
|
|
53
53
|
/** True-north rotation in degrees (clockwise from default screen-up).
|
|
54
54
|
* Persists across storey switches but resets to 0 on tool dispose. */
|
|
55
55
|
this._northAngle = 0;
|
|
56
|
+
/** True while the user is drawing the two-point north line. */
|
|
56
57
|
this._pickingNorth = false;
|
|
57
58
|
this._pickHandler = null;
|
|
59
|
+
this._moveHandler = null;
|
|
60
|
+
this._keyHandler = null;
|
|
61
|
+
/** First clicked point of the north line, in drawing-local space (Y=0).
|
|
62
|
+
* Null until the user places the first point. */
|
|
63
|
+
this._drawStart = null;
|
|
64
|
+
/** Cached snap targets — projected-geometry vertices flattened as
|
|
65
|
+
* [x0,z0, x1,z1, …] in drawing-local space. Rebuilt each time draw mode
|
|
66
|
+
* starts so it reflects the active storey's lines. */
|
|
67
|
+
this._snapVerts = null;
|
|
68
|
+
/** Rubber-band preview line + cursor snap marker, parented to the active
|
|
69
|
+
* drawing so they inherit its world transform. */
|
|
70
|
+
this._previewLine = null;
|
|
71
|
+
this._snapMarker = null;
|
|
72
|
+
/** Canvas cursor before draw mode swapped in the crosshair — typically the
|
|
73
|
+
* floorplan-mode "grab" hand. Restored (not cleared) on exit so panning
|
|
74
|
+
* keeps the hand; only leaving floorplan mode reverts to the default. */
|
|
75
|
+
this._savedPickCursor = null;
|
|
58
76
|
components.add(_FloorplanTool.uuid, this);
|
|
59
77
|
this.projector = new StoreyProjector(components);
|
|
60
78
|
this.renderer = new FloorplanRenderer(components, this.projector);
|
|
@@ -222,61 +240,275 @@ const _FloorplanTool = class _FloorplanTool extends OBC.Component {
|
|
|
222
240
|
this.onNorthAngleChanged.trigger(normalized);
|
|
223
241
|
if (this._activeId) this._applyNorthToCamera();
|
|
224
242
|
}
|
|
225
|
-
/** Enter
|
|
226
|
-
*
|
|
227
|
-
*
|
|
243
|
+
/** Enter two-point draw mode. The user clicks two points on the active
|
|
244
|
+
* floorplan (each snapped to the nearest projected-geometry vertex); the
|
|
245
|
+
* bearing of the segment between them becomes the new true-north angle.
|
|
246
|
+
* A rubber-band preview + snap marker track the cursor; Esc cancels.
|
|
247
|
+
* No-op if no floorplan is active. */
|
|
228
248
|
startPickNorth() {
|
|
229
249
|
if (this._pickingNorth || !this._activeId) return;
|
|
250
|
+
const entry = this.activeDrawing;
|
|
230
251
|
const world = this.components.get(CurrentWorld).world;
|
|
231
|
-
if (!(world == null ? void 0 : world.renderer)) return;
|
|
252
|
+
if (!(entry == null ? void 0 : entry.drawing) || !(world == null ? void 0 : world.renderer)) return;
|
|
232
253
|
const canvas = world.renderer.three.domElement;
|
|
254
|
+
this._drawStart = null;
|
|
255
|
+
this._snapVerts = this._collectSnapVertices(entry);
|
|
233
256
|
this._pickHandler = (e) => this._onPickClick(e);
|
|
257
|
+
this._moveHandler = (e) => this._onPickMove(e);
|
|
258
|
+
this._keyHandler = (e) => {
|
|
259
|
+
if (e.key === "Escape") this.cancelPickNorth();
|
|
260
|
+
};
|
|
234
261
|
canvas.addEventListener("click", this._pickHandler);
|
|
262
|
+
canvas.addEventListener("mousemove", this._moveHandler);
|
|
263
|
+
window.addEventListener("keydown", this._keyHandler);
|
|
264
|
+
this._savedPickCursor = canvas.style.cursor;
|
|
235
265
|
canvas.style.cursor = "crosshair";
|
|
236
266
|
this._pickingNorth = true;
|
|
237
267
|
this.onPickingNorthChanged.trigger(true);
|
|
238
268
|
}
|
|
239
|
-
/** Exit
|
|
269
|
+
/** Exit draw mode without applying any rotation. Tears down the canvas
|
|
270
|
+
* listeners and removes the rubber-band preview. */
|
|
240
271
|
cancelPickNorth() {
|
|
241
|
-
var _a, _b;
|
|
272
|
+
var _a, _b, _c;
|
|
242
273
|
if (!this._pickingNorth) return;
|
|
243
274
|
const world = this.components.get(CurrentWorld).world;
|
|
244
275
|
const canvas = (_b = (_a = world == null ? void 0 : world.renderer) == null ? void 0 : _a.three.domElement) != null ? _b : null;
|
|
245
|
-
if (canvas
|
|
246
|
-
canvas.removeEventListener("click", this._pickHandler);
|
|
247
|
-
canvas.
|
|
276
|
+
if (canvas) {
|
|
277
|
+
if (this._pickHandler) canvas.removeEventListener("click", this._pickHandler);
|
|
278
|
+
if (this._moveHandler) canvas.removeEventListener("mousemove", this._moveHandler);
|
|
279
|
+
canvas.style.cursor = (_c = this._savedPickCursor) != null ? _c : "grab";
|
|
248
280
|
}
|
|
281
|
+
this._savedPickCursor = null;
|
|
282
|
+
if (this._keyHandler) window.removeEventListener("keydown", this._keyHandler);
|
|
249
283
|
this._pickHandler = null;
|
|
284
|
+
this._moveHandler = null;
|
|
285
|
+
this._keyHandler = null;
|
|
286
|
+
this._drawStart = null;
|
|
287
|
+
this._snapVerts = null;
|
|
288
|
+
this._clearPreview();
|
|
250
289
|
this._pickingNorth = false;
|
|
251
290
|
this.onPickingNorthChanged.trigger(false);
|
|
252
291
|
}
|
|
253
|
-
/** Click handler
|
|
254
|
-
*
|
|
255
|
-
* (
|
|
292
|
+
/** Click handler for draw mode. First click places the start point; the
|
|
293
|
+
* second rotates the view so the drawn segment becomes parallel to the
|
|
294
|
+
* screen X-axis (horizontal). Both points lie on the drawing's horizontal
|
|
295
|
+
* plane (Y=0), so only the in-plane direction matters. */
|
|
256
296
|
_onPickClick(event) {
|
|
257
297
|
const entry = this.activeDrawing;
|
|
258
298
|
if (!(entry == null ? void 0 : entry.drawing)) return;
|
|
299
|
+
const local = this._eventToLocalPoint(event, entry);
|
|
300
|
+
if (!local) return;
|
|
301
|
+
const point = this._snap(local);
|
|
302
|
+
if (!this._drawStart) {
|
|
303
|
+
this._drawStart = point;
|
|
304
|
+
this._updatePreview(entry, point);
|
|
305
|
+
this._requestUpdate();
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const dx = point.x - this._drawStart.x;
|
|
309
|
+
const dz = point.z - this._drawStart.z;
|
|
310
|
+
if (dx * dx + dz * dz < 1e-6) return;
|
|
311
|
+
const drawing = entry.drawing;
|
|
312
|
+
drawing.three.updateWorldMatrix(true, false);
|
|
313
|
+
const aWorld = drawing.three.localToWorld(this._drawStart.clone());
|
|
314
|
+
const bWorld = drawing.three.localToWorld(point.clone());
|
|
315
|
+
const azimuthDeg = this._azimuthToAlignLineToX(aWorld, bWorld);
|
|
316
|
+
if (azimuthDeg !== null) this.setNorthAngle(azimuthDeg);
|
|
317
|
+
this.cancelPickNorth();
|
|
318
|
+
}
|
|
319
|
+
/** Camera azimuth (degrees) that rotates the top-down view so the world
|
|
320
|
+
* segment a→b lands parallel to the screen X-axis (horizontal).
|
|
321
|
+
*
|
|
322
|
+
* Derivation: with the standard Y-up spherical convention camera-controls
|
|
323
|
+
* uses, the camera's screen-right world direction has angle ρ = −θ + C
|
|
324
|
+
* (θ = azimuth). We measure ρ₀ and θ₀ from the live camera so C cancels —
|
|
325
|
+
* making the result independent of the drawing's orientation and the
|
|
326
|
+
* controls' up-space. We then solve ρ(θ) = λ (the segment's world angle),
|
|
327
|
+
* giving θ = ρ₀ + θ₀ − λ. Returns null if the controls are unavailable. */
|
|
328
|
+
_azimuthToAlignLineToX(aWorld, bWorld) {
|
|
329
|
+
var _a, _b;
|
|
330
|
+
const world = this.components.get(CurrentWorld).world;
|
|
331
|
+
const cam = (_a = world == null ? void 0 : world.camera) == null ? void 0 : _a.three;
|
|
332
|
+
const controls = (_b = world == null ? void 0 : world.camera) == null ? void 0 : _b.controls;
|
|
333
|
+
if (!cam || typeof (controls == null ? void 0 : controls.azimuthAngle) !== "number") return null;
|
|
334
|
+
const lx = bWorld.x - aWorld.x;
|
|
335
|
+
const lz = bWorld.z - aWorld.z;
|
|
336
|
+
if (lx * lx + lz * lz < 1e-12) return null;
|
|
337
|
+
const lambda = Math.atan2(lz, lx);
|
|
338
|
+
cam.updateMatrixWorld();
|
|
339
|
+
const e = cam.matrixWorld.elements;
|
|
340
|
+
const rho0 = Math.atan2(e[2], e[0]);
|
|
341
|
+
const theta0 = controls.azimuthAngle;
|
|
342
|
+
return (rho0 + theta0 - lambda) * 180 / Math.PI;
|
|
343
|
+
}
|
|
344
|
+
/** Mousemove handler for draw mode — keeps the snap marker (and, after the
|
|
345
|
+
* first click, the rubber-band line) glued to the cursor's snapped point. */
|
|
346
|
+
_onPickMove(event) {
|
|
347
|
+
const entry = this.activeDrawing;
|
|
348
|
+
if (!(entry == null ? void 0 : entry.drawing)) return;
|
|
349
|
+
const local = this._eventToLocalPoint(event, entry);
|
|
350
|
+
if (!local) return;
|
|
351
|
+
this._updatePreview(entry, this._snap(local));
|
|
352
|
+
this._requestUpdate();
|
|
353
|
+
}
|
|
354
|
+
/** Convert a canvas mouse event into a point on the drawing plane, in
|
|
355
|
+
* drawing-local space (XZ plane, Y=0). Casts a ray from the active camera,
|
|
356
|
+
* transforms it into the drawing's local frame, and intersects Y=0. */
|
|
357
|
+
_eventToLocalPoint(event, entry) {
|
|
259
358
|
const world = this.components.get(CurrentWorld).world;
|
|
260
|
-
if (!(world == null ? void 0 : world.renderer) || !
|
|
359
|
+
if (!(world == null ? void 0 : world.renderer) || !world.camera || !entry.drawing) return null;
|
|
261
360
|
const canvas = world.renderer.three.domElement;
|
|
262
361
|
const rect = canvas.getBoundingClientRect();
|
|
263
362
|
const x = (event.clientX - rect.left) / rect.width * 2 - 1;
|
|
264
363
|
const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
|
265
364
|
const raycaster = new THREE.Raycaster();
|
|
266
|
-
raycaster.params.Line.threshold = 0.5;
|
|
267
365
|
raycaster.setFromCamera(
|
|
268
366
|
new THREE.Vector2(x, y),
|
|
269
367
|
world.camera.three
|
|
270
368
|
);
|
|
271
|
-
const
|
|
272
|
-
|
|
369
|
+
const drawing = entry.drawing;
|
|
370
|
+
drawing.three.updateWorldMatrix(true, false);
|
|
371
|
+
const inv = new THREE.Matrix4().copy(drawing.three.matrixWorld).invert();
|
|
372
|
+
const origin = raycaster.ray.origin.clone().applyMatrix4(inv);
|
|
373
|
+
const dir = raycaster.ray.direction.clone().transformDirection(inv);
|
|
374
|
+
if (Math.abs(dir.y) < 1e-9) return null;
|
|
375
|
+
const t = -origin.y / dir.y;
|
|
376
|
+
if (!Number.isFinite(t)) return null;
|
|
377
|
+
return new THREE.Vector3(
|
|
378
|
+
origin.x + dir.x * t,
|
|
379
|
+
0,
|
|
380
|
+
origin.z + dir.z * t
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
/** Snap a drawing-local point to the nearest projected-geometry vertex
|
|
384
|
+
* within the snap radius; returns the point unchanged if none is close. */
|
|
385
|
+
_snap(local) {
|
|
386
|
+
const verts = this._snapVerts;
|
|
387
|
+
if (!verts) return local;
|
|
388
|
+
const radius = this._snapRadiusLocal();
|
|
389
|
+
let best = -1;
|
|
390
|
+
let bestD2 = radius * radius;
|
|
391
|
+
for (let i = 0; i < verts.length; i += 2) {
|
|
392
|
+
const dx = verts[i] - local.x;
|
|
393
|
+
const dz = verts[i + 1] - local.z;
|
|
394
|
+
const d2 = dx * dx + dz * dz;
|
|
395
|
+
if (d2 < bestD2) {
|
|
396
|
+
bestD2 = d2;
|
|
397
|
+
best = i;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (best < 0) return local;
|
|
401
|
+
return new THREE.Vector3(verts[best], 0, verts[best + 1]);
|
|
402
|
+
}
|
|
403
|
+
/** Snap radius in drawing-local units (= world units; the drawing is
|
|
404
|
+
* unscaled), derived from a fixed ~12 px tolerance at the current ortho
|
|
405
|
+
* zoom so it feels consistent as the user zooms. */
|
|
406
|
+
_snapRadiusLocal() {
|
|
407
|
+
var _a, _b;
|
|
408
|
+
const SNAP_PX = 12;
|
|
409
|
+
const FALLBACK = 0.5;
|
|
410
|
+
const world = this.components.get(CurrentWorld).world;
|
|
411
|
+
const cam = (_a = world == null ? void 0 : world.camera) == null ? void 0 : _a.three;
|
|
412
|
+
const canvas = (_b = world == null ? void 0 : world.renderer) == null ? void 0 : _b.three.domElement;
|
|
413
|
+
if (!(cam == null ? void 0 : cam.isOrthographicCamera) || !canvas) return FALLBACK;
|
|
414
|
+
const worldWidth = (cam.right - cam.left) / (cam.zoom || 1);
|
|
415
|
+
const worldPerPixel = worldWidth / Math.max(1, canvas.clientWidth);
|
|
416
|
+
return worldPerPixel * SNAP_PX || FALLBACK;
|
|
417
|
+
}
|
|
418
|
+
/** Flatten every visible projected line vertex into drawing-local [x,z]
|
|
419
|
+
* pairs for endpoint snapping. Each vertex is transformed through its
|
|
420
|
+
* owning object's world matrix into the drawing's local frame, so it
|
|
421
|
+
* works regardless of how layers nest the `LineSegments`. */
|
|
422
|
+
_collectSnapVertices(entry) {
|
|
423
|
+
const drawing = entry.drawing;
|
|
424
|
+
if (!drawing) return null;
|
|
425
|
+
drawing.three.updateWorldMatrix(true, true);
|
|
426
|
+
const inv = new THREE.Matrix4().copy(drawing.three.matrixWorld).invert();
|
|
427
|
+
const v = new THREE.Vector3();
|
|
428
|
+
const out = [];
|
|
429
|
+
drawing.three.traverse((child) => {
|
|
430
|
+
var _a, _b, _c;
|
|
431
|
+
if (!(child instanceof THREE.LineSegments) || !child.visible) return;
|
|
432
|
+
if ((_a = child.userData) == null ? void 0 : _a.isDimension) return;
|
|
433
|
+
const pos = (_c = (_b = child.geometry) == null ? void 0 : _b.attributes) == null ? void 0 : _c.position;
|
|
434
|
+
if (!pos) return;
|
|
435
|
+
for (let i = 0; i < pos.count; i++) {
|
|
436
|
+
v.set(pos.getX(i), pos.getY(i), pos.getZ(i)).applyMatrix4(child.matrixWorld).applyMatrix4(inv);
|
|
437
|
+
out.push(v.x, v.z);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
return out.length ? new Float32Array(out) : null;
|
|
441
|
+
}
|
|
442
|
+
/** Update (creating on first use) the cursor snap marker and, once the
|
|
443
|
+
* first point is placed, the rubber-band line from start → cursor. Both
|
|
444
|
+
* live in drawing-local space, Y=0. */
|
|
445
|
+
_updatePreview(entry, current) {
|
|
446
|
+
const drawing = entry.drawing;
|
|
447
|
+
if (!drawing) return;
|
|
448
|
+
const COLOR = 2450411;
|
|
449
|
+
if (!this._snapMarker) {
|
|
450
|
+
const geom = new THREE.BufferGeometry();
|
|
451
|
+
geom.setAttribute(
|
|
452
|
+
"position",
|
|
453
|
+
new THREE.Float32BufferAttribute(
|
|
454
|
+
new Float32Array([-1, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 1]),
|
|
455
|
+
3
|
|
456
|
+
)
|
|
457
|
+
);
|
|
458
|
+
this._snapMarker = new THREE.LineSegments(
|
|
459
|
+
geom,
|
|
460
|
+
new THREE.LineBasicMaterial({ color: COLOR })
|
|
461
|
+
);
|
|
462
|
+
this._snapMarker.renderOrder = 999;
|
|
463
|
+
drawing.three.add(this._snapMarker);
|
|
464
|
+
}
|
|
465
|
+
const arm = this._snapRadiusLocal();
|
|
466
|
+
this._snapMarker.scale.setScalar(arm);
|
|
467
|
+
this._snapMarker.position.set(current.x, 0, current.z);
|
|
468
|
+
this._snapMarker.visible = true;
|
|
469
|
+
if (!this._drawStart) {
|
|
470
|
+
if (this._previewLine) this._previewLine.visible = false;
|
|
273
471
|
return;
|
|
274
472
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
473
|
+
if (!this._previewLine) {
|
|
474
|
+
const geom = new THREE.BufferGeometry();
|
|
475
|
+
geom.setAttribute(
|
|
476
|
+
"position",
|
|
477
|
+
new THREE.Float32BufferAttribute(new Float32Array(6), 3)
|
|
478
|
+
);
|
|
479
|
+
this._previewLine = new THREE.Line(
|
|
480
|
+
geom,
|
|
481
|
+
new THREE.LineBasicMaterial({ color: COLOR })
|
|
482
|
+
);
|
|
483
|
+
this._previewLine.renderOrder = 999;
|
|
484
|
+
drawing.three.add(this._previewLine);
|
|
485
|
+
}
|
|
486
|
+
const pos = this._previewLine.geometry.attributes.position;
|
|
487
|
+
pos.setXYZ(0, this._drawStart.x, 0, this._drawStart.z);
|
|
488
|
+
pos.setXYZ(1, current.x, 0, current.z);
|
|
489
|
+
pos.needsUpdate = true;
|
|
490
|
+
this._previewLine.visible = true;
|
|
491
|
+
}
|
|
492
|
+
/** Remove + dispose the preview line and snap marker. Uses each object's
|
|
493
|
+
* own parent so it stays correct even when called from deactivate(),
|
|
494
|
+
* where `_activeId` is already null. */
|
|
495
|
+
_clearPreview() {
|
|
496
|
+
var _a, _b;
|
|
497
|
+
if (this._previewLine) {
|
|
498
|
+
(_a = this._previewLine.parent) == null ? void 0 : _a.remove(this._previewLine);
|
|
499
|
+
this._previewLine.geometry.dispose();
|
|
500
|
+
const m = this._previewLine.material;
|
|
501
|
+
if (!Array.isArray(m)) m.dispose();
|
|
502
|
+
this._previewLine = null;
|
|
503
|
+
}
|
|
504
|
+
if (this._snapMarker) {
|
|
505
|
+
(_b = this._snapMarker.parent) == null ? void 0 : _b.remove(this._snapMarker);
|
|
506
|
+
this._snapMarker.geometry.dispose();
|
|
507
|
+
const m = this._snapMarker.material;
|
|
508
|
+
if (!Array.isArray(m)) m.dispose();
|
|
509
|
+
this._snapMarker = null;
|
|
510
|
+
}
|
|
511
|
+
this._requestUpdate();
|
|
280
512
|
}
|
|
281
513
|
/** Push `_northAngle` into the camera-controls azimuth so the view
|
|
282
514
|
* rotates around the active floor's centre. Called on every activate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../src/core/components/viewers/bim/src/FloorplanTool/index.ts"],"sourcesContent":["import * as OBC from '@thatopen/components'\r\nimport * as OBF from '@thatopen/components-front'\r\nimport * as THREE from 'three'\r\nimport { CurrentWorld } from '../CurrentWorld'\r\nimport { CameraController } from '../lib/CameraController'\r\nimport { ChromeController } from '../lib/ChromeController'\r\nimport { ClipController } from '../lib/ClipController'\r\nimport { CUT_CLASSES, FILL_CLASSES } from '../lib/drawingLayers'\r\nimport { disposeDrawing } from '../lib/drawingProjection'\r\nimport { GridController } from '../lib/GridController'\r\nimport { safeRun, safeRunAsync } from '../lib/safeRun'\r\nimport { stagePercent, ViewLoadingState } from '../lib/viewSection'\r\nimport { ViewModeCoordinator } from '../lib/ViewModeCoordinator'\r\nimport { FloorplanRenderer, RenderStage } from './src/FloorplanRenderer'\r\nimport { StoreyProjector } from './src/StoreyProjector'\r\nimport { CUT_COLOR, FILL_COLOR, FloorplanEntry, FLOORPLAN_TOOL_UUID } from './src/types'\r\nimport { normalizeElevation } from './src/utils'\r\n\r\nconst SLOT_SECTION = 'floorplan:section'\r\nconst SLOT_LOWER = 'floorplan:lower'\r\n\r\nexport type { FloorplanEntry } from './src/types'\r\n\r\nexport type FloorplanLoadingStage =\r\n | 'init'\r\n | 'readingStoreys'\r\n | RenderStage\r\n | 'project'\r\n | 'done'\r\n\r\nexport type FloorplanLoadingState = ViewLoadingState<FloorplanLoadingStage>\r\n\r\nconst STAGE_PERCENT: Record<FloorplanLoadingStage, number> = {\r\n init: 5,\r\n readingStoreys: 10,\r\n resolve: 20,\r\n cull: 35,\r\n switching: 35,\r\n cut: 55,\r\n fill: 75,\r\n project: 90,\r\n done: 100,\r\n}\r\n\r\nexport function getFloorplanStagePercent(\r\n stage: FloorplanLoadingStage | undefined,\r\n): number {\r\n return stagePercent(stage, STAGE_PERCENT)\r\n}\r\n\r\nexport class FloorplanTool extends OBC.Component {\r\n static uuid = FLOORPLAN_TOOL_UUID\r\n\r\n enabled = false\r\n\r\n readonly onDrawingsChanged = new OBC.Event<FloorplanEntry[]>()\r\n readonly onActiveDrawingChanged = new OBC.Event<FloorplanEntry | null>()\r\n readonly onGenerationStateChanged = new OBC.Event<FloorplanLoadingState>()\r\n /** Fires whenever an entry's layer metadata changes (toggle / color). */\r\n readonly onLayersChanged = new OBC.Event<FloorplanEntry>()\r\n /** Fires when the building's true-north angle (in degrees) is updated. */\r\n readonly onNorthAngleChanged = new OBC.Event<number>()\r\n /** Fires when line-pick mode toggles on/off. */\r\n readonly onPickingNorthChanged = new OBC.Event<boolean>()\r\n\r\n private _entries = new Map<string, FloorplanEntry>()\r\n private _activeId: string | null = null\r\n /** Sequence guard: when activate() is called multiple times in quick\r\n * succession (e.g. user clicks two storeys), only the last call applies\r\n * its final state. Prior calls bail out at await boundaries. */\r\n private _activateSeq = 0\r\n /** True-north rotation in degrees (clockwise from default screen-up).\r\n * Persists across storey switches but resets to 0 on tool dispose. */\r\n private _northAngle = 0\r\n private _pickingNorth = false\r\n private _pickHandler: ((e: MouseEvent) => void) | null = null\r\n\r\n private projector: StoreyProjector\r\n private renderer: FloorplanRenderer\r\n private camera: CameraController\r\n private chrome: ChromeController\r\n private clip: ClipController\r\n private grid: GridController\r\n\r\n constructor(components: OBC.Components) {\r\n super(components)\r\n components.add(FloorplanTool.uuid, this)\r\n\r\n this.projector = new StoreyProjector(components)\r\n this.renderer = new FloorplanRenderer(components, this.projector)\r\n this.camera = new CameraController(components)\r\n this.chrome = new ChromeController(components)\r\n this.clip = new ClipController(components)\r\n this.grid = new GridController(components)\r\n\r\n const fragments = components.get(OBC.FragmentsManager)\r\n fragments.core.onModelLoaded.add((model) => {\r\n void this.generate(model.modelId)\r\n })\r\n }\r\n\r\n get drawings(): FloorplanEntry[] {\r\n return Array.from(this._entries.values()).sort(\r\n (a, b) => a.elevation - b.elevation,\r\n )\r\n }\r\n\r\n get activeDrawingId() {\r\n return this._activeId\r\n }\r\n\r\n get activeDrawing(): FloorplanEntry | null {\r\n return this._activeId ? this._entries.get(this._activeId) ?? null : null\r\n }\r\n\r\n /** Inject the world grid (typically `bimState.bim.grid`). Without this\r\n * the tool falls back to looking it up via `OBC.Grids`. */\r\n setGrid(grid: any | null) {\r\n this.grid.setGrid(grid)\r\n }\r\n\r\n /** Toggle visibility of a single per-class layer on an entry's drawing. */\r\n setLayerVisible(entryId: string, className: string, visible: boolean) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry?.drawing || !entry.drawing.layers.has(className)) return\r\n entry.drawing.layers.setVisibility(className, visible)\r\n const meta = entry.layers.find((l) => l.className === className)\r\n if (meta) meta.visible = visible\r\n this._requestUpdate()\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Update the color (hex int, e.g. 0xff0000) of a per-class layer. Updates\r\n * both the projected-line color in the drawing AND the 3D highlight\r\n * color for FILL (slabs / roofs) and CUT (walls / columns / curtain-\r\n * walls) classes — so changing the IFCSLAB color repaints both its\r\n * outline and its solid fill underneath. */\r\n async setLayerColor(entryId: string, className: string, color: number) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry?.drawing || !entry.drawing.layers.has(className)) return\r\n entry.drawing.layers.setColor(className, color)\r\n const meta = entry.layers.find((l) => l.className === className)\r\n if (meta) meta.color = color\r\n\r\n if (FILL_CLASSES.has(className) || CUT_CLASSES.has(className)) {\r\n await this._updateClassHighlight(entry, className, color)\r\n }\r\n\r\n this._requestUpdate()\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Prepend Fill / Cut group-color rows to entry.layers so the sidebar\r\n * shows group-level color pickers at the top of the layer list. Idempotent\r\n * — removes any existing group entries before re-inserting. */\r\n private _injectGroupColorLayers(entry: FloorplanEntry) {\r\n // Read current group colors from the renderer config so subsequent\r\n // setFillGroupColor / setCutGroupColor calls are reflected immediately.\r\n const groups = (this.renderer as any)._highlighter?.config?.groups ?? []\r\n const cutColor: number = (groups[0]?.color as number | undefined) ?? CUT_COLOR\r\n const fillColor: number = (groups[1]?.color as number | undefined) ?? FILL_COLOR\r\n const filtered = entry.layers.filter(\r\n (l) => l.className !== 'DrawingLayers.fill' && l.className !== 'DrawingLayers.cut',\r\n )\r\n entry.layers = [\r\n {\r\n className: 'DrawingLayers.cut',\r\n layerName: 'DrawingLayers.cut',\r\n visible: true,\r\n color: cutColor,\r\n itemCount: 0,\r\n displayKey: 'DrawingLayers.cut',\r\n },\r\n {\r\n className: 'DrawingLayers.fill',\r\n layerName: 'DrawingLayers.fill',\r\n visible: true,\r\n color: fillColor,\r\n itemCount: 0,\r\n displayKey: 'DrawingLayers.fill',\r\n },\r\n ...filtered,\r\n ]\r\n }\r\n\r\n /** Re-apply the 3D highlight (mesh fill color) for a single IFC class on\r\n * the active model, scoped to the active storey. Called after the user\r\n * edits a layer color in the sidebar so the 3D underlay stays in sync\r\n * with the line color. */\r\n private async _updateClassHighlight(\r\n entry: FloorplanEntry,\r\n className: string,\r\n color: number,\r\n ) {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n const model = fragments.list.get(entry.modelId) as any\r\n if (!model) return\r\n\r\n // Match this specific class only (no partial-match regex).\r\n const map = await model.getItemsOfCategories([\r\n new RegExp(`^${className}$`),\r\n ])\r\n let ids = Object.values(map).flat() as number[]\r\n\r\n // Restrict to the active storey so changes don't leak into other floors.\r\n try {\r\n const storeyIds = await this.projector.getCachedStoreyIds(\r\n entry.modelId,\r\n entry.storeyLocalId,\r\n model,\r\n )\r\n if (storeyIds.length > 0) {\r\n const set = new Set(storeyIds)\r\n ids = ids.filter((id) => set.has(id))\r\n }\r\n } catch {\r\n // best-effort — fall through with unfiltered ids\r\n }\r\n\r\n if (ids.length === 0) return\r\n try {\r\n await model.highlight(ids, {\r\n color: new THREE.Color(color),\r\n opacity: 1,\r\n transparent: false,\r\n renderedFaces: 1,\r\n preserveOriginalMaterial: false,\r\n })\r\n fragments.core.update(true)\r\n } catch (error) {\r\n console.warn(\r\n `[FloorplanTool] 3D highlight update failed for ${className}:`,\r\n error,\r\n )\r\n }\r\n }\r\n\r\n /** Change the 3D fill color for ALL fill-group items (slabs / roofs) on\r\n * the active entry. Updates the layer metadata so the sidebar swatch\r\n * reflects the change immediately. */\r\n async setFillGroupColor(entryId: string, color: number) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry) return\r\n await this.renderer.setFillColor(entryId, color)\r\n const meta = entry.layers.find((l) => l.className === 'DrawingLayers.fill')\r\n if (meta) meta.color = color\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Change the 3D cut color for ALL cut-group items (walls / columns /\r\n * curtain walls) on the active entry. */\r\n async setCutGroupColor(entryId: string, color: number) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry) return\r\n await this.renderer.setCutColor(entryId, color)\r\n const meta = entry.layers.find((l) => l.className === 'DrawingLayers.cut')\r\n if (meta) meta.color = color\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Current true-north rotation (degrees, clockwise from default up). */\r\n get northAngle(): number {\r\n return this._northAngle\r\n }\r\n\r\n /** True while the line-pick mode is awaiting a click on the drawing. */\r\n get isPickingNorth(): boolean {\r\n return this._pickingNorth\r\n }\r\n\r\n /** Set the true-north rotation. Normalised to [0, 360). Applied to the\r\n * camera azimuth immediately if a floorplan is currently active so the\r\n * view re-orients. */\r\n setNorthAngle(degrees: number) {\r\n const normalized = ((degrees % 360) + 360) % 360\r\n if (this._northAngle === normalized) return\r\n this._northAngle = normalized\r\n this.onNorthAngleChanged.trigger(normalized)\r\n if (this._activeId) this._applyNorthToCamera()\r\n }\r\n\r\n /** Enter line-pick mode. The next click on the canvas raycasts against\r\n * the active drawing's lines; the hit line's bearing becomes the new\r\n * true-north angle. No-op if no floorplan is active. */\r\n startPickNorth() {\r\n if (this._pickingNorth || !this._activeId) return\r\n const world = this.components.get(CurrentWorld).world\r\n if (!world?.renderer) return\r\n const canvas = world.renderer.three.domElement\r\n this._pickHandler = (e: MouseEvent) => this._onPickClick(e)\r\n canvas.addEventListener('click', this._pickHandler)\r\n canvas.style.cursor = 'crosshair'\r\n this._pickingNorth = true\r\n this.onPickingNorthChanged.trigger(true)\r\n }\r\n\r\n /** Exit line-pick mode without applying any rotation. */\r\n cancelPickNorth() {\r\n if (!this._pickingNorth) return\r\n const world = this.components.get(CurrentWorld).world\r\n const canvas = world?.renderer?.three.domElement ?? null\r\n if (canvas && this._pickHandler) {\r\n canvas.removeEventListener('click', this._pickHandler)\r\n canvas.style.cursor = ''\r\n }\r\n this._pickHandler = null\r\n this._pickingNorth = false\r\n this.onPickingNorthChanged.trigger(false)\r\n }\r\n\r\n /** Click handler installed during line-pick mode. Raycasts against the\r\n * active drawing's `LineSegments` and applies the hit line's bearing\r\n * (clockwise from local north) as the new true-north angle. */\r\n private _onPickClick(event: MouseEvent) {\r\n const entry = this.activeDrawing\r\n if (!entry?.drawing) return\r\n const world = this.components.get(CurrentWorld).world\r\n if (!world?.renderer || !world?.camera) return\r\n const canvas = world.renderer.three.domElement\r\n const rect = canvas.getBoundingClientRect()\r\n const x = ((event.clientX - rect.left) / rect.width) * 2 - 1\r\n const y = -((event.clientY - rect.top) / rect.height) * 2 + 1\r\n const raycaster = new THREE.Raycaster()\r\n raycaster.params.Line.threshold = 0.5\r\n raycaster.setFromCamera(\r\n new THREE.Vector2(x, y),\r\n world.camera.three as THREE.Camera,\r\n )\r\n const hit = entry.drawing.raycast(raycaster.ray, null)\r\n if (!hit?.line) {\r\n // No line hit — keep picking active so the user can try again.\r\n return\r\n }\r\n // Drawing local space: X=right, Z=down-screen, Y=0. Compass bearing\r\n // (clockwise from local north which is -Z): atan2(dx, -dz).\r\n const dx = hit.line.end.x - hit.line.start.x\r\n const dz = hit.line.end.z - hit.line.start.z\r\n const bearingDeg = (Math.atan2(dx, -dz) * 180) / Math.PI\r\n this.setNorthAngle(bearingDeg)\r\n this.cancelPickNorth()\r\n }\r\n\r\n /** Push `_northAngle` into the camera-controls azimuth so the view\r\n * rotates around the active floor's centre. Called on every activate\r\n * and whenever the angle changes while a floorplan is active. */\r\n private _applyNorthToCamera() {\r\n const world = this.components.get(CurrentWorld).world\r\n if (!world?.camera?.controls) return\r\n const controls = world.camera.controls as any\r\n const radians = (this._northAngle * Math.PI) / 180\r\n if (typeof controls.rotateAzimuthTo === 'function') {\r\n void controls.rotateAzimuthTo(radians, true)\r\n } else {\r\n controls.azimuthAngle = radians\r\n }\r\n }\r\n\r\n /** Force a render update so layer visibility/color changes paint\r\n * immediately even when the camera is at rest. */\r\n private _requestUpdate() {\r\n try {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n fragments.core.update(true)\r\n } catch {\r\n // FragmentsManager not initialized yet — no-op.\r\n }\r\n }\r\n\r\n /** Build one entry per IFC storey. Drawings are projected lazily on\r\n * first activation. */\r\n async generate(modelId: string): Promise<FloorplanEntry[]> {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n const model = fragments.list.get(modelId)\r\n if (!model) return []\r\n\r\n const sourceWorld = this.components.get(CurrentWorld).world\r\n if (!sourceWorld) return []\r\n\r\n this._emit({ isLoading: true, stage: 'readingStoreys' })\r\n\r\n try {\r\n this.disposeEntriesForModel(modelId)\r\n await this.projector.ensureEditorReady()\r\n\r\n const storeyIds = Object.values(\r\n await model.getItemsOfCategories([/BUILDINGSTOREY/]),\r\n ).flat()\r\n if (storeyIds.length === 0) return []\r\n\r\n const storeysData = await model.getItemsData(storeyIds)\r\n const [, coordHeight] = await model.getCoordinates()\r\n const box = model.box\r\n const minY = box.min.y\r\n const maxY = box.max.y\r\n\r\n const created: FloorplanEntry[] = []\r\n\r\n // storeysData is parallel to storeyIds — preserve the mapping so each\r\n // entry remembers its storey's localId for later per-storey queries.\r\n for (let i = 0; i < storeysData.length; i++) {\r\n const storey = storeysData[i]\r\n const storeyLocalId = storeyIds[i]\r\n if (!('value' in storey.Name && 'value' in storey.Elevation)) continue\r\n\r\n const name = String(storey.Name.value)\r\n const rawElev = Number(storey.Elevation.value)\r\n const elevation = normalizeElevation(rawElev, coordHeight, minY, maxY)\r\n\r\n const entry: FloorplanEntry = {\r\n id: `${modelId}::${name}`,\r\n name,\r\n elevation,\r\n storeyLocalId,\r\n modelId,\r\n drawing: null,\r\n projected: false,\r\n layers: [],\r\n }\r\n this._entries.set(entry.id, entry)\r\n created.push(entry)\r\n }\r\n\r\n this.onDrawingsChanged.trigger(this.drawings)\r\n return created\r\n } finally {\r\n this._emit({ isLoading: false })\r\n }\r\n }\r\n\r\n /**\r\n * Activate a floorplan with progressive feedback. Camera, lighting and\r\n * clip planes are applied synchronously so the user gets an immediate\r\n * top-down framing. The slow steps — fill/cut highlighting and line\r\n * projection — run in parallel and emit stage events as each phase\r\n * completes, so a loading bar can advance through `init → resolve → cull\r\n * → fill → cut → project → done`.\r\n */\r\n async activate(id: string) {\r\n const entry = this._entries.get(id)\r\n if (!entry) return\r\n if (this._activeId === id) return\r\n\r\n const sourceWorld = this.components.get(CurrentWorld).world\r\n if (!sourceWorld) return\r\n\r\n const seq = ++this._activateSeq\r\n const wasActive = this._activeId !== null\r\n\r\n this._emit({ isLoading: true, stage: 'init' })\r\n\r\n // Mutual exclusion: deactivate any other view tool before claiming.\r\n await this._tryClaimCoordinator()\r\n if (seq !== this._activateSeq) return\r\n\r\n try {\r\n // ----- Phase 1: synchronous chrome + clip + camera (instant feedback)\r\n if (!wasActive) {\r\n this.chrome.applyLighting()\r\n this.chrome.applyDrawingBackground()\r\n // Lock to top-down (polar = 0).\r\n this.camera.lock(0)\r\n this.chrome.setCursor()\r\n this.chrome.disableHighlighter()\r\n this.chrome.hideGizmo()\r\n }\r\n\r\n // Section clip just above the drawing plane. StoreyProjector positions\r\n // the drawing at elevation + 1.5; clip normal is -Y so anything above\r\n // 1.55 is hidden but the drawing's own lines survive.\r\n this.clip.set(\r\n SLOT_SECTION,\r\n new THREE.Vector3(0, -1, 0),\r\n new THREE.Vector3(0, entry.elevation + 1.5 + 0.05, 0),\r\n )\r\n safeRun(() => this._applyLowerClip(entry), 'applyLower')\r\n safeRun(() => this.grid.hide(), 'hideGrid')\r\n\r\n // Hide previously visible drawings synchronously so they don't bleed\r\n // through while the new one is being projected.\r\n for (const other of this._entries.values()) {\r\n if (other.drawing && other.id !== entry.id) {\r\n other.drawing.three.visible = false\r\n }\r\n }\r\n\r\n this._frameCamera(entry)\r\n\r\n // Mark active immediately so the React UI shows Exit and the user can\r\n // bail out at any point during loading.\r\n this._activeId = id\r\n this.onActiveDrawingChanged.trigger(entry)\r\n\r\n // ----- Phase 2: parallel render + project (slow) -----\r\n const renderPromise = this.renderer.apply(entry, (stage) => {\r\n if (seq !== this._activateSeq) return\r\n this._emit({ isLoading: true, stage })\r\n })\r\n\r\n // Project once render-stage events have started flowing — this lets\r\n // the bar progress through resolve/cull/fill/cut while line generation\r\n // runs in the background. Once render completes we flip to 'project'.\r\n const projectPromise = this.projector.project(entry)\r\n\r\n renderPromise\r\n .then(() => {\r\n if (seq !== this._activateSeq) return\r\n this._emit({ isLoading: true, stage: 'project' })\r\n })\r\n .catch(() => {})\r\n\r\n await Promise.all([renderPromise, projectPromise])\r\n if (seq !== this._activateSeq) return\r\n\r\n // Drawing visible + editor swap (fast, post-projection).\r\n const editor = this.components.get(OBF.DrawingEditor)\r\n editor.activeDrawing = entry.drawing\r\n if (entry.drawing) {\r\n entry.drawing.three.visible = true\r\n }\r\n\r\n // Prepend Fill / Cut group-color controls so the sidebar shows them\r\n // at the top of the layers list.\r\n this._injectGroupColorLayers(entry)\r\n\r\n this._emit({ isLoading: false, stage: 'done' })\r\n } catch (error) {\r\n console.warn('[FloorplanTool] activate failed:', error)\r\n this._emit({ isLoading: false })\r\n }\r\n }\r\n\r\n /**\r\n * Exit floorplan mode. Each cleanup step is independently guarded so a\r\n * failure in one (e.g. resetHighlight on a huge model) cannot strand\r\n * camera, clip, or gizmo state.\r\n */\r\n async deactivate() {\r\n if (!this._activeId) return\r\n\r\n // Reset active state immediately so the React UI hides Exit and double\r\n // calls become no-ops.\r\n this._activeId = null\r\n this.onActiveDrawingChanged.trigger(null)\r\n\r\n // Drop any in-flight north-pick listener so the canvas stops\r\n // intercepting clicks once the floorplan is closed.\r\n safeRun(() => this.cancelPickNorth(), 'cancelPickNorth')\r\n\r\n // Clear editor + drawing visibility (synchronous, fast).\r\n safeRun(() => {\r\n const editor = this.components.get(OBF.DrawingEditor)\r\n editor.activeDrawing = null\r\n }, 'clear active drawing')\r\n for (const entry of this._entries.values()) {\r\n if (entry.drawing) {\r\n safeRun(() => {\r\n entry.drawing!.three.visible = false\r\n }, 'hide drawing')\r\n }\r\n }\r\n\r\n // Restore user-facing state FIRST so input feels responsive even if\r\n // model-render restoration takes a beat.\r\n safeRun(() => this.clip.removeAll(), 'removeClips')\r\n safeRun(() => this.grid.restore(), 'showGrid')\r\n safeRun(() => this.camera.unlock(), 'unlockCamera')\r\n safeRun(() => this.chrome.restoreCursor(), 'restoreCursor')\r\n safeRun(() => this.chrome.restoreHighlighter(), 'restoreHighlighter')\r\n safeRun(() => this.chrome.showGizmo(), 'showGizmo')\r\n safeRun(() => this.chrome.removeLighting(), 'removeLighting')\r\n safeRun(() => this.chrome.restoreBackground(), 'restoreBackground')\r\n\r\n // Slow async step last. Awaited so callers can chain on it, but failures\r\n // can't undo the synchronous restores above.\r\n await safeRunAsync(() => this.renderer.restore(), 'restoreModelRendering')\r\n\r\n safeRun(() => this._releaseCoordinator(), 'releaseCoordinator')\r\n }\r\n\r\n disposeEntriesForModel(modelId: string) {\r\n let touched = false\r\n for (const [id, entry] of this._entries) {\r\n if (entry.modelId !== modelId) continue\r\n if (this._activeId === id) void this.deactivate()\r\n disposeDrawing(this.components, entry.drawing)\r\n this._entries.delete(id)\r\n this.renderer.invalidateForEntry(id)\r\n touched = true\r\n }\r\n this.renderer.invalidateForModel(modelId)\r\n this.projector.invalidateForModel(modelId)\r\n if (touched) this.onDrawingsChanged.trigger(this.drawings)\r\n }\r\n\r\n dispose() {\r\n void this.deactivate()\r\n for (const entry of this._entries.values()) {\r\n disposeDrawing(this.components, entry.drawing)\r\n }\r\n this._entries.clear()\r\n this.onDrawingsChanged.trigger([])\r\n }\r\n\r\n private _emit(state: FloorplanLoadingState) {\r\n this.onGenerationStateChanged.trigger(state)\r\n }\r\n\r\n /** Mutual-exclusion claim. If ElevationsTool (or any other view tool)\r\n * was active, the coordinator awaits its deactivate() first. */\r\n private async _tryClaimCoordinator() {\r\n try {\r\n const coordinator = this.components.get(ViewModeCoordinator)\r\n await coordinator.claim(this)\r\n } catch {\r\n // ViewModeCoordinator not registered in this viewer — ignore.\r\n }\r\n }\r\n\r\n private _releaseCoordinator() {\r\n try {\r\n this.components.get(ViewModeCoordinator).release(this)\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n /** Lower clip plane sits just under the active floor's slab (normal +Y),\r\n * so ceiling fixtures / lights / equipment of the storey below never\r\n * bleed into the projection or the 3D underlay. */\r\n private _applyLowerClip(entry: FloorplanEntry) {\r\n const cutY = entry.elevation - 0.5\r\n this.clip.set(\r\n SLOT_LOWER,\r\n new THREE.Vector3(0, 1, 0),\r\n new THREE.Vector3(0, cutY, 0),\r\n )\r\n }\r\n\r\n /** Frame the camera over the active floor in orthographic top-down,\r\n * then re-apply the building's true-north rotation so storey switches\r\n * preserve the user's chosen orientation. */\r\n private _frameCamera(entry: FloorplanEntry) {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n const model = fragments.list.get(entry.modelId)\r\n if (!model) return\r\n const center = new THREE.Vector3()\r\n const size = new THREE.Vector3()\r\n model.box.getCenter(center)\r\n model.box.getSize(size)\r\n const span = Math.max(size.x, size.z, 10)\r\n const target = new THREE.Vector3(\r\n center.x,\r\n entry.elevation + 1.2,\r\n center.z,\r\n )\r\n this.camera.frame(target, new THREE.Vector3(0, -1, 0), span)\r\n this._applyNorthToCamera()\r\n }\r\n\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/core/components/viewers/bim/src/FloorplanTool/index.ts"],"sourcesContent":["import * as OBC from '@thatopen/components'\r\nimport * as OBF from '@thatopen/components-front'\r\nimport * as THREE from 'three'\r\nimport { CurrentWorld } from '../CurrentWorld'\r\nimport { CameraController } from '../lib/CameraController'\r\nimport { ChromeController } from '../lib/ChromeController'\r\nimport { ClipController } from '../lib/ClipController'\r\nimport { CUT_CLASSES, FILL_CLASSES } from '../lib/drawingLayers'\r\nimport { disposeDrawing } from '../lib/drawingProjection'\r\nimport { GridController } from '../lib/GridController'\r\nimport { safeRun, safeRunAsync } from '../lib/safeRun'\r\nimport { stagePercent, ViewLoadingState } from '../lib/viewSection'\r\nimport { ViewModeCoordinator } from '../lib/ViewModeCoordinator'\r\nimport { FloorplanRenderer, RenderStage } from './src/FloorplanRenderer'\r\nimport { StoreyProjector } from './src/StoreyProjector'\r\nimport { CUT_COLOR, FILL_COLOR, FloorplanEntry, FLOORPLAN_TOOL_UUID } from './src/types'\r\nimport { normalizeElevation } from './src/utils'\r\n\r\nconst SLOT_SECTION = 'floorplan:section'\r\nconst SLOT_LOWER = 'floorplan:lower'\r\n\r\nexport type { FloorplanEntry } from './src/types'\r\n\r\nexport type FloorplanLoadingStage =\r\n | 'init'\r\n | 'readingStoreys'\r\n | RenderStage\r\n | 'project'\r\n | 'done'\r\n\r\nexport type FloorplanLoadingState = ViewLoadingState<FloorplanLoadingStage>\r\n\r\nconst STAGE_PERCENT: Record<FloorplanLoadingStage, number> = {\r\n init: 5,\r\n readingStoreys: 10,\r\n resolve: 20,\r\n cull: 35,\r\n switching: 35,\r\n cut: 55,\r\n fill: 75,\r\n project: 90,\r\n done: 100,\r\n}\r\n\r\nexport function getFloorplanStagePercent(\r\n stage: FloorplanLoadingStage | undefined,\r\n): number {\r\n return stagePercent(stage, STAGE_PERCENT)\r\n}\r\n\r\nexport class FloorplanTool extends OBC.Component {\r\n static uuid = FLOORPLAN_TOOL_UUID\r\n\r\n enabled = false\r\n\r\n readonly onDrawingsChanged = new OBC.Event<FloorplanEntry[]>()\r\n readonly onActiveDrawingChanged = new OBC.Event<FloorplanEntry | null>()\r\n readonly onGenerationStateChanged = new OBC.Event<FloorplanLoadingState>()\r\n /** Fires whenever an entry's layer metadata changes (toggle / color). */\r\n readonly onLayersChanged = new OBC.Event<FloorplanEntry>()\r\n /** Fires when the building's true-north angle (in degrees) is updated. */\r\n readonly onNorthAngleChanged = new OBC.Event<number>()\r\n /** Fires when line-pick mode toggles on/off. */\r\n readonly onPickingNorthChanged = new OBC.Event<boolean>()\r\n\r\n private _entries = new Map<string, FloorplanEntry>()\r\n private _activeId: string | null = null\r\n /** Sequence guard: when activate() is called multiple times in quick\r\n * succession (e.g. user clicks two storeys), only the last call applies\r\n * its final state. Prior calls bail out at await boundaries. */\r\n private _activateSeq = 0\r\n /** True-north rotation in degrees (clockwise from default screen-up).\r\n * Persists across storey switches but resets to 0 on tool dispose. */\r\n private _northAngle = 0\r\n /** True while the user is drawing the two-point north line. */\r\n private _pickingNorth = false\r\n private _pickHandler: ((e: MouseEvent) => void) | null = null\r\n private _moveHandler: ((e: MouseEvent) => void) | null = null\r\n private _keyHandler: ((e: KeyboardEvent) => void) | null = null\r\n /** First clicked point of the north line, in drawing-local space (Y=0).\r\n * Null until the user places the first point. */\r\n private _drawStart: THREE.Vector3 | null = null\r\n /** Cached snap targets — projected-geometry vertices flattened as\r\n * [x0,z0, x1,z1, …] in drawing-local space. Rebuilt each time draw mode\r\n * starts so it reflects the active storey's lines. */\r\n private _snapVerts: Float32Array | null = null\r\n /** Rubber-band preview line + cursor snap marker, parented to the active\r\n * drawing so they inherit its world transform. */\r\n private _previewLine: THREE.Line | null = null\r\n private _snapMarker: THREE.LineSegments | null = null\r\n /** Canvas cursor before draw mode swapped in the crosshair — typically the\r\n * floorplan-mode \"grab\" hand. Restored (not cleared) on exit so panning\r\n * keeps the hand; only leaving floorplan mode reverts to the default. */\r\n private _savedPickCursor: string | null = null\r\n\r\n private projector: StoreyProjector\r\n private renderer: FloorplanRenderer\r\n private camera: CameraController\r\n private chrome: ChromeController\r\n private clip: ClipController\r\n private grid: GridController\r\n\r\n constructor(components: OBC.Components) {\r\n super(components)\r\n components.add(FloorplanTool.uuid, this)\r\n\r\n this.projector = new StoreyProjector(components)\r\n this.renderer = new FloorplanRenderer(components, this.projector)\r\n this.camera = new CameraController(components)\r\n this.chrome = new ChromeController(components)\r\n this.clip = new ClipController(components)\r\n this.grid = new GridController(components)\r\n\r\n const fragments = components.get(OBC.FragmentsManager)\r\n fragments.core.onModelLoaded.add((model) => {\r\n void this.generate(model.modelId)\r\n })\r\n }\r\n\r\n get drawings(): FloorplanEntry[] {\r\n return Array.from(this._entries.values()).sort(\r\n (a, b) => a.elevation - b.elevation,\r\n )\r\n }\r\n\r\n get activeDrawingId() {\r\n return this._activeId\r\n }\r\n\r\n get activeDrawing(): FloorplanEntry | null {\r\n return this._activeId ? this._entries.get(this._activeId) ?? null : null\r\n }\r\n\r\n /** Inject the world grid (typically `bimState.bim.grid`). Without this\r\n * the tool falls back to looking it up via `OBC.Grids`. */\r\n setGrid(grid: any | null) {\r\n this.grid.setGrid(grid)\r\n }\r\n\r\n /** Toggle visibility of a single per-class layer on an entry's drawing. */\r\n setLayerVisible(entryId: string, className: string, visible: boolean) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry?.drawing || !entry.drawing.layers.has(className)) return\r\n entry.drawing.layers.setVisibility(className, visible)\r\n const meta = entry.layers.find((l) => l.className === className)\r\n if (meta) meta.visible = visible\r\n this._requestUpdate()\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Update the color (hex int, e.g. 0xff0000) of a per-class layer. Updates\r\n * both the projected-line color in the drawing AND the 3D highlight\r\n * color for FILL (slabs / roofs) and CUT (walls / columns / curtain-\r\n * walls) classes — so changing the IFCSLAB color repaints both its\r\n * outline and its solid fill underneath. */\r\n async setLayerColor(entryId: string, className: string, color: number) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry?.drawing || !entry.drawing.layers.has(className)) return\r\n entry.drawing.layers.setColor(className, color)\r\n const meta = entry.layers.find((l) => l.className === className)\r\n if (meta) meta.color = color\r\n\r\n if (FILL_CLASSES.has(className) || CUT_CLASSES.has(className)) {\r\n await this._updateClassHighlight(entry, className, color)\r\n }\r\n\r\n this._requestUpdate()\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Prepend Fill / Cut group-color rows to entry.layers so the sidebar\r\n * shows group-level color pickers at the top of the layer list. Idempotent\r\n * — removes any existing group entries before re-inserting. */\r\n private _injectGroupColorLayers(entry: FloorplanEntry) {\r\n // Read current group colors from the renderer config so subsequent\r\n // setFillGroupColor / setCutGroupColor calls are reflected immediately.\r\n const groups = (this.renderer as any)._highlighter?.config?.groups ?? []\r\n const cutColor: number = (groups[0]?.color as number | undefined) ?? CUT_COLOR\r\n const fillColor: number = (groups[1]?.color as number | undefined) ?? FILL_COLOR\r\n const filtered = entry.layers.filter(\r\n (l) => l.className !== 'DrawingLayers.fill' && l.className !== 'DrawingLayers.cut',\r\n )\r\n entry.layers = [\r\n {\r\n className: 'DrawingLayers.cut',\r\n layerName: 'DrawingLayers.cut',\r\n visible: true,\r\n color: cutColor,\r\n itemCount: 0,\r\n displayKey: 'DrawingLayers.cut',\r\n },\r\n {\r\n className: 'DrawingLayers.fill',\r\n layerName: 'DrawingLayers.fill',\r\n visible: true,\r\n color: fillColor,\r\n itemCount: 0,\r\n displayKey: 'DrawingLayers.fill',\r\n },\r\n ...filtered,\r\n ]\r\n }\r\n\r\n /** Re-apply the 3D highlight (mesh fill color) for a single IFC class on\r\n * the active model, scoped to the active storey. Called after the user\r\n * edits a layer color in the sidebar so the 3D underlay stays in sync\r\n * with the line color. */\r\n private async _updateClassHighlight(\r\n entry: FloorplanEntry,\r\n className: string,\r\n color: number,\r\n ) {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n const model = fragments.list.get(entry.modelId) as any\r\n if (!model) return\r\n\r\n // Match this specific class only (no partial-match regex).\r\n const map = await model.getItemsOfCategories([\r\n new RegExp(`^${className}$`),\r\n ])\r\n let ids = Object.values(map).flat() as number[]\r\n\r\n // Restrict to the active storey so changes don't leak into other floors.\r\n try {\r\n const storeyIds = await this.projector.getCachedStoreyIds(\r\n entry.modelId,\r\n entry.storeyLocalId,\r\n model,\r\n )\r\n if (storeyIds.length > 0) {\r\n const set = new Set(storeyIds)\r\n ids = ids.filter((id) => set.has(id))\r\n }\r\n } catch {\r\n // best-effort — fall through with unfiltered ids\r\n }\r\n\r\n if (ids.length === 0) return\r\n try {\r\n await model.highlight(ids, {\r\n color: new THREE.Color(color),\r\n opacity: 1,\r\n transparent: false,\r\n renderedFaces: 1,\r\n preserveOriginalMaterial: false,\r\n })\r\n fragments.core.update(true)\r\n } catch (error) {\r\n console.warn(\r\n `[FloorplanTool] 3D highlight update failed for ${className}:`,\r\n error,\r\n )\r\n }\r\n }\r\n\r\n /** Change the 3D fill color for ALL fill-group items (slabs / roofs) on\r\n * the active entry. Updates the layer metadata so the sidebar swatch\r\n * reflects the change immediately. */\r\n async setFillGroupColor(entryId: string, color: number) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry) return\r\n await this.renderer.setFillColor(entryId, color)\r\n const meta = entry.layers.find((l) => l.className === 'DrawingLayers.fill')\r\n if (meta) meta.color = color\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Change the 3D cut color for ALL cut-group items (walls / columns /\r\n * curtain walls) on the active entry. */\r\n async setCutGroupColor(entryId: string, color: number) {\r\n const entry = this._entries.get(entryId)\r\n if (!entry) return\r\n await this.renderer.setCutColor(entryId, color)\r\n const meta = entry.layers.find((l) => l.className === 'DrawingLayers.cut')\r\n if (meta) meta.color = color\r\n this.onLayersChanged.trigger(entry)\r\n }\r\n\r\n /** Current true-north rotation (degrees, clockwise from default up). */\r\n get northAngle(): number {\r\n return this._northAngle\r\n }\r\n\r\n /** True while the line-pick mode is awaiting a click on the drawing. */\r\n get isPickingNorth(): boolean {\r\n return this._pickingNorth\r\n }\r\n\r\n /** Set the true-north rotation. Normalised to [0, 360). Applied to the\r\n * camera azimuth immediately if a floorplan is currently active so the\r\n * view re-orients. */\r\n setNorthAngle(degrees: number) {\r\n const normalized = ((degrees % 360) + 360) % 360\r\n if (this._northAngle === normalized) return\r\n this._northAngle = normalized\r\n this.onNorthAngleChanged.trigger(normalized)\r\n if (this._activeId) this._applyNorthToCamera()\r\n }\r\n\r\n /** Enter two-point draw mode. The user clicks two points on the active\r\n * floorplan (each snapped to the nearest projected-geometry vertex); the\r\n * bearing of the segment between them becomes the new true-north angle.\r\n * A rubber-band preview + snap marker track the cursor; Esc cancels.\r\n * No-op if no floorplan is active. */\r\n startPickNorth() {\r\n if (this._pickingNorth || !this._activeId) return\r\n const entry = this.activeDrawing\r\n const world = this.components.get(CurrentWorld).world\r\n if (!entry?.drawing || !world?.renderer) return\r\n const canvas = world.renderer.three.domElement\r\n\r\n this._drawStart = null\r\n this._snapVerts = this._collectSnapVertices(entry)\r\n\r\n this._pickHandler = (e: MouseEvent) => this._onPickClick(e)\r\n this._moveHandler = (e: MouseEvent) => this._onPickMove(e)\r\n this._keyHandler = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') this.cancelPickNorth()\r\n }\r\n canvas.addEventListener('click', this._pickHandler)\r\n canvas.addEventListener('mousemove', this._moveHandler)\r\n window.addEventListener('keydown', this._keyHandler)\r\n this._savedPickCursor = canvas.style.cursor\r\n canvas.style.cursor = 'crosshair'\r\n this._pickingNorth = true\r\n this.onPickingNorthChanged.trigger(true)\r\n }\r\n\r\n /** Exit draw mode without applying any rotation. Tears down the canvas\r\n * listeners and removes the rubber-band preview. */\r\n cancelPickNorth() {\r\n if (!this._pickingNorth) return\r\n const world = this.components.get(CurrentWorld).world\r\n const canvas = world?.renderer?.three.domElement ?? null\r\n if (canvas) {\r\n if (this._pickHandler) canvas.removeEventListener('click', this._pickHandler)\r\n if (this._moveHandler) canvas.removeEventListener('mousemove', this._moveHandler)\r\n // Restore the floorplan-mode cursor (the grab hand), not the OS default\r\n // — that only comes back when the tool deactivates.\r\n canvas.style.cursor = this._savedPickCursor ?? 'grab'\r\n }\r\n this._savedPickCursor = null\r\n if (this._keyHandler) window.removeEventListener('keydown', this._keyHandler)\r\n this._pickHandler = null\r\n this._moveHandler = null\r\n this._keyHandler = null\r\n this._drawStart = null\r\n this._snapVerts = null\r\n this._clearPreview()\r\n this._pickingNorth = false\r\n this.onPickingNorthChanged.trigger(false)\r\n }\r\n\r\n /** Click handler for draw mode. First click places the start point; the\r\n * second rotates the view so the drawn segment becomes parallel to the\r\n * screen X-axis (horizontal). Both points lie on the drawing's horizontal\r\n * plane (Y=0), so only the in-plane direction matters. */\r\n private _onPickClick(event: MouseEvent) {\r\n const entry = this.activeDrawing\r\n if (!entry?.drawing) return\r\n const local = this._eventToLocalPoint(event, entry)\r\n if (!local) return\r\n const point = this._snap(local)\r\n\r\n if (!this._drawStart) {\r\n this._drawStart = point\r\n this._updatePreview(entry, point)\r\n this._requestUpdate()\r\n return\r\n }\r\n\r\n // Ignore a degenerate (near-zero-length) segment so a stray double-click\r\n // can't set a bogus angle.\r\n const dx = point.x - this._drawStart.x\r\n const dz = point.z - this._drawStart.z\r\n if (dx * dx + dz * dz < 1e-6) return\r\n\r\n // Resolve the segment in WORLD space (the drawing has its own orientTo\r\n // rotation, so a drawing-local bearing wouldn't match the world-space\r\n // camera azimuth), then rotate the view to lay it on the X-axis.\r\n const drawing = entry.drawing\r\n drawing.three.updateWorldMatrix(true, false)\r\n const aWorld = drawing.three.localToWorld(this._drawStart.clone())\r\n const bWorld = drawing.three.localToWorld(point.clone())\r\n const azimuthDeg = this._azimuthToAlignLineToX(aWorld, bWorld)\r\n if (azimuthDeg !== null) this.setNorthAngle(azimuthDeg)\r\n this.cancelPickNorth()\r\n }\r\n\r\n /** Camera azimuth (degrees) that rotates the top-down view so the world\r\n * segment a→b lands parallel to the screen X-axis (horizontal).\r\n *\r\n * Derivation: with the standard Y-up spherical convention camera-controls\r\n * uses, the camera's screen-right world direction has angle ρ = −θ + C\r\n * (θ = azimuth). We measure ρ₀ and θ₀ from the live camera so C cancels —\r\n * making the result independent of the drawing's orientation and the\r\n * controls' up-space. We then solve ρ(θ) = λ (the segment's world angle),\r\n * giving θ = ρ₀ + θ₀ − λ. Returns null if the controls are unavailable. */\r\n private _azimuthToAlignLineToX(\r\n aWorld: THREE.Vector3,\r\n bWorld: THREE.Vector3,\r\n ): number | null {\r\n const world = this.components.get(CurrentWorld).world\r\n const cam = world?.camera?.three as THREE.Camera | undefined\r\n const controls = world?.camera?.controls as any\r\n if (!cam || typeof controls?.azimuthAngle !== 'number') return null\r\n\r\n const lx = bWorld.x - aWorld.x\r\n const lz = bWorld.z - aWorld.z\r\n if (lx * lx + lz * lz < 1e-12) return null\r\n const lambda = Math.atan2(lz, lx)\r\n\r\n // Screen-right = camera local +X axis = first column of matrixWorld.\r\n cam.updateMatrixWorld()\r\n const e = cam.matrixWorld.elements\r\n const rho0 = Math.atan2(e[2], e[0])\r\n const theta0 = controls.azimuthAngle as number\r\n\r\n return ((rho0 + theta0 - lambda) * 180) / Math.PI\r\n }\r\n\r\n /** Mousemove handler for draw mode — keeps the snap marker (and, after the\r\n * first click, the rubber-band line) glued to the cursor's snapped point. */\r\n private _onPickMove(event: MouseEvent) {\r\n const entry = this.activeDrawing\r\n if (!entry?.drawing) return\r\n const local = this._eventToLocalPoint(event, entry)\r\n if (!local) return\r\n this._updatePreview(entry, this._snap(local))\r\n this._requestUpdate()\r\n }\r\n\r\n /** Convert a canvas mouse event into a point on the drawing plane, in\r\n * drawing-local space (XZ plane, Y=0). Casts a ray from the active camera,\r\n * transforms it into the drawing's local frame, and intersects Y=0. */\r\n private _eventToLocalPoint(\r\n event: MouseEvent,\r\n entry: FloorplanEntry,\r\n ): THREE.Vector3 | null {\r\n const world = this.components.get(CurrentWorld).world\r\n if (!world?.renderer || !world.camera || !entry.drawing) return null\r\n const canvas = world.renderer.three.domElement\r\n const rect = canvas.getBoundingClientRect()\r\n const x = ((event.clientX - rect.left) / rect.width) * 2 - 1\r\n const y = -((event.clientY - rect.top) / rect.height) * 2 + 1\r\n const raycaster = new THREE.Raycaster()\r\n raycaster.setFromCamera(\r\n new THREE.Vector2(x, y),\r\n world.camera.three as THREE.Camera,\r\n )\r\n const drawing = entry.drawing\r\n drawing.three.updateWorldMatrix(true, false)\r\n const inv = new THREE.Matrix4().copy(drawing.three.matrixWorld).invert()\r\n const origin = raycaster.ray.origin.clone().applyMatrix4(inv)\r\n const dir = raycaster.ray.direction.clone().transformDirection(inv)\r\n if (Math.abs(dir.y) < 1e-9) return null\r\n const t = -origin.y / dir.y\r\n if (!Number.isFinite(t)) return null\r\n return new THREE.Vector3(\r\n origin.x + dir.x * t,\r\n 0,\r\n origin.z + dir.z * t,\r\n )\r\n }\r\n\r\n /** Snap a drawing-local point to the nearest projected-geometry vertex\r\n * within the snap radius; returns the point unchanged if none is close. */\r\n private _snap(local: THREE.Vector3): THREE.Vector3 {\r\n const verts = this._snapVerts\r\n if (!verts) return local\r\n const radius = this._snapRadiusLocal()\r\n let best = -1\r\n let bestD2 = radius * radius\r\n for (let i = 0; i < verts.length; i += 2) {\r\n const dx = verts[i] - local.x\r\n const dz = verts[i + 1] - local.z\r\n const d2 = dx * dx + dz * dz\r\n if (d2 < bestD2) {\r\n bestD2 = d2\r\n best = i\r\n }\r\n }\r\n if (best < 0) return local\r\n return new THREE.Vector3(verts[best], 0, verts[best + 1])\r\n }\r\n\r\n /** Snap radius in drawing-local units (= world units; the drawing is\r\n * unscaled), derived from a fixed ~12 px tolerance at the current ortho\r\n * zoom so it feels consistent as the user zooms. */\r\n private _snapRadiusLocal(): number {\r\n const SNAP_PX = 12\r\n const FALLBACK = 0.5\r\n const world = this.components.get(CurrentWorld).world\r\n const cam = world?.camera?.three as any\r\n const canvas = world?.renderer?.three.domElement\r\n if (!cam?.isOrthographicCamera || !canvas) return FALLBACK\r\n const worldWidth = (cam.right - cam.left) / (cam.zoom || 1)\r\n const worldPerPixel = worldWidth / Math.max(1, canvas.clientWidth)\r\n return worldPerPixel * SNAP_PX || FALLBACK\r\n }\r\n\r\n /** Flatten every visible projected line vertex into drawing-local [x,z]\r\n * pairs for endpoint snapping. Each vertex is transformed through its\r\n * owning object's world matrix into the drawing's local frame, so it\r\n * works regardless of how layers nest the `LineSegments`. */\r\n private _collectSnapVertices(entry: FloorplanEntry): Float32Array | null {\r\n const drawing = entry.drawing\r\n if (!drawing) return null\r\n drawing.three.updateWorldMatrix(true, true)\r\n const inv = new THREE.Matrix4().copy(drawing.three.matrixWorld).invert()\r\n const v = new THREE.Vector3()\r\n const out: number[] = []\r\n drawing.three.traverse((child: THREE.Object3D) => {\r\n if (!(child instanceof THREE.LineSegments) || !child.visible) return\r\n if (child.userData?.isDimension) return\r\n const pos = child.geometry?.attributes?.position as\r\n | THREE.BufferAttribute\r\n | undefined\r\n if (!pos) return\r\n for (let i = 0; i < pos.count; i++) {\r\n v.set(pos.getX(i), pos.getY(i), pos.getZ(i))\r\n .applyMatrix4(child.matrixWorld)\r\n .applyMatrix4(inv)\r\n out.push(v.x, v.z)\r\n }\r\n })\r\n return out.length ? new Float32Array(out) : null\r\n }\r\n\r\n /** Update (creating on first use) the cursor snap marker and, once the\r\n * first point is placed, the rubber-band line from start → cursor. Both\r\n * live in drawing-local space, Y=0. */\r\n private _updatePreview(entry: FloorplanEntry, current: THREE.Vector3) {\r\n const drawing = entry.drawing\r\n if (!drawing) return\r\n const COLOR = 0x2563eb\r\n\r\n if (!this._snapMarker) {\r\n // Unit-armed cross scaled to the snap radius so it reads as the\r\n // current snap tolerance.\r\n const geom = new THREE.BufferGeometry()\r\n geom.setAttribute(\r\n 'position',\r\n new THREE.Float32BufferAttribute(\r\n new Float32Array([-1, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 1]),\r\n 3,\r\n ),\r\n )\r\n this._snapMarker = new THREE.LineSegments(\r\n geom,\r\n new THREE.LineBasicMaterial({ color: COLOR }),\r\n )\r\n this._snapMarker.renderOrder = 999\r\n drawing.three.add(this._snapMarker)\r\n }\r\n const arm = this._snapRadiusLocal()\r\n this._snapMarker.scale.setScalar(arm)\r\n this._snapMarker.position.set(current.x, 0, current.z)\r\n this._snapMarker.visible = true\r\n\r\n if (!this._drawStart) {\r\n if (this._previewLine) this._previewLine.visible = false\r\n return\r\n }\r\n if (!this._previewLine) {\r\n const geom = new THREE.BufferGeometry()\r\n geom.setAttribute(\r\n 'position',\r\n new THREE.Float32BufferAttribute(new Float32Array(6), 3),\r\n )\r\n this._previewLine = new THREE.Line(\r\n geom,\r\n new THREE.LineBasicMaterial({ color: COLOR }),\r\n )\r\n this._previewLine.renderOrder = 999\r\n drawing.three.add(this._previewLine)\r\n }\r\n const pos = this._previewLine.geometry.attributes\r\n .position as THREE.BufferAttribute\r\n pos.setXYZ(0, this._drawStart.x, 0, this._drawStart.z)\r\n pos.setXYZ(1, current.x, 0, current.z)\r\n pos.needsUpdate = true\r\n this._previewLine.visible = true\r\n }\r\n\r\n /** Remove + dispose the preview line and snap marker. Uses each object's\r\n * own parent so it stays correct even when called from deactivate(),\r\n * where `_activeId` is already null. */\r\n private _clearPreview() {\r\n if (this._previewLine) {\r\n this._previewLine.parent?.remove(this._previewLine)\r\n this._previewLine.geometry.dispose()\r\n const m = this._previewLine.material\r\n if (!Array.isArray(m)) m.dispose()\r\n this._previewLine = null\r\n }\r\n if (this._snapMarker) {\r\n this._snapMarker.parent?.remove(this._snapMarker)\r\n this._snapMarker.geometry.dispose()\r\n const m = this._snapMarker.material\r\n if (!Array.isArray(m)) m.dispose()\r\n this._snapMarker = null\r\n }\r\n this._requestUpdate()\r\n }\r\n\r\n /** Push `_northAngle` into the camera-controls azimuth so the view\r\n * rotates around the active floor's centre. Called on every activate\r\n * and whenever the angle changes while a floorplan is active. */\r\n private _applyNorthToCamera() {\r\n const world = this.components.get(CurrentWorld).world\r\n if (!world?.camera?.controls) return\r\n const controls = world.camera.controls as any\r\n const radians = (this._northAngle * Math.PI) / 180\r\n if (typeof controls.rotateAzimuthTo === 'function') {\r\n void controls.rotateAzimuthTo(radians, true)\r\n } else {\r\n controls.azimuthAngle = radians\r\n }\r\n }\r\n\r\n /** Force a render update so layer visibility/color changes paint\r\n * immediately even when the camera is at rest. */\r\n private _requestUpdate() {\r\n try {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n fragments.core.update(true)\r\n } catch {\r\n // FragmentsManager not initialized yet — no-op.\r\n }\r\n }\r\n\r\n /** Build one entry per IFC storey. Drawings are projected lazily on\r\n * first activation. */\r\n async generate(modelId: string): Promise<FloorplanEntry[]> {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n const model = fragments.list.get(modelId)\r\n if (!model) return []\r\n\r\n const sourceWorld = this.components.get(CurrentWorld).world\r\n if (!sourceWorld) return []\r\n\r\n this._emit({ isLoading: true, stage: 'readingStoreys' })\r\n\r\n try {\r\n this.disposeEntriesForModel(modelId)\r\n await this.projector.ensureEditorReady()\r\n\r\n const storeyIds = Object.values(\r\n await model.getItemsOfCategories([/BUILDINGSTOREY/]),\r\n ).flat()\r\n if (storeyIds.length === 0) return []\r\n\r\n const storeysData = await model.getItemsData(storeyIds)\r\n const [, coordHeight] = await model.getCoordinates()\r\n const box = model.box\r\n const minY = box.min.y\r\n const maxY = box.max.y\r\n\r\n const created: FloorplanEntry[] = []\r\n\r\n // storeysData is parallel to storeyIds — preserve the mapping so each\r\n // entry remembers its storey's localId for later per-storey queries.\r\n for (let i = 0; i < storeysData.length; i++) {\r\n const storey = storeysData[i]\r\n const storeyLocalId = storeyIds[i]\r\n if (!('value' in storey.Name && 'value' in storey.Elevation)) continue\r\n\r\n const name = String(storey.Name.value)\r\n const rawElev = Number(storey.Elevation.value)\r\n const elevation = normalizeElevation(rawElev, coordHeight, minY, maxY)\r\n\r\n const entry: FloorplanEntry = {\r\n id: `${modelId}::${name}`,\r\n name,\r\n elevation,\r\n storeyLocalId,\r\n modelId,\r\n drawing: null,\r\n projected: false,\r\n layers: [],\r\n }\r\n this._entries.set(entry.id, entry)\r\n created.push(entry)\r\n }\r\n\r\n this.onDrawingsChanged.trigger(this.drawings)\r\n return created\r\n } finally {\r\n this._emit({ isLoading: false })\r\n }\r\n }\r\n\r\n /**\r\n * Activate a floorplan with progressive feedback. Camera, lighting and\r\n * clip planes are applied synchronously so the user gets an immediate\r\n * top-down framing. The slow steps — fill/cut highlighting and line\r\n * projection — run in parallel and emit stage events as each phase\r\n * completes, so a loading bar can advance through `init → resolve → cull\r\n * → fill → cut → project → done`.\r\n */\r\n async activate(id: string) {\r\n const entry = this._entries.get(id)\r\n if (!entry) return\r\n if (this._activeId === id) return\r\n\r\n const sourceWorld = this.components.get(CurrentWorld).world\r\n if (!sourceWorld) return\r\n\r\n const seq = ++this._activateSeq\r\n const wasActive = this._activeId !== null\r\n\r\n this._emit({ isLoading: true, stage: 'init' })\r\n\r\n // Mutual exclusion: deactivate any other view tool before claiming.\r\n await this._tryClaimCoordinator()\r\n if (seq !== this._activateSeq) return\r\n\r\n try {\r\n // ----- Phase 1: synchronous chrome + clip + camera (instant feedback)\r\n if (!wasActive) {\r\n this.chrome.applyLighting()\r\n this.chrome.applyDrawingBackground()\r\n // Lock to top-down (polar = 0).\r\n this.camera.lock(0)\r\n this.chrome.setCursor()\r\n this.chrome.disableHighlighter()\r\n this.chrome.hideGizmo()\r\n }\r\n\r\n // Section clip just above the drawing plane. StoreyProjector positions\r\n // the drawing at elevation + 1.5; clip normal is -Y so anything above\r\n // 1.55 is hidden but the drawing's own lines survive.\r\n this.clip.set(\r\n SLOT_SECTION,\r\n new THREE.Vector3(0, -1, 0),\r\n new THREE.Vector3(0, entry.elevation + 1.5 + 0.05, 0),\r\n )\r\n safeRun(() => this._applyLowerClip(entry), 'applyLower')\r\n safeRun(() => this.grid.hide(), 'hideGrid')\r\n\r\n // Hide previously visible drawings synchronously so they don't bleed\r\n // through while the new one is being projected.\r\n for (const other of this._entries.values()) {\r\n if (other.drawing && other.id !== entry.id) {\r\n other.drawing.three.visible = false\r\n }\r\n }\r\n\r\n this._frameCamera(entry)\r\n\r\n // Mark active immediately so the React UI shows Exit and the user can\r\n // bail out at any point during loading.\r\n this._activeId = id\r\n this.onActiveDrawingChanged.trigger(entry)\r\n\r\n // ----- Phase 2: parallel render + project (slow) -----\r\n const renderPromise = this.renderer.apply(entry, (stage) => {\r\n if (seq !== this._activateSeq) return\r\n this._emit({ isLoading: true, stage })\r\n })\r\n\r\n // Project once render-stage events have started flowing — this lets\r\n // the bar progress through resolve/cull/fill/cut while line generation\r\n // runs in the background. Once render completes we flip to 'project'.\r\n const projectPromise = this.projector.project(entry)\r\n\r\n renderPromise\r\n .then(() => {\r\n if (seq !== this._activateSeq) return\r\n this._emit({ isLoading: true, stage: 'project' })\r\n })\r\n .catch(() => {})\r\n\r\n await Promise.all([renderPromise, projectPromise])\r\n if (seq !== this._activateSeq) return\r\n\r\n // Drawing visible + editor swap (fast, post-projection).\r\n const editor = this.components.get(OBF.DrawingEditor)\r\n editor.activeDrawing = entry.drawing\r\n if (entry.drawing) {\r\n entry.drawing.three.visible = true\r\n }\r\n\r\n // Prepend Fill / Cut group-color controls so the sidebar shows them\r\n // at the top of the layers list.\r\n this._injectGroupColorLayers(entry)\r\n\r\n this._emit({ isLoading: false, stage: 'done' })\r\n } catch (error) {\r\n console.warn('[FloorplanTool] activate failed:', error)\r\n this._emit({ isLoading: false })\r\n }\r\n }\r\n\r\n /**\r\n * Exit floorplan mode. Each cleanup step is independently guarded so a\r\n * failure in one (e.g. resetHighlight on a huge model) cannot strand\r\n * camera, clip, or gizmo state.\r\n */\r\n async deactivate() {\r\n if (!this._activeId) return\r\n\r\n // Reset active state immediately so the React UI hides Exit and double\r\n // calls become no-ops.\r\n this._activeId = null\r\n this.onActiveDrawingChanged.trigger(null)\r\n\r\n // Drop any in-flight north-pick listener so the canvas stops\r\n // intercepting clicks once the floorplan is closed.\r\n safeRun(() => this.cancelPickNorth(), 'cancelPickNorth')\r\n\r\n // Clear editor + drawing visibility (synchronous, fast).\r\n safeRun(() => {\r\n const editor = this.components.get(OBF.DrawingEditor)\r\n editor.activeDrawing = null\r\n }, 'clear active drawing')\r\n for (const entry of this._entries.values()) {\r\n if (entry.drawing) {\r\n safeRun(() => {\r\n entry.drawing!.three.visible = false\r\n }, 'hide drawing')\r\n }\r\n }\r\n\r\n // Restore user-facing state FIRST so input feels responsive even if\r\n // model-render restoration takes a beat.\r\n safeRun(() => this.clip.removeAll(), 'removeClips')\r\n safeRun(() => this.grid.restore(), 'showGrid')\r\n safeRun(() => this.camera.unlock(), 'unlockCamera')\r\n safeRun(() => this.chrome.restoreCursor(), 'restoreCursor')\r\n safeRun(() => this.chrome.restoreHighlighter(), 'restoreHighlighter')\r\n safeRun(() => this.chrome.showGizmo(), 'showGizmo')\r\n safeRun(() => this.chrome.removeLighting(), 'removeLighting')\r\n safeRun(() => this.chrome.restoreBackground(), 'restoreBackground')\r\n\r\n // Slow async step last. Awaited so callers can chain on it, but failures\r\n // can't undo the synchronous restores above.\r\n await safeRunAsync(() => this.renderer.restore(), 'restoreModelRendering')\r\n\r\n safeRun(() => this._releaseCoordinator(), 'releaseCoordinator')\r\n }\r\n\r\n disposeEntriesForModel(modelId: string) {\r\n let touched = false\r\n for (const [id, entry] of this._entries) {\r\n if (entry.modelId !== modelId) continue\r\n if (this._activeId === id) void this.deactivate()\r\n disposeDrawing(this.components, entry.drawing)\r\n this._entries.delete(id)\r\n this.renderer.invalidateForEntry(id)\r\n touched = true\r\n }\r\n this.renderer.invalidateForModel(modelId)\r\n this.projector.invalidateForModel(modelId)\r\n if (touched) this.onDrawingsChanged.trigger(this.drawings)\r\n }\r\n\r\n dispose() {\r\n void this.deactivate()\r\n for (const entry of this._entries.values()) {\r\n disposeDrawing(this.components, entry.drawing)\r\n }\r\n this._entries.clear()\r\n this.onDrawingsChanged.trigger([])\r\n }\r\n\r\n private _emit(state: FloorplanLoadingState) {\r\n this.onGenerationStateChanged.trigger(state)\r\n }\r\n\r\n /** Mutual-exclusion claim. If ElevationsTool (or any other view tool)\r\n * was active, the coordinator awaits its deactivate() first. */\r\n private async _tryClaimCoordinator() {\r\n try {\r\n const coordinator = this.components.get(ViewModeCoordinator)\r\n await coordinator.claim(this)\r\n } catch {\r\n // ViewModeCoordinator not registered in this viewer — ignore.\r\n }\r\n }\r\n\r\n private _releaseCoordinator() {\r\n try {\r\n this.components.get(ViewModeCoordinator).release(this)\r\n } catch {\r\n // ignore\r\n }\r\n }\r\n\r\n /** Lower clip plane sits just under the active floor's slab (normal +Y),\r\n * so ceiling fixtures / lights / equipment of the storey below never\r\n * bleed into the projection or the 3D underlay. */\r\n private _applyLowerClip(entry: FloorplanEntry) {\r\n const cutY = entry.elevation - 0.5\r\n this.clip.set(\r\n SLOT_LOWER,\r\n new THREE.Vector3(0, 1, 0),\r\n new THREE.Vector3(0, cutY, 0),\r\n )\r\n }\r\n\r\n /** Frame the camera over the active floor in orthographic top-down,\r\n * then re-apply the building's true-north rotation so storey switches\r\n * preserve the user's chosen orientation. */\r\n private _frameCamera(entry: FloorplanEntry) {\r\n const fragments = this.components.get(OBC.FragmentsManager)\r\n const model = fragments.list.get(entry.modelId)\r\n if (!model) return\r\n const center = new THREE.Vector3()\r\n const size = new THREE.Vector3()\r\n model.box.getCenter(center)\r\n model.box.getSize(size)\r\n const span = Math.max(size.x, size.z, 10)\r\n const target = new THREE.Vector3(\r\n center.x,\r\n entry.elevation + 1.2,\r\n center.z,\r\n )\r\n this.camera.frame(target, new THREE.Vector3(0, -1, 0), span)\r\n this._applyNorthToCamera()\r\n }\r\n\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/bim/src/ModelManager/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAA;AAM3C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAG7D,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,KAAK,CAAC,KAAK,CAAA;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC,cAAc,CAAA;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,OAAO,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,OAAO,CAAA;IAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC,KAAK,CAAA;IACtB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,YAAa,SAAQ,GAAG,CAAC,SAAS;IAC7C,MAAM,CAAC,IAAI,EAAG,sCAAsC,CAAS;IAE7D,OAAO,UAAO;IAEd,aAAa,uBAA6B;IAC1C,kBAAkB,uBAA6B;IAE/C,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,cAAc,CAAe;IACrC,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,YAAY,CAAsB;gBAE9B,UAAU,EAAE,GAAG,CAAC,UAAU;IAYtC;;OAEG;IACG,IAAI,CACR,SAAS,EAAE,IAAI,GAAG,MAAM,EACxB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA0E5B;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IA2B3B;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI3C;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAOnD;;OAEG;IACH,YAAY,IAAI,SAAS,EAAE;IAI3B;;OAEG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO;IAiBjD;;OAEG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,GAAG,OAAO;IASzD;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC,OAAO,GAAG,OAAO;IAe5D;;OAEG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,GAAG,OAAO;IASvD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAQxB;;OAEG;YACW,eAAe;IAiB7B;;OAEG;IACH,OAAO,CAAC,QAAQ;IAWhB;;OAEG;IACH,OAAO,CAAC,OAAO;IAWf;;OAEG;IACH,OAAO,CAAC,OAAO;IAWf;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAWvB;;OAEG;IACH,OAAO,CAAC,UAAU;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/bim/src/ModelManager/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -272,6 +272,15 @@ const _ModelManager = class _ModelManager extends OBC.Component {
|
|
|
272
272
|
throw new Error("World not available for gizmo setup");
|
|
273
273
|
}
|
|
274
274
|
const gizmoController = new GizmoController(this._world);
|
|
275
|
+
const endEditing = () => {
|
|
276
|
+
const modelInfo = [...this._models.values()].find((info) => info.model === model);
|
|
277
|
+
if (!modelInfo) return;
|
|
278
|
+
model.updateMatrixWorld(true);
|
|
279
|
+
modelInfo.gizmoController = void 0;
|
|
280
|
+
this.onModelTransformed.trigger(modelInfo);
|
|
281
|
+
};
|
|
282
|
+
gizmoController.onAccept = endEditing;
|
|
283
|
+
gizmoController.onCancel = endEditing;
|
|
275
284
|
gizmoController.attach(model);
|
|
276
285
|
return gizmoController;
|
|
277
286
|
}
|