@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
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
export interface DesktopPreferences {
|
|
6
|
+
reopenLastModelOnLaunch: boolean;
|
|
7
|
+
restoreWorkspaceLayoutOnLaunch: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const STORAGE_KEY = 'ifc-lite:desktop-preferences:v1';
|
|
11
|
+
const CHANGED_EVENT = 'ifc-lite:desktop-preferences-changed';
|
|
12
|
+
|
|
13
|
+
const DEFAULT_PREFERENCES: DesktopPreferences = {
|
|
14
|
+
reopenLastModelOnLaunch: true,
|
|
15
|
+
restoreWorkspaceLayoutOnLaunch: true,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function sanitizePreferences(value: unknown): DesktopPreferences {
|
|
19
|
+
const parsed = (value && typeof value === 'object') ? value as Partial<DesktopPreferences> : {};
|
|
20
|
+
return {
|
|
21
|
+
reopenLastModelOnLaunch: parsed.reopenLastModelOnLaunch ?? DEFAULT_PREFERENCES.reopenLastModelOnLaunch,
|
|
22
|
+
restoreWorkspaceLayoutOnLaunch: parsed.restoreWorkspaceLayoutOnLaunch ?? DEFAULT_PREFERENCES.restoreWorkspaceLayoutOnLaunch,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getDesktopPreferences(): DesktopPreferences {
|
|
27
|
+
try {
|
|
28
|
+
return sanitizePreferences(JSON.parse(localStorage.getItem(STORAGE_KEY) ?? '{}'));
|
|
29
|
+
} catch {
|
|
30
|
+
return { ...DEFAULT_PREFERENCES };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function updateDesktopPreferences(updates: Partial<DesktopPreferences>): DesktopPreferences {
|
|
35
|
+
const next = { ...getDesktopPreferences(), ...updates };
|
|
36
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
|
|
37
|
+
window.dispatchEvent(new Event(CHANGED_EVENT));
|
|
38
|
+
return next;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function subscribeDesktopPreferences(listener: () => void): () => void {
|
|
42
|
+
window.addEventListener(CHANGED_EVENT, listener);
|
|
43
|
+
return () => window.removeEventListener(CHANGED_EVENT, listener);
|
|
44
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
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
|
+
type InvokeFn = <T>(cmd: string, args?: Record<string, unknown>) => Promise<T>;
|
|
6
|
+
|
|
7
|
+
export interface NativeFileHandle {
|
|
8
|
+
path: string;
|
|
9
|
+
name: string;
|
|
10
|
+
size: number;
|
|
11
|
+
modifiedMs?: number | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface GenericFileDialogOptions {
|
|
15
|
+
title?: string;
|
|
16
|
+
filters?: Array<{ name: string; extensions: string[] }>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function loadInvokeFromTauriModule(): Promise<InvokeFn | null> {
|
|
20
|
+
try {
|
|
21
|
+
const core = await import('@tauri-apps/api/core');
|
|
22
|
+
return typeof core.invoke === 'function' ? core.invoke as InvokeFn : null;
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function loadDialogModule(): Promise<{
|
|
29
|
+
open: (options?: {
|
|
30
|
+
multiple?: boolean;
|
|
31
|
+
directory?: boolean;
|
|
32
|
+
filters?: Array<{ name: string; extensions: string[] }>;
|
|
33
|
+
title?: string;
|
|
34
|
+
}) => Promise<string | string[] | null>;
|
|
35
|
+
} | null> {
|
|
36
|
+
try {
|
|
37
|
+
return await import('@tauri-apps/plugin-dialog');
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function loadFsModule(): Promise<{
|
|
44
|
+
stat: (path: string) => Promise<{ size: number }>;
|
|
45
|
+
} | null> {
|
|
46
|
+
try {
|
|
47
|
+
return await import('@tauri-apps/plugin-fs');
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function getInvoke(): Promise<InvokeFn> {
|
|
54
|
+
const win = globalThis as unknown as { __TAURI_INTERNALS__?: { invoke: InvokeFn } };
|
|
55
|
+
if (win.__TAURI_INTERNALS__?.invoke) {
|
|
56
|
+
return win.__TAURI_INTERNALS__.invoke;
|
|
57
|
+
}
|
|
58
|
+
const moduleInvoke = await loadInvokeFromTauriModule();
|
|
59
|
+
if (moduleInvoke) {
|
|
60
|
+
return moduleInvoke;
|
|
61
|
+
}
|
|
62
|
+
throw new Error('Tauri API not available');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function openIfcFileDialog(): Promise<NativeFileHandle | null> {
|
|
66
|
+
try {
|
|
67
|
+
const invoke = await getInvoke();
|
|
68
|
+
return await invoke<NativeFileHandle | null>('open_ifc_file');
|
|
69
|
+
} catch {
|
|
70
|
+
// Expected in browser builds — fall through to plugin fallback, then browser file input.
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const dialog = await loadDialogModule();
|
|
75
|
+
const fs = await loadFsModule();
|
|
76
|
+
if (!dialog || !fs) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const selected = await dialog.open({
|
|
81
|
+
multiple: false,
|
|
82
|
+
directory: false,
|
|
83
|
+
title: 'Open IFC File',
|
|
84
|
+
filters: [
|
|
85
|
+
{ name: 'IFC Files', extensions: ['ifc', 'ifczip', 'ifcxml'] },
|
|
86
|
+
{ name: 'All Files', extensions: ['*'] },
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
if (!selected || Array.isArray(selected)) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const metadata = await fs.stat(selected);
|
|
94
|
+
const normalizedPath = selected.toString();
|
|
95
|
+
const pathSegments = normalizedPath.split(/[\\/]/);
|
|
96
|
+
const name = pathSegments[pathSegments.length - 1] || 'unknown.ifc';
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
path: normalizedPath,
|
|
100
|
+
name,
|
|
101
|
+
size: metadata.size,
|
|
102
|
+
};
|
|
103
|
+
} catch {
|
|
104
|
+
// No Tauri plugin available — caller falls back to browser <input type="file">.
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export async function readNativeFile(path: string): Promise<Uint8Array> {
|
|
110
|
+
try {
|
|
111
|
+
const invoke = await getInvoke();
|
|
112
|
+
const bytes = await invoke<number[]>('read_native_file', { path });
|
|
113
|
+
return Uint8Array.from(bytes);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.warn('[FileDialog] Falling back to plugin-fs read for native file:', error);
|
|
116
|
+
const fs = await import('@tauri-apps/plugin-fs');
|
|
117
|
+
return fs.readFile(path);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function openGenericFileDialog(options: GenericFileDialogOptions = {}): Promise<File | null> {
|
|
122
|
+
try {
|
|
123
|
+
const dialog = await loadDialogModule();
|
|
124
|
+
if (!dialog) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const selected = await dialog.open({
|
|
129
|
+
multiple: false,
|
|
130
|
+
directory: false,
|
|
131
|
+
title: options.title,
|
|
132
|
+
filters: options.filters,
|
|
133
|
+
});
|
|
134
|
+
if (!selected || Array.isArray(selected)) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const normalizedPath = selected.toString();
|
|
139
|
+
const bytes = await readNativeFile(normalizedPath);
|
|
140
|
+
const pathSegments = normalizedPath.split(/[\\/]/);
|
|
141
|
+
const name = pathSegments[pathSegments.length - 1] || 'document';
|
|
142
|
+
return new File([bytes], name, { type: 'application/octet-stream' });
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.warn('[FileDialog] Failed to open generic native file dialog:', error);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
export async function invoke(): Promise<never> {
|
|
6
|
+
throw new Error('Tauri core API is unavailable in the browser build');
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
export async function open(): Promise<null> {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
export async function readFile(_path: string): Promise<Uint8Array> {
|
|
6
|
+
throw new Error('Tauri file system API is unavailable in the browser benchmark build');
|
|
7
|
+
}
|
package/src/store/index.ts
CHANGED
|
@@ -32,6 +32,8 @@ import { createPinboardSlice, type PinboardSlice } from './slices/pinboardSlice.
|
|
|
32
32
|
import { createLensSlice, type LensSlice } from './slices/lensSlice.js';
|
|
33
33
|
import { createScriptSlice, type ScriptSlice } from './slices/scriptSlice.js';
|
|
34
34
|
import { createChatSlice, type ChatSlice } from './slices/chatSlice.js';
|
|
35
|
+
import { createCesiumSlice, type CesiumSlice } from './slices/cesiumSlice.js';
|
|
36
|
+
import { createDesktopEntitlementSlice, type DesktopEntitlementSlice } from './slices/desktopEntitlementSlice.js';
|
|
35
37
|
import { invalidateVisibleBasketCache } from './basketVisibleSet.js';
|
|
36
38
|
|
|
37
39
|
// Import constants for reset function
|
|
@@ -76,6 +78,10 @@ export type { ScriptSlice } from './slices/scriptSlice.js';
|
|
|
76
78
|
|
|
77
79
|
// Re-export Chat types
|
|
78
80
|
export type { ChatSlice } from './slices/chatSlice.js';
|
|
81
|
+
export type { DesktopEntitlementSlice } from './slices/desktopEntitlementSlice.js';
|
|
82
|
+
|
|
83
|
+
// Re-export Cesium types
|
|
84
|
+
export type { CesiumSlice, CesiumDataSource } from './slices/cesiumSlice.js';
|
|
79
85
|
|
|
80
86
|
// Combined store type
|
|
81
87
|
export type ViewerState = LoadingSlice &
|
|
@@ -97,14 +103,16 @@ export type ViewerState = LoadingSlice &
|
|
|
97
103
|
PinboardSlice &
|
|
98
104
|
LensSlice &
|
|
99
105
|
ScriptSlice &
|
|
100
|
-
ChatSlice &
|
|
106
|
+
ChatSlice &
|
|
107
|
+
CesiumSlice &
|
|
108
|
+
DesktopEntitlementSlice & {
|
|
101
109
|
resetViewerState: () => void;
|
|
102
110
|
};
|
|
103
111
|
|
|
104
112
|
/**
|
|
105
113
|
* Main viewer store combining all slices
|
|
106
114
|
*/
|
|
107
|
-
|
|
115
|
+
const createViewerStore = () => create<ViewerState>()((...args) => ({
|
|
108
116
|
// Spread all slices
|
|
109
117
|
...createLoadingSlice(...args),
|
|
110
118
|
...createSelectionSlice(...args),
|
|
@@ -126,6 +134,8 @@ export const useViewerStore = create<ViewerState>()((...args) => ({
|
|
|
126
134
|
...createLensSlice(...args),
|
|
127
135
|
...createScriptSlice(...args),
|
|
128
136
|
...createChatSlice(...args),
|
|
137
|
+
...createCesiumSlice(...args),
|
|
138
|
+
...createDesktopEntitlementSlice(...args),
|
|
129
139
|
|
|
130
140
|
// Reset all viewer state when loading new file
|
|
131
141
|
// Note: Does NOT clear models - use clearAllModels() for that
|
|
@@ -157,6 +167,13 @@ export const useViewerStore = create<ViewerState>()((...args) => ({
|
|
|
157
167
|
isolatedEntitiesByModel: new Map(),
|
|
158
168
|
|
|
159
169
|
// Data
|
|
170
|
+
loading: false,
|
|
171
|
+
geometryStreamingActive: false,
|
|
172
|
+
geometryUpdateTick: 0,
|
|
173
|
+
progress: null,
|
|
174
|
+
geometryProgress: null,
|
|
175
|
+
metadataProgress: null,
|
|
176
|
+
error: null,
|
|
160
177
|
pendingColorUpdates: null,
|
|
161
178
|
pendingMeshColorUpdates: null,
|
|
162
179
|
|
|
@@ -206,6 +223,14 @@ export const useViewerStore = create<ViewerState>()((...args) => ({
|
|
|
206
223
|
separationLinesIntensity: UI_DEFAULTS.SEPARATION_LINES_INTENSITY,
|
|
207
224
|
separationLinesRadius: UI_DEFAULTS.SEPARATION_LINES_RADIUS,
|
|
208
225
|
|
|
226
|
+
// Cesium
|
|
227
|
+
cesiumEnabled: false,
|
|
228
|
+
cesiumTerrainHeight: null,
|
|
229
|
+
cesiumTerrainClamp: false,
|
|
230
|
+
cesiumSourceModelId: null,
|
|
231
|
+
cesiumTerrainClipY: null,
|
|
232
|
+
cesiumGlbLoaded: false,
|
|
233
|
+
|
|
209
234
|
// Drawing 2D
|
|
210
235
|
drawing2D: null,
|
|
211
236
|
drawing2DStatus: 'idle' as const,
|
|
@@ -317,3 +342,16 @@ export const useViewerStore = create<ViewerState>()((...args) => ({
|
|
|
317
342
|
});
|
|
318
343
|
},
|
|
319
344
|
}));
|
|
345
|
+
|
|
346
|
+
const STORE_SINGLETON_KEY = '__ifc_lite_viewer_store__';
|
|
347
|
+
const globalStoreRegistry = globalThis as typeof globalThis & {
|
|
348
|
+
[STORE_SINGLETON_KEY]?: ReturnType<typeof createViewerStore>;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
export function getViewerStoreApi() {
|
|
352
|
+
return globalStoreRegistry[STORE_SINGLETON_KEY] ?? (
|
|
353
|
+
globalStoreRegistry[STORE_SINGLETON_KEY] = createViewerStore()
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export const useViewerStore = getViewerStoreApi();
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
* Cesium 3D Tiles overlay state slice.
|
|
7
|
+
*
|
|
8
|
+
* Manages the enabled/disabled state, selected data source, and Cesium ion
|
|
9
|
+
* access token for the optional real-world 3D context overlay.
|
|
10
|
+
*
|
|
11
|
+
* Token resolution:
|
|
12
|
+
* 1. User-provided override in localStorage
|
|
13
|
+
* 2. Build-time default token via VITE_CESIUM_ION_TOKEN env var
|
|
14
|
+
* → Users never need to configure anything; the app ships with a working token.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { StateCreator } from 'zustand';
|
|
18
|
+
|
|
19
|
+
export type CesiumDataSource =
|
|
20
|
+
| 'osm-buildings' // Cesium OSM Buildings (free via Cesium ion)
|
|
21
|
+
| 'bing-aerial' // Bing Maps aerial imagery draped on terrain
|
|
22
|
+
| 'google-photorealistic'; // Google Photorealistic 3D Tiles (requires API key)
|
|
23
|
+
|
|
24
|
+
export interface CesiumSlice {
|
|
25
|
+
// State
|
|
26
|
+
cesiumEnabled: boolean;
|
|
27
|
+
cesiumDataSource: CesiumDataSource;
|
|
28
|
+
/** Resolved Cesium ion access token (user override or build-time default). */
|
|
29
|
+
cesiumIonToken: string;
|
|
30
|
+
/** Terrain enabled (Cesium World Terrain). */
|
|
31
|
+
cesiumTerrainEnabled: boolean;
|
|
32
|
+
/** Clamp model to terrain height at its geodetic position. */
|
|
33
|
+
cesiumTerrainClamp: boolean;
|
|
34
|
+
/** Terrain height at model position (queried from Cesium, meters). null = not yet queried. */
|
|
35
|
+
cesiumTerrainHeight: number | null;
|
|
36
|
+
/** Model ID that the Cesium overlay is currently displaying. */
|
|
37
|
+
cesiumSourceModelId: string | null;
|
|
38
|
+
/** Terrain clip Y position in viewer space. When set, fragments below this Y are discarded. */
|
|
39
|
+
cesiumTerrainClipY: number | null;
|
|
40
|
+
/** Whether the GLB model has been loaded into Cesium (hides WebGPU overlay). */
|
|
41
|
+
cesiumGlbLoaded: boolean;
|
|
42
|
+
|
|
43
|
+
// Actions
|
|
44
|
+
setCesiumEnabled: (enabled: boolean) => void;
|
|
45
|
+
toggleCesium: () => void;
|
|
46
|
+
setCesiumDataSource: (source: CesiumDataSource) => void;
|
|
47
|
+
setCesiumIonToken: (token: string) => void;
|
|
48
|
+
setCesiumTerrainEnabled: (enabled: boolean) => void;
|
|
49
|
+
setCesiumTerrainClamp: (clamp: boolean) => void;
|
|
50
|
+
setCesiumTerrainHeight: (height: number | null) => void;
|
|
51
|
+
setCesiumSourceModelId: (modelId: string | null) => void;
|
|
52
|
+
setCesiumTerrainClipY: (y: number | null) => void;
|
|
53
|
+
setCesiumGlbLoaded: (loaded: boolean) => void;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const STORAGE_KEY_ION_TOKEN = 'ifc-lite:cesium-ion-token';
|
|
57
|
+
const STORAGE_KEY_DATA_SOURCE = 'ifc-lite:cesium-data-source';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Default Cesium ion token provided at build time.
|
|
61
|
+
* Set via VITE_CESIUM_ION_TOKEN in .env or CI environment.
|
|
62
|
+
* This means users never need to configure a token manually.
|
|
63
|
+
*/
|
|
64
|
+
const DEFAULT_ION_TOKEN: string = (import.meta as any).env?.VITE_CESIUM_ION_TOKEN ?? '';
|
|
65
|
+
|
|
66
|
+
function loadFromStorage(key: string, fallback: string): string {
|
|
67
|
+
try {
|
|
68
|
+
return localStorage.getItem(key) ?? fallback;
|
|
69
|
+
} catch {
|
|
70
|
+
return fallback;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function saveToStorage(key: string, value: string): void {
|
|
75
|
+
try {
|
|
76
|
+
localStorage.setItem(key, value);
|
|
77
|
+
} catch { /* storage unavailable */ }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const VALID_DATA_SOURCES = new Set<CesiumDataSource>(['osm-buildings', 'bing-aerial', 'google-photorealistic']);
|
|
81
|
+
|
|
82
|
+
function loadDataSource(): CesiumDataSource {
|
|
83
|
+
const stored = loadFromStorage(STORAGE_KEY_DATA_SOURCE, '');
|
|
84
|
+
return VALID_DATA_SOURCES.has(stored as CesiumDataSource)
|
|
85
|
+
? (stored as CesiumDataSource)
|
|
86
|
+
: 'google-photorealistic';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Resolve the Cesium ion token: user override > build-time default */
|
|
90
|
+
function resolveIonToken(): string {
|
|
91
|
+
const userToken = loadFromStorage(STORAGE_KEY_ION_TOKEN, '');
|
|
92
|
+
return userToken || DEFAULT_ION_TOKEN;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const createCesiumSlice: StateCreator<CesiumSlice, [], [], CesiumSlice> = (set) => ({
|
|
96
|
+
cesiumEnabled: false,
|
|
97
|
+
cesiumDataSource: loadDataSource(),
|
|
98
|
+
cesiumIonToken: resolveIonToken(),
|
|
99
|
+
cesiumTerrainEnabled: true,
|
|
100
|
+
cesiumTerrainClamp: false,
|
|
101
|
+
cesiumTerrainHeight: null,
|
|
102
|
+
cesiumSourceModelId: null,
|
|
103
|
+
cesiumTerrainClipY: null,
|
|
104
|
+
cesiumGlbLoaded: false,
|
|
105
|
+
|
|
106
|
+
setCesiumEnabled: (enabled) => set({ cesiumEnabled: enabled }),
|
|
107
|
+
toggleCesium: () => set((s) => ({ cesiumEnabled: !s.cesiumEnabled })),
|
|
108
|
+
setCesiumDataSource: (source) => {
|
|
109
|
+
saveToStorage(STORAGE_KEY_DATA_SOURCE, source);
|
|
110
|
+
set({ cesiumDataSource: source });
|
|
111
|
+
},
|
|
112
|
+
setCesiumIonToken: (token) => {
|
|
113
|
+
saveToStorage(STORAGE_KEY_ION_TOKEN, token);
|
|
114
|
+
set({ cesiumIonToken: token || DEFAULT_ION_TOKEN });
|
|
115
|
+
},
|
|
116
|
+
setCesiumTerrainEnabled: (enabled) => set({ cesiumTerrainEnabled: enabled }),
|
|
117
|
+
setCesiumTerrainClamp: (clamp) => set({ cesiumTerrainClamp: clamp }),
|
|
118
|
+
setCesiumTerrainHeight: (height) => set({ cesiumTerrainHeight: height }),
|
|
119
|
+
setCesiumSourceModelId: (modelId) => set({ cesiumSourceModelId: modelId }),
|
|
120
|
+
setCesiumTerrainClipY: (y) => set({ cesiumTerrainClipY: y }),
|
|
121
|
+
setCesiumGlbLoaded: (loaded) => set({ cesiumGlbLoaded: loaded }),
|
|
122
|
+
});
|
|
@@ -177,6 +177,10 @@ function loadStoredModel(userId: string | null, fallback?: string): string {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
function loadValidStoredModel(userId: string | null, hasPro: boolean, fallback?: string): string {
|
|
181
|
+
return coerceModelForEntitlement(loadStoredModel(userId, fallback), hasPro);
|
|
182
|
+
}
|
|
183
|
+
|
|
180
184
|
function loadStoredAutoExecute(): boolean {
|
|
181
185
|
try {
|
|
182
186
|
const val = localStorage.getItem(AUTO_EXEC_STORAGE_KEY);
|
|
@@ -275,7 +279,7 @@ export const createChatSlice: StateCreator<ChatSlice, [], [], ChatSlice> = (set,
|
|
|
275
279
|
chatMessages: loadStoredMessages(null),
|
|
276
280
|
chatStatus: 'idle',
|
|
277
281
|
chatStreamingContent: '',
|
|
278
|
-
chatActiveModel:
|
|
282
|
+
chatActiveModel: loadValidStoredModel(null, false),
|
|
279
283
|
chatAutoExecute: loadStoredAutoExecute(),
|
|
280
284
|
chatError: null,
|
|
281
285
|
chatAbortController: null,
|
|
@@ -9,12 +9,28 @@
|
|
|
9
9
|
import type { StateCreator } from 'zustand';
|
|
10
10
|
import type { IfcDataStore } from '@ifc-lite/parser';
|
|
11
11
|
import type { GeometryResult, CoordinateInfo } from '@ifc-lite/geometry';
|
|
12
|
+
import type { FederatedModel } from '../types.js';
|
|
12
13
|
import { DATA_DEFAULTS } from '../constants.js';
|
|
13
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Cross-slice state that dataSlice reads/writes via the combined store.
|
|
17
|
+
*
|
|
18
|
+
* Data updaters sync `ifcDataStore` / `geometryResult` into the per-model
|
|
19
|
+
* entry inside the ModelSlice `models` map so that federation stays
|
|
20
|
+
* consistent. The types below describe the minimal ModelSlice surface
|
|
21
|
+
* that dataSlice accesses through the merged Zustand state.
|
|
22
|
+
*/
|
|
23
|
+
interface DataCrossSliceState {
|
|
24
|
+
activeModelId: string | null;
|
|
25
|
+
models: Map<string, FederatedModel>;
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
export interface DataSlice {
|
|
15
29
|
// State
|
|
16
30
|
ifcDataStore: IfcDataStore | null;
|
|
17
31
|
geometryResult: GeometryResult | null;
|
|
32
|
+
geometryUpdateTick: number;
|
|
33
|
+
boundedGeometryMode: boolean;
|
|
18
34
|
/** Transient overlay colors (lens/IDS/sdk overlays). */
|
|
19
35
|
pendingColorUpdates: Map<number, [number, number, number, number]> | null;
|
|
20
36
|
/** Persistent mesh color updates (IFC deferred style/material colors). */
|
|
@@ -23,7 +39,9 @@ export interface DataSlice {
|
|
|
23
39
|
// Actions
|
|
24
40
|
setIfcDataStore: (result: IfcDataStore | null) => void;
|
|
25
41
|
setGeometryResult: (result: GeometryResult | null) => void;
|
|
42
|
+
setBoundedGeometryMode: (enabled: boolean) => void;
|
|
26
43
|
appendGeometryBatch: (meshes: GeometryResult['meshes'], coordinateInfo?: CoordinateInfo) => void;
|
|
44
|
+
releaseGeometryMemory: () => void;
|
|
27
45
|
/** Persist mesh color changes in geometryResult (used for IFC style/material updates). */
|
|
28
46
|
updateMeshColors: (updates: Map<number, [number, number, number, number]>) => void;
|
|
29
47
|
/** Set pending color updates for the renderer without cloning mesh data.
|
|
@@ -49,17 +67,53 @@ const getDefaultCoordinateInfo = (): CoordinateInfo => ({
|
|
|
49
67
|
hasLargeCoordinates: DATA_DEFAULTS.HAS_LARGE_COORDINATES,
|
|
50
68
|
});
|
|
51
69
|
|
|
52
|
-
|
|
70
|
+
const EMPTY_POSITIONS = new Float32Array(0);
|
|
71
|
+
const EMPTY_NORMALS = new Float32Array(0);
|
|
72
|
+
const EMPTY_INDICES = new Uint32Array(0);
|
|
73
|
+
|
|
74
|
+
export const createDataSlice: StateCreator<DataSlice & DataCrossSliceState, [], [], DataSlice> = (set, get) => ({
|
|
53
75
|
// Initial state
|
|
54
76
|
ifcDataStore: null,
|
|
55
77
|
geometryResult: null,
|
|
78
|
+
geometryUpdateTick: 0,
|
|
79
|
+
boundedGeometryMode: false,
|
|
56
80
|
pendingColorUpdates: null,
|
|
57
81
|
pendingMeshColorUpdates: null,
|
|
58
82
|
|
|
59
83
|
// Actions
|
|
60
|
-
setIfcDataStore: (ifcDataStore) => set(
|
|
84
|
+
setIfcDataStore: (ifcDataStore) => set((state) => {
|
|
85
|
+
const modelId = state.activeModelId;
|
|
86
|
+
if (!modelId) {
|
|
87
|
+
return { ifcDataStore };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const model = state.models.get(modelId);
|
|
91
|
+
if (!model) {
|
|
92
|
+
return { ifcDataStore };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const models = new Map(state.models);
|
|
96
|
+
models.set(modelId, { ...model, ifcDataStore });
|
|
97
|
+
return { ifcDataStore, models };
|
|
98
|
+
}),
|
|
61
99
|
|
|
62
|
-
setGeometryResult: (geometryResult) => set(
|
|
100
|
+
setGeometryResult: (geometryResult) => set((state) => {
|
|
101
|
+
const modelId = state.activeModelId;
|
|
102
|
+
if (!modelId) {
|
|
103
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const model = state.models.get(modelId);
|
|
107
|
+
if (!model) {
|
|
108
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const models = new Map(state.models);
|
|
112
|
+
models.set(modelId, { ...model, geometryResult });
|
|
113
|
+
return { geometryResult, models, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
114
|
+
}),
|
|
115
|
+
|
|
116
|
+
setBoundedGeometryMode: (boundedGeometryMode) => set({ boundedGeometryMode }),
|
|
63
117
|
|
|
64
118
|
appendGeometryBatch: (meshes, coordinateInfo) => set((state) => {
|
|
65
119
|
// Incremental totals: O(batch_size) instead of O(total_accumulated) .reduce()
|
|
@@ -71,33 +125,81 @@ export const createDataSlice: StateCreator<DataSlice, [], [], DataSlice> = (set)
|
|
|
71
125
|
}
|
|
72
126
|
|
|
73
127
|
if (!state.geometryResult) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
coordinateInfo: coordinateInfo || getDefaultCoordinateInfo(),
|
|
80
|
-
},
|
|
128
|
+
const geometryResult = {
|
|
129
|
+
meshes: meshes.slice(),
|
|
130
|
+
totalTriangles: batchTriangles,
|
|
131
|
+
totalVertices: batchVertices,
|
|
132
|
+
coordinateInfo: coordinateInfo || getDefaultCoordinateInfo(),
|
|
81
133
|
};
|
|
134
|
+
const modelId = state.activeModelId;
|
|
135
|
+
if (!modelId) {
|
|
136
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
137
|
+
}
|
|
138
|
+
const model = state.models.get(modelId);
|
|
139
|
+
if (!model) {
|
|
140
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
141
|
+
}
|
|
142
|
+
const models = new Map(state.models);
|
|
143
|
+
models.set(modelId, { ...model, geometryResult });
|
|
144
|
+
return { geometryResult, models, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
82
145
|
}
|
|
83
146
|
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
// Zustand
|
|
88
|
-
const
|
|
147
|
+
// Mutate the existing array in-place (O(batch) per append) instead of
|
|
148
|
+
// .concat() (O(total) per append) to avoid O(N²) for large files.
|
|
149
|
+
// The new geometryResult object reference below is sufficient for
|
|
150
|
+
// Zustand/React change detection — array identity doesn't need to change.
|
|
151
|
+
const existingMeshes = state.geometryResult.meshes;
|
|
89
152
|
for (let i = 0; i < meshes.length; i++) {
|
|
90
|
-
|
|
153
|
+
existingMeshes.push(meshes[i]);
|
|
91
154
|
}
|
|
92
155
|
|
|
93
|
-
|
|
94
|
-
geometryResult
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
156
|
+
const geometryResult = {
|
|
157
|
+
...state.geometryResult,
|
|
158
|
+
meshes: existingMeshes,
|
|
159
|
+
totalTriangles: state.geometryResult.totalTriangles + batchTriangles,
|
|
160
|
+
totalVertices: state.geometryResult.totalVertices + batchVertices,
|
|
161
|
+
coordinateInfo: coordinateInfo || state.geometryResult.coordinateInfo,
|
|
162
|
+
};
|
|
163
|
+
const modelId = state.activeModelId;
|
|
164
|
+
if (!modelId) {
|
|
165
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
166
|
+
}
|
|
167
|
+
const model = state.models.get(modelId);
|
|
168
|
+
if (!model) {
|
|
169
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
170
|
+
}
|
|
171
|
+
const models = new Map(state.models);
|
|
172
|
+
models.set(modelId, { ...model, geometryResult });
|
|
173
|
+
return { geometryResult, models, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
174
|
+
}),
|
|
175
|
+
|
|
176
|
+
releaseGeometryMemory: () => set((state) => {
|
|
177
|
+
if (!state.geometryResult || !state.boundedGeometryMode) {
|
|
178
|
+
return {};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const meshes = state.geometryResult.meshes;
|
|
182
|
+
for (let i = 0; i < meshes.length; i++) {
|
|
183
|
+
meshes[i].positions = EMPTY_POSITIONS;
|
|
184
|
+
meshes[i].normals = EMPTY_NORMALS;
|
|
185
|
+
meshes[i].indices = EMPTY_INDICES;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const geometryResult = {
|
|
189
|
+
...state.geometryResult,
|
|
190
|
+
meshes,
|
|
100
191
|
};
|
|
192
|
+
const modelId = state.activeModelId;
|
|
193
|
+
if (!modelId) {
|
|
194
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
195
|
+
}
|
|
196
|
+
const model = state.models.get(modelId);
|
|
197
|
+
if (!model) {
|
|
198
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
199
|
+
}
|
|
200
|
+
const models = new Map(state.models);
|
|
201
|
+
models.set(modelId, { ...model, geometryResult });
|
|
202
|
+
return { geometryResult, models, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
101
203
|
}),
|
|
102
204
|
|
|
103
205
|
updateMeshColors: (updates) => set((state) => {
|
|
@@ -136,11 +238,20 @@ export const createDataSlice: StateCreator<DataSlice, [], [], DataSlice> = (set)
|
|
|
136
238
|
|
|
137
239
|
updateCoordinateInfo: (coordinateInfo) => set((state) => {
|
|
138
240
|
if (!state.geometryResult) return {};
|
|
139
|
-
|
|
140
|
-
geometryResult
|
|
141
|
-
|
|
142
|
-
coordinateInfo,
|
|
143
|
-
},
|
|
241
|
+
const geometryResult = {
|
|
242
|
+
...state.geometryResult,
|
|
243
|
+
coordinateInfo,
|
|
144
244
|
};
|
|
245
|
+
const modelId = state.activeModelId;
|
|
246
|
+
if (!modelId) {
|
|
247
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
248
|
+
}
|
|
249
|
+
const model = state.models.get(modelId);
|
|
250
|
+
if (!model) {
|
|
251
|
+
return { geometryResult, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
252
|
+
}
|
|
253
|
+
const models = new Map(state.models);
|
|
254
|
+
models.set(modelId, { ...model, geometryResult });
|
|
255
|
+
return { geometryResult, models, geometryUpdateTick: state.geometryUpdateTick + 1 };
|
|
145
256
|
}),
|
|
146
257
|
});
|