@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
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Cap-surface appearance controls shown inside the expanded Section panel.
|
|
7
|
+
*
|
|
8
|
+
* Layout principle (tight compact panel, ≤ 260 px wide):
|
|
9
|
+
* [Display] Surfaces ⬛ Lines ⬛
|
|
10
|
+
* ───────────────────────────────────────────────
|
|
11
|
+
* [Hatch] <pattern select>
|
|
12
|
+
* [Colours] Fill ▣ Hatch ▣
|
|
13
|
+
* [Shape] Spacing __px Angle __° Width __px
|
|
14
|
+
*
|
|
15
|
+
* Surfaces and Lines toggle independently so users can get a clean
|
|
16
|
+
* "architectural drawing" look (outlines only), a pure hatched fill, or
|
|
17
|
+
* the combination. All style inputs are hidden when Surfaces is off.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { useCallback, useId } from 'react';
|
|
21
|
+
import { useViewerStore } from '@/store';
|
|
22
|
+
import type { SectionCapHatchId } from '@/store/types';
|
|
23
|
+
|
|
24
|
+
const PATTERN_LABELS: Record<SectionCapHatchId, string> = {
|
|
25
|
+
solid: 'Solid fill',
|
|
26
|
+
diagonal: 'Diagonal',
|
|
27
|
+
crossHatch: 'Cross-hatch',
|
|
28
|
+
horizontal: 'Horizontal',
|
|
29
|
+
vertical: 'Vertical',
|
|
30
|
+
concrete: 'Concrete',
|
|
31
|
+
brick: 'Brick',
|
|
32
|
+
insulation: 'Insulation',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const PATTERN_IDS: SectionCapHatchId[] = [
|
|
36
|
+
'diagonal', 'crossHatch', 'horizontal', 'vertical',
|
|
37
|
+
'concrete', 'brick', 'insulation', 'solid',
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
function rgbaToHex(c: [number, number, number, number]): string {
|
|
41
|
+
const to2 = (v: number) => Math.round(Math.max(0, Math.min(1, v)) * 255).toString(16).padStart(2, '0');
|
|
42
|
+
return `#${to2(c[0])}${to2(c[1])}${to2(c[2])}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function hexToRgba(hex: string, alpha: number): [number, number, number, number] {
|
|
46
|
+
const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
47
|
+
if (!m) return [1, 1, 1, alpha];
|
|
48
|
+
return [
|
|
49
|
+
parseInt(m[1], 16) / 255,
|
|
50
|
+
parseInt(m[2], 16) / 255,
|
|
51
|
+
parseInt(m[3], 16) / 255,
|
|
52
|
+
alpha,
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface DisplayToggleProps {
|
|
57
|
+
active: boolean;
|
|
58
|
+
label: string;
|
|
59
|
+
onToggle: () => void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function DisplayToggle({ active, label, onToggle }: DisplayToggleProps): React.JSX.Element {
|
|
63
|
+
return (
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
onClick={onToggle}
|
|
67
|
+
aria-pressed={active}
|
|
68
|
+
className={`flex items-center justify-center gap-1.5 px-2 py-1 text-[10px] font-mono uppercase tracking-wide border rounded transition-colors ${
|
|
69
|
+
active
|
|
70
|
+
? 'bg-primary text-primary-foreground border-primary'
|
|
71
|
+
: 'bg-muted text-muted-foreground border-muted hover:border-foreground/20'
|
|
72
|
+
}`}
|
|
73
|
+
title={`${active ? 'Hide' : 'Show'} ${label.toLowerCase()}`}
|
|
74
|
+
>
|
|
75
|
+
<span
|
|
76
|
+
aria-hidden
|
|
77
|
+
className={`inline-block h-1.5 w-1.5 rounded-full ${active ? 'bg-primary-foreground' : 'bg-muted-foreground'}`}
|
|
78
|
+
/>
|
|
79
|
+
{label}
|
|
80
|
+
</button>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function SectionCapControls(): React.JSX.Element {
|
|
85
|
+
const sectionPlane = useViewerStore((s) => s.sectionPlane);
|
|
86
|
+
const setShowCap = useViewerStore((s) => s.setSectionShowCap);
|
|
87
|
+
const setShowOutlines = useViewerStore((s) => s.setSectionShowOutlines);
|
|
88
|
+
const setCapStyle = useViewerStore((s) => s.setSectionCapStyle);
|
|
89
|
+
|
|
90
|
+
const onPattern = useCallback((e: React.ChangeEvent<HTMLSelectElement>) => {
|
|
91
|
+
setCapStyle({ pattern: e.target.value as SectionCapHatchId });
|
|
92
|
+
}, [setCapStyle]);
|
|
93
|
+
|
|
94
|
+
const onFillColor = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
95
|
+
setCapStyle({ fillColor: hexToRgba(e.target.value, sectionPlane.capStyle.fillColor[3]) });
|
|
96
|
+
}, [setCapStyle, sectionPlane.capStyle.fillColor]);
|
|
97
|
+
|
|
98
|
+
const onStrokeColor = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
99
|
+
setCapStyle({ strokeColor: hexToRgba(e.target.value, sectionPlane.capStyle.strokeColor[3]) });
|
|
100
|
+
}, [setCapStyle, sectionPlane.capStyle.strokeColor]);
|
|
101
|
+
|
|
102
|
+
const onSpacing = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
103
|
+
const v = Number(e.target.value);
|
|
104
|
+
if (Number.isFinite(v)) setCapStyle({ spacingPx: Math.max(2, v) });
|
|
105
|
+
}, [setCapStyle]);
|
|
106
|
+
|
|
107
|
+
const onAngle = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
108
|
+
const deg = Number(e.target.value);
|
|
109
|
+
if (Number.isFinite(deg)) setCapStyle({ angleRad: (deg * Math.PI) / 180 });
|
|
110
|
+
}, [setCapStyle]);
|
|
111
|
+
|
|
112
|
+
const onWidth = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
113
|
+
const v = Number(e.target.value);
|
|
114
|
+
if (Number.isFinite(v)) setCapStyle({ widthPx: Math.max(1, v) });
|
|
115
|
+
}, [setCapStyle]);
|
|
116
|
+
|
|
117
|
+
const onToggleCap = useCallback(() => setShowCap(!sectionPlane.showCap), [setShowCap, sectionPlane.showCap]);
|
|
118
|
+
const onToggleOutlines = useCallback(() => setShowOutlines(!sectionPlane.showOutlines), [setShowOutlines, sectionPlane.showOutlines]);
|
|
119
|
+
|
|
120
|
+
const angleDeg = Math.round((sectionPlane.capStyle.angleRad * 180) / Math.PI);
|
|
121
|
+
|
|
122
|
+
// Stable ids for label/control association. Multiple instances of the
|
|
123
|
+
// panel (rare, but possible during HMR) each get their own id namespace.
|
|
124
|
+
const baseId = useId();
|
|
125
|
+
const patternId = `${baseId}-pattern`;
|
|
126
|
+
const fillId = `${baseId}-fill`;
|
|
127
|
+
const strokeId = `${baseId}-stroke`;
|
|
128
|
+
const spacingId = `${baseId}-spacing`;
|
|
129
|
+
const angleId = `${baseId}-angle`;
|
|
130
|
+
const widthId = `${baseId}-width`;
|
|
131
|
+
|
|
132
|
+
const hatchInputsDisabled = !sectionPlane.showCap;
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<div className="mt-3 border-t pt-3 space-y-3">
|
|
136
|
+
{/* Display toggles — surfaces and lines independently. */}
|
|
137
|
+
<div>
|
|
138
|
+
<div className="text-[10px] uppercase tracking-wider text-muted-foreground mb-1.5">Display</div>
|
|
139
|
+
<div className="grid grid-cols-2 gap-2">
|
|
140
|
+
<DisplayToggle active={sectionPlane.showCap} label="Surfaces" onToggle={onToggleCap} />
|
|
141
|
+
<DisplayToggle active={sectionPlane.showOutlines} label="Lines" onToggle={onToggleOutlines} />
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
{/* Hatch style — disabled visually when surfaces are off. */}
|
|
146
|
+
<fieldset
|
|
147
|
+
disabled={hatchInputsDisabled}
|
|
148
|
+
className={`space-y-2 ${hatchInputsDisabled ? 'opacity-50 pointer-events-none' : ''}`}
|
|
149
|
+
>
|
|
150
|
+
<div>
|
|
151
|
+
<label htmlFor={patternId} className="text-[10px] uppercase tracking-wider text-muted-foreground block mb-1">
|
|
152
|
+
Hatch pattern
|
|
153
|
+
</label>
|
|
154
|
+
<select
|
|
155
|
+
id={patternId}
|
|
156
|
+
value={sectionPlane.capStyle.pattern}
|
|
157
|
+
onChange={onPattern}
|
|
158
|
+
className="w-full text-xs bg-muted px-2 py-1.5 rounded border-none"
|
|
159
|
+
>
|
|
160
|
+
{PATTERN_IDS.map((id) => (
|
|
161
|
+
<option key={id} value={id}>{PATTERN_LABELS[id]}</option>
|
|
162
|
+
))}
|
|
163
|
+
</select>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<div className="grid grid-cols-2 gap-2">
|
|
167
|
+
<label htmlFor={fillId} className="flex items-center gap-2 text-[10px] uppercase tracking-wider text-muted-foreground">
|
|
168
|
+
<input
|
|
169
|
+
id={fillId}
|
|
170
|
+
type="color"
|
|
171
|
+
value={rgbaToHex(sectionPlane.capStyle.fillColor)}
|
|
172
|
+
onChange={onFillColor}
|
|
173
|
+
className="h-5 w-5 rounded cursor-pointer border border-muted"
|
|
174
|
+
aria-label="Fill colour"
|
|
175
|
+
/>
|
|
176
|
+
Fill
|
|
177
|
+
</label>
|
|
178
|
+
<label htmlFor={strokeId} className="flex items-center gap-2 text-[10px] uppercase tracking-wider text-muted-foreground">
|
|
179
|
+
<input
|
|
180
|
+
id={strokeId}
|
|
181
|
+
type="color"
|
|
182
|
+
value={rgbaToHex(sectionPlane.capStyle.strokeColor)}
|
|
183
|
+
onChange={onStrokeColor}
|
|
184
|
+
className="h-5 w-5 rounded cursor-pointer border border-muted"
|
|
185
|
+
aria-label="Hatch colour"
|
|
186
|
+
/>
|
|
187
|
+
Hatch
|
|
188
|
+
</label>
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
<div className="grid grid-cols-3 gap-2">
|
|
192
|
+
<div>
|
|
193
|
+
<label htmlFor={spacingId} className="text-[10px] text-muted-foreground block mb-1">Spacing (px)</label>
|
|
194
|
+
<input
|
|
195
|
+
id={spacingId}
|
|
196
|
+
type="number"
|
|
197
|
+
min="2"
|
|
198
|
+
max="64"
|
|
199
|
+
step="1"
|
|
200
|
+
value={sectionPlane.capStyle.spacingPx}
|
|
201
|
+
onChange={onSpacing}
|
|
202
|
+
className="w-full text-xs bg-muted px-1.5 py-0.5 rounded border-none text-right"
|
|
203
|
+
/>
|
|
204
|
+
</div>
|
|
205
|
+
<div>
|
|
206
|
+
<label htmlFor={angleId} className="text-[10px] text-muted-foreground block mb-1">Angle (°)</label>
|
|
207
|
+
<input
|
|
208
|
+
id={angleId}
|
|
209
|
+
type="number"
|
|
210
|
+
min="-180"
|
|
211
|
+
max="180"
|
|
212
|
+
step="5"
|
|
213
|
+
value={angleDeg}
|
|
214
|
+
onChange={onAngle}
|
|
215
|
+
className="w-full text-xs bg-muted px-1.5 py-0.5 rounded border-none text-right"
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
<div>
|
|
219
|
+
<label htmlFor={widthId} className="text-[10px] text-muted-foreground block mb-1">Width (px)</label>
|
|
220
|
+
<input
|
|
221
|
+
id={widthId}
|
|
222
|
+
type="number"
|
|
223
|
+
min="1"
|
|
224
|
+
max="16"
|
|
225
|
+
step="0.5"
|
|
226
|
+
value={sectionPlane.capStyle.widthPx}
|
|
227
|
+
onChange={onWidth}
|
|
228
|
+
className="w-full text-xs bg-muted px-1.5 py-0.5 rounded border-none text-right"
|
|
229
|
+
/>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
</fieldset>
|
|
233
|
+
</div>
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export default SectionCapControls;
|
|
@@ -7,17 +7,19 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import React, { useCallback, useState } from 'react';
|
|
10
|
-
import { X, Slice, ChevronDown, FileImage } from 'lucide-react';
|
|
10
|
+
import { X, Slice, ChevronDown, FileImage, FlipHorizontal2 } from 'lucide-react';
|
|
11
11
|
import { Button } from '@/components/ui/button';
|
|
12
12
|
import { useViewerStore } from '@/store';
|
|
13
13
|
import { AXIS_INFO } from './sectionConstants';
|
|
14
14
|
import { SectionPlaneVisualization } from './SectionVisualization';
|
|
15
|
+
import { SectionCapControls } from './SectionCapControls';
|
|
15
16
|
|
|
16
17
|
export function SectionOverlay() {
|
|
17
18
|
const sectionPlane = useViewerStore((s) => s.sectionPlane);
|
|
18
19
|
const setSectionPlaneAxis = useViewerStore((s) => s.setSectionPlaneAxis);
|
|
19
20
|
const setSectionPlanePosition = useViewerStore((s) => s.setSectionPlanePosition);
|
|
20
21
|
const toggleSectionPlane = useViewerStore((s) => s.toggleSectionPlane);
|
|
22
|
+
const flipSectionPlane = useViewerStore((s) => s.flipSectionPlane);
|
|
21
23
|
const setActiveTool = useViewerStore((s) => s.setActiveTool);
|
|
22
24
|
const setDrawingPanelVisible = useViewerStore((s) => s.setDrawing2DPanelVisible);
|
|
23
25
|
const drawingPanelVisible = useViewerStore((s) => s.drawing2DPanelVisible);
|
|
@@ -83,10 +85,10 @@ export function SectionOverlay() {
|
|
|
83
85
|
|
|
84
86
|
{/* Expandable content */}
|
|
85
87
|
{!isPanelCollapsed && (
|
|
86
|
-
<div className="border-t px-3 pb-3 min-w-
|
|
88
|
+
<div className="border-t px-3 pb-3 min-w-72">
|
|
87
89
|
{/* Direction Selection */}
|
|
88
90
|
<div className="mt-3">
|
|
89
|
-
<
|
|
91
|
+
<div className="text-[10px] uppercase tracking-wider text-muted-foreground mb-1.5">Direction</div>
|
|
90
92
|
<div className="flex gap-1">
|
|
91
93
|
{(['down', 'front', 'side'] as const).map((axis) => (
|
|
92
94
|
<Button
|
|
@@ -105,16 +107,29 @@ export function SectionOverlay() {
|
|
|
105
107
|
{/* Position Slider */}
|
|
106
108
|
<div className="mt-3">
|
|
107
109
|
<div className="flex items-center justify-between mb-1">
|
|
108
|
-
<
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
<div className="text-[10px] uppercase tracking-wider text-muted-foreground">Position</div>
|
|
111
|
+
<div className="flex items-center gap-1">
|
|
112
|
+
<Button
|
|
113
|
+
variant={sectionPlane.flipped ? 'default' : 'ghost'}
|
|
114
|
+
size="icon-sm"
|
|
115
|
+
onClick={flipSectionPlane}
|
|
116
|
+
aria-pressed={sectionPlane.flipped}
|
|
117
|
+
aria-label={sectionPlane.flipped ? 'Unflip cut direction' : 'Flip cut direction'}
|
|
118
|
+
title={sectionPlane.flipped ? 'Cut direction is flipped' : 'Flip cut direction'}
|
|
119
|
+
>
|
|
120
|
+
<FlipHorizontal2 className="h-3 w-3" />
|
|
121
|
+
</Button>
|
|
122
|
+
<input
|
|
123
|
+
type="number"
|
|
124
|
+
min="0"
|
|
125
|
+
max="100"
|
|
126
|
+
step="0.1"
|
|
127
|
+
value={sectionPlane.position}
|
|
128
|
+
onChange={handlePositionChange}
|
|
129
|
+
aria-label="Section plane position percentage"
|
|
130
|
+
className="w-16 text-xs font-mono bg-muted px-1.5 py-0.5 rounded border-none text-right [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
118
133
|
</div>
|
|
119
134
|
<input
|
|
120
135
|
type="range"
|
|
@@ -123,10 +138,14 @@ export function SectionOverlay() {
|
|
|
123
138
|
step="0.1"
|
|
124
139
|
value={sectionPlane.position}
|
|
125
140
|
onChange={handlePositionChange}
|
|
141
|
+
aria-label="Section plane position slider"
|
|
126
142
|
className="w-full h-2 bg-muted rounded-lg appearance-none cursor-pointer accent-primary"
|
|
127
143
|
/>
|
|
128
144
|
</div>
|
|
129
145
|
|
|
146
|
+
{/* Cap surface controls (hatch, colour, spacing) */}
|
|
147
|
+
<SectionCapControls />
|
|
148
|
+
|
|
130
149
|
{/* Show 2D panel button - only when panel is closed */}
|
|
131
150
|
{!drawingPanelVisible && (
|
|
132
151
|
<div className="mt-3 pt-3 border-t">
|
|
@@ -156,12 +175,14 @@ export function SectionOverlay() {
|
|
|
156
175
|
>
|
|
157
176
|
<span className="font-mono text-xs uppercase tracking-wide">
|
|
158
177
|
{sectionPlane.enabled
|
|
159
|
-
? `
|
|
160
|
-
: '
|
|
178
|
+
? `Cut ${AXIS_INFO[sectionPlane.axis].label.toLowerCase()} at ${sectionPlane.position.toFixed(1)}%${sectionPlane.flipped ? ' (flipped)' : ''}`
|
|
179
|
+
: 'Clip off — drag slider to cut'}
|
|
161
180
|
</span>
|
|
162
181
|
</div>
|
|
163
182
|
|
|
164
|
-
{/* Enable toggle
|
|
183
|
+
{/* Enable toggle — when OFF the model is not clipped even though the
|
|
184
|
+
plane visual is shown. Label is explicit so users don't mistake
|
|
185
|
+
"Preview" for "nothing will happen". */}
|
|
165
186
|
<div className="pointer-events-auto absolute bottom-4 left-1/2 -translate-x-1/2 z-30">
|
|
166
187
|
<button
|
|
167
188
|
onClick={toggleSectionPlane}
|
|
@@ -170,9 +191,9 @@ export function SectionOverlay() {
|
|
|
170
191
|
? 'bg-primary text-primary-foreground border-primary'
|
|
171
192
|
: 'bg-zinc-100 dark:bg-zinc-900 text-zinc-500 border-zinc-300 dark:border-zinc-700'
|
|
172
193
|
}`}
|
|
173
|
-
title=
|
|
194
|
+
title={sectionPlane.enabled ? 'Click to disable the cut' : 'Click to enable the cut'}
|
|
174
195
|
>
|
|
175
|
-
{sectionPlane.enabled ? '
|
|
196
|
+
{sectionPlane.enabled ? 'Clipping' : 'Clip off'}
|
|
176
197
|
</button>
|
|
177
198
|
</div>
|
|
178
199
|
|
|
@@ -29,6 +29,8 @@ export interface UseAnimationLoopParams {
|
|
|
29
29
|
lastFrameTimeRef: MutableRefObject<number>;
|
|
30
30
|
mouseIsDraggingRef: MutableRefObject<boolean>;
|
|
31
31
|
activeToolRef: MutableRefObject<string>;
|
|
32
|
+
/** When set, clips model below this Y value (terrain clipping for Cesium overlay). */
|
|
33
|
+
terrainClipYRef: MutableRefObject<number | null>;
|
|
32
34
|
hiddenEntitiesRef: MutableRefObject<Set<number>>;
|
|
33
35
|
isolatedEntitiesRef: MutableRefObject<Set<number> | null>;
|
|
34
36
|
selectedEntityIdRef: MutableRefObject<number | null>;
|
|
@@ -62,6 +64,7 @@ export function useAnimationLoop(params: UseAnimationLoopParams): void {
|
|
|
62
64
|
lastFrameTimeRef,
|
|
63
65
|
mouseIsDraggingRef,
|
|
64
66
|
activeToolRef,
|
|
67
|
+
terrainClipYRef,
|
|
65
68
|
hiddenEntitiesRef,
|
|
66
69
|
isolatedEntitiesRef,
|
|
67
70
|
selectedEntityIdRef,
|
|
@@ -167,10 +170,19 @@ export function useAnimationLoop(params: UseAnimationLoopParams): void {
|
|
|
167
170
|
isInteracting: isInteractingRef.current || isAnimating,
|
|
168
171
|
buildingRotation: coordinateInfoRef.current?.buildingRotation,
|
|
169
172
|
sectionPlane: activeToolRef.current === 'section' ? {
|
|
170
|
-
|
|
173
|
+
axis: sectionPlaneRef.current.axis,
|
|
174
|
+
position: sectionPlaneRef.current.position,
|
|
175
|
+
enabled: sectionPlaneRef.current.enabled,
|
|
176
|
+
flipped: sectionPlaneRef.current.flipped,
|
|
177
|
+
// Cap rendering settings — the renderer reads these to draw the
|
|
178
|
+
// filled, hatched cut surfaces.
|
|
179
|
+
showCap: sectionPlaneRef.current.showCap,
|
|
180
|
+
showOutlines: sectionPlaneRef.current.showOutlines,
|
|
181
|
+
capStyle: sectionPlaneRef.current.capStyle,
|
|
171
182
|
min: sectionRangeRef.current?.min,
|
|
172
183
|
max: sectionRangeRef.current?.max,
|
|
173
184
|
} : undefined,
|
|
185
|
+
terrainClipY: terrainClipYRef.current ?? undefined,
|
|
174
186
|
});
|
|
175
187
|
lastRenderTime = currentTime;
|
|
176
188
|
}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import { useEffect, useRef, type MutableRefObject } from 'react';
|
|
22
22
|
import type { Renderer } from '@ifc-lite/renderer';
|
|
23
23
|
import type { MeshData, CoordinateInfo } from '@ifc-lite/geometry';
|
|
24
|
+
import { logToDesktopTerminal } from '@/services/desktop-logger';
|
|
24
25
|
|
|
25
26
|
export interface UseGeometryStreamingParams {
|
|
26
27
|
rendererRef: MutableRefObject<Renderer | null>;
|
|
@@ -37,6 +38,8 @@ export interface UseGeometryStreamingParams {
|
|
|
37
38
|
clearPendingMeshColorUpdates: () => void;
|
|
38
39
|
clearPendingColorUpdates: () => void;
|
|
39
40
|
clearColorRef: MutableRefObject<[number, number, number, number]>;
|
|
41
|
+
releaseGeometryAfterFinalize?: boolean;
|
|
42
|
+
onGeometryReleased?: () => void;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
// Default bounds used when geometry is cleared
|
|
@@ -47,6 +50,11 @@ const DEFAULT_BOUNDS = {
|
|
|
47
50
|
|
|
48
51
|
const MAX_VALID_COORD = 10000;
|
|
49
52
|
|
|
53
|
+
function traceGeometrySync(message: string): void {
|
|
54
|
+
console.log(`[GeomSync] ${message}`);
|
|
55
|
+
void logToDesktopTerminal('info', `[GeomSync] ${message}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
50
58
|
export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
51
59
|
const {
|
|
52
60
|
rendererRef,
|
|
@@ -61,6 +69,8 @@ export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
|
61
69
|
clearPendingMeshColorUpdates,
|
|
62
70
|
clearPendingColorUpdates,
|
|
63
71
|
clearColorRef,
|
|
72
|
+
releaseGeometryAfterFinalize = false,
|
|
73
|
+
onGeometryReleased,
|
|
64
74
|
} = params;
|
|
65
75
|
|
|
66
76
|
// ─── Tracking refs ───────────────────────────────────────────────────
|
|
@@ -71,6 +81,33 @@ export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
|
71
81
|
const finalBoundsRefittedRef = useRef(false);
|
|
72
82
|
const cameraSnapshotRef = useRef<{ px: number; py: number; pz: number; tx: number; ty: number; tz: number } | null>(null);
|
|
73
83
|
const prevIsStreamingRef = useRef(isStreaming);
|
|
84
|
+
const queuePumpTimerRef = useRef<ReturnType<typeof globalThis.setTimeout> | null>(null);
|
|
85
|
+
|
|
86
|
+
// Only activate the timer-based queue pump when the tab is background-throttled
|
|
87
|
+
// (rAF stops firing). In the foreground, the animation loop already drains the
|
|
88
|
+
// queue every frame — a parallel setTimeout(0) pump doubles the GPU work and
|
|
89
|
+
// hurts Chrome (Dawn) where each buffer op is an IPC round-trip.
|
|
90
|
+
const ensureQueuePump = () => {
|
|
91
|
+
if (queuePumpTimerRef.current !== null) return;
|
|
92
|
+
if (!globalThis.document?.hidden) return; // rAF is active — let the animation loop drain
|
|
93
|
+
queuePumpTimerRef.current = globalThis.setTimeout(() => {
|
|
94
|
+
queuePumpTimerRef.current = null;
|
|
95
|
+
const renderer = rendererRef.current;
|
|
96
|
+
if (!renderer || !isInitialized) return;
|
|
97
|
+
const device = renderer.getGPUDevice();
|
|
98
|
+
const pipeline = renderer.getPipeline();
|
|
99
|
+
const scene = renderer.getScene();
|
|
100
|
+
if (!device || !pipeline || !scene.hasQueuedMeshes()) return;
|
|
101
|
+
const flushed = scene.flushPending(device, pipeline);
|
|
102
|
+
if (flushed) {
|
|
103
|
+
renderer.clearCaches();
|
|
104
|
+
renderer.requestRender();
|
|
105
|
+
}
|
|
106
|
+
if (scene.hasQueuedMeshes()) {
|
|
107
|
+
ensureQueuePump();
|
|
108
|
+
}
|
|
109
|
+
}, 0);
|
|
110
|
+
};
|
|
74
111
|
|
|
75
112
|
// ─── Main geometry effect ────────────────────────────────────────────
|
|
76
113
|
// Runs on every geometry change (new file, incremental batch, visibility toggle).
|
|
@@ -81,6 +118,7 @@ export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
|
81
118
|
// Geometry cleared/null — reset so next load is fresh
|
|
82
119
|
if (!geometry) {
|
|
83
120
|
if (lastGeometryLengthRef.current > 0 || lastGeometryRef.current !== null) {
|
|
121
|
+
traceGeometrySync(`geometry cleared lastLength=${lastGeometryLengthRef.current}`);
|
|
84
122
|
lastGeometryLengthRef.current = 0;
|
|
85
123
|
lastGeometryRef.current = null;
|
|
86
124
|
processedMeshIdsRef.current.clear();
|
|
@@ -121,7 +159,9 @@ export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
|
121
159
|
}
|
|
122
160
|
|
|
123
161
|
if (isNewFile) {
|
|
162
|
+
traceGeometrySync(`new file currentLength=${currentLength} lastLength=${lastLength} releaseAfterFinalize=${releaseGeometryAfterFinalize}`);
|
|
124
163
|
scene.clear();
|
|
164
|
+
scene.setEphemeralStreamingMode(releaseGeometryAfterFinalize);
|
|
125
165
|
processedMeshIdsRef.current.clear();
|
|
126
166
|
cameraFittedRef.current = false;
|
|
127
167
|
finalBoundsRefittedRef.current = false;
|
|
@@ -132,14 +172,18 @@ export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
|
132
172
|
geometryBoundsRef.current = { ...DEFAULT_BOUNDS };
|
|
133
173
|
} else if (!isIncremental && currentLength !== lastLength) {
|
|
134
174
|
if (currentLength < lastLength) {
|
|
175
|
+
traceGeometrySync(`geometry rebuilt after shrink currentLength=${currentLength} lastLength=${lastLength}`);
|
|
135
176
|
// Length decreased (model hidden) — rebuild scene, keep camera
|
|
136
177
|
scene.clear();
|
|
178
|
+
scene.setEphemeralStreamingMode(releaseGeometryAfterFinalize);
|
|
137
179
|
processedMeshIdsRef.current.clear();
|
|
138
180
|
lastGeometryLengthRef.current = 0;
|
|
139
181
|
lastGeometryRef.current = geometry;
|
|
140
182
|
} else {
|
|
183
|
+
traceGeometrySync(`geometry rebuilt after replace currentLength=${currentLength} lastLength=${lastLength} releaseAfterFinalize=${releaseGeometryAfterFinalize}`);
|
|
141
184
|
// New file while another was open — full reset
|
|
142
185
|
scene.clear();
|
|
186
|
+
scene.setEphemeralStreamingMode(releaseGeometryAfterFinalize);
|
|
143
187
|
processedMeshIdsRef.current.clear();
|
|
144
188
|
cameraFittedRef.current = false;
|
|
145
189
|
finalBoundsRefittedRef.current = false;
|
|
@@ -193,6 +237,10 @@ export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
|
193
237
|
if (isStreaming) {
|
|
194
238
|
// Queue for the animation loop — zero GPU work here.
|
|
195
239
|
scene.queueMeshes(newMeshes);
|
|
240
|
+
// Desktop benchmark windows can become background-throttled, which
|
|
241
|
+
// stalls requestAnimationFrame-based draining. Keep a timer-based
|
|
242
|
+
// pump active so large native loads still finish offscreen.
|
|
243
|
+
ensureQueuePump();
|
|
196
244
|
} else {
|
|
197
245
|
// Non-streaming: process immediately (visibility toggles, etc.)
|
|
198
246
|
scene.appendToBatches(newMeshes, device, pipeline, false);
|
|
@@ -230,66 +278,105 @@ export function useGeometryStreaming(params: UseGeometryStreamingParams): void {
|
|
|
230
278
|
renderer.requestRender();
|
|
231
279
|
}, [geometry, geometryVersion, coordinateInfo, isInitialized, isStreaming]);
|
|
232
280
|
|
|
281
|
+
useEffect(() => {
|
|
282
|
+
return () => {
|
|
283
|
+
if (queuePumpTimerRef.current !== null) {
|
|
284
|
+
globalThis.clearTimeout(queuePumpTimerRef.current);
|
|
285
|
+
queuePumpTimerRef.current = null;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}, []);
|
|
289
|
+
|
|
233
290
|
// ─── Streaming complete: finalize + bounds refit ─────────────────────
|
|
234
291
|
useEffect(() => {
|
|
235
292
|
const renderer = rendererRef.current;
|
|
236
293
|
if (!renderer || !isInitialized) return;
|
|
237
294
|
|
|
238
295
|
if (prevIsStreamingRef.current && !isStreaming) {
|
|
239
|
-
// Flush any remaining queued meshes synchronously before finalize
|
|
240
|
-
const device = renderer.getGPUDevice();
|
|
241
|
-
const pipeline = renderer.getPipeline();
|
|
242
296
|
const scene = renderer.getScene();
|
|
243
|
-
|
|
244
|
-
scene.
|
|
245
|
-
|
|
246
|
-
|
|
297
|
+
traceGeometrySync(
|
|
298
|
+
`stream transition complete geometryLength=${geometry?.length ?? 0} queued=${scene.hasQueuedMeshes()} batches=${scene.getBatchedMeshes().length}`
|
|
299
|
+
);
|
|
247
300
|
renderer.requestRender();
|
|
248
301
|
|
|
249
|
-
// Defer heavy work so the browser processes pending input events first.
|
|
250
|
-
// Streaming fragments keep rendering until proper batches replace them.
|
|
251
302
|
const capturedGeometry = geometry;
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
303
|
+
let timeoutId: ReturnType<typeof globalThis.setTimeout> | null = null;
|
|
304
|
+
let rafId: number | null = null;
|
|
305
|
+
|
|
306
|
+
const startFinalize = () => {
|
|
307
|
+
timeoutId = globalThis.setTimeout(() => {
|
|
308
|
+
const r = rendererRef.current;
|
|
309
|
+
if (!r) return;
|
|
310
|
+
|
|
311
|
+
console.log('[GeomStream] Streaming ended — starting finalize');
|
|
312
|
+
traceGeometrySync(
|
|
313
|
+
`finalize start geometryLength=${capturedGeometry?.length ?? 0} releaseAfterFinalize=${releaseGeometryAfterFinalize}`
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
// Compute exact bounds and refit camera (fast ~15ms scan)
|
|
317
|
+
if (cameraFittedRef.current && !finalBoundsRefittedRef.current && capturedGeometry && capturedGeometry.length > 0) {
|
|
318
|
+
const t0 = performance.now();
|
|
319
|
+
const exactBounds = computeBounds(capturedGeometry);
|
|
320
|
+
console.log(`[GeomStream] computeBounds: ${(performance.now() - t0).toFixed(0)}ms`);
|
|
321
|
+
if (exactBounds) {
|
|
322
|
+
if (!userMovedCamera(r, cameraSnapshotRef.current)) {
|
|
323
|
+
r.getCamera().fitToBounds(exactBounds.min, exactBounds.max);
|
|
324
|
+
}
|
|
325
|
+
geometryBoundsRef.current = exactBounds;
|
|
326
|
+
finalBoundsRefittedRef.current = true;
|
|
266
327
|
}
|
|
267
|
-
geometryBoundsRef.current = exactBounds;
|
|
268
|
-
finalBoundsRefittedRef.current = true;
|
|
269
328
|
}
|
|
270
|
-
}
|
|
271
329
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const t0 = performance.now();
|
|
277
|
-
r.getScene().finalizeStreamingAsync(dev, pipe).then(() => {
|
|
278
|
-
const batchCount = r.getScene().getBatchedMeshes().length;
|
|
279
|
-
let totalIdx = 0;
|
|
280
|
-
for (const b of r.getScene().getBatchedMeshes()) totalIdx += b.indexCount;
|
|
281
|
-
console.log(`[GeomStream] finalizeStreamingAsync complete: ${(performance.now() - t0).toFixed(0)}ms → ${batchCount} consolidated batches, ${(totalIdx / 3 / 1e6).toFixed(1)}M triangles`);
|
|
330
|
+
// Time-sliced finalize: rebuild proper batches in ~8ms chunks
|
|
331
|
+
if (releaseGeometryAfterFinalize) {
|
|
332
|
+
r.getScene().finishEphemeralStreaming();
|
|
333
|
+
onGeometryReleased?.();
|
|
282
334
|
r.clearCaches();
|
|
283
335
|
r.requestRender();
|
|
284
|
-
|
|
336
|
+
traceGeometrySync(`ephemeral finalize complete batches=${r.getScene().getBatchedMeshes().length}`);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const dev = r.getGPUDevice();
|
|
341
|
+
const pipe = r.getPipeline();
|
|
342
|
+
if (dev && pipe) {
|
|
343
|
+
const t0 = performance.now();
|
|
344
|
+
r.getScene().finalizeStreamingAsync(dev, pipe).then(() => {
|
|
345
|
+
const batchCount = r.getScene().getBatchedMeshes().length;
|
|
346
|
+
let totalIdx = 0;
|
|
347
|
+
for (const b of r.getScene().getBatchedMeshes()) totalIdx += b.indexCount;
|
|
348
|
+
console.log(`[GeomStream] finalizeStreamingAsync complete: ${(performance.now() - t0).toFixed(0)}ms → ${batchCount} consolidated batches, ${(totalIdx / 3 / 1e6).toFixed(1)}M triangles`);
|
|
349
|
+
traceGeometrySync(
|
|
350
|
+
`finalize complete elapsed=${(performance.now() - t0).toFixed(0)}ms batches=${batchCount} queued=${r.getScene().hasQueuedMeshes()}`
|
|
351
|
+
);
|
|
352
|
+
r.clearCaches();
|
|
353
|
+
r.requestRender();
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}, 0);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const waitForQueueDrain = () => {
|
|
360
|
+
const currentRenderer = rendererRef.current;
|
|
361
|
+
if (!currentRenderer) return;
|
|
362
|
+
if (!currentRenderer.getScene().hasQueuedMeshes()) {
|
|
363
|
+
startFinalize();
|
|
364
|
+
return;
|
|
285
365
|
}
|
|
286
|
-
|
|
366
|
+
currentRenderer.requestRender();
|
|
367
|
+
rafId = requestAnimationFrame(waitForQueueDrain);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
waitForQueueDrain();
|
|
287
371
|
|
|
288
372
|
prevIsStreamingRef.current = isStreaming;
|
|
289
|
-
return () =>
|
|
373
|
+
return () => {
|
|
374
|
+
if (timeoutId !== null) globalThis.clearTimeout(timeoutId);
|
|
375
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
376
|
+
};
|
|
290
377
|
}
|
|
291
378
|
prevIsStreamingRef.current = isStreaming;
|
|
292
|
-
}, [isStreaming, isInitialized]);
|
|
379
|
+
}, [isStreaming, isInitialized, releaseGeometryAfterFinalize, onGeometryReleased]);
|
|
293
380
|
|
|
294
381
|
// ─── Mesh color updates (style/material deferred colors) ─────────────
|
|
295
382
|
useEffect(() => {
|