@ifc-lite/viewer 1.17.3 → 1.17.4
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 +15 -0
- package/DESKTOP_CONTRACT_VERSION +1 -0
- package/dist/assets/arrow-CZ5kQ26f.js +20 -0
- package/dist/assets/basketViewActivator-BmnNtVfZ.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/{exporters-C_6J153K.js → exporters-ChAtBmlj.js} +2225 -1754
- package/dist/assets/geometry.worker-BQ0rzNo-.js +1 -0
- package/dist/assets/ifc-lite_bg-BX4E7TX8.wasm +0 -0
- package/dist/assets/{index-jhBr1wbn.js → index-Co8E2-FE.js} +28959 -24612
- package/dist/assets/index-DckuDqlv.css +1 -0
- package/dist/assets/{maplibre-gl-BpvwNKKy.js → maplibre-gl-CGLcoNXc.js} +1 -1
- package/dist/assets/native-bridge-BRvbckFQ.js +429 -0
- package/dist/assets/{sandbox-B79eavQ3.js → sandbox-DZiNLNMk.js} +5 -5
- package/dist/assets/{server-client-D3bUPJJc.js → server-client-BV8zHZ7Y.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-g01g7T9b.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 +10 -8
- package/package.json +15 -12
- package/src/App.tsx +1 -17
- package/src/components/viewer/BCFPanel.tsx +46 -4
- package/src/components/viewer/CesiumOverlay.tsx +672 -0
- package/src/components/viewer/CesiumSettingsDialog.tsx +100 -0
- package/src/components/viewer/ChatPanel.tsx +54 -16
- 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 +353 -27
- package/src/components/viewer/PropertiesPanel.tsx +218 -79
- package/src/components/viewer/ScriptPanel.tsx +34 -8
- package/src/components/viewer/SettingsPage.tsx +430 -0
- package/src/components/viewer/StatusBar.tsx +17 -1
- package/src/components/viewer/UpgradePage.tsx +6 -4
- package/src/components/viewer/ViewerLayout.tsx +47 -6
- package/src/components/viewer/Viewport.tsx +49 -8
- package/src/components/viewer/ViewportContainer.tsx +280 -28
- package/src/components/viewer/ViewportOverlays.tsx +129 -27
- package/src/components/viewer/properties/GeoreferencingPanel.tsx +117 -5
- package/src/components/viewer/properties/LocationMap.tsx +458 -17
- package/src/components/viewer/selectionHandlers.ts +4 -3
- package/src/components/viewer/useAnimationLoop.ts +4 -0
- package/src/components/viewer/useGeometryStreaming.ts +127 -40
- package/src/components/viewer/useMouseControls.ts +4 -1
- package/src/hooks/ingest/viewerModelIngest.ts +275 -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 +57 -225
- package/src/hooks/useIfcLoader.ts +1656 -130
- package/src/hooks/useIfcServer.ts +0 -69
- package/src/lib/desktop/ClerkDesktopEntitlementSync.tsx +175 -0
- package/src/lib/desktop/desktopEntitlementEvents.ts +39 -0
- package/src/lib/desktop-entitlement.ts +45 -0
- package/src/lib/desktop-product.ts +124 -0
- package/src/lib/geo/cesium-bridge.ts +310 -0
- package/src/lib/geo/reproject.ts +151 -25
- package/src/lib/recent-files.ts +2 -1
- package/src/services/analysis-extensions.ts +125 -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/index.ts +40 -2
- package/src/store/slices/cesiumSlice.ts +122 -0
- package/src/store/slices/chatSlice.ts +5 -1
- 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/types.ts +96 -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 +250 -0
- package/src/utils/serverDataModel.ts +4 -0
- package/src/utils/spatialHierarchy.ts +10 -11
- 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/geometry.worker-Nz9_YIqh.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
|
@@ -46,9 +46,23 @@ interface ViewportProps {
|
|
|
46
46
|
coordinateInfo?: CoordinateInfo;
|
|
47
47
|
computedIsolatedIds?: Set<number> | null;
|
|
48
48
|
modelIdToIndex?: Map<string, number>;
|
|
49
|
+
/** When true, the WebGPU canvas uses a transparent clear color so the
|
|
50
|
+
* CesiumJS globe behind it is visible. */
|
|
51
|
+
cesiumActive?: boolean;
|
|
52
|
+
releaseGeometryAfterStream?: boolean;
|
|
53
|
+
onGeometryReleased?: () => void;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
export function Viewport({
|
|
56
|
+
export function Viewport({
|
|
57
|
+
geometry,
|
|
58
|
+
geometryVersion,
|
|
59
|
+
coordinateInfo,
|
|
60
|
+
computedIsolatedIds,
|
|
61
|
+
modelIdToIndex,
|
|
62
|
+
cesiumActive,
|
|
63
|
+
releaseGeometryAfterStream = false,
|
|
64
|
+
onGeometryReleased,
|
|
65
|
+
}: ViewportProps) {
|
|
52
66
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
53
67
|
const rendererRef = useRef<Renderer | null>(null);
|
|
54
68
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
@@ -94,7 +108,7 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
94
108
|
}, [modelIdToIndex]);
|
|
95
109
|
|
|
96
110
|
// Compute selectedModelIndex for renderer (multi-model selection highlighting)
|
|
97
|
-
const selectedModelIndex = selectedEntity && modelIdToIndex
|
|
111
|
+
const selectedModelIndex = models.size > 1 && selectedEntity && modelIdToIndex
|
|
98
112
|
? modelIdToIndex.get(selectedEntity.modelId) ?? undefined
|
|
99
113
|
: undefined;
|
|
100
114
|
|
|
@@ -114,12 +128,13 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
114
128
|
}
|
|
115
129
|
|
|
116
130
|
const globalId = pickResult.expressId;
|
|
131
|
+
const resolvedRef = resolveEntityRef(globalId);
|
|
117
132
|
|
|
118
133
|
// Set globalId for renderer (highlighting uses globalIds directly)
|
|
119
134
|
setSelectedEntityId(globalId);
|
|
120
135
|
|
|
121
136
|
// Resolve globalId → EntityRef for property panel (single source of truth, never null)
|
|
122
|
-
setSelectedEntity(
|
|
137
|
+
setSelectedEntity(resolvedRef);
|
|
123
138
|
}, [setSelectedEntityId, setSelectedEntity]);
|
|
124
139
|
|
|
125
140
|
// Ref to always access latest handlePickForSelection from event handlers
|
|
@@ -291,6 +306,17 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
291
306
|
separationLinesIntensity,
|
|
292
307
|
separationLinesRadius,
|
|
293
308
|
]);
|
|
309
|
+
|
|
310
|
+
// Override clear color when Cesium overlay is active (transparent background)
|
|
311
|
+
useEffect(() => {
|
|
312
|
+
if (cesiumActive) {
|
|
313
|
+
clearColorRef.current = [0, 0, 0, 0]; // fully transparent
|
|
314
|
+
} else {
|
|
315
|
+
clearColorRef.current = getThemeClearColor(theme as 'light' | 'dark');
|
|
316
|
+
}
|
|
317
|
+
rendererRef.current?.requestRender();
|
|
318
|
+
}, [cesiumActive, theme]);
|
|
319
|
+
|
|
294
320
|
// Animation frame ref
|
|
295
321
|
const animationFrameRef = useRef<number | null>(null);
|
|
296
322
|
const lastFrameTimeRef = useRef<number>(0);
|
|
@@ -356,6 +382,11 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
356
382
|
const sectionPlaneRef = useLatestRef(sectionPlane);
|
|
357
383
|
const sectionRangeRef = useLatestRef(sectionRange);
|
|
358
384
|
const visualEnhancementRef = useLatestRef(visualEnhancement);
|
|
385
|
+
|
|
386
|
+
// Terrain clip Y from Cesium store (read as ref for animation loop)
|
|
387
|
+
const cesiumTerrainClipY = useViewerStore((s) => s.cesiumTerrainClipY);
|
|
388
|
+
const fastZoomRef = useLatestRef(!!cesiumActive);
|
|
389
|
+
const terrainClipYRef = useLatestRef(cesiumActive ? cesiumTerrainClipY : null);
|
|
359
390
|
const geometryRef = useLatestRef(geometry);
|
|
360
391
|
|
|
361
392
|
// Hover throttling
|
|
@@ -457,8 +488,10 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
457
488
|
|
|
458
489
|
// Helper: get pick options with visibility filtering
|
|
459
490
|
const getPickOptions = () => {
|
|
460
|
-
const
|
|
461
|
-
const
|
|
491
|
+
const currentState = useViewerStore.getState();
|
|
492
|
+
const currentProgress = currentState.progress;
|
|
493
|
+
const currentIsStreaming = currentState.geometryStreamingActive
|
|
494
|
+
|| (currentProgress !== null && currentProgress.percent < 100);
|
|
462
495
|
return {
|
|
463
496
|
isStreaming: currentIsStreaming,
|
|
464
497
|
hiddenIds: hiddenEntitiesRef.current,
|
|
@@ -656,8 +689,7 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
656
689
|
const showHiddenLines = useViewerStore((s) => s.drawing2DDisplayOptions.showHiddenLines);
|
|
657
690
|
|
|
658
691
|
// ===== Streaming progress =====
|
|
659
|
-
const
|
|
660
|
-
const isStreaming = progress !== null && progress.percent < 100;
|
|
692
|
+
const isStreaming = useViewerStore((state) => state.geometryStreamingActive);
|
|
661
693
|
|
|
662
694
|
// Mouse isDragging proxy ref for animation loop
|
|
663
695
|
// The animation loop reads this to decide whether to update rotation
|
|
@@ -728,6 +760,7 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
728
760
|
RENDER_THROTTLE_MS_SMALL,
|
|
729
761
|
RENDER_THROTTLE_MS_LARGE,
|
|
730
762
|
RENDER_THROTTLE_MS_HUGE,
|
|
763
|
+
fastZoomRef,
|
|
731
764
|
});
|
|
732
765
|
|
|
733
766
|
useTouchControls({
|
|
@@ -777,6 +810,7 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
777
810
|
lastFrameTimeRef,
|
|
778
811
|
mouseIsDraggingRef,
|
|
779
812
|
activeToolRef,
|
|
813
|
+
terrainClipYRef,
|
|
780
814
|
hiddenEntitiesRef,
|
|
781
815
|
isolatedEntitiesRef,
|
|
782
816
|
selectedEntityIdRef,
|
|
@@ -808,6 +842,8 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
808
842
|
clearPendingColorUpdates,
|
|
809
843
|
clearPendingMeshColorUpdates,
|
|
810
844
|
clearColorRef,
|
|
845
|
+
releaseGeometryAfterFinalize: releaseGeometryAfterStream,
|
|
846
|
+
onGeometryReleased,
|
|
811
847
|
});
|
|
812
848
|
|
|
813
849
|
useRenderUpdates({
|
|
@@ -838,12 +874,17 @@ export function Viewport({ geometry, geometryVersion, coordinateInfo, computedIs
|
|
|
838
874
|
showHiddenLines,
|
|
839
875
|
});
|
|
840
876
|
|
|
877
|
+
// Hide WebGPU canvas immediately when Cesium is active.
|
|
878
|
+
// The model will be rendered by Cesium (as GLB) for correct positioning.
|
|
879
|
+
// Canvas stays in the DOM for picking/interaction.
|
|
880
|
+
|
|
841
881
|
return (
|
|
842
882
|
<canvas
|
|
843
883
|
ref={canvasRef}
|
|
844
884
|
data-viewport="main"
|
|
845
885
|
tabIndex={-1}
|
|
846
|
-
className=
|
|
886
|
+
className={`w-full h-full block ${cesiumActive ? 'relative z-[1]' : ''}`}
|
|
887
|
+
style={cesiumActive ? { opacity: 0 } : undefined}
|
|
847
888
|
onPointerDown={focusViewportForKeyboardShortcuts}
|
|
848
889
|
/>
|
|
849
890
|
);
|
|
@@ -2,20 +2,26 @@
|
|
|
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 '@/utils/ifcConfig';
|
|
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 { extractGeoreferencingOnDemand, type IfcDataStore, type MapConversion, type ProjectedCRS } from '@ifc-lite/parser';
|
|
19
25
|
|
|
20
26
|
const ZERO_VEC3 = { x: 0, y: 0, z: 0 };
|
|
21
27
|
const DEFAULT_COORDINATE_INFO: CoordinateInfo = {
|
|
@@ -26,20 +32,41 @@ const DEFAULT_COORDINATE_INFO: CoordinateInfo = {
|
|
|
26
32
|
};
|
|
27
33
|
|
|
28
34
|
export function ViewportContainer() {
|
|
29
|
-
const {
|
|
35
|
+
const { loadFile, loading, clearAllModels, loadFilesSequentially } = useIfc();
|
|
36
|
+
const releaseGeometryMemory = useViewerStore((s) => s.releaseGeometryMemory);
|
|
30
37
|
const selectedStoreys = useViewerStore((s) => s.selectedStoreys);
|
|
31
38
|
const typeVisibility = useViewerStore((s) => s.typeVisibility);
|
|
32
39
|
const isolatedEntities = useViewerStore((s) => s.isolatedEntities);
|
|
33
40
|
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
41
|
const resetViewerState = useViewerStore((s) => s.resetViewerState);
|
|
37
42
|
const bcfOverlayVisible = useViewerStore((s) => s.bcfOverlayVisible);
|
|
43
|
+
const cesiumEnabled = useViewerStore((s) => s.cesiumEnabled);
|
|
44
|
+
const georefMutations = useViewerStore((s) => s.georefMutations);
|
|
45
|
+
const setCesiumSourceModelId = useViewerStore((s) => s.setCesiumSourceModelId);
|
|
46
|
+
// Subscribe to mutationVersion so Cesium reacts to georef edits
|
|
47
|
+
const mutationVersion = useViewerStore((s) => s.mutationVersion);
|
|
38
48
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
39
49
|
const [isDragging, setIsDragging] = useState(false);
|
|
40
50
|
const [showTroubleshooting, setShowTroubleshooting] = useState(false);
|
|
51
|
+
const [recentFiles, setRecentFiles] = useState<RecentFileEntry[]>([]);
|
|
41
52
|
const webgpu = useWebGPU();
|
|
42
53
|
|
|
54
|
+
const viewerStoreApi = getViewerStoreApi();
|
|
55
|
+
const viewportStoreState = useSyncExternalStore(
|
|
56
|
+
viewerStoreApi.subscribe,
|
|
57
|
+
viewerStoreApi.getState,
|
|
58
|
+
viewerStoreApi.getState,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const {
|
|
62
|
+
geometryResult,
|
|
63
|
+
ifcDataStore,
|
|
64
|
+
models,
|
|
65
|
+
boundedGeometryMode,
|
|
66
|
+
geometryUpdateTick,
|
|
67
|
+
} = viewportStoreState;
|
|
68
|
+
const storeModels = models;
|
|
69
|
+
|
|
43
70
|
// Check if we have models loaded (for determining add vs replace behavior)
|
|
44
71
|
const hasModelsLoaded = models.size > 0 || (geometryResult?.meshes && geometryResult.meshes.length > 0);
|
|
45
72
|
|
|
@@ -53,39 +80,87 @@ export function ViewportContainer() {
|
|
|
53
80
|
return map;
|
|
54
81
|
}, [storeModels]);
|
|
55
82
|
|
|
83
|
+
const mergedCacheRef = useRef<MeshData[]>([]);
|
|
84
|
+
const mergedLengthsRef = useRef<Map<string, number>>(new Map());
|
|
85
|
+
const mergedVisibilityRef = useRef<Map<string, boolean>>(new Map());
|
|
86
|
+
|
|
56
87
|
// Multi-model: merge geometries from all visible models
|
|
57
88
|
const mergedGeometryResult = useMemo(() => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
89
|
+
if (storeModels.size === 1) {
|
|
90
|
+
const firstModel = storeModels.values().next().value;
|
|
91
|
+
if (!firstModel?.visible) {
|
|
92
|
+
return {
|
|
93
|
+
meshes: [],
|
|
94
|
+
totalVertices: 0,
|
|
95
|
+
totalTriangles: 0,
|
|
96
|
+
coordinateInfo: DEFAULT_COORDINATE_INFO,
|
|
97
|
+
} satisfies GeometryResult;
|
|
98
|
+
}
|
|
99
|
+
return firstModel.geometryResult ?? geometryResult;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (storeModels.size > 1) {
|
|
61
103
|
let totalVertices = 0;
|
|
62
104
|
let totalTriangles = 0;
|
|
63
105
|
let mergedCoordinateInfo: CoordinateInfo | undefined;
|
|
106
|
+
let shouldRebuild = false;
|
|
64
107
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
108
|
+
if (mergedLengthsRef.current.size !== storeModels.size) {
|
|
109
|
+
shouldRebuild = true;
|
|
110
|
+
}
|
|
68
111
|
|
|
112
|
+
for (const [modelId, model] of storeModels) {
|
|
69
113
|
const modelGeometry = model.geometryResult;
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
114
|
+
const meshCount = model.visible ? (modelGeometry?.meshes.length ?? 0) : 0;
|
|
115
|
+
totalVertices += model.visible ? (modelGeometry?.totalVertices ?? 0) : 0;
|
|
116
|
+
totalTriangles += model.visible ? (modelGeometry?.totalTriangles ?? 0) : 0;
|
|
117
|
+
if (!mergedCoordinateInfo && model.visible && modelGeometry?.coordinateInfo) {
|
|
118
|
+
mergedCoordinateInfo = modelGeometry.coordinateInfo;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (
|
|
122
|
+
mergedVisibilityRef.current.get(modelId) !== model.visible ||
|
|
123
|
+
(mergedLengthsRef.current.get(modelId) ?? 0) > meshCount
|
|
124
|
+
) {
|
|
125
|
+
shouldRebuild = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (shouldRebuild) {
|
|
130
|
+
const rebuilt: MeshData[] = [];
|
|
131
|
+
mergedLengthsRef.current = new Map();
|
|
132
|
+
mergedVisibilityRef.current = new Map();
|
|
133
|
+
for (const [modelId, model] of storeModels) {
|
|
134
|
+
const modelGeometry = model.geometryResult;
|
|
135
|
+
mergedVisibilityRef.current.set(modelId, model.visible);
|
|
136
|
+
const modelIndex = modelIdToIndex.get(modelId) ?? 0;
|
|
137
|
+
if (!model.visible || !modelGeometry?.meshes) {
|
|
138
|
+
mergedLengthsRef.current.set(modelId, 0);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
73
141
|
for (const mesh of modelGeometry.meshes) {
|
|
74
|
-
|
|
142
|
+
rebuilt.push({ ...mesh, modelIndex });
|
|
75
143
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
144
|
+
mergedLengthsRef.current.set(modelId, modelGeometry.meshes.length);
|
|
145
|
+
}
|
|
146
|
+
mergedCacheRef.current = rebuilt;
|
|
147
|
+
} else {
|
|
148
|
+
for (const [modelId, model] of storeModels) {
|
|
149
|
+
const modelGeometry = model.geometryResult;
|
|
150
|
+
const modelIndex = modelIdToIndex.get(modelId) ?? 0;
|
|
151
|
+
const previousLength = mergedLengthsRef.current.get(modelId) ?? 0;
|
|
152
|
+
const nextMeshes = model.visible ? (modelGeometry?.meshes ?? []) : [];
|
|
153
|
+
for (let i = previousLength; i < nextMeshes.length; i++) {
|
|
154
|
+
const mesh = nextMeshes[i];
|
|
155
|
+
mergedCacheRef.current.push({ ...mesh, modelIndex });
|
|
82
156
|
}
|
|
157
|
+
mergedLengthsRef.current.set(modelId, nextMeshes.length);
|
|
158
|
+
mergedVisibilityRef.current.set(modelId, model.visible);
|
|
83
159
|
}
|
|
84
160
|
}
|
|
85
161
|
|
|
86
|
-
// Return merged result (may be empty if all models hidden)
|
|
87
162
|
return {
|
|
88
|
-
meshes:
|
|
163
|
+
meshes: mergedCacheRef.current,
|
|
89
164
|
totalVertices,
|
|
90
165
|
totalTriangles,
|
|
91
166
|
coordinateInfo: mergedCoordinateInfo ?? DEFAULT_COORDINATE_INFO,
|
|
@@ -96,6 +171,106 @@ export function ViewportContainer() {
|
|
|
96
171
|
return geometryResult;
|
|
97
172
|
}, [storeModels, geometryResult, modelIdToIndex]);
|
|
98
173
|
|
|
174
|
+
// Extract georeferencing info merged with any live mutations (for Cesium overlay).
|
|
175
|
+
// Reacts to: model load, Cesium toggle, and every georef field edit.
|
|
176
|
+
const georef = useMemo(() => {
|
|
177
|
+
if (!cesiumEnabled) return null;
|
|
178
|
+
|
|
179
|
+
// Helper: merge original georef with mutations for a model
|
|
180
|
+
function mergeGeoref(
|
|
181
|
+
originalCRS: ProjectedCRS | undefined,
|
|
182
|
+
originalConv: MapConversion | undefined,
|
|
183
|
+
modelId: string,
|
|
184
|
+
): { mapConversion: MapConversion; projectedCRS: ProjectedCRS } | null {
|
|
185
|
+
const muts = georefMutations.get(modelId);
|
|
186
|
+
const mutCRS = muts?.projectedCRS;
|
|
187
|
+
const mutConv = muts?.mapConversion;
|
|
188
|
+
|
|
189
|
+
// Build merged ProjectedCRS — mutation fields override originals
|
|
190
|
+
const hasCRS = originalCRS || mutCRS;
|
|
191
|
+
if (!hasCRS) return null;
|
|
192
|
+
const projectedCRS: ProjectedCRS = {
|
|
193
|
+
id: originalCRS?.id ?? 0,
|
|
194
|
+
name: (mutCRS?.name ?? originalCRS?.name ?? '') as string,
|
|
195
|
+
description: mutCRS?.description ?? originalCRS?.description,
|
|
196
|
+
geodeticDatum: mutCRS?.geodeticDatum ?? originalCRS?.geodeticDatum,
|
|
197
|
+
verticalDatum: mutCRS?.verticalDatum ?? originalCRS?.verticalDatum,
|
|
198
|
+
mapProjection: mutCRS?.mapProjection ?? originalCRS?.mapProjection,
|
|
199
|
+
mapZone: mutCRS?.mapZone ?? originalCRS?.mapZone,
|
|
200
|
+
mapUnit: mutCRS?.mapUnit ?? originalCRS?.mapUnit,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Need at least an EPSG name to resolve projection
|
|
204
|
+
if (!projectedCRS.name) return null;
|
|
205
|
+
|
|
206
|
+
// Build merged MapConversion
|
|
207
|
+
const mapConversion: MapConversion = {
|
|
208
|
+
id: originalConv?.id ?? 0,
|
|
209
|
+
sourceCRS: originalConv?.sourceCRS ?? 0,
|
|
210
|
+
targetCRS: originalConv?.targetCRS ?? 0,
|
|
211
|
+
eastings: (mutConv?.eastings ?? originalConv?.eastings ?? 0) as number,
|
|
212
|
+
northings: (mutConv?.northings ?? originalConv?.northings ?? 0) as number,
|
|
213
|
+
orthogonalHeight: (mutConv?.orthogonalHeight ?? originalConv?.orthogonalHeight ?? 0) as number,
|
|
214
|
+
xAxisAbscissa: mutConv?.xAxisAbscissa ?? originalConv?.xAxisAbscissa,
|
|
215
|
+
xAxisOrdinate: mutConv?.xAxisOrdinate ?? originalConv?.xAxisOrdinate,
|
|
216
|
+
scale: mutConv?.scale ?? originalConv?.scale,
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
return { mapConversion, projectedCRS };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Check federated models first
|
|
223
|
+
for (const [modelId, model] of storeModels) {
|
|
224
|
+
const ds = model.ifcDataStore;
|
|
225
|
+
if (!ds) continue;
|
|
226
|
+
const original = extractGeoreferencingOnDemand(ds as IfcDataStore);
|
|
227
|
+
const merged = mergeGeoref(
|
|
228
|
+
original?.projectedCRS,
|
|
229
|
+
original?.mapConversion,
|
|
230
|
+
modelId,
|
|
231
|
+
);
|
|
232
|
+
if (merged) {
|
|
233
|
+
// Return coordinateInfo from the SAME model to avoid mismatched transforms
|
|
234
|
+
const coordInfo = model.geometryResult?.coordinateInfo;
|
|
235
|
+
return { hasGeoreference: true, ...merged, sourceModelId: modelId, coordinateInfo: coordInfo };
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Fallback to legacy single-model
|
|
240
|
+
if (ifcDataStore) {
|
|
241
|
+
const original = extractGeoreferencingOnDemand(ifcDataStore as IfcDataStore);
|
|
242
|
+
const merged = mergeGeoref(
|
|
243
|
+
original?.projectedCRS,
|
|
244
|
+
original?.mapConversion,
|
|
245
|
+
'__legacy__',
|
|
246
|
+
);
|
|
247
|
+
if (merged) {
|
|
248
|
+
return { hasGeoreference: true, ...merged, sourceModelId: '__legacy__', coordinateInfo: mergedGeometryResult?.coordinateInfo };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return null;
|
|
253
|
+
}, [cesiumEnabled, storeModels, ifcDataStore, georefMutations, mutationVersion, mergedGeometryResult]);
|
|
254
|
+
|
|
255
|
+
// Sync the active Cesium source model ID so terrain actions are scoped correctly
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
setCesiumSourceModelId(georef?.sourceModelId ?? null);
|
|
258
|
+
}, [georef?.sourceModelId, setCesiumSourceModelId]);
|
|
259
|
+
|
|
260
|
+
useEffect(() => {
|
|
261
|
+
// Recent files are a desktop-only feature — the web viewer should not
|
|
262
|
+
// show previously opened files in the landing page empty state.
|
|
263
|
+
if (!isTauri()) return;
|
|
264
|
+
|
|
265
|
+
const refreshRecentFiles = () => {
|
|
266
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
refreshRecentFiles();
|
|
270
|
+
window.addEventListener('focus', refreshRecentFiles);
|
|
271
|
+
return () => window.removeEventListener('focus', refreshRecentFiles);
|
|
272
|
+
}, []);
|
|
273
|
+
|
|
99
274
|
const handleDragOver = useCallback((e: React.DragEvent) => {
|
|
100
275
|
e.preventDefault();
|
|
101
276
|
e.stopPropagation();
|
|
@@ -128,6 +303,10 @@ export function ViewportContainer() {
|
|
|
128
303
|
|
|
129
304
|
if (supportedFiles.length === 0) return;
|
|
130
305
|
|
|
306
|
+
recordRecentFiles(supportedFiles.map((file) => ({ name: file.name, size: file.size })));
|
|
307
|
+
void cacheFileBlobs(supportedFiles);
|
|
308
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
309
|
+
|
|
131
310
|
if (hasModelsLoaded) {
|
|
132
311
|
// Models already loaded - add new files sequentially
|
|
133
312
|
loadFilesSequentially(supportedFiles);
|
|
@@ -158,6 +337,10 @@ export function ViewportContainer() {
|
|
|
158
337
|
|
|
159
338
|
if (supportedFiles.length === 0) return;
|
|
160
339
|
|
|
340
|
+
recordRecentFiles(supportedFiles.map((file) => ({ name: file.name, size: file.size })));
|
|
341
|
+
void cacheFileBlobs(supportedFiles);
|
|
342
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
343
|
+
|
|
161
344
|
if (supportedFiles.length === 1) {
|
|
162
345
|
// Single file - use loadFile (simpler single-model path)
|
|
163
346
|
loadFile(supportedFiles[0]);
|
|
@@ -184,6 +367,7 @@ export function ViewportContainer() {
|
|
|
184
367
|
// A version counter triggers downstream re-renders via the Viewport prop.
|
|
185
368
|
const filteredCacheRef = useRef<MeshData[]>([]);
|
|
186
369
|
const filteredSourceLenRef = useRef(0);
|
|
370
|
+
const filteredSourceRef = useRef<MeshData[] | null>(null);
|
|
187
371
|
const filteredTypeVisRef = useRef(typeVisibility);
|
|
188
372
|
const filteredVersionRef = useRef(0);
|
|
189
373
|
|
|
@@ -191,6 +375,7 @@ export function ViewportContainer() {
|
|
|
191
375
|
if (!mergedGeometryResult?.meshes) {
|
|
192
376
|
filteredCacheRef.current = [];
|
|
193
377
|
filteredSourceLenRef.current = 0;
|
|
378
|
+
filteredSourceRef.current = null;
|
|
194
379
|
filteredVersionRef.current = 0;
|
|
195
380
|
return null;
|
|
196
381
|
}
|
|
@@ -204,9 +389,11 @@ export function ViewportContainer() {
|
|
|
204
389
|
prevVis.spaces !== typeVisibility.spaces ||
|
|
205
390
|
prevVis.openings !== typeVisibility.openings ||
|
|
206
391
|
prevVis.site !== typeVisibility.site;
|
|
207
|
-
|
|
392
|
+
const sourceChanged = filteredSourceRef.current !== allMeshes;
|
|
393
|
+
if (typeVisChanged || sourceChanged || allMeshes.length < filteredSourceLenRef.current) {
|
|
208
394
|
cache.length = 0;
|
|
209
395
|
filteredSourceLenRef.current = 0;
|
|
396
|
+
filteredSourceRef.current = allMeshes;
|
|
210
397
|
filteredTypeVisRef.current = typeVisibility;
|
|
211
398
|
}
|
|
212
399
|
|
|
@@ -238,7 +425,7 @@ export function ViewportContainer() {
|
|
|
238
425
|
|
|
239
426
|
// Only bump version when cache content actually changed — avoids
|
|
240
427
|
// unnecessary downstream re-renders when memo runs with same data.
|
|
241
|
-
if (cache.length !== prevCacheLen || typeVisChanged) {
|
|
428
|
+
if (cache.length !== prevCacheLen || typeVisChanged || sourceChanged) {
|
|
242
429
|
filteredVersionRef.current++;
|
|
243
430
|
}
|
|
244
431
|
|
|
@@ -531,7 +718,29 @@ export function ViewportContainer() {
|
|
|
531
718
|
|
|
532
719
|
{/* Action */}
|
|
533
720
|
<button
|
|
534
|
-
onClick={() =>
|
|
721
|
+
onClick={async () => {
|
|
722
|
+
if (!webgpu.supported) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
void logToDesktopTerminal('info', '[ViewportContainer] Empty-state open button clicked');
|
|
727
|
+
const file = await openIfcFileDialog();
|
|
728
|
+
if (file) {
|
|
729
|
+
void logToDesktopTerminal('info', `[ViewportContainer] Native dialog selected ${file.path}`);
|
|
730
|
+
recordRecentFiles([{
|
|
731
|
+
name: file.name,
|
|
732
|
+
size: file.size,
|
|
733
|
+
path: file.path,
|
|
734
|
+
modifiedMs: file.modifiedMs ?? null,
|
|
735
|
+
}]);
|
|
736
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
737
|
+
loadFile(file);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
void logToDesktopTerminal('info', '[ViewportContainer] Falling back to browser file input');
|
|
742
|
+
fileInputRef.current?.click();
|
|
743
|
+
}}
|
|
535
744
|
disabled={!webgpu.supported || webgpu.checking}
|
|
536
745
|
className={`group w-full flex items-center justify-center gap-3 px-6 py-3 font-mono text-sm border transition-all ${
|
|
537
746
|
!webgpu.supported || webgpu.checking
|
|
@@ -546,6 +755,37 @@ export function ViewportContainer() {
|
|
|
546
755
|
<p className="mt-3 text-xs font-mono text-zinc-400 dark:text-[#565f89]">
|
|
547
756
|
{webgpu.supported ? 'or drag & drop anywhere' : 'file upload disabled'}
|
|
548
757
|
</p>
|
|
758
|
+
|
|
759
|
+
{recentFiles.length > 0 && (
|
|
760
|
+
<div className="mt-6 w-full border-t border-zinc-200 dark:border-[#3b4261] pt-4">
|
|
761
|
+
<div className="mb-3 flex items-center gap-2 text-xs font-mono uppercase tracking-[0.2em] text-zinc-400 dark:text-[#565f89]">
|
|
762
|
+
<Clock3 className="h-3.5 w-3.5" />
|
|
763
|
+
<span>Recent Files</span>
|
|
764
|
+
</div>
|
|
765
|
+
<div className="flex flex-col gap-2">
|
|
766
|
+
{recentFiles.map((file) => (
|
|
767
|
+
<button
|
|
768
|
+
key={`${file.name}-${file.timestamp}`}
|
|
769
|
+
type="button"
|
|
770
|
+
onClick={async () => {
|
|
771
|
+
const cached = await getCachedFile(file);
|
|
772
|
+
if (cached) {
|
|
773
|
+
await loadFile(cached);
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
fileInputRef.current?.click();
|
|
777
|
+
}}
|
|
778
|
+
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"
|
|
779
|
+
>
|
|
780
|
+
<span className="min-w-0 truncate font-mono text-xs">{file.name}</span>
|
|
781
|
+
<span className="shrink-0 font-mono text-[10px] uppercase tracking-wide text-zinc-400 dark:text-[#565f89]">
|
|
782
|
+
{formatFileSize(file.size)}
|
|
783
|
+
</span>
|
|
784
|
+
</button>
|
|
785
|
+
))}
|
|
786
|
+
</div>
|
|
787
|
+
</div>
|
|
788
|
+
)}
|
|
549
789
|
</div>
|
|
550
790
|
|
|
551
791
|
{/* Feature Grid */}
|
|
@@ -607,18 +847,30 @@ export function ViewportContainer() {
|
|
|
607
847
|
</div>
|
|
608
848
|
)}
|
|
609
849
|
|
|
850
|
+
{/* Cesium 3D world context overlay — rendered behind the WebGPU canvas */}
|
|
851
|
+
{cesiumEnabled && georef && (
|
|
852
|
+
<CesiumOverlay
|
|
853
|
+
mapConversion={georef.mapConversion}
|
|
854
|
+
projectedCRS={georef.projectedCRS}
|
|
855
|
+
coordinateInfo={georef.coordinateInfo}
|
|
856
|
+
geometryResult={mergedGeometryResult}
|
|
857
|
+
/>
|
|
858
|
+
)}
|
|
610
859
|
<Viewport
|
|
611
860
|
geometry={filteredGeometry}
|
|
612
861
|
geometryVersion={geometryVersion}
|
|
613
862
|
coordinateInfo={mergedGeometryResult?.coordinateInfo}
|
|
614
863
|
computedIsolatedIds={computedIsolatedIds}
|
|
615
864
|
modelIdToIndex={modelIdToIndex}
|
|
865
|
+
cesiumActive={cesiumEnabled && georef !== null}
|
|
866
|
+
releaseGeometryAfterStream={false}
|
|
867
|
+
onGeometryReleased={releaseGeometryMemory}
|
|
616
868
|
/>
|
|
617
869
|
{bcfOverlayVisible && <BCFOverlay />}
|
|
618
870
|
<ViewportOverlays />
|
|
619
871
|
<ToolOverlays />
|
|
620
872
|
<BasketPresentationDock />
|
|
621
|
-
<Section2DPanel
|
|
873
|
+
<Section2DPanel
|
|
622
874
|
mergedGeometry={mergedGeometryResult}
|
|
623
875
|
computedIsolatedIds={computedIsolatedIds}
|
|
624
876
|
modelIdToIndex={modelIdToIndex}
|