@ifc-lite/viewer 1.17.3 → 1.17.6
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/.turbo/turbo-build.log +39 -30
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +132 -0
- package/DESKTOP_CONTRACT_VERSION +1 -0
- package/dist/assets/arrow-CZ5kQ26f.js +20 -0
- package/dist/assets/basketViewActivator-86rgogji.js +1 -0
- package/dist/assets/{bcf-D5-QWGO9.js → bcf-DOG9_WPX.js} +1 -1
- package/dist/assets/{browser-CKs-FY1P.js → browser-C5TFR7sH.js} +1 -1
- package/dist/assets/cesium-ADbP7waU.css +1 -0
- package/dist/assets/cesium-DUOzBlqv.js +17817 -0
- package/dist/assets/drawing-2d-DoxKMqbO.js +257 -0
- package/dist/assets/{exporters-C_6J153K.js → exporters-CcPS9MK5.js} +2898 -2380
- package/dist/assets/geometry.worker-BFUYA08u.js +1 -0
- package/dist/assets/ids-DQ5jY0E8.js +1 -0
- package/dist/assets/ifc-lite_bg-BINvzoCP.wasm +0 -0
- package/dist/assets/{index-jhBr1wbn.js → index-Bfms9I4A.js} +41036 -34613
- package/dist/assets/index-_bfZsDCC.css +1 -0
- package/dist/assets/{maplibre-gl-BpvwNKKy.js → maplibre-gl-CGLcoNXc.js} +1 -1
- package/dist/assets/native-bridge-DUyLCMZS.js +429 -0
- package/dist/assets/{sandbox-B79eavQ3.js → sandbox-C8575tul.js} +4342 -4324
- package/dist/assets/{server-client-D3bUPJJc.js → server-client-BuZK7OST.js} +4 -4
- package/dist/assets/tauri-core-stub-D8Fa-u43.js +1 -0
- package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +1 -0
- package/dist/assets/tauri-fs-stub-BdeRC7aK.js +1 -0
- package/dist/assets/wasm-bridge-JsqEGDV8.js +1 -0
- package/dist/assets/{zip-B-jFFAGa.js → zip-DBEtpeu6.js} +3 -3
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json +1 -0
- package/dist/cesium/Assets/Images/bing_maps_credit.png +0 -0
- package/dist/cesium/Assets/Images/cesium_credit.png +0 -0
- package/dist/cesium/Assets/Images/google_earth_credit.png +0 -0
- package/dist/cesium/Assets/Images/ion-credit.png +0 -0
- package/dist/cesium/Assets/Textures/LensFlare/DirtMask.jpg +0 -0
- package/dist/cesium/Assets/Textures/LensFlare/StarBurst.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/0/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/0/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/tilemapresource.xml +14 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mx.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_my.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mz.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_px.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_py.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_pz.jpg +0 -0
- package/dist/cesium/Assets/Textures/maki/airfield.png +0 -0
- package/dist/cesium/Assets/Textures/maki/airport.png +0 -0
- package/dist/cesium/Assets/Textures/maki/alcohol-shop.png +0 -0
- package/dist/cesium/Assets/Textures/maki/america-football.png +0 -0
- package/dist/cesium/Assets/Textures/maki/art-gallery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bakery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bank.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bar.png +0 -0
- package/dist/cesium/Assets/Textures/maki/baseball.png +0 -0
- package/dist/cesium/Assets/Textures/maki/basketball.png +0 -0
- package/dist/cesium/Assets/Textures/maki/beer.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bicycle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/building.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bus.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cafe.png +0 -0
- package/dist/cesium/Assets/Textures/maki/camera.png +0 -0
- package/dist/cesium/Assets/Textures/maki/campsite.png +0 -0
- package/dist/cesium/Assets/Textures/maki/car.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cemetery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cesium.png +0 -0
- package/dist/cesium/Assets/Textures/maki/chemist.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cinema.png +0 -0
- package/dist/cesium/Assets/Textures/maki/circle-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/circle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/city.png +0 -0
- package/dist/cesium/Assets/Textures/maki/clothing-store.png +0 -0
- package/dist/cesium/Assets/Textures/maki/college.png +0 -0
- package/dist/cesium/Assets/Textures/maki/commercial.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cricket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cross.png +0 -0
- package/dist/cesium/Assets/Textures/maki/dam.png +0 -0
- package/dist/cesium/Assets/Textures/maki/danger.png +0 -0
- package/dist/cesium/Assets/Textures/maki/disability.png +0 -0
- package/dist/cesium/Assets/Textures/maki/dog-park.png +0 -0
- package/dist/cesium/Assets/Textures/maki/embassy.png +0 -0
- package/dist/cesium/Assets/Textures/maki/emergency-telephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/entrance.png +0 -0
- package/dist/cesium/Assets/Textures/maki/farm.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fast-food.png +0 -0
- package/dist/cesium/Assets/Textures/maki/ferry.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fire-station.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fuel.png +0 -0
- package/dist/cesium/Assets/Textures/maki/garden.png +0 -0
- package/dist/cesium/Assets/Textures/maki/gift.png +0 -0
- package/dist/cesium/Assets/Textures/maki/golf.png +0 -0
- package/dist/cesium/Assets/Textures/maki/grocery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/hairdresser.png +0 -0
- package/dist/cesium/Assets/Textures/maki/harbor.png +0 -0
- package/dist/cesium/Assets/Textures/maki/heart.png +0 -0
- package/dist/cesium/Assets/Textures/maki/heliport.png +0 -0
- package/dist/cesium/Assets/Textures/maki/hospital.png +0 -0
- package/dist/cesium/Assets/Textures/maki/ice-cream.png +0 -0
- package/dist/cesium/Assets/Textures/maki/industrial.png +0 -0
- package/dist/cesium/Assets/Textures/maki/land-use.png +0 -0
- package/dist/cesium/Assets/Textures/maki/laundry.png +0 -0
- package/dist/cesium/Assets/Textures/maki/library.png +0 -0
- package/dist/cesium/Assets/Textures/maki/lighthouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/lodging.png +0 -0
- package/dist/cesium/Assets/Textures/maki/logging.png +0 -0
- package/dist/cesium/Assets/Textures/maki/london-underground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/marker-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/marker.png +0 -0
- package/dist/cesium/Assets/Textures/maki/minefield.png +0 -0
- package/dist/cesium/Assets/Textures/maki/mobilephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/monument.png +0 -0
- package/dist/cesium/Assets/Textures/maki/museum.png +0 -0
- package/dist/cesium/Assets/Textures/maki/music.png +0 -0
- package/dist/cesium/Assets/Textures/maki/oil-well.png +0 -0
- package/dist/cesium/Assets/Textures/maki/park.png +0 -0
- package/dist/cesium/Assets/Textures/maki/park2.png +0 -0
- package/dist/cesium/Assets/Textures/maki/parking-garage.png +0 -0
- package/dist/cesium/Assets/Textures/maki/parking.png +0 -0
- package/dist/cesium/Assets/Textures/maki/pharmacy.png +0 -0
- package/dist/cesium/Assets/Textures/maki/pitch.png +0 -0
- package/dist/cesium/Assets/Textures/maki/place-of-worship.png +0 -0
- package/dist/cesium/Assets/Textures/maki/playground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/police.png +0 -0
- package/dist/cesium/Assets/Textures/maki/polling-place.png +0 -0
- package/dist/cesium/Assets/Textures/maki/post.png +0 -0
- package/dist/cesium/Assets/Textures/maki/prison.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-above.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-light.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-metro.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-underground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-christian.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-jewish.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-muslim.png +0 -0
- package/dist/cesium/Assets/Textures/maki/restaurant.png +0 -0
- package/dist/cesium/Assets/Textures/maki/roadblock.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rocket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/school.png +0 -0
- package/dist/cesium/Assets/Textures/maki/scooter.png +0 -0
- package/dist/cesium/Assets/Textures/maki/shop.png +0 -0
- package/dist/cesium/Assets/Textures/maki/skiing.png +0 -0
- package/dist/cesium/Assets/Textures/maki/slaughterhouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/soccer.png +0 -0
- package/dist/cesium/Assets/Textures/maki/square-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/square.png +0 -0
- package/dist/cesium/Assets/Textures/maki/star-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/star.png +0 -0
- package/dist/cesium/Assets/Textures/maki/suitcase.png +0 -0
- package/dist/cesium/Assets/Textures/maki/swimming.png +0 -0
- package/dist/cesium/Assets/Textures/maki/telephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/tennis.png +0 -0
- package/dist/cesium/Assets/Textures/maki/theatre.png +0 -0
- package/dist/cesium/Assets/Textures/maki/toilets.png +0 -0
- package/dist/cesium/Assets/Textures/maki/town-hall.png +0 -0
- package/dist/cesium/Assets/Textures/maki/town.png +0 -0
- package/dist/cesium/Assets/Textures/maki/triangle-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/triangle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/village.png +0 -0
- package/dist/cesium/Assets/Textures/maki/warehouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/waste-basket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/water.png +0 -0
- package/dist/cesium/Assets/Textures/maki/wetland.png +0 -0
- package/dist/cesium/Assets/Textures/maki/zoo.png +0 -0
- package/dist/cesium/Assets/Textures/moonSmall.jpg +0 -0
- package/dist/cesium/Assets/Textures/pin.svg +1 -0
- package/dist/cesium/Assets/Textures/waterNormals.jpg +0 -0
- package/dist/cesium/Assets/Textures/waterNormalsSmall.jpg +0 -0
- package/dist/cesium/Assets/approximateTerrainHeights.json +1 -0
- package/dist/cesium/ThirdParty/Workers/package.json +1 -0
- package/dist/cesium/ThirdParty/Workers/zip-web-worker.js +1 -0
- package/dist/cesium/ThirdParty/basis_transcoder.wasm +0 -0
- package/dist/cesium/ThirdParty/draco_decoder.wasm +0 -0
- package/dist/cesium/ThirdParty/google-earth-dbroot-parser.js +1 -0
- package/dist/cesium/ThirdParty/wasm_splats_bg.wasm +0 -0
- package/dist/cesium/ThirdParty/zip-module.wasm +0 -0
- package/dist/cesium/Widgets/Animation/Animation.css +127 -0
- package/dist/cesium/Widgets/Animation/lighter.css +70 -0
- package/dist/cesium/Widgets/BaseLayerPicker/BaseLayerPicker.css +108 -0
- package/dist/cesium/Widgets/BaseLayerPicker/lighter.css +22 -0
- package/dist/cesium/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspector.css +102 -0
- package/dist/cesium/Widgets/CesiumInspector/CesiumInspector.css +113 -0
- package/dist/cesium/Widgets/CesiumWidget/CesiumWidget.css +119 -0
- package/dist/cesium/Widgets/CesiumWidget/lighter.css +14 -0
- package/dist/cesium/Widgets/FullscreenButton/FullscreenButton.css +8 -0
- package/dist/cesium/Widgets/Geocoder/Geocoder.css +70 -0
- package/dist/cesium/Widgets/Geocoder/lighter.css +17 -0
- package/dist/cesium/Widgets/I3SBuildingSceneLayerExplorer/I3SBuildingSceneLayerExplorer.css +27 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldHillshade.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldImagery.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldOcean.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/azureAerial.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/azureRoads.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingAerial.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingAerialLabels.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingRoads.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/blueMarble.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/earthAtNight.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleContour.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleRoadmap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleSatellite.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleSatelliteLabels.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapQuestOpenStreetMap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxSatellite.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxStreets.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxTerrain.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/naturalEarthII.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/openStreetMap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/sentinel-2.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmooth.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmoothDark.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stamenToner.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stamenWatercolor.png +0 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/Mouse.svg +84 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseLeft.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseMiddle.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseRight.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/Touch.svg +120 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchDrag.svg +129 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchRotate.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchTilt.svg +135 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchZoom.svg +74 -0
- package/dist/cesium/Widgets/Images/TerrainProviders/CesiumWorldTerrain.png +0 -0
- package/dist/cesium/Widgets/Images/TerrainProviders/Ellipsoid.png +0 -0
- package/dist/cesium/Widgets/Images/TimelineIcons.png +0 -0
- package/dist/cesium/Widgets/Images/info-loading.gif +0 -0
- package/dist/cesium/Widgets/InfoBox/InfoBox.css +92 -0
- package/dist/cesium/Widgets/InfoBox/InfoBoxDescription.css +178 -0
- package/dist/cesium/Widgets/NavigationHelpButton/NavigationHelpButton.css +93 -0
- package/dist/cesium/Widgets/NavigationHelpButton/lighter.css +38 -0
- package/dist/cesium/Widgets/PerformanceWatchdog/PerformanceWatchdog.css +15 -0
- package/dist/cesium/Widgets/ProjectionPicker/ProjectionPicker.css +38 -0
- package/dist/cesium/Widgets/SceneModePicker/SceneModePicker.css +56 -0
- package/dist/cesium/Widgets/SelectionIndicator/SelectionIndicator.css +20 -0
- package/dist/cesium/Widgets/Timeline/Timeline.css +103 -0
- package/dist/cesium/Widgets/Timeline/lighter.css +23 -0
- package/dist/cesium/Widgets/VRButton/VRButton.css +8 -0
- package/dist/cesium/Widgets/Viewer/Viewer.css +107 -0
- package/dist/cesium/Widgets/VoxelInspector/VoxelInspector.css +16 -0
- package/dist/cesium/Widgets/lighter.css +237 -0
- package/dist/cesium/Widgets/lighterShared.css +46 -0
- package/dist/cesium/Widgets/shared.css +103 -0
- package/dist/cesium/Widgets/widgets.css +1342 -0
- package/dist/cesium/Workers/chunk-23ZQ2IVV.js +29 -0
- package/dist/cesium/Workers/chunk-2EQO3Q56.js +26 -0
- package/dist/cesium/Workers/chunk-2MJIIVP4.js +26 -0
- package/dist/cesium/Workers/chunk-2TE5NTVD.js +26 -0
- package/dist/cesium/Workers/chunk-2ZBHLJST.js +26 -0
- package/dist/cesium/Workers/chunk-5TJMAQVL.js +26 -0
- package/dist/cesium/Workers/chunk-6BD4U3VO.js +26 -0
- package/dist/cesium/Workers/chunk-7TVGLKQF.js +26 -0
- package/dist/cesium/Workers/chunk-BTSYJ5XU.js +26 -0
- package/dist/cesium/Workers/chunk-BXMEEOCS.js +63 -0
- package/dist/cesium/Workers/chunk-BYLCY7GP.js +29 -0
- package/dist/cesium/Workers/chunk-CTHM3W6I.js +26 -0
- package/dist/cesium/Workers/chunk-CUUSNIVQ.js +26 -0
- package/dist/cesium/Workers/chunk-E3JOOS3S.js +26 -0
- package/dist/cesium/Workers/chunk-E7KYDCM5.js +26 -0
- package/dist/cesium/Workers/chunk-EDVBB7SS.js +27 -0
- package/dist/cesium/Workers/chunk-EFBN7QNX.js +26 -0
- package/dist/cesium/Workers/chunk-EQ4YRVWL.js +26 -0
- package/dist/cesium/Workers/chunk-F6PRE7D6.js +26 -0
- package/dist/cesium/Workers/chunk-FC4ZZ65J.js +26 -0
- package/dist/cesium/Workers/chunk-FFBVWF2L.js +26 -0
- package/dist/cesium/Workers/chunk-GBAA6GVX.js +26 -0
- package/dist/cesium/Workers/chunk-ICALLYLG.js +26 -0
- package/dist/cesium/Workers/chunk-ILRYTWTP.js +26 -0
- package/dist/cesium/Workers/chunk-IRNLBSEJ.js +26 -0
- package/dist/cesium/Workers/chunk-IX4VMHEV.js +26 -0
- package/dist/cesium/Workers/chunk-L6QHHACZ.js +26 -0
- package/dist/cesium/Workers/chunk-LI2ZSORM.js +26 -0
- package/dist/cesium/Workers/chunk-LSLE2RL4.js +26 -0
- package/dist/cesium/Workers/chunk-M4HLDBCG.js +26 -0
- package/dist/cesium/Workers/chunk-MJHHSGEH.js +26 -0
- package/dist/cesium/Workers/chunk-NMVKML6W.js +26 -0
- package/dist/cesium/Workers/chunk-OCWJRAXS.js +26 -0
- package/dist/cesium/Workers/chunk-OIRKANTH.js +26 -0
- package/dist/cesium/Workers/chunk-OIT7J4IC.js +26 -0
- package/dist/cesium/Workers/chunk-OLZ3FYUM.js +26 -0
- package/dist/cesium/Workers/chunk-Q5BPHJQF.js +26 -0
- package/dist/cesium/Workers/chunk-QFM5DCMQ.js +26 -0
- package/dist/cesium/Workers/chunk-QKUIYMGC.js +28 -0
- package/dist/cesium/Workers/chunk-S44JILQT.js +26 -0
- package/dist/cesium/Workers/chunk-SLT4J352.js +26 -0
- package/dist/cesium/Workers/chunk-SQMIIXB7.js +26 -0
- package/dist/cesium/Workers/chunk-TJ4XLGBQ.js +26 -0
- package/dist/cesium/Workers/chunk-TNSUQXWK.js +27 -0
- package/dist/cesium/Workers/chunk-UBOGZS7F.js +26 -0
- package/dist/cesium/Workers/chunk-V3OSTMM6.js +26 -0
- package/dist/cesium/Workers/chunk-V7QEYVP3.js +26 -0
- package/dist/cesium/Workers/chunk-VUKYSU4H.js +26 -0
- package/dist/cesium/Workers/chunk-W37FE5GR.js +26 -0
- package/dist/cesium/Workers/chunk-WBOV35NL.js +26 -0
- package/dist/cesium/Workers/chunk-WPMZLB3Y.js +26 -0
- package/dist/cesium/Workers/chunk-WWWZVEEH.js +26 -0
- package/dist/cesium/Workers/chunk-XFIQ5DEQ.js +28 -0
- package/dist/cesium/Workers/chunk-XQHLGIO7.js +26 -0
- package/dist/cesium/Workers/chunk-XUSCFAVF.js +26 -0
- package/dist/cesium/Workers/chunk-YP7I5QBZ.js +26 -0
- package/dist/cesium/Workers/chunk-Z3QF2EHT.js +26 -0
- package/dist/cesium/Workers/combineGeometry.js +26 -0
- package/dist/cesium/Workers/createBoxGeometry.js +26 -0
- package/dist/cesium/Workers/createBoxOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCircleGeometry.js +26 -0
- package/dist/cesium/Workers/createCircleOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCoplanarPolygonGeometry.js +26 -0
- package/dist/cesium/Workers/createCoplanarPolygonOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCorridorGeometry.js +26 -0
- package/dist/cesium/Workers/createCorridorOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCylinderGeometry.js +26 -0
- package/dist/cesium/Workers/createCylinderOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipseGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipseOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipsoidGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipsoidOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createFrustumGeometry.js +26 -0
- package/dist/cesium/Workers/createFrustumOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createGeometry.js +26 -0
- package/dist/cesium/Workers/createGroundPolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createPlaneGeometry.js +26 -0
- package/dist/cesium/Workers/createPlaneOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolygonGeometry.js +26 -0
- package/dist/cesium/Workers/createPolygonOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineVolumeGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineVolumeOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createRectangleGeometry.js +26 -0
- package/dist/cesium/Workers/createRectangleOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createSimplePolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createSphereGeometry.js +26 -0
- package/dist/cesium/Workers/createSphereOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createTaskProcessorWorker.js +26 -0
- package/dist/cesium/Workers/createVectorTileClampedPolylines.js +26 -0
- package/dist/cesium/Workers/createVectorTileGeometries.js +26 -0
- package/dist/cesium/Workers/createVectorTilePoints.js +26 -0
- package/dist/cesium/Workers/createVectorTilePolygons.js +26 -0
- package/dist/cesium/Workers/createVectorTilePolylines.js +26 -0
- package/dist/cesium/Workers/createVerticesFromCesium3DTilesTerrain.js +26 -0
- package/dist/cesium/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +26 -0
- package/dist/cesium/Workers/createVerticesFromHeightmap.js +26 -0
- package/dist/cesium/Workers/createVerticesFromQuantizedTerrainMesh.js +26 -0
- package/dist/cesium/Workers/createWallGeometry.js +26 -0
- package/dist/cesium/Workers/createWallOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/decodeDraco.js +26 -0
- package/dist/cesium/Workers/decodeGoogleEarthEnterprisePacket.js +26 -0
- package/dist/cesium/Workers/decodeI3S.js +26 -0
- package/dist/cesium/Workers/gaussianSplatSorter.js +26 -0
- package/dist/cesium/Workers/gaussianSplatTextureGenerator.js +26 -0
- package/dist/cesium/Workers/incrementallyBuildTerrainPicker.js +26 -0
- package/dist/cesium/Workers/transcodeKTX2.js +56 -0
- package/dist/cesium/Workers/transferTypedArrayTest.js +26 -0
- package/dist/cesium/Workers/upsampleQuantizedTerrainMesh.js +26 -0
- package/dist/cesium/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +26 -0
- package/dist/index.html +13 -10
- package/index.html +1 -0
- package/package.json +18 -15
- package/src/App.tsx +7 -9
- package/src/components/viewer/BCFPanel.tsx +46 -4
- package/src/components/viewer/CesiumOverlay.tsx +715 -0
- package/src/components/viewer/CesiumSettingsDialog.tsx +100 -0
- package/src/components/viewer/ChatPanel.tsx +232 -90
- package/src/components/viewer/CommandPalette.tsx +6 -1
- package/src/components/viewer/DesktopEntitlementBanner.tsx +74 -0
- package/src/components/viewer/ExportChangesButton.tsx +6 -1
- package/src/components/viewer/ExportDialog.tsx +22 -6
- package/src/components/viewer/HierarchyPanel.tsx +196 -0
- package/src/components/viewer/IDSPanel.tsx +52 -3
- package/src/components/viewer/KeyboardShortcutsDialog.tsx +1 -1
- package/src/components/viewer/MainToolbar.tsx +355 -28
- package/src/components/viewer/PropertiesPanel.tsx +234 -81
- package/src/components/viewer/ScriptPanel.tsx +34 -8
- package/src/components/viewer/SettingsPage.tsx +581 -0
- package/src/components/viewer/StatusBar.tsx +17 -1
- package/src/components/viewer/ThemeSwitch.tsx +63 -7
- package/src/components/viewer/ViewerLayout.tsx +48 -6
- package/src/components/viewer/Viewport.tsx +61 -8
- package/src/components/viewer/ViewportContainer.tsx +265 -28
- package/src/components/viewer/ViewportOverlays.tsx +132 -27
- package/src/components/viewer/bcf/BCFTopicDetail.tsx +4 -4
- package/src/components/viewer/chat/ModelSelector.tsx +90 -54
- package/src/components/viewer/properties/GeoreferencingPanel.tsx +229 -55
- package/src/components/viewer/properties/LocationMap.tsx +462 -19
- package/src/components/viewer/properties/ModelMetadataPanel.tsx +1 -1
- package/src/components/viewer/selectionHandlers.ts +4 -3
- package/src/components/viewer/tools/SectionCapControls.tsx +237 -0
- package/src/components/viewer/tools/SectionPanel.tsx +39 -18
- package/src/components/viewer/useAnimationLoop.ts +13 -1
- package/src/components/viewer/useGeometryStreaming.ts +127 -40
- package/src/components/viewer/useMouseControls.ts +4 -1
- package/src/components/viewer/useRenderUpdates.ts +1 -1
- package/src/hooks/ids/idsDataAccessor.ts +60 -24
- package/src/hooks/ingest/viewerModelIngest.ts +280 -0
- package/src/hooks/useIDS.ts +1 -1
- package/src/hooks/useIfc.ts +7 -1
- package/src/hooks/useIfcCache.ts +28 -15
- package/src/hooks/useIfcFederation.ts +378 -291
- package/src/hooks/useIfcLoader.ts +1657 -130
- package/src/hooks/useIfcServer.ts +0 -69
- package/src/hooks/useViewControls.ts +13 -5
- package/src/index.css +484 -10
- package/src/lib/desktop/desktopEntitlementEvents.ts +39 -0
- package/src/lib/desktop-entitlement.ts +43 -0
- package/src/lib/desktop-product.ts +124 -0
- package/src/lib/geo/cesium-bridge.ts +318 -0
- package/src/lib/geo/effective-georef.test.ts +73 -0
- package/src/lib/geo/effective-georef.ts +111 -0
- package/src/lib/geo/reproject.ts +249 -37
- package/src/lib/llm/byok-guard.test.ts +77 -0
- package/src/lib/llm/byok-guard.ts +39 -0
- package/src/lib/llm/free-models.test.ts +0 -6
- package/src/lib/llm/models.ts +104 -42
- package/src/lib/llm/stream-client.ts +74 -110
- package/src/lib/llm/stream-direct.test.ts +130 -0
- package/src/lib/llm/stream-direct.ts +316 -0
- package/src/lib/llm/types.ts +14 -2
- package/src/lib/recent-files.ts +2 -1
- package/src/main.tsx +1 -10
- package/src/services/analysis-extensions.ts +125 -0
- package/src/services/api-keys.ts +73 -0
- package/src/services/app-navigation.ts +13 -0
- package/src/services/bsdd.ts +53 -4
- package/src/services/cacheService.ts +1 -1
- package/src/services/desktop-cache.ts +43 -0
- package/src/services/desktop-export.ts +77 -0
- package/src/services/desktop-harness.ts +196 -0
- package/src/services/desktop-logger.ts +20 -0
- package/src/services/desktop-native-metadata.ts +207 -0
- package/src/services/desktop-panel-actions.ts +43 -0
- package/src/services/desktop-preferences.ts +44 -0
- package/src/services/file-dialog.ts +147 -0
- package/src/services/tauri-core-stub.ts +7 -0
- package/src/services/tauri-dialog-stub.ts +7 -0
- package/src/services/tauri-fs-stub.ts +7 -0
- package/src/store/constants.ts +20 -2
- package/src/store/index.ts +52 -7
- package/src/store/slices/cesiumSlice.ts +127 -0
- package/src/store/slices/chatSlice.test.ts +6 -76
- package/src/store/slices/chatSlice.ts +21 -58
- package/src/store/slices/dataSlice.ts +139 -28
- package/src/store/slices/desktopEntitlementSlice.ts +86 -0
- package/src/store/slices/loadingSlice.ts +14 -2
- package/src/store/slices/modelSlice.ts +58 -3
- package/src/store/slices/sectionSlice.test.ts +87 -7
- package/src/store/slices/sectionSlice.ts +151 -5
- package/src/store/slices/uiSlice.ts +28 -5
- package/src/store/types.ts +122 -2
- package/src/store.ts +1 -1
- package/src/utils/desktopModelSnapshot.ts +358 -0
- package/src/utils/ifcConfig.ts +6 -1
- package/src/utils/nativeSpatialDataStore.ts +253 -0
- package/src/utils/serverDataModel.ts +4 -0
- package/src/utils/spatialHierarchy.ts +10 -11
- package/src/utils/viewportUtils.ts +7 -2
- package/src/vite-env.d.ts +0 -4
- package/vite.config.ts +24 -0
- package/dist/assets/arrow-DJf2ErbF.js +0 -20
- package/dist/assets/basketViewActivator-aojwdomq.js +0 -1
- package/dist/assets/desktop-cache-oPzaWXYE.js +0 -1
- package/dist/assets/drawing-2d-gWfpdfYe.js +0 -257
- package/dist/assets/geometry.worker-Nz9_YIqh.js +0 -1
- package/dist/assets/ids-B4jTqB1O.js +0 -1
- package/dist/assets/ifc-lite_bg-eSkBTizQ.wasm +0 -0
- package/dist/assets/index-pbE7itQS.css +0 -1
- package/dist/assets/native-bridge-DSIyEYXG.js +0 -113
- package/dist/assets/wasm-bridge-B0J07fZZ.js +0 -1
- package/src/components/viewer/UpgradePage.tsx +0 -69
- package/src/lib/llm/ClerkChatSync.tsx +0 -74
- package/src/lib/llm/clerk-auth.ts +0 -62
|
@@ -2,20 +2,27 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
|
|
5
|
-
import { useMemo, useRef, useState, useCallback } from 'react';
|
|
5
|
+
import { useMemo, useRef, useState, useCallback, useEffect, useSyncExternalStore } from 'react';
|
|
6
6
|
import { Viewport } from './Viewport';
|
|
7
7
|
import { ViewportOverlays } from './ViewportOverlays';
|
|
8
8
|
import { ToolOverlays } from './ToolOverlays';
|
|
9
9
|
import { Section2DPanel } from './Section2DPanel';
|
|
10
10
|
import { BasketPresentationDock } from './BasketPresentationDock';
|
|
11
11
|
import { BCFOverlay } from './bcf/BCFOverlay';
|
|
12
|
-
import {
|
|
12
|
+
import { CesiumOverlay } from './CesiumOverlay';
|
|
13
|
+
import { getViewerStoreApi, useViewerStore } from '@/store';
|
|
13
14
|
import { toGlobalIdFromModels } from '@/store/globalId';
|
|
14
15
|
import { collectIfcBuildingStoreyElementsWithIfcSpace } from '@/store/basketVisibleSet';
|
|
15
16
|
import { useIfc } from '@/hooks/useIfc';
|
|
16
17
|
import { useWebGPU } from '@/hooks/useWebGPU';
|
|
17
|
-
import {
|
|
18
|
+
import { openIfcFileDialog } from '@/services/file-dialog';
|
|
19
|
+
import { logToDesktopTerminal } from '@/services/desktop-logger';
|
|
20
|
+
import { cacheFileBlobs, formatFileSize, getCachedFile, getRecentFiles, recordRecentFiles, type RecentFileEntry } from '@/lib/recent-files';
|
|
21
|
+
import { isTauri } from '@/lib/platform';
|
|
22
|
+
import { Upload, MousePointer, Layers, Info, Command, AlertTriangle, ChevronDown, ExternalLink, Plus, Clock3 } from 'lucide-react';
|
|
18
23
|
import type { MeshData, CoordinateInfo, GeometryResult } from '@ifc-lite/geometry';
|
|
24
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
25
|
+
import { getEffectiveGeoreference } from '@/lib/geo/effective-georef';
|
|
19
26
|
|
|
20
27
|
const ZERO_VEC3 = { x: 0, y: 0, z: 0 };
|
|
21
28
|
const DEFAULT_COORDINATE_INFO: CoordinateInfo = {
|
|
@@ -26,20 +33,42 @@ const DEFAULT_COORDINATE_INFO: CoordinateInfo = {
|
|
|
26
33
|
};
|
|
27
34
|
|
|
28
35
|
export function ViewportContainer() {
|
|
29
|
-
const {
|
|
36
|
+
const { loadFile, loading, clearAllModels, loadFilesSequentially } = useIfc();
|
|
37
|
+
const releaseGeometryMemory = useViewerStore((s) => s.releaseGeometryMemory);
|
|
30
38
|
const selectedStoreys = useViewerStore((s) => s.selectedStoreys);
|
|
31
39
|
const typeVisibility = useViewerStore((s) => s.typeVisibility);
|
|
32
40
|
const isolatedEntities = useViewerStore((s) => s.isolatedEntities);
|
|
33
41
|
const classFilter = useViewerStore((s) => s.classFilter);
|
|
34
|
-
// Multi-model support: get all loaded models from store (for merged geometry)
|
|
35
|
-
const storeModels = useViewerStore((s) => s.models);
|
|
36
42
|
const resetViewerState = useViewerStore((s) => s.resetViewerState);
|
|
37
43
|
const bcfOverlayVisible = useViewerStore((s) => s.bcfOverlayVisible);
|
|
44
|
+
const cesiumEnabled = useViewerStore((s) => s.cesiumEnabled);
|
|
45
|
+
const georefMutations = useViewerStore((s) => s.georefMutations);
|
|
46
|
+
const setCesiumSourceModelId = useViewerStore((s) => s.setCesiumSourceModelId);
|
|
47
|
+
const setCesiumAvailable = useViewerStore((s) => s.setCesiumAvailable);
|
|
48
|
+
// Subscribe to mutationVersion so Cesium reacts to georef edits
|
|
49
|
+
const mutationVersion = useViewerStore((s) => s.mutationVersion);
|
|
38
50
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
39
51
|
const [isDragging, setIsDragging] = useState(false);
|
|
40
52
|
const [showTroubleshooting, setShowTroubleshooting] = useState(false);
|
|
53
|
+
const [recentFiles, setRecentFiles] = useState<RecentFileEntry[]>([]);
|
|
41
54
|
const webgpu = useWebGPU();
|
|
42
55
|
|
|
56
|
+
const viewerStoreApi = getViewerStoreApi();
|
|
57
|
+
const viewportStoreState = useSyncExternalStore(
|
|
58
|
+
viewerStoreApi.subscribe,
|
|
59
|
+
viewerStoreApi.getState,
|
|
60
|
+
viewerStoreApi.getState,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const {
|
|
64
|
+
geometryResult,
|
|
65
|
+
ifcDataStore,
|
|
66
|
+
models,
|
|
67
|
+
boundedGeometryMode,
|
|
68
|
+
geometryUpdateTick,
|
|
69
|
+
} = viewportStoreState;
|
|
70
|
+
const storeModels = models;
|
|
71
|
+
|
|
43
72
|
// Check if we have models loaded (for determining add vs replace behavior)
|
|
44
73
|
const hasModelsLoaded = models.size > 0 || (geometryResult?.meshes && geometryResult.meshes.length > 0);
|
|
45
74
|
|
|
@@ -53,39 +82,87 @@ export function ViewportContainer() {
|
|
|
53
82
|
return map;
|
|
54
83
|
}, [storeModels]);
|
|
55
84
|
|
|
85
|
+
const mergedCacheRef = useRef<MeshData[]>([]);
|
|
86
|
+
const mergedLengthsRef = useRef<Map<string, number>>(new Map());
|
|
87
|
+
const mergedVisibilityRef = useRef<Map<string, boolean>>(new Map());
|
|
88
|
+
|
|
56
89
|
// Multi-model: merge geometries from all visible models
|
|
57
90
|
const mergedGeometryResult = useMemo(() => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
91
|
+
if (storeModels.size === 1) {
|
|
92
|
+
const firstModel = storeModels.values().next().value;
|
|
93
|
+
if (!firstModel?.visible) {
|
|
94
|
+
return {
|
|
95
|
+
meshes: [],
|
|
96
|
+
totalVertices: 0,
|
|
97
|
+
totalTriangles: 0,
|
|
98
|
+
coordinateInfo: DEFAULT_COORDINATE_INFO,
|
|
99
|
+
} satisfies GeometryResult;
|
|
100
|
+
}
|
|
101
|
+
return firstModel.geometryResult ?? geometryResult;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (storeModels.size > 1) {
|
|
61
105
|
let totalVertices = 0;
|
|
62
106
|
let totalTriangles = 0;
|
|
63
107
|
let mergedCoordinateInfo: CoordinateInfo | undefined;
|
|
108
|
+
let shouldRebuild = false;
|
|
64
109
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
110
|
+
if (mergedLengthsRef.current.size !== storeModels.size) {
|
|
111
|
+
shouldRebuild = true;
|
|
112
|
+
}
|
|
68
113
|
|
|
114
|
+
for (const [modelId, model] of storeModels) {
|
|
69
115
|
const modelGeometry = model.geometryResult;
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
116
|
+
const meshCount = model.visible ? (modelGeometry?.meshes.length ?? 0) : 0;
|
|
117
|
+
totalVertices += model.visible ? (modelGeometry?.totalVertices ?? 0) : 0;
|
|
118
|
+
totalTriangles += model.visible ? (modelGeometry?.totalTriangles ?? 0) : 0;
|
|
119
|
+
if (!mergedCoordinateInfo && model.visible && modelGeometry?.coordinateInfo) {
|
|
120
|
+
mergedCoordinateInfo = modelGeometry.coordinateInfo;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (
|
|
124
|
+
mergedVisibilityRef.current.get(modelId) !== model.visible ||
|
|
125
|
+
(mergedLengthsRef.current.get(modelId) ?? 0) > meshCount
|
|
126
|
+
) {
|
|
127
|
+
shouldRebuild = true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (shouldRebuild) {
|
|
132
|
+
const rebuilt: MeshData[] = [];
|
|
133
|
+
mergedLengthsRef.current = new Map();
|
|
134
|
+
mergedVisibilityRef.current = new Map();
|
|
135
|
+
for (const [modelId, model] of storeModels) {
|
|
136
|
+
const modelGeometry = model.geometryResult;
|
|
137
|
+
mergedVisibilityRef.current.set(modelId, model.visible);
|
|
138
|
+
const modelIndex = modelIdToIndex.get(modelId) ?? 0;
|
|
139
|
+
if (!model.visible || !modelGeometry?.meshes) {
|
|
140
|
+
mergedLengthsRef.current.set(modelId, 0);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
73
143
|
for (const mesh of modelGeometry.meshes) {
|
|
74
|
-
|
|
144
|
+
rebuilt.push({ ...mesh, modelIndex });
|
|
75
145
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
146
|
+
mergedLengthsRef.current.set(modelId, modelGeometry.meshes.length);
|
|
147
|
+
}
|
|
148
|
+
mergedCacheRef.current = rebuilt;
|
|
149
|
+
} else {
|
|
150
|
+
for (const [modelId, model] of storeModels) {
|
|
151
|
+
const modelGeometry = model.geometryResult;
|
|
152
|
+
const modelIndex = modelIdToIndex.get(modelId) ?? 0;
|
|
153
|
+
const previousLength = mergedLengthsRef.current.get(modelId) ?? 0;
|
|
154
|
+
const nextMeshes = model.visible ? (modelGeometry?.meshes ?? []) : [];
|
|
155
|
+
for (let i = previousLength; i < nextMeshes.length; i++) {
|
|
156
|
+
const mesh = nextMeshes[i];
|
|
157
|
+
mergedCacheRef.current.push({ ...mesh, modelIndex });
|
|
82
158
|
}
|
|
159
|
+
mergedLengthsRef.current.set(modelId, nextMeshes.length);
|
|
160
|
+
mergedVisibilityRef.current.set(modelId, model.visible);
|
|
83
161
|
}
|
|
84
162
|
}
|
|
85
163
|
|
|
86
|
-
// Return merged result (may be empty if all models hidden)
|
|
87
164
|
return {
|
|
88
|
-
meshes:
|
|
165
|
+
meshes: mergedCacheRef.current,
|
|
89
166
|
totalVertices,
|
|
90
167
|
totalTriangles,
|
|
91
168
|
coordinateInfo: mergedCoordinateInfo ?? DEFAULT_COORDINATE_INFO,
|
|
@@ -96,6 +173,88 @@ export function ViewportContainer() {
|
|
|
96
173
|
return geometryResult;
|
|
97
174
|
}, [storeModels, geometryResult, modelIdToIndex]);
|
|
98
175
|
|
|
176
|
+
// Extract georeferencing info merged with any live mutations (for Cesium overlay).
|
|
177
|
+
// Reacts to: model load, Cesium toggle, and every georef field edit.
|
|
178
|
+
const georef = useMemo(() => {
|
|
179
|
+
if (!cesiumEnabled) return null;
|
|
180
|
+
|
|
181
|
+
// Check federated models first
|
|
182
|
+
for (const [modelId, model] of storeModels) {
|
|
183
|
+
const ds = model.ifcDataStore;
|
|
184
|
+
if (!ds) continue;
|
|
185
|
+
const effective = getEffectiveGeoreference(
|
|
186
|
+
ds as IfcDataStore,
|
|
187
|
+
model.geometryResult?.coordinateInfo,
|
|
188
|
+
georefMutations.get(modelId),
|
|
189
|
+
);
|
|
190
|
+
if (effective?.projectedCRS?.name && effective.mapConversion) {
|
|
191
|
+
return { ...effective, sourceModelId: modelId };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Fallback to legacy single-model
|
|
196
|
+
if (ifcDataStore) {
|
|
197
|
+
const effective = getEffectiveGeoreference(
|
|
198
|
+
ifcDataStore as IfcDataStore,
|
|
199
|
+
mergedGeometryResult?.coordinateInfo,
|
|
200
|
+
georefMutations.get('__legacy__'),
|
|
201
|
+
);
|
|
202
|
+
if (effective?.projectedCRS?.name && effective.mapConversion) {
|
|
203
|
+
return { ...effective, sourceModelId: '__legacy__' };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return null;
|
|
208
|
+
}, [cesiumEnabled, storeModels, ifcDataStore, georefMutations, mutationVersion, mergedGeometryResult]);
|
|
209
|
+
|
|
210
|
+
// Determine whether Cesium button should be visible (model has georef or user added it via mutations).
|
|
211
|
+
// Runs independently of cesiumEnabled so the button appears/disappears reactively.
|
|
212
|
+
useEffect(() => {
|
|
213
|
+
function hasGeoref(): boolean {
|
|
214
|
+
// Check federated models
|
|
215
|
+
for (const [modelId, model] of storeModels) {
|
|
216
|
+
const ds = model.ifcDataStore;
|
|
217
|
+
if (!ds) continue;
|
|
218
|
+
const effective = getEffectiveGeoreference(
|
|
219
|
+
ds as IfcDataStore,
|
|
220
|
+
model.geometryResult?.coordinateInfo,
|
|
221
|
+
georefMutations.get(modelId),
|
|
222
|
+
);
|
|
223
|
+
if (effective?.projectedCRS?.name) return true;
|
|
224
|
+
}
|
|
225
|
+
// Fallback to legacy single-model
|
|
226
|
+
if (ifcDataStore) {
|
|
227
|
+
const effective = getEffectiveGeoreference(
|
|
228
|
+
ifcDataStore as IfcDataStore,
|
|
229
|
+
mergedGeometryResult?.coordinateInfo,
|
|
230
|
+
georefMutations.get('__legacy__'),
|
|
231
|
+
);
|
|
232
|
+
if (effective?.projectedCRS?.name) return true;
|
|
233
|
+
}
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
setCesiumAvailable(hasGeoref());
|
|
237
|
+
}, [storeModels, ifcDataStore, georefMutations, mutationVersion, setCesiumAvailable, mergedGeometryResult]);
|
|
238
|
+
|
|
239
|
+
// Sync the active Cesium source model ID so terrain actions are scoped correctly
|
|
240
|
+
useEffect(() => {
|
|
241
|
+
setCesiumSourceModelId(georef?.sourceModelId ?? null);
|
|
242
|
+
}, [georef?.sourceModelId, setCesiumSourceModelId]);
|
|
243
|
+
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
// Recent files are a desktop-only feature — the web viewer should not
|
|
246
|
+
// show previously opened files in the landing page empty state.
|
|
247
|
+
if (!isTauri()) return;
|
|
248
|
+
|
|
249
|
+
const refreshRecentFiles = () => {
|
|
250
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
refreshRecentFiles();
|
|
254
|
+
window.addEventListener('focus', refreshRecentFiles);
|
|
255
|
+
return () => window.removeEventListener('focus', refreshRecentFiles);
|
|
256
|
+
}, []);
|
|
257
|
+
|
|
99
258
|
const handleDragOver = useCallback((e: React.DragEvent) => {
|
|
100
259
|
e.preventDefault();
|
|
101
260
|
e.stopPropagation();
|
|
@@ -128,6 +287,10 @@ export function ViewportContainer() {
|
|
|
128
287
|
|
|
129
288
|
if (supportedFiles.length === 0) return;
|
|
130
289
|
|
|
290
|
+
recordRecentFiles(supportedFiles.map((file) => ({ name: file.name, size: file.size })));
|
|
291
|
+
void cacheFileBlobs(supportedFiles);
|
|
292
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
293
|
+
|
|
131
294
|
if (hasModelsLoaded) {
|
|
132
295
|
// Models already loaded - add new files sequentially
|
|
133
296
|
loadFilesSequentially(supportedFiles);
|
|
@@ -158,6 +321,10 @@ export function ViewportContainer() {
|
|
|
158
321
|
|
|
159
322
|
if (supportedFiles.length === 0) return;
|
|
160
323
|
|
|
324
|
+
recordRecentFiles(supportedFiles.map((file) => ({ name: file.name, size: file.size })));
|
|
325
|
+
void cacheFileBlobs(supportedFiles);
|
|
326
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
327
|
+
|
|
161
328
|
if (supportedFiles.length === 1) {
|
|
162
329
|
// Single file - use loadFile (simpler single-model path)
|
|
163
330
|
loadFile(supportedFiles[0]);
|
|
@@ -184,6 +351,7 @@ export function ViewportContainer() {
|
|
|
184
351
|
// A version counter triggers downstream re-renders via the Viewport prop.
|
|
185
352
|
const filteredCacheRef = useRef<MeshData[]>([]);
|
|
186
353
|
const filteredSourceLenRef = useRef(0);
|
|
354
|
+
const filteredSourceRef = useRef<MeshData[] | null>(null);
|
|
187
355
|
const filteredTypeVisRef = useRef(typeVisibility);
|
|
188
356
|
const filteredVersionRef = useRef(0);
|
|
189
357
|
|
|
@@ -191,6 +359,7 @@ export function ViewportContainer() {
|
|
|
191
359
|
if (!mergedGeometryResult?.meshes) {
|
|
192
360
|
filteredCacheRef.current = [];
|
|
193
361
|
filteredSourceLenRef.current = 0;
|
|
362
|
+
filteredSourceRef.current = null;
|
|
194
363
|
filteredVersionRef.current = 0;
|
|
195
364
|
return null;
|
|
196
365
|
}
|
|
@@ -204,9 +373,11 @@ export function ViewportContainer() {
|
|
|
204
373
|
prevVis.spaces !== typeVisibility.spaces ||
|
|
205
374
|
prevVis.openings !== typeVisibility.openings ||
|
|
206
375
|
prevVis.site !== typeVisibility.site;
|
|
207
|
-
|
|
376
|
+
const sourceChanged = filteredSourceRef.current !== allMeshes;
|
|
377
|
+
if (typeVisChanged || sourceChanged || allMeshes.length < filteredSourceLenRef.current) {
|
|
208
378
|
cache.length = 0;
|
|
209
379
|
filteredSourceLenRef.current = 0;
|
|
380
|
+
filteredSourceRef.current = allMeshes;
|
|
210
381
|
filteredTypeVisRef.current = typeVisibility;
|
|
211
382
|
}
|
|
212
383
|
|
|
@@ -238,7 +409,7 @@ export function ViewportContainer() {
|
|
|
238
409
|
|
|
239
410
|
// Only bump version when cache content actually changed — avoids
|
|
240
411
|
// unnecessary downstream re-renders when memo runs with same data.
|
|
241
|
-
if (cache.length !== prevCacheLen || typeVisChanged) {
|
|
412
|
+
if (cache.length !== prevCacheLen || typeVisChanged || sourceChanged) {
|
|
242
413
|
filteredVersionRef.current++;
|
|
243
414
|
}
|
|
244
415
|
|
|
@@ -531,7 +702,29 @@ export function ViewportContainer() {
|
|
|
531
702
|
|
|
532
703
|
{/* Action */}
|
|
533
704
|
<button
|
|
534
|
-
onClick={() =>
|
|
705
|
+
onClick={async () => {
|
|
706
|
+
if (!webgpu.supported) {
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
void logToDesktopTerminal('info', '[ViewportContainer] Empty-state open button clicked');
|
|
711
|
+
const file = await openIfcFileDialog();
|
|
712
|
+
if (file) {
|
|
713
|
+
void logToDesktopTerminal('info', `[ViewportContainer] Native dialog selected ${file.path}`);
|
|
714
|
+
recordRecentFiles([{
|
|
715
|
+
name: file.name,
|
|
716
|
+
size: file.size,
|
|
717
|
+
path: file.path,
|
|
718
|
+
modifiedMs: file.modifiedMs ?? null,
|
|
719
|
+
}]);
|
|
720
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
721
|
+
loadFile(file);
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
void logToDesktopTerminal('info', '[ViewportContainer] Falling back to browser file input');
|
|
726
|
+
fileInputRef.current?.click();
|
|
727
|
+
}}
|
|
535
728
|
disabled={!webgpu.supported || webgpu.checking}
|
|
536
729
|
className={`group w-full flex items-center justify-center gap-3 px-6 py-3 font-mono text-sm border transition-all ${
|
|
537
730
|
!webgpu.supported || webgpu.checking
|
|
@@ -546,6 +739,37 @@ export function ViewportContainer() {
|
|
|
546
739
|
<p className="mt-3 text-xs font-mono text-zinc-400 dark:text-[#565f89]">
|
|
547
740
|
{webgpu.supported ? 'or drag & drop anywhere' : 'file upload disabled'}
|
|
548
741
|
</p>
|
|
742
|
+
|
|
743
|
+
{recentFiles.length > 0 && (
|
|
744
|
+
<div className="mt-6 w-full border-t border-zinc-200 dark:border-[#3b4261] pt-4">
|
|
745
|
+
<div className="mb-3 flex items-center gap-2 text-xs font-mono uppercase tracking-[0.2em] text-zinc-400 dark:text-[#565f89]">
|
|
746
|
+
<Clock3 className="h-3.5 w-3.5" />
|
|
747
|
+
<span>Recent Files</span>
|
|
748
|
+
</div>
|
|
749
|
+
<div className="flex flex-col gap-2">
|
|
750
|
+
{recentFiles.map((file) => (
|
|
751
|
+
<button
|
|
752
|
+
key={`${file.name}-${file.timestamp}`}
|
|
753
|
+
type="button"
|
|
754
|
+
onClick={async () => {
|
|
755
|
+
const cached = await getCachedFile(file);
|
|
756
|
+
if (cached) {
|
|
757
|
+
await loadFile(cached);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
fileInputRef.current?.click();
|
|
761
|
+
}}
|
|
762
|
+
className="flex items-center justify-between gap-3 border border-zinc-200 bg-zinc-50 px-3 py-2 text-left transition-colors hover:border-primary hover:text-primary dark:border-[#3b4261] dark:bg-[#1f2335] dark:hover:border-primary"
|
|
763
|
+
>
|
|
764
|
+
<span className="min-w-0 truncate font-mono text-xs">{file.name}</span>
|
|
765
|
+
<span className="shrink-0 font-mono text-[10px] uppercase tracking-wide text-zinc-400 dark:text-[#565f89]">
|
|
766
|
+
{formatFileSize(file.size)}
|
|
767
|
+
</span>
|
|
768
|
+
</button>
|
|
769
|
+
))}
|
|
770
|
+
</div>
|
|
771
|
+
</div>
|
|
772
|
+
)}
|
|
549
773
|
</div>
|
|
550
774
|
|
|
551
775
|
{/* Feature Grid */}
|
|
@@ -607,18 +831,31 @@ export function ViewportContainer() {
|
|
|
607
831
|
</div>
|
|
608
832
|
)}
|
|
609
833
|
|
|
834
|
+
{/* Cesium 3D world context overlay — rendered behind the WebGPU canvas (web only) */}
|
|
835
|
+
{cesiumEnabled && georef && !isTauri() && (
|
|
836
|
+
<CesiumOverlay
|
|
837
|
+
mapConversion={georef.mapConversion}
|
|
838
|
+
projectedCRS={georef.projectedCRS}
|
|
839
|
+
coordinateInfo={georef.coordinateInfo}
|
|
840
|
+
geometryResult={mergedGeometryResult}
|
|
841
|
+
lengthUnitScale={georef.lengthUnitScale}
|
|
842
|
+
/>
|
|
843
|
+
)}
|
|
610
844
|
<Viewport
|
|
611
845
|
geometry={filteredGeometry}
|
|
612
846
|
geometryVersion={geometryVersion}
|
|
613
847
|
coordinateInfo={mergedGeometryResult?.coordinateInfo}
|
|
614
848
|
computedIsolatedIds={computedIsolatedIds}
|
|
615
849
|
modelIdToIndex={modelIdToIndex}
|
|
850
|
+
cesiumActive={cesiumEnabled && georef !== null && !isTauri()}
|
|
851
|
+
releaseGeometryAfterStream={false}
|
|
852
|
+
onGeometryReleased={releaseGeometryMemory}
|
|
616
853
|
/>
|
|
617
854
|
{bcfOverlayVisible && <BCFOverlay />}
|
|
618
855
|
<ViewportOverlays />
|
|
619
856
|
<ToolOverlays />
|
|
620
857
|
<BasketPresentationDock />
|
|
621
|
-
<Section2DPanel
|
|
858
|
+
<Section2DPanel
|
|
622
859
|
mergedGeometry={mergedGeometryResult}
|
|
623
860
|
computedIsolatedIds={computedIsolatedIds}
|
|
624
861
|
modelIdToIndex={modelIdToIndex}
|
|
@@ -8,13 +8,22 @@ import {
|
|
|
8
8
|
ZoomIn,
|
|
9
9
|
ZoomOut,
|
|
10
10
|
Layers,
|
|
11
|
+
Globe2,
|
|
12
|
+
Mountain,
|
|
13
|
+
Building2,
|
|
14
|
+
Satellite,
|
|
15
|
+
X,
|
|
11
16
|
} from 'lucide-react';
|
|
12
17
|
import { Button } from '@/components/ui/button';
|
|
13
18
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
|
14
19
|
import { useViewerStore } from '@/store';
|
|
20
|
+
import type { CesiumDataSource } from '@/store/slices/cesiumSlice';
|
|
15
21
|
import { goHomeFromStore } from '@/store/homeView';
|
|
16
22
|
import { useIfc } from '@/hooks/useIfc';
|
|
17
23
|
import { cn } from '@/lib/utils';
|
|
24
|
+
import { isTauri } from '@/lib/platform';
|
|
25
|
+
|
|
26
|
+
const isDesktop = isTauri();
|
|
18
27
|
import { ViewCube, type ViewCubeRef } from './ViewCube';
|
|
19
28
|
import { AxisHelper, type AxisHelperRef } from './AxisHelper';
|
|
20
29
|
|
|
@@ -28,6 +37,14 @@ export function ViewportOverlays({ hideViewCube = false }: { hideViewCube?: bool
|
|
|
28
37
|
const setOnScaleChange = useViewerStore((s) => s.setOnScaleChange);
|
|
29
38
|
const { ifcDataStore, geometryResult } = useIfc();
|
|
30
39
|
|
|
40
|
+
// Cesium state
|
|
41
|
+
const cesiumEnabled = useViewerStore((s) => s.cesiumEnabled);
|
|
42
|
+
const cesiumDataSource = useViewerStore((s) => s.cesiumDataSource);
|
|
43
|
+
const setCesiumDataSource = useViewerStore((s) => s.setCesiumDataSource);
|
|
44
|
+
const cesiumTerrainEnabled = useViewerStore((s) => s.cesiumTerrainEnabled);
|
|
45
|
+
const setCesiumTerrainEnabled = useViewerStore((s) => s.setCesiumTerrainEnabled);
|
|
46
|
+
const toggleCesium = useViewerStore((s) => s.toggleCesium);
|
|
47
|
+
|
|
31
48
|
// Use refs for rotation to avoid re-renders - ViewCube updates itself directly
|
|
32
49
|
const cameraRotationRef = useRef({ azimuth: 45, elevation: 25 });
|
|
33
50
|
const viewCubeRef = useRef<ViewCubeRef | null>(null);
|
|
@@ -132,35 +149,45 @@ export function ViewportOverlays({ hideViewCube = false }: { hideViewCube?: bool
|
|
|
132
149
|
|
|
133
150
|
return (
|
|
134
151
|
<>
|
|
135
|
-
{/* Navigation
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
152
|
+
{/* Bottom-right: Cesium settings overlay OR Navigation controls (Cesium is web-only) */}
|
|
153
|
+
{cesiumEnabled && !isDesktop ? (
|
|
154
|
+
<CesiumSettingsOverlay
|
|
155
|
+
dataSource={cesiumDataSource}
|
|
156
|
+
onDataSourceChange={setCesiumDataSource}
|
|
157
|
+
terrainEnabled={cesiumTerrainEnabled}
|
|
158
|
+
onTerrainChange={setCesiumTerrainEnabled}
|
|
159
|
+
onClose={toggleCesium}
|
|
160
|
+
/>
|
|
161
|
+
) : (
|
|
162
|
+
<div className="absolute bottom-4 right-4 flex flex-col gap-1 bg-background/80 backdrop-blur-sm rounded-lg border shadow-sm p-1">
|
|
163
|
+
<Tooltip>
|
|
164
|
+
<TooltipTrigger asChild>
|
|
165
|
+
<Button variant="ghost" size="icon-sm" onClick={handleHome}>
|
|
166
|
+
<Home className="h-4 w-4" />
|
|
167
|
+
</Button>
|
|
168
|
+
</TooltipTrigger>
|
|
169
|
+
<TooltipContent side="left">Home (H)</TooltipContent>
|
|
170
|
+
</Tooltip>
|
|
145
171
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
<Tooltip>
|
|
173
|
+
<TooltipTrigger asChild>
|
|
174
|
+
<Button variant="ghost" size="icon-sm" onClick={handleZoomIn}>
|
|
175
|
+
<ZoomIn className="h-4 w-4" />
|
|
176
|
+
</Button>
|
|
177
|
+
</TooltipTrigger>
|
|
178
|
+
<TooltipContent side="left">Zoom In (+)</TooltipContent>
|
|
179
|
+
</Tooltip>
|
|
154
180
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
181
|
+
<Tooltip>
|
|
182
|
+
<TooltipTrigger asChild>
|
|
183
|
+
<Button variant="ghost" size="icon-sm" onClick={handleZoomOut}>
|
|
184
|
+
<ZoomOut className="h-4 w-4" />
|
|
185
|
+
</Button>
|
|
186
|
+
</TooltipTrigger>
|
|
187
|
+
<TooltipContent side="left">Zoom Out (-)</TooltipContent>
|
|
188
|
+
</Tooltip>
|
|
189
|
+
</div>
|
|
190
|
+
)}
|
|
164
191
|
|
|
165
192
|
{/* Context Info (bottom-center) - Storey names */}
|
|
166
193
|
{storeyNames && storeyNames.length > 0 && (
|
|
@@ -209,3 +236,81 @@ export function ViewportOverlays({ hideViewCube = false }: { hideViewCube?: bool
|
|
|
209
236
|
</>
|
|
210
237
|
);
|
|
211
238
|
}
|
|
239
|
+
|
|
240
|
+
/* ------------------------------------------------------------------ */
|
|
241
|
+
/* Cesium Settings Overlay — replaces nav controls when Cesium is on */
|
|
242
|
+
/* ------------------------------------------------------------------ */
|
|
243
|
+
|
|
244
|
+
const DATA_SOURCES: { value: CesiumDataSource; label: string; icon: typeof Globe2 }[] = [
|
|
245
|
+
{ value: 'google-photorealistic', label: 'Google 3D', icon: Globe2 },
|
|
246
|
+
{ value: 'osm-buildings', label: 'OSM', icon: Building2 },
|
|
247
|
+
{ value: 'bing-aerial', label: 'Aerial', icon: Satellite },
|
|
248
|
+
];
|
|
249
|
+
|
|
250
|
+
function CesiumSettingsOverlay({
|
|
251
|
+
dataSource,
|
|
252
|
+
onDataSourceChange,
|
|
253
|
+
terrainEnabled,
|
|
254
|
+
onTerrainChange,
|
|
255
|
+
onClose,
|
|
256
|
+
}: {
|
|
257
|
+
dataSource: CesiumDataSource;
|
|
258
|
+
onDataSourceChange: (ds: CesiumDataSource) => void;
|
|
259
|
+
terrainEnabled: boolean;
|
|
260
|
+
onTerrainChange: (enabled: boolean) => void;
|
|
261
|
+
onClose: () => void;
|
|
262
|
+
}) {
|
|
263
|
+
return (
|
|
264
|
+
<div className="absolute bottom-4 right-4 z-10 pointer-events-auto bg-background/90 backdrop-blur-sm rounded-lg border shadow-lg p-2 flex flex-col gap-2 min-w-[160px]">
|
|
265
|
+
{/* Header */}
|
|
266
|
+
<div className="flex items-center justify-between gap-2">
|
|
267
|
+
<span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
|
268
|
+
3D World
|
|
269
|
+
</span>
|
|
270
|
+
<Tooltip>
|
|
271
|
+
<TooltipTrigger asChild>
|
|
272
|
+
<Button variant="ghost" size="icon-sm" className="h-5 w-5" onClick={onClose}>
|
|
273
|
+
<X className="h-3 w-3" />
|
|
274
|
+
</Button>
|
|
275
|
+
</TooltipTrigger>
|
|
276
|
+
<TooltipContent side="left">Disable Cesium overlay</TooltipContent>
|
|
277
|
+
</Tooltip>
|
|
278
|
+
</div>
|
|
279
|
+
|
|
280
|
+
{/* Data Source Buttons */}
|
|
281
|
+
<div className="flex flex-col gap-0.5">
|
|
282
|
+
{DATA_SOURCES.map((ds) => {
|
|
283
|
+
const Icon = ds.icon;
|
|
284
|
+
const active = dataSource === ds.value;
|
|
285
|
+
return (
|
|
286
|
+
<button
|
|
287
|
+
key={ds.value}
|
|
288
|
+
onClick={() => onDataSourceChange(ds.value)}
|
|
289
|
+
className={cn(
|
|
290
|
+
'flex items-center gap-2 px-2 py-1.5 rounded text-xs transition-colors text-left',
|
|
291
|
+
active
|
|
292
|
+
? 'bg-teal-600 text-white'
|
|
293
|
+
: 'hover:bg-muted text-foreground/80',
|
|
294
|
+
)}
|
|
295
|
+
>
|
|
296
|
+
<Icon className="h-3.5 w-3.5 shrink-0" />
|
|
297
|
+
{ds.label}
|
|
298
|
+
</button>
|
|
299
|
+
);
|
|
300
|
+
})}
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
{/* Terrain Toggle */}
|
|
304
|
+
<label className="flex items-center gap-2 px-2 py-1 cursor-pointer border-t border-border pt-2">
|
|
305
|
+
<Mountain className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
|
|
306
|
+
<span className="text-xs text-foreground/80">Terrain</span>
|
|
307
|
+
<input
|
|
308
|
+
type="checkbox"
|
|
309
|
+
checked={terrainEnabled}
|
|
310
|
+
onChange={(e) => onTerrainChange(e.target.checked)}
|
|
311
|
+
className="ml-auto accent-teal-500"
|
|
312
|
+
/>
|
|
313
|
+
</label>
|
|
314
|
+
</div>
|
|
315
|
+
);
|
|
316
|
+
}
|
|
@@ -215,12 +215,12 @@ export function BCFTopicDetail({
|
|
|
215
215
|
<img
|
|
216
216
|
src={vp.snapshot}
|
|
217
217
|
alt="Viewpoint"
|
|
218
|
-
className="w-full
|
|
218
|
+
className="w-full max-h-48 object-contain bg-muted cursor-pointer hover:opacity-90 transition-opacity"
|
|
219
219
|
onClick={() => onActivateViewpoint(vp)}
|
|
220
220
|
/>
|
|
221
221
|
) : (
|
|
222
222
|
<div
|
|
223
|
-
className="w-full aspect-video bg-muted flex items-center justify-center cursor-pointer hover:bg-muted/80 transition-colors"
|
|
223
|
+
className="w-full aspect-video bg-muted flex items-center justify-center cursor-pointer hover:bg-muted/80 transition-colors min-h-[120px]"
|
|
224
224
|
onClick={() => onActivateViewpoint(vp)}
|
|
225
225
|
>
|
|
226
226
|
<Camera className="h-6 w-6 text-muted-foreground" />
|
|
@@ -294,7 +294,7 @@ export function BCFTopicDetail({
|
|
|
294
294
|
<img
|
|
295
295
|
src={associatedViewpoint.snapshot}
|
|
296
296
|
alt="Associated viewpoint"
|
|
297
|
-
className="w-full h-
|
|
297
|
+
className="w-full max-h-24 object-contain bg-muted"
|
|
298
298
|
/>
|
|
299
299
|
</div>
|
|
300
300
|
)}
|
|
@@ -327,7 +327,7 @@ export function BCFTopicDetail({
|
|
|
327
327
|
<img
|
|
328
328
|
src={selectedViewpoint.snapshot}
|
|
329
329
|
alt="Selected viewpoint"
|
|
330
|
-
className="w-
|
|
330
|
+
className="w-12 h-10 object-contain rounded bg-muted"
|
|
331
331
|
/>
|
|
332
332
|
)}
|
|
333
333
|
<div className="flex-1 min-w-0">
|