@mapvx/web-js 3.4.0-dev.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/umd/index.js CHANGED
@@ -43,6 +43,14 @@ module.exports = require("three");
43
43
 
44
44
  /***/ },
45
45
 
46
+ /***/ 502
47
+ (module) {
48
+
49
+ "use strict";
50
+ module.exports = require("three/addons/libs/meshopt_decoder.module.js");
51
+
52
+ /***/ },
53
+
46
54
  /***/ 303
47
55
  (module) {
48
56
 
@@ -11240,7 +11248,7 @@ const extractSafariExtensionDetails = (func, filename) => {
11240
11248
  // exists only for the type-checker, so in the ES/CJS builds the identifier is
11241
11249
  // genuinely absent and a direct comparison throws ReferenceError at module load.
11242
11250
  // `typeof` is the only safe way to probe a possibly-undeclared global.
11243
- var sentry_SDK_VERSION = false ? 0 : "3.4.0-dev.1";
11251
+ var sentry_SDK_VERSION = false ? 0 : "3.4.0";
11244
11252
  var DSN = false ? 0 : "https://872f598f020e3cd73a0933b562d24c81@sentry.mapvx.app/5";
11245
11253
 
11246
11254
  /**
@@ -18654,6 +18662,89 @@ function _3d_unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof
18654
18662
  function _3d_iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
18655
18663
  function _3d_arrayWithoutHoles(r) { if (Array.isArray(r)) return _3d_arrayLikeToArray(r); }
18656
18664
  function _3d_arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
18665
+ /** Default LOD hysteresis (zoom units) when {@link Models3DLodConfig.hysteresis} is unset. */
18666
+ var DEFAULT_LOD_HYSTERESIS = 0.5;
18667
+
18668
+ /**
18669
+ * Resolved LOD zoom boundaries: models unload strictly below `unloadBelow` and (re)load at or
18670
+ * above `reloadAtOrAbove`. The gap between them is the hysteresis dead-band.
18671
+ * @internal
18672
+ */
18673
+
18674
+ /**
18675
+ * Computes the unload/reload zoom boundaries from {@link Models3DConfig.lod}, or `null` when LOD is
18676
+ * disabled (no `lod`, no models, or a non-finite `minZoom`). Pure — safe to unit-test without WebGL.
18677
+ */
18678
+ var resolveModels3DLodThresholds = function resolveModels3DLodThresholds(models) {
18679
+ var lod = models === null || models === void 0 ? void 0 : models.lod;
18680
+ if (!models || models.enabled === false || !lod || typeof lod.minZoom !== "number" || !Number.isFinite(lod.minZoom)) {
18681
+ return null;
18682
+ }
18683
+ var hysteresis = typeof lod.hysteresis === "number" && Number.isFinite(lod.hysteresis) && lod.hysteresis >= 0 ? lod.hysteresis : DEFAULT_LOD_HYSTERESIS;
18684
+ return {
18685
+ reloadAtOrAbove: lod.minZoom,
18686
+ unloadBelow: lod.minZoom - hysteresis
18687
+ };
18688
+ };
18689
+
18690
+ /**
18691
+ * Decides what the LOD controller should do at the current zoom given whether the models are
18692
+ * currently unloaded. Returns `"unload"` when they are loaded but the camera is below the unload
18693
+ * boundary, `"reload"` when they are unloaded but the camera has returned to/above the reload
18694
+ * boundary, and `"none"` otherwise (including within the hysteresis band). Pure/testable.
18695
+ */
18696
+ var lodActionForZoom = function lodActionForZoom(zoom, thresholds, currentlyUnloaded) {
18697
+ if (!currentlyUnloaded && zoom < thresholds.unloadBelow) {
18698
+ return "unload";
18699
+ }
18700
+ if (currentlyUnloaded && zoom >= thresholds.reloadAtOrAbove) {
18701
+ return "reload";
18702
+ }
18703
+ return "none";
18704
+ };
18705
+
18706
+ /**
18707
+ * Resolved deck.gl tile-cache props: every field concrete, ready to spread onto an `MVTLayer`.
18708
+ * @internal
18709
+ */
18710
+
18711
+ /**
18712
+ * Conservative defaults that bound each deck.gl overlay layer's in-memory tile cache. Chosen to
18713
+ * favor low RAM: only the visible working set (plus a small margin) stays parsed in memory; the
18714
+ * raw tile bytes remain on disk in the Service Worker cache, so an evicted tile is re-parsed
18715
+ * rather than re-downloaded. Raise `maxCacheSize` only if profiling shows flashing at the
18716
+ * viewport edge while panning.
18717
+ * @internal
18718
+ */
18719
+ var DEFAULT_DECK_TILE_CACHE = {
18720
+ // Per layer; with four overlay layers this caps the parsed-tile set at ~4x this number.
18721
+ maxCacheSize: 64,
18722
+ maxRequests: 6,
18723
+ // Drop parent tiles once children cover the viewport — keeps the resident set smallest.
18724
+ refinementStrategy: "no-overlap",
18725
+ // Byte budget is opt-in (deck.gl only enforces it when a tile's byte size is known).
18726
+ maxCacheByteSize: undefined
18727
+ };
18728
+
18729
+ /**
18730
+ * Merges an optional {@link DeckTileCacheConfig} over {@link DEFAULT_DECK_TILE_CACHE}, ignoring
18731
+ * `undefined`/`null` fields and clamping numeric bounds to at least 1. The result is always
18732
+ * bounded — passing `undefined` yields the defaults, never an unlimited cache.
18733
+ */
18734
+ var resolveDeckTileCache = function resolveDeckTileCache(config) {
18735
+ var _config$refinementStr;
18736
+ var clampPositive = function clampPositive(value, fallback) {
18737
+ return typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;
18738
+ };
18739
+ var maxCacheByteSize = typeof (config === null || config === void 0 ? void 0 : config.maxCacheByteSize) === "number" && Number.isFinite(config.maxCacheByteSize) && config.maxCacheByteSize >= 1 ? Math.floor(config.maxCacheByteSize) : DEFAULT_DECK_TILE_CACHE.maxCacheByteSize;
18740
+ return {
18741
+ maxCacheSize: clampPositive(config === null || config === void 0 ? void 0 : config.maxCacheSize, DEFAULT_DECK_TILE_CACHE.maxCacheSize),
18742
+ maxRequests: clampPositive(config === null || config === void 0 ? void 0 : config.maxRequests, DEFAULT_DECK_TILE_CACHE.maxRequests),
18743
+ refinementStrategy: (_config$refinementStr = config === null || config === void 0 ? void 0 : config.refinementStrategy) !== null && _config$refinementStr !== void 0 ? _config$refinementStr : DEFAULT_DECK_TILE_CACHE.refinementStrategy,
18744
+ maxCacheByteSize: maxCacheByteSize
18745
+ };
18746
+ };
18747
+
18657
18748
  /**
18658
18749
  * Default lights matching the legacy escalator scene when {@link Models3DConfig.lights} is unset.
18659
18750
  * @internal
@@ -19063,17 +19154,19 @@ var deckPromise;
19063
19154
  * Subsequent calls return the same promise, so a single Three.js instance is shared.
19064
19155
  */
19065
19156
  function loadThree() {
19066
- threePromise !== null && threePromise !== void 0 ? threePromise : threePromise = Promise.all([Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 912, 23)), Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 833, 23)), Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 303, 23)), Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 373, 23))]).then(function (_ref) {
19067
- var _ref2 = three_slicedToArray(_ref, 4),
19157
+ threePromise !== null && threePromise !== void 0 ? threePromise : threePromise = Promise.all([Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 912, 23)), Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 833, 23)), Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 303, 23)), Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 373, 23)), Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 502, 23))]).then(function (_ref) {
19158
+ var _ref2 = three_slicedToArray(_ref, 5),
19068
19159
  three = _ref2[0],
19069
19160
  gltf = _ref2[1],
19070
19161
  draco = _ref2[2],
19071
- ktx2 = _ref2[3];
19162
+ ktx2 = _ref2[3],
19163
+ meshopt = _ref2[4];
19072
19164
  return {
19073
19165
  THREE: three,
19074
19166
  GLTFLoader: gltf.GLTFLoader,
19075
19167
  DRACOLoader: draco.DRACOLoader,
19076
- KTX2Loader: ktx2.KTX2Loader
19168
+ KTX2Loader: ktx2.KTX2Loader,
19169
+ MeshoptDecoder: meshopt.MeshoptDecoder
19077
19170
  };
19078
19171
  });
19079
19172
  return threePromise;
@@ -19131,6 +19224,12 @@ function getGltfLoader() {
19131
19224
  ktx2Loader.detectSupport(new mod.THREE.WebGLRenderer({
19132
19225
  antialias: true
19133
19226
  }));
19227
+
19228
+ // Enable EXT_meshopt_compression so meshopt-compressed GLBs decode. The decoder is a WASM
19229
+ // singleton; GLTFLoader awaits its `.ready` promise internally before parsing. Assets that
19230
+ // don't use the extension are unaffected. This lets the offline pipeline pick meshopt (often
19231
+ // smaller than Draco for the scene's meshes) without a runtime change.
19232
+ gltfLoader.setMeshoptDecoder(mod.MeshoptDecoder);
19134
19233
  return gltfLoader;
19135
19234
  });
19136
19235
  return gltfLoaderPromise;
@@ -19488,6 +19587,7 @@ function scene3DController_toPrimitive(t, r) { if ("object" != scene3DController
19488
19587
  */
19489
19588
  var Scene3DController = /*#__PURE__*/function () {
19490
19589
  function Scene3DController(map, scene3DConfig, initialCenter, onModelsProgress) {
19590
+ var _scene3DConfig$custom;
19491
19591
  scene3DController_classCallCheck(this, Scene3DController);
19492
19592
  /** Latest known floor key; updated by the floor-change hooks and read when (re)building layers. */
19493
19593
  scene3DController_defineProperty(this, "currentFloor", "");
@@ -19515,10 +19615,21 @@ var Scene3DController = /*#__PURE__*/function () {
19515
19615
  scene3DController_defineProperty(this, "scene3DRouteCollisionPoints", []);
19516
19616
  scene3DController_defineProperty(this, "spriteIconMapping", {});
19517
19617
  scene3DController_defineProperty(this, "spriteAtlasImage", new Image());
19618
+ /** True while the GLB models are unloaded by LOD (camera zoomed out past the threshold). */
19619
+ scene3DController_defineProperty(this, "modelsUnloadedByLod", false);
19620
+ /**
19621
+ * True while {@link loadScene3DGlbTemplates} is populating `scene3DGlbRootByUrl` /
19622
+ * `scene3DGlbTemplateById` (initial load or an LOD reload). Guards against overlapping reloads
19623
+ * and, in {@link updateLodForZoom}, against an LOD unload running concurrently and clearing
19624
+ * those same maps out from under the in-flight load.
19625
+ */
19626
+ scene3DController_defineProperty(this, "glbTemplatesLoadInFlight", false);
19518
19627
  this.map = map;
19519
19628
  this.scene3DConfig = scene3DConfig;
19520
19629
  this.initialCenter = initialCenter;
19521
19630
  this.onModelsProgress = onModelsProgress;
19631
+ this.deckTileCache = resolveDeckTileCache((_scene3DConfig$custom = scene3DConfig.customLayers) === null || _scene3DConfig$custom === void 0 ? void 0 : _scene3DConfig$custom.tileCache);
19632
+ this.lodThresholds = resolveModels3DLodThresholds(scene3DConfig.models);
19522
19633
  }
19523
19634
 
19524
19635
  // Lifecycle entry points forwarded by the map ---------------------------------------------
@@ -19572,6 +19683,7 @@ var Scene3DController = /*#__PURE__*/function () {
19572
19683
  this.map.addControl(this.deckOverlay);
19573
19684
  // Hide MapLibre icon layers — replaced by deck.gl IconLayer
19574
19685
  this.hideLayers(this.scene3DConfig.hideLayers);
19686
+ this.installDebugStatsHook();
19575
19687
  models = this.scene3DConfig.models;
19576
19688
  glbModelsActive = models !== undefined && models.enabled !== false && models.assets.length > 0;
19577
19689
  if (glbModelsActive) {
@@ -19592,19 +19704,136 @@ var Scene3DController = /*#__PURE__*/function () {
19592
19704
  return _onMapLoad.apply(this, arguments);
19593
19705
  }
19594
19706
  return onMapLoad;
19595
- }() /** Re-applies zoom-based model transparency; call on every map `zoom`. */
19707
+ }() /** Re-applies zoom-based model transparency and evaluates LOD; call on every map `zoom`. */
19596
19708
  }, {
19597
19709
  key: "onZoom",
19598
19710
  value: function onZoom() {
19599
19711
  this.applyModelOpacity();
19712
+ this.updateLodForZoom();
19713
+ }
19714
+
19715
+ /**
19716
+ * Evaluates the zoom-based LOD (see {@link Models3DConfig.lod}): unloads the GLB models from
19717
+ * memory when the camera drops below the unload boundary and reloads them when it returns to the
19718
+ * reload boundary. No-op when LOD is disabled. Cheap enough to call on every `zoom` event — it
19719
+ * only acts on a boundary crossing.
19720
+ */
19721
+ }, {
19722
+ key: "updateLodForZoom",
19723
+ value: function updateLodForZoom() {
19724
+ if (!this.lodThresholds) {
19725
+ return;
19726
+ }
19727
+ var action = lodActionForZoom(this.map.getZoom(), this.lodThresholds, this.modelsUnloadedByLod);
19728
+ if (action === "unload") {
19729
+ if (this.glbTemplatesLoadInFlight) {
19730
+ // A load is already populating the model maps; unloading now would race with it.
19731
+ // reloadScene3DModelsForLod()/the initial load re-evaluate the zoom once they settle.
19732
+ return;
19733
+ }
19734
+ this.unloadScene3DModelsForLod();
19735
+ } else if (action === "reload") {
19736
+ void this.reloadScene3DModelsForLod();
19737
+ }
19600
19738
  }
19601
19739
 
19740
+ /**
19741
+ * Frees the GLB models' GPU resources (placed group's material clones + every cached template's
19742
+ * geometry/textures) while keeping the custom layer, its `WebGLRenderer`, scene and lights alive,
19743
+ * so a later {@link reloadScene3DModelsForLod} can repopulate without recreating the map layer.
19744
+ * Distinct from {@link dispose}, which tears the whole controller down.
19745
+ */
19746
+ }, {
19747
+ key: "unloadScene3DModelsForLod",
19748
+ value: function unloadScene3DModelsForLod() {
19749
+ var _this$threeMod;
19750
+ var three = (_this$threeMod = this.threeMod) === null || _this$threeMod === void 0 ? void 0 : _this$threeMod.THREE;
19751
+ if (!three) {
19752
+ return;
19753
+ }
19754
+ if (this.scene3DModelsGroup) {
19755
+ var _this$scene3DGlbScene;
19756
+ disposeMaterialsOnly(three, this.scene3DModelsGroup);
19757
+ (_this$scene3DGlbScene = this.scene3DGlbScene) === null || _this$scene3DGlbScene === void 0 || _this$scene3DGlbScene.remove(this.scene3DModelsGroup);
19758
+ this.scene3DModelsGroup = undefined;
19759
+ }
19760
+ // Iterate the deduped-by-URL roots so a shared root is never disposed twice (mirrors dispose()).
19761
+ var _iterator = scene3DController_createForOfIteratorHelper(this.scene3DGlbRootByUrl.values()),
19762
+ _step;
19763
+ try {
19764
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
19765
+ var root = _step.value;
19766
+ disposeObject3D(three, root);
19767
+ }
19768
+ } catch (err) {
19769
+ _iterator.e(err);
19770
+ } finally {
19771
+ _iterator.f();
19772
+ }
19773
+ this.scene3DGlbRootByUrl.clear();
19774
+ this.scene3DGlbTemplateById.clear();
19775
+ this.modelsUnloadedByLod = true;
19776
+ this.map.triggerRepaint();
19777
+ }
19778
+
19779
+ /**
19780
+ * Reloads the GLB templates from disk/network and re-places them for the current floor after an
19781
+ * LOD unload. Guards against overlapping reloads, and re-evaluates the zoom on completion so a
19782
+ * camera that zoomed back out mid-download ends up unloaded again rather than stuck loaded.
19783
+ */
19784
+ }, {
19785
+ key: "reloadScene3DModelsForLod",
19786
+ value: (function () {
19787
+ var _reloadScene3DModelsForLod = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee2() {
19788
+ var _t2;
19789
+ return scene3DController_regenerator().w(function (_context2) {
19790
+ while (1) switch (_context2.p = _context2.n) {
19791
+ case 0:
19792
+ if (!this.glbTemplatesLoadInFlight) {
19793
+ _context2.n = 1;
19794
+ break;
19795
+ }
19796
+ return _context2.a(2);
19797
+ case 1:
19798
+ this.glbTemplatesLoadInFlight = true;
19799
+ _context2.p = 2;
19800
+ _context2.n = 3;
19801
+ return this.loadScene3DGlbTemplates();
19802
+ case 3:
19803
+ this.placeScene3DModels();
19804
+ // Only mark as loaded once placement actually succeeded, so a failed reload leaves
19805
+ // modelsUnloadedByLod = true and the trailing updateLodForZoom() below retries it.
19806
+ this.modelsUnloadedByLod = false;
19807
+ _context2.n = 5;
19808
+ break;
19809
+ case 4:
19810
+ _context2.p = 4;
19811
+ _t2 = _context2.v;
19812
+ console.error("Failed to reload declarative GLB models after LOD unload", _t2);
19813
+ case 5:
19814
+ _context2.p = 5;
19815
+ this.glbTemplatesLoadInFlight = false;
19816
+ return _context2.f(5);
19817
+ case 6:
19818
+ // The camera may have moved during the async load; re-evaluate so a zoom back out unloads again.
19819
+ this.updateLodForZoom();
19820
+ case 7:
19821
+ return _context2.a(2);
19822
+ }
19823
+ }, _callee2, this, [[2, 4, 5, 6]]);
19824
+ }));
19825
+ function reloadScene3DModelsForLod() {
19826
+ return _reloadScene3DModelsForLod.apply(this, arguments);
19827
+ }
19828
+ return reloadScene3DModelsForLod;
19829
+ }()
19602
19830
  /**
19603
19831
  * Sets the route path used for GLB route-transparency collision and re-evaluates which models a
19604
19832
  * route currently crosses. Points are tagged with the floor on which their route segment is
19605
19833
  * visible; only points on the current floor participate, so a model never fades unless a route is
19606
19834
  * visibly crossing it on the displayed floor. Pass an empty array to clear.
19607
19835
  */
19836
+ )
19608
19837
  }, {
19609
19838
  key: "setRouteCollisionPath",
19610
19839
  value: function setRouteCollisionPath(points) {
@@ -19639,6 +19868,93 @@ var Scene3DController = /*#__PURE__*/function () {
19639
19868
  this.updateDeckOverlay();
19640
19869
  }
19641
19870
 
19871
+ /**
19872
+ * A point-in-time snapshot of the 3D scene's memory drivers, for profiling. The Three.js
19873
+ * `renderer.info` counters are the best in-page proxy for GLB VRAM (decoded geometries/textures
19874
+ * live on the GPU and are not visible to `performance.memory`, which only reports the JS heap).
19875
+ * The deck tile counts approximate the overlay's parsed-tile working set — the thing the tile-cache
19876
+ * bounds (see {@link DeckTileCacheConfig}) keep from growing without limit as the map pans/zooms.
19877
+ *
19878
+ * @group Map
19879
+ */
19880
+ }, {
19881
+ key: "getDebugStats",
19882
+ value: function getDebugStats() {
19883
+ var _this$glbRenderer, _info$programs$length, _info$programs, _this$scene3DModelsGr, _this$scene3DModelsGr2;
19884
+ var info = (_this$glbRenderer = this.glbRenderer) === null || _this$glbRenderer === void 0 ? void 0 : _this$glbRenderer.info;
19885
+ var three = info ? {
19886
+ geometries: info.memory.geometries,
19887
+ textures: info.memory.textures,
19888
+ programs: (_info$programs$length = (_info$programs = info.programs) === null || _info$programs === void 0 ? void 0 : _info$programs.length) !== null && _info$programs$length !== void 0 ? _info$programs$length : 0,
19889
+ renderCalls: info.render.calls,
19890
+ triangles: info.render.triangles
19891
+ } : null;
19892
+ var deckTiles = null;
19893
+ try {
19894
+ var _overlay$_deck;
19895
+ // Best-effort read of each overlay layer's parsed-tile count. deck.gl internals are private,
19896
+ // so this is guarded — it degrades to `null` rather than throwing if the shape changes.
19897
+ var overlay = this.deckOverlay;
19898
+ var layers = overlay === null || overlay === void 0 || (_overlay$_deck = overlay._deck) === null || _overlay$_deck === void 0 || (_overlay$_deck = _overlay$_deck.layerManager) === null || _overlay$_deck === void 0 ? void 0 : _overlay$_deck.layers;
19899
+ if (Array.isArray(layers)) {
19900
+ var counts = {};
19901
+ for (var _i = 0, _arr = layers; _i < _arr.length; _i++) {
19902
+ var _layer$state;
19903
+ var layer = _arr[_i];
19904
+ var size = layer === null || layer === void 0 || (_layer$state = layer.state) === null || _layer$state === void 0 || (_layer$state = _layer$state.tileset) === null || _layer$state === void 0 || (_layer$state = _layer$state._cache) === null || _layer$state === void 0 ? void 0 : _layer$state.size;
19905
+ if (typeof size === "number" && layer.id) {
19906
+ var _counts$baseId;
19907
+ // Strip deck's per-sublayer suffixes so the four MVT roots aggregate by base id.
19908
+ var baseId = layer.id.split("-sublayer")[0];
19909
+ counts[baseId] = Math.max((_counts$baseId = counts[baseId]) !== null && _counts$baseId !== void 0 ? _counts$baseId : 0, size);
19910
+ }
19911
+ }
19912
+ deckTiles = counts;
19913
+ }
19914
+ } catch (_unused) {
19915
+ deckTiles = null;
19916
+ }
19917
+ return {
19918
+ zoom: this.map.getZoom(),
19919
+ currentFloor: this.currentFloor,
19920
+ modelsUnloadedByLod: this.modelsUnloadedByLod,
19921
+ glbRoots: this.scene3DGlbRootByUrl.size,
19922
+ glbTemplates: this.scene3DGlbTemplateById.size,
19923
+ placedModels: (_this$scene3DModelsGr = (_this$scene3DModelsGr2 = this.scene3DModelsGroup) === null || _this$scene3DModelsGr2 === void 0 ? void 0 : _this$scene3DModelsGr2.children.length) !== null && _this$scene3DModelsGr !== void 0 ? _this$scene3DModelsGr : 0,
19924
+ three: three,
19925
+ deckTiles: deckTiles,
19926
+ deckTileCache: this.deckTileCache,
19927
+ lodThresholds: this.lodThresholds
19928
+ };
19929
+ }
19930
+
19931
+ /**
19932
+ * Exposes {@link getDebugStats} as `globalThis.__mvxScene3DStats()` when the opt-in flag
19933
+ * `globalThis.__MVX_SCENE3D_DEBUG__` is truthy, so a profiling session can read the scene's memory
19934
+ * drivers from the console/tests without external tooling. No-op (and no global written) otherwise.
19935
+ */
19936
+ }, {
19937
+ key: "installDebugStatsHook",
19938
+ value: function installDebugStatsHook() {
19939
+ var _this = this;
19940
+ var g = globalThis;
19941
+ if (g.__MVX_SCENE3D_DEBUG__) {
19942
+ g.__mvxScene3DStats = function () {
19943
+ return _this.getDebugStats();
19944
+ };
19945
+ }
19946
+ }
19947
+
19948
+ /** Removes the debug hook if it points at this controller. Called from {@link dispose}. */
19949
+ }, {
19950
+ key: "uninstallDebugStatsHook",
19951
+ value: function uninstallDebugStatsHook() {
19952
+ var g = globalThis;
19953
+ if (g.__mvxScene3DStats) {
19954
+ delete g.__mvxScene3DStats;
19955
+ }
19956
+ }
19957
+
19642
19958
  /**
19643
19959
  * Releases every GPU resource this controller owns: the placed models group's material clones,
19644
19960
  * the cached GLB templates' geometries/materials/textures, and the `WebGLRenderer` created for the
@@ -19652,8 +19968,8 @@ var Scene3DController = /*#__PURE__*/function () {
19652
19968
  }, {
19653
19969
  key: "dispose",
19654
19970
  value: function dispose() {
19655
- var _this$threeMod, _this$glbRenderer;
19656
- var three = (_this$threeMod = this.threeMod) === null || _this$threeMod === void 0 ? void 0 : _this$threeMod.THREE;
19971
+ var _this$threeMod2, _this$glbRenderer2;
19972
+ var three = (_this$threeMod2 = this.threeMod) === null || _this$threeMod2 === void 0 ? void 0 : _this$threeMod2.THREE;
19657
19973
  if (three) {
19658
19974
  if (this.scene3DModelsGroup) {
19659
19975
  disposeMaterialsOnly(three, this.scene3DModelsGroup);
@@ -19661,24 +19977,25 @@ var Scene3DController = /*#__PURE__*/function () {
19661
19977
  }
19662
19978
  // Iterate the deduplicated-by-URL roots (not `scene3DGlbTemplateById`, which may map several
19663
19979
  // asset ids to the same root) so a shared root is never disposed more than once.
19664
- var _iterator = scene3DController_createForOfIteratorHelper(this.scene3DGlbRootByUrl.values()),
19665
- _step;
19980
+ var _iterator2 = scene3DController_createForOfIteratorHelper(this.scene3DGlbRootByUrl.values()),
19981
+ _step2;
19666
19982
  try {
19667
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
19668
- var root = _step.value;
19983
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
19984
+ var root = _step2.value;
19669
19985
  disposeObject3D(three, root);
19670
19986
  }
19671
19987
  } catch (err) {
19672
- _iterator.e(err);
19988
+ _iterator2.e(err);
19673
19989
  } finally {
19674
- _iterator.f();
19990
+ _iterator2.f();
19675
19991
  }
19676
19992
  }
19677
19993
  this.scene3DGlbRootByUrl.clear();
19678
19994
  this.scene3DGlbTemplateById.clear();
19679
19995
  this.scene3DGlbScene = undefined;
19680
- (_this$glbRenderer = this.glbRenderer) === null || _this$glbRenderer === void 0 || _this$glbRenderer.dispose();
19996
+ (_this$glbRenderer2 = this.glbRenderer) === null || _this$glbRenderer2 === void 0 || _this$glbRenderer2.dispose();
19681
19997
  this.glbRenderer = undefined;
19998
+ this.uninstallDebugStatsHook();
19682
19999
  }
19683
20000
 
19684
20001
  // Internal implementation -----------------------------------------------------------------
@@ -19690,40 +20007,40 @@ var Scene3DController = /*#__PURE__*/function () {
19690
20007
  }, {
19691
20008
  key: "ensure3DLibs",
19692
20009
  value: function () {
19693
- var _ensure3DLibs = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee2() {
19694
- var _this$threeMod2, _this$deckMod;
19695
- return scene3DController_regenerator().w(function (_context2) {
19696
- while (1) switch (_context2.n) {
20010
+ var _ensure3DLibs = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee3() {
20011
+ var _this$threeMod3, _this$deckMod;
20012
+ return scene3DController_regenerator().w(function (_context3) {
20013
+ while (1) switch (_context3.n) {
19697
20014
  case 0:
19698
- if (!((_this$threeMod2 = this.threeMod) !== null && _this$threeMod2 !== void 0)) {
19699
- _context2.n = 1;
20015
+ if (!((_this$threeMod3 = this.threeMod) !== null && _this$threeMod3 !== void 0)) {
20016
+ _context3.n = 1;
19700
20017
  break;
19701
20018
  }
19702
- _this$threeMod2;
19703
- _context2.n = 3;
20019
+ _this$threeMod3;
20020
+ _context3.n = 3;
19704
20021
  break;
19705
20022
  case 1:
19706
- _context2.n = 2;
20023
+ _context3.n = 2;
19707
20024
  return loadThree();
19708
20025
  case 2:
19709
- this.threeMod = _context2.v;
20026
+ this.threeMod = _context3.v;
19710
20027
  case 3:
19711
20028
  if (!((_this$deckMod = this.deckMod) !== null && _this$deckMod !== void 0)) {
19712
- _context2.n = 4;
20029
+ _context3.n = 4;
19713
20030
  break;
19714
20031
  }
19715
20032
  _this$deckMod;
19716
- _context2.n = 6;
20033
+ _context3.n = 6;
19717
20034
  break;
19718
20035
  case 4:
19719
- _context2.n = 5;
20036
+ _context3.n = 5;
19720
20037
  return loadDeck();
19721
20038
  case 5:
19722
- this.deckMod = _context2.v;
20039
+ this.deckMod = _context3.v;
19723
20040
  case 6:
19724
- return _context2.a(2);
20041
+ return _context3.a(2);
19725
20042
  }
19726
- }, _callee2, this);
20043
+ }, _callee3, this);
19727
20044
  }));
19728
20045
  function ensure3DLibs() {
19729
20046
  return _ensure3DLibs.apply(this, arguments);
@@ -19733,7 +20050,7 @@ var Scene3DController = /*#__PURE__*/function () {
19733
20050
  }, {
19734
20051
  key: "createGlbCustomLayer",
19735
20052
  value: function createGlbCustomLayer() {
19736
- var _this = this;
20053
+ var _this2 = this;
19737
20054
  var three = this.threeMod.THREE;
19738
20055
  var refMercator = maplibre_gl.MercatorCoordinate.fromLngLat(this.initialCenter, 0);
19739
20056
  var meterScale = refMercator.meterInMercatorCoordinateUnits();
@@ -19746,10 +20063,16 @@ var Scene3DController = /*#__PURE__*/function () {
19746
20063
  } else {
19747
20064
  this.scene3DGlbLightCount = 0;
19748
20065
  }
20066
+ this.glbTemplatesLoadInFlight = true;
19749
20067
  void this.loadScene3DGlbTemplates().then(function () {
19750
- return _this.placeScene3DModels();
20068
+ _this2.placeScene3DModels();
19751
20069
  })["catch"](function (err) {
19752
20070
  console.error("Failed to initialize declarative GLB models", err);
20071
+ })["finally"](function () {
20072
+ _this2.glbTemplatesLoadInFlight = false;
20073
+ // Honor LOD from the first frame: if the map opened below the unload threshold, free the
20074
+ // models just loaded (they reload when the user zooms in). No-op when LOD is disabled.
20075
+ _this2.updateLodForZoom();
19753
20076
  });
19754
20077
  var renderer = undefined;
19755
20078
  var camera = undefined;
@@ -19773,17 +20096,17 @@ var Scene3DController = /*#__PURE__*/function () {
19773
20096
  // Stored on the controller (not just this closure) so `dispose()` can release it — MapLibre
19774
20097
  // does not call a custom layer's `onRemove` when the whole map/style is torn down via
19775
20098
  // `map.remove()`, so callers must dispose this controller explicitly before that happens.
19776
- _this.glbRenderer = renderer;
20099
+ _this2.glbRenderer = renderer;
19777
20100
  },
19778
20101
  onRemove: function onRemove() {
19779
- _this.dispose();
20102
+ _this2.dispose();
19780
20103
  },
19781
20104
  render: function render(_gl, args) {
19782
20105
  var _args$defaultProjecti;
19783
- if (!camera || !renderer || !_this.scene3DGlbScene || !_this.scene3DModelsGroup || _this.scene3DModelsGroup.children.length === 0) {
20106
+ if (!camera || !renderer || !_this2.scene3DGlbScene || !_this2.scene3DModelsGroup || _this2.scene3DModelsGroup.children.length === 0) {
19784
20107
  return;
19785
20108
  }
19786
- var canvas = _this.map.getCanvas();
20109
+ var canvas = _this2.map.getCanvas();
19787
20110
  var width = canvas.width;
19788
20111
  var height = canvas.height;
19789
20112
  // Skip while the framebuffer has no drawable area (e.g. devtools opening).
@@ -19798,27 +20121,27 @@ var Scene3DController = /*#__PURE__*/function () {
19798
20121
  tmpMatrix.fromArray(mainMatrix).multiply(modelTransform);
19799
20122
  camera.projectionMatrix.copy(tmpMatrix);
19800
20123
  renderer.resetState();
19801
- renderer.render(_this.scene3DGlbScene, camera);
20124
+ renderer.render(_this2.scene3DGlbScene, camera);
19802
20125
  }
19803
20126
  };
19804
20127
  }
19805
20128
  }, {
19806
20129
  key: "loadScene3DGlbTemplates",
19807
20130
  value: function () {
19808
- var _loadScene3DGlbTemplates = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee4() {
19809
- var _this$threeMod3,
19810
- _this2 = this;
19811
- var three, models, uniqueUrls, errorByUrl, semaphore, loadedBytesByUrl, totalBytesByUrl, settledAssets, totalAssets, reportProgress, _iterator3, _step3, asset, root, center, _t5;
19812
- return scene3DController_regenerator().w(function (_context4) {
19813
- while (1) switch (_context4.p = _context4.n) {
20131
+ var _loadScene3DGlbTemplates = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee5() {
20132
+ var _this$threeMod4,
20133
+ _this3 = this;
20134
+ var three, models, uniqueUrls, errorByUrl, semaphore, loadedBytesByUrl, totalBytesByUrl, settledAssets, totalAssets, reportProgress, _iterator4, _step4, asset, root, center, _t6;
20135
+ return scene3DController_regenerator().w(function (_context5) {
20136
+ while (1) switch (_context5.p = _context5.n) {
19814
20137
  case 0:
19815
- three = (_this$threeMod3 = this.threeMod) === null || _this$threeMod3 === void 0 ? void 0 : _this$threeMod3.THREE;
20138
+ three = (_this$threeMod4 = this.threeMod) === null || _this$threeMod4 === void 0 ? void 0 : _this$threeMod4.THREE;
19816
20139
  models = this.scene3DConfig.models;
19817
20140
  if (!(!three || !models || models.enabled === false || models.assets.length === 0)) {
19818
- _context4.n = 1;
20141
+ _context5.n = 1;
19819
20142
  break;
19820
20143
  }
19821
- return _context4.a(2);
20144
+ return _context5.a(2);
19822
20145
  case 1:
19823
20146
  this.scene3DGlbRootByUrl.clear();
19824
20147
  this.scene3DGlbTemplateById.clear();
@@ -19839,26 +20162,26 @@ var Scene3DController = /*#__PURE__*/function () {
19839
20162
  settledAssets = 0;
19840
20163
  totalAssets = uniqueUrls.length;
19841
20164
  reportProgress = function reportProgress(done) {
19842
- if (!_this2.onModelsProgress) return;
20165
+ if (!_this3.onModelsProgress) return;
19843
20166
  var loadedBytes = 0;
19844
20167
  var totalBytes = 0;
19845
- var _iterator2 = scene3DController_createForOfIteratorHelper(uniqueUrls),
19846
- _step2;
20168
+ var _iterator3 = scene3DController_createForOfIteratorHelper(uniqueUrls),
20169
+ _step3;
19847
20170
  try {
19848
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
20171
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
19849
20172
  var _loadedBytesByUrl$get;
19850
- var url = _step2.value;
20173
+ var url = _step3.value;
19851
20174
  loadedBytes += (_loadedBytesByUrl$get = loadedBytesByUrl.get(url)) !== null && _loadedBytesByUrl$get !== void 0 ? _loadedBytesByUrl$get : 0;
19852
20175
  var total = totalBytesByUrl.get(url);
19853
20176
  totalBytes = total == null || totalBytes === null ? null : totalBytes + total;
19854
20177
  }
19855
20178
  } catch (err) {
19856
- _iterator2.e(err);
20179
+ _iterator3.e(err);
19857
20180
  } finally {
19858
- _iterator2.f();
20181
+ _iterator3.f();
19859
20182
  }
19860
20183
  try {
19861
- _this2.onModelsProgress({
20184
+ _this3.onModelsProgress({
19862
20185
  loadedAssets: settledAssets,
19863
20186
  totalAssets: totalAssets,
19864
20187
  loadedBytes: loadedBytes,
@@ -19872,20 +20195,20 @@ var Scene3DController = /*#__PURE__*/function () {
19872
20195
  console.error("onScene3DModelsProgress callback threw", err);
19873
20196
  }
19874
20197
  };
19875
- _context4.n = 2;
20198
+ _context5.n = 2;
19876
20199
  return Promise.all(uniqueUrls.map(/*#__PURE__*/function () {
19877
- var _ref = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee3(url) {
19878
- var _ref2, _totalBytesByUrl$get, _t2, _t3, _t4;
19879
- return scene3DController_regenerator().w(function (_context3) {
19880
- while (1) switch (_context3.p = _context3.n) {
20200
+ var _ref = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee4(url) {
20201
+ var _ref2, _totalBytesByUrl$get, _t3, _t4, _t5;
20202
+ return scene3DController_regenerator().w(function (_context4) {
20203
+ while (1) switch (_context4.p = _context4.n) {
19881
20204
  case 0:
19882
- _context3.n = 1;
20205
+ _context4.n = 1;
19883
20206
  return semaphore.acquire();
19884
20207
  case 1:
19885
- _context3.p = 1;
19886
- _t2 = _this2.scene3DGlbRootByUrl;
19887
- _t3 = url;
19888
- _context3.n = 2;
20208
+ _context4.p = 1;
20209
+ _t3 = _this3.scene3DGlbRootByUrl;
20210
+ _t4 = url;
20211
+ _context4.n = 2;
19889
20212
  return loadGlbRoot(url, {
19890
20213
  onProgress: function onProgress(event) {
19891
20214
  loadedBytesByUrl.set(url, event.loaded);
@@ -19894,15 +20217,15 @@ var Scene3DController = /*#__PURE__*/function () {
19894
20217
  }
19895
20218
  });
19896
20219
  case 2:
19897
- _t2.set.call(_t2, _t3, _context3.v);
19898
- _context3.n = 4;
20220
+ _t3.set.call(_t3, _t4, _context4.v);
20221
+ _context4.n = 4;
19899
20222
  break;
19900
20223
  case 3:
19901
- _context3.p = 3;
19902
- _t4 = _context3.v;
19903
- errorByUrl.set(url, _t4);
20224
+ _context4.p = 3;
20225
+ _t5 = _context4.v;
20226
+ errorByUrl.set(url, _t5);
19904
20227
  case 4:
19905
- _context3.p = 4;
20228
+ _context4.p = 4;
19906
20229
  settledAssets++;
19907
20230
  // Once a URL has settled, its total is knowable even if no progress event ever supplied
19908
20231
  // one (failed before the first byte, or the server omitted Content-Length): fall back to
@@ -19911,11 +20234,11 @@ var Scene3DController = /*#__PURE__*/function () {
19911
20234
  totalBytesByUrl.set(url, (_ref2 = (_totalBytesByUrl$get = totalBytesByUrl.get(url)) !== null && _totalBytesByUrl$get !== void 0 ? _totalBytesByUrl$get : loadedBytesByUrl.get(url)) !== null && _ref2 !== void 0 ? _ref2 : 0);
19912
20235
  semaphore.release();
19913
20236
  reportProgress(false);
19914
- return _context3.f(4);
20237
+ return _context4.f(4);
19915
20238
  case 5:
19916
- return _context3.a(2);
20239
+ return _context4.a(2);
19917
20240
  }
19918
- }, _callee3, null, [[1, 3, 4, 5]]);
20241
+ }, _callee4, null, [[1, 3, 4, 5]]);
19919
20242
  }));
19920
20243
  return function (_x) {
19921
20244
  return _ref.apply(this, arguments);
@@ -19923,22 +20246,22 @@ var Scene3DController = /*#__PURE__*/function () {
19923
20246
  }()));
19924
20247
  case 2:
19925
20248
  reportProgress(true);
19926
- _iterator3 = scene3DController_createForOfIteratorHelper(models.assets);
19927
- _context4.p = 3;
19928
- _iterator3.s();
20249
+ _iterator4 = scene3DController_createForOfIteratorHelper(models.assets);
20250
+ _context5.p = 3;
20251
+ _iterator4.s();
19929
20252
  case 4:
19930
- if ((_step3 = _iterator3.n()).done) {
19931
- _context4.n = 7;
20253
+ if ((_step4 = _iterator4.n()).done) {
20254
+ _context5.n = 7;
19932
20255
  break;
19933
20256
  }
19934
- asset = _step3.value;
20257
+ asset = _step4.value;
19935
20258
  root = this.scene3DGlbRootByUrl.get(asset.url);
19936
20259
  if (root) {
19937
- _context4.n = 5;
20260
+ _context5.n = 5;
19938
20261
  break;
19939
20262
  }
19940
20263
  console.error("Failed to load GLB asset \"".concat(asset.id, "\" from ").concat(asset.url), errorByUrl.get(asset.url));
19941
- return _context4.a(3, 6);
20264
+ return _context5.a(3, 6);
19942
20265
  case 5:
19943
20266
  center = computeGlbBottomAnchor(three, root);
19944
20267
  this.scene3DGlbTemplateById.set(asset.id, {
@@ -19946,23 +20269,23 @@ var Scene3DController = /*#__PURE__*/function () {
19946
20269
  center: center
19947
20270
  });
19948
20271
  case 6:
19949
- _context4.n = 4;
20272
+ _context5.n = 4;
19950
20273
  break;
19951
20274
  case 7:
19952
- _context4.n = 9;
20275
+ _context5.n = 9;
19953
20276
  break;
19954
20277
  case 8:
19955
- _context4.p = 8;
19956
- _t5 = _context4.v;
19957
- _iterator3.e(_t5);
20278
+ _context5.p = 8;
20279
+ _t6 = _context5.v;
20280
+ _iterator4.e(_t6);
19958
20281
  case 9:
19959
- _context4.p = 9;
19960
- _iterator3.f();
19961
- return _context4.f(9);
20282
+ _context5.p = 9;
20283
+ _iterator4.f();
20284
+ return _context5.f(9);
19962
20285
  case 10:
19963
- return _context4.a(2);
20286
+ return _context5.a(2);
19964
20287
  }
19965
- }, _callee4, this, [[3, 8, 9, 10]]);
20288
+ }, _callee5, this, [[3, 8, 9, 10]]);
19966
20289
  }));
19967
20290
  function loadScene3DGlbTemplates() {
19968
20291
  return _loadScene3DGlbTemplates.apply(this, arguments);
@@ -19972,15 +20295,15 @@ var Scene3DController = /*#__PURE__*/function () {
19972
20295
  }, {
19973
20296
  key: "placeScene3DModels",
19974
20297
  value: function placeScene3DModels() {
19975
- var _this$threeMod4,
20298
+ var _this$threeMod5,
19976
20299
  _models$globalOffset$,
19977
20300
  _models$globalOffset,
19978
20301
  _models$globalOffset$2,
19979
20302
  _models$globalOffset2,
19980
20303
  _models$globalOffset$3,
19981
20304
  _models$globalOffset3,
19982
- _this3 = this;
19983
- var three = (_this$threeMod4 = this.threeMod) === null || _this$threeMod4 === void 0 ? void 0 : _this$threeMod4.THREE;
20305
+ _this4 = this;
20306
+ var three = (_this$threeMod5 = this.threeMod) === null || _this$threeMod5 === void 0 ? void 0 : _this$threeMod5.THREE;
19984
20307
  if (!three || !this.scene3DGlbScene) {
19985
20308
  return;
19986
20309
  }
@@ -20004,16 +20327,16 @@ var Scene3DController = /*#__PURE__*/function () {
20004
20327
  var floorKey = this.currentFloor;
20005
20328
  var modelsGroup = new three.Group();
20006
20329
  modelsGroup.position.set((_models$globalOffset$ = (_models$globalOffset = models.globalOffset) === null || _models$globalOffset === void 0 ? void 0 : _models$globalOffset.x) !== null && _models$globalOffset$ !== void 0 ? _models$globalOffset$ : 0, (_models$globalOffset$2 = (_models$globalOffset2 = models.globalOffset) === null || _models$globalOffset2 === void 0 ? void 0 : _models$globalOffset2.y) !== null && _models$globalOffset$2 !== void 0 ? _models$globalOffset$2 : 0, (_models$globalOffset$3 = (_models$globalOffset3 = models.globalOffset) === null || _models$globalOffset3 === void 0 ? void 0 : _models$globalOffset3.z) !== null && _models$globalOffset$3 !== void 0 ? _models$globalOffset$3 : 0);
20007
- var _iterator4 = scene3DController_createForOfIteratorHelper(models.placements),
20008
- _step4;
20330
+ var _iterator5 = scene3DController_createForOfIteratorHelper(models.placements),
20331
+ _step5;
20009
20332
  try {
20010
20333
  var _loop = function _loop() {
20011
20334
  var _placement$position$a;
20012
- var placement = _step4.value;
20335
+ var placement = _step5.value;
20013
20336
  if (!isPlacementVisibleOnFloor(placement, floorKey)) {
20014
20337
  return 0; // continue
20015
20338
  }
20016
- var template = _this3.scene3DGlbTemplateById.get(placement.assetId);
20339
+ var template = _this4.scene3DGlbTemplateById.get(placement.assetId);
20017
20340
  if (!template) {
20018
20341
  return 0; // continue
20019
20342
  }
@@ -20075,14 +20398,14 @@ var Scene3DController = /*#__PURE__*/function () {
20075
20398
  modelsGroup.add(pivot);
20076
20399
  },
20077
20400
  _ret;
20078
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
20401
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
20079
20402
  _ret = _loop();
20080
20403
  if (_ret === 0) continue;
20081
20404
  }
20082
20405
  } catch (err) {
20083
- _iterator4.e(err);
20406
+ _iterator5.e(err);
20084
20407
  } finally {
20085
- _iterator4.f();
20408
+ _iterator5.f();
20086
20409
  }
20087
20410
  this.scene3DModelsGroup = modelsGroup;
20088
20411
  this.scene3DGlbScene.add(modelsGroup);
@@ -20102,15 +20425,15 @@ var Scene3DController = /*#__PURE__*/function () {
20102
20425
  }, {
20103
20426
  key: "recomputeRouteAffectedModels",
20104
20427
  value: function recomputeRouteAffectedModels() {
20105
- var _this$threeMod5,
20106
- _this4 = this;
20107
- var three = (_this$threeMod5 = this.threeMod) === null || _this$threeMod5 === void 0 ? void 0 : _this$threeMod5.THREE;
20428
+ var _this$threeMod6,
20429
+ _this5 = this;
20430
+ var three = (_this$threeMod6 = this.threeMod) === null || _this$threeMod6 === void 0 ? void 0 : _this$threeMod6.THREE;
20108
20431
  var modelsGroup = this.scene3DModelsGroup;
20109
20432
  if (!three || !modelsGroup) {
20110
20433
  return;
20111
20434
  }
20112
20435
  var points = this.scene3DRouteCollisionPoints.filter(function (p) {
20113
- return p.floorKey === _this4.currentFloor;
20436
+ return p.floorKey === _this5.currentFloor;
20114
20437
  });
20115
20438
 
20116
20439
  // Convert each route point into the models group's local frame (metres relative to
@@ -20127,11 +20450,11 @@ var Scene3DController = /*#__PURE__*/function () {
20127
20450
  });
20128
20451
  modelsGroup.updateMatrixWorld(true);
20129
20452
  var local = new three.Vector3();
20130
- var _iterator5 = scene3DController_createForOfIteratorHelper(modelsGroup.children),
20131
- _step5;
20453
+ var _iterator6 = scene3DController_createForOfIteratorHelper(modelsGroup.children),
20454
+ _step6;
20132
20455
  try {
20133
20456
  var _loop2 = function _loop2() {
20134
- var pivot = _step5.value;
20457
+ var pivot = _step6.value;
20135
20458
  var routeCfg = pivot.userData.routeTransparency;
20136
20459
  var footprint = pivot.userData.footprint;
20137
20460
  // Only models with a route-transparency config participate (feature activation gate).
@@ -20148,13 +20471,13 @@ var Scene3DController = /*#__PURE__*/function () {
20148
20471
  return pointInFootprint(footprint, local.x, local.z);
20149
20472
  });
20150
20473
  };
20151
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
20474
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
20152
20475
  if (_loop2()) continue;
20153
20476
  }
20154
20477
  } catch (err) {
20155
- _iterator5.e(err);
20478
+ _iterator6.e(err);
20156
20479
  } finally {
20157
- _iterator5.f();
20480
+ _iterator6.f();
20158
20481
  }
20159
20482
  }
20160
20483
 
@@ -20174,11 +20497,11 @@ var Scene3DController = /*#__PURE__*/function () {
20174
20497
  }
20175
20498
  var zoom = this.map.getZoom();
20176
20499
  var changed = false;
20177
- var _iterator6 = scene3DController_createForOfIteratorHelper(this.scene3DModelsGroup.children),
20178
- _step6;
20500
+ var _iterator7 = scene3DController_createForOfIteratorHelper(this.scene3DModelsGroup.children),
20501
+ _step7;
20179
20502
  try {
20180
20503
  var _loop3 = function _loop3() {
20181
- var pivot = _step6.value;
20504
+ var pivot = _step7.value;
20182
20505
  var zoomCfg = pivot.userData.zoomTransparency;
20183
20506
  var routeCfg = pivot.userData.routeTransparency;
20184
20507
  var routeAffected = pivot.userData.routeAffected === true;
@@ -20189,11 +20512,11 @@ var Scene3DController = /*#__PURE__*/function () {
20189
20512
  return;
20190
20513
  }
20191
20514
  var materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
20192
- var _iterator7 = scene3DController_createForOfIteratorHelper(materials),
20193
- _step7;
20515
+ var _iterator8 = scene3DController_createForOfIteratorHelper(materials),
20516
+ _step8;
20194
20517
  try {
20195
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
20196
- var material = _step7.value;
20518
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
20519
+ var material = _step8.value;
20197
20520
  if (material.opacity !== opacity) {
20198
20521
  material.transparent = opacity < 1;
20199
20522
  material.opacity = opacity;
@@ -20203,19 +20526,19 @@ var Scene3DController = /*#__PURE__*/function () {
20203
20526
  }
20204
20527
  }
20205
20528
  } catch (err) {
20206
- _iterator7.e(err);
20529
+ _iterator8.e(err);
20207
20530
  } finally {
20208
- _iterator7.f();
20531
+ _iterator8.f();
20209
20532
  }
20210
20533
  });
20211
20534
  };
20212
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
20535
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
20213
20536
  _loop3();
20214
20537
  }
20215
20538
  } catch (err) {
20216
- _iterator6.e(err);
20539
+ _iterator7.e(err);
20217
20540
  } finally {
20218
- _iterator6.f();
20541
+ _iterator7.f();
20219
20542
  }
20220
20543
  if (changed) {
20221
20544
  this.map.triggerRepaint();
@@ -20224,12 +20547,12 @@ var Scene3DController = /*#__PURE__*/function () {
20224
20547
  }, {
20225
20548
  key: "loadSpriteAtlas",
20226
20549
  value: function () {
20227
- var _loadSpriteAtlas = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee5(spriteUrl) {
20550
+ var _loadSpriteAtlas = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee6(spriteUrl) {
20228
20551
  var _yield$Promise$all, _yield$Promise$all2, json, img;
20229
- return scene3DController_regenerator().w(function (_context5) {
20230
- while (1) switch (_context5.n) {
20552
+ return scene3DController_regenerator().w(function (_context6) {
20553
+ while (1) switch (_context6.n) {
20231
20554
  case 0:
20232
- _context5.n = 1;
20555
+ _context6.n = 1;
20233
20556
  return Promise.all([fetch("".concat(spriteUrl, ".json")).then(function (r) {
20234
20557
  return r.json();
20235
20558
  }), new Promise(function (resolve, reject) {
@@ -20242,29 +20565,52 @@ var Scene3DController = /*#__PURE__*/function () {
20242
20565
  image.src = "".concat(spriteUrl, ".png");
20243
20566
  })]);
20244
20567
  case 1:
20245
- _yield$Promise$all = _context5.v;
20568
+ _yield$Promise$all = _context6.v;
20246
20569
  _yield$Promise$all2 = scene3DController_slicedToArray(_yield$Promise$all, 2);
20247
20570
  json = _yield$Promise$all2[0];
20248
20571
  img = _yield$Promise$all2[1];
20249
20572
  this.spriteIconMapping = json;
20250
20573
  this.spriteAtlasImage = img;
20251
20574
  case 2:
20252
- return _context5.a(2);
20575
+ return _context6.a(2);
20253
20576
  }
20254
- }, _callee5, this);
20577
+ }, _callee6, this);
20255
20578
  }));
20256
20579
  function loadSpriteAtlas(_x2) {
20257
20580
  return _loadSpriteAtlas.apply(this, arguments);
20258
20581
  }
20259
20582
  return loadSpriteAtlas;
20260
20583
  }()
20584
+ /**
20585
+ * Cache-bounding props spread onto every deck.gl `MVTLayer` so the overlays never keep an
20586
+ * unbounded set of parsed tiles in memory. `maxCacheByteSize` is only included when configured
20587
+ * (deck.gl enforces it only when a tile's byte size is known).
20588
+ */
20589
+ }, {
20590
+ key: "deckTileCacheProps",
20591
+ get: function get() {
20592
+ var _this$deckTileCache = this.deckTileCache,
20593
+ maxCacheSize = _this$deckTileCache.maxCacheSize,
20594
+ maxRequests = _this$deckTileCache.maxRequests,
20595
+ refinementStrategy = _this$deckTileCache.refinementStrategy,
20596
+ maxCacheByteSize = _this$deckTileCache.maxCacheByteSize;
20597
+ var props = {
20598
+ maxCacheSize: maxCacheSize,
20599
+ maxRequests: maxRequests,
20600
+ refinementStrategy: refinementStrategy
20601
+ };
20602
+ if (maxCacheByteSize !== undefined) {
20603
+ props.maxCacheByteSize = maxCacheByteSize;
20604
+ }
20605
+ return props;
20606
+ }
20261
20607
  }, {
20262
20608
  key: "makeElevatedLinesLayer",
20263
20609
  value: function makeElevatedLinesLayer(floorKey, layerConfig) {
20264
20610
  var _layerConfig$binaryDa;
20265
20611
  var deck = this.deckMod;
20266
20612
  if (!deck) return null;
20267
- return new deck.MVTLayer({
20613
+ return new deck.MVTLayer(scene3DController_objectSpread(scene3DController_objectSpread({}, this.deckTileCacheProps), {}, {
20268
20614
  id: "indoor-lines-elevated",
20269
20615
  data: layerConfig.dataUrl,
20270
20616
  binary: (_layerConfig$binaryDa = layerConfig.binaryData) !== null && _layerConfig$binaryDa !== void 0 ? _layerConfig$binaryDa : false,
@@ -20289,7 +20635,7 @@ var Scene3DController = /*#__PURE__*/function () {
20289
20635
  updateTriggers: {
20290
20636
  renderSubLayers: [floorKey]
20291
20637
  }
20292
- });
20638
+ }));
20293
20639
  }
20294
20640
  }, {
20295
20641
  key: "makeLabelLayer",
@@ -20297,11 +20643,11 @@ var Scene3DController = /*#__PURE__*/function () {
20297
20643
  var _layerConfig$binaryDa2,
20298
20644
  _layerConfig$minZoom,
20299
20645
  _layerConfig$maxZoom,
20300
- _this5 = this;
20646
+ _this6 = this;
20301
20647
  var useSdf = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
20302
20648
  var deck = this.deckMod;
20303
20649
  if (!deck) return null;
20304
- return new deck.MVTLayer({
20650
+ return new deck.MVTLayer(scene3DController_objectSpread(scene3DController_objectSpread({}, this.deckTileCacheProps), {}, {
20305
20651
  id: "indoor-labels",
20306
20652
  data: layerConfig.dataUrl,
20307
20653
  binary: (_layerConfig$binaryDa2 = layerConfig.binaryData) !== null && _layerConfig$binaryDa2 !== void 0 ? _layerConfig$binaryDa2 : false,
@@ -20312,7 +20658,7 @@ var Scene3DController = /*#__PURE__*/function () {
20312
20658
  // Use area_name and poi Point features — unique per tile, no duplicates.
20313
20659
  // If a logo-{name} image exists in the sprite, the icon takes priority over the text label.
20314
20660
  var textData = buildLabelData(props.data || [], floorKey, function (imageId) {
20315
- return _this5.map.hasImage(imageId);
20661
+ return _this6.map.hasImage(imageId);
20316
20662
  }, (_layerConfig$defaultH2 = layerConfig.defaultHeight) !== null && _layerConfig$defaultH2 !== void 0 ? _layerConfig$defaultH2 : 5);
20317
20663
  if (!textData.length) return null;
20318
20664
  return new deck.TextLayer(scene3DController_objectSpread(scene3DController_objectSpread({}, props), {}, {
@@ -20343,7 +20689,7 @@ var Scene3DController = /*#__PURE__*/function () {
20343
20689
  updateTriggers: {
20344
20690
  renderSubLayers: [floorKey]
20345
20691
  }
20346
- });
20692
+ }));
20347
20693
  }
20348
20694
  }, {
20349
20695
  key: "makePoiIconLayer",
@@ -20351,10 +20697,10 @@ var Scene3DController = /*#__PURE__*/function () {
20351
20697
  var _layerConfig$binaryDa3,
20352
20698
  _layerConfig$minZoom2,
20353
20699
  _layerConfig$maxZoom2,
20354
- _this6 = this;
20700
+ _this7 = this;
20355
20701
  var deck = this.deckMod;
20356
20702
  if (!deck || !this.spriteIconMapping || !this.spriteAtlasImage) return null;
20357
- return new deck.MVTLayer({
20703
+ return new deck.MVTLayer(scene3DController_objectSpread(scene3DController_objectSpread({}, this.deckTileCacheProps), {}, {
20358
20704
  id: "indoor-poi-icons",
20359
20705
  data: layerConfig.dataUrl,
20360
20706
  binary: (_layerConfig$binaryDa3 = layerConfig.binaryData) !== null && _layerConfig$binaryDa3 !== void 0 ? _layerConfig$binaryDa3 : false,
@@ -20367,8 +20713,8 @@ var Scene3DController = /*#__PURE__*/function () {
20367
20713
  return new deck.IconLayer(scene3DController_objectSpread(scene3DController_objectSpread({}, props), {}, {
20368
20714
  id: "".concat(props.id, "-poi-icons"),
20369
20715
  data: iconData,
20370
- iconAtlas: _this6.spriteAtlasImage,
20371
- iconMapping: _this6.spriteIconMapping,
20716
+ iconAtlas: _this7.spriteAtlasImage,
20717
+ iconMapping: _this7.spriteIconMapping,
20372
20718
  getIcon: function getIcon(d) {
20373
20719
  return d.icon;
20374
20720
  },
@@ -20385,7 +20731,7 @@ var Scene3DController = /*#__PURE__*/function () {
20385
20731
  updateTriggers: {
20386
20732
  renderSubLayers: [floorKey]
20387
20733
  }
20388
- });
20734
+ }));
20389
20735
  }
20390
20736
  }, {
20391
20737
  key: "makeStoreLogoLayer",
@@ -20393,10 +20739,10 @@ var Scene3DController = /*#__PURE__*/function () {
20393
20739
  var _layerConfig$binaryDa4,
20394
20740
  _layerConfig$minZoom3,
20395
20741
  _layerConfig$maxZoom3,
20396
- _this7 = this;
20742
+ _this8 = this;
20397
20743
  var deck = this.deckMod;
20398
20744
  if (!deck || !this.spriteIconMapping || !this.spriteAtlasImage) return null;
20399
- return new deck.MVTLayer({
20745
+ return new deck.MVTLayer(scene3DController_objectSpread(scene3DController_objectSpread({}, this.deckTileCacheProps), {}, {
20400
20746
  id: "indoor-store-logos",
20401
20747
  data: layerConfig.dataUrl,
20402
20748
  binary: (_layerConfig$binaryDa4 = layerConfig.binaryData) !== null && _layerConfig$binaryDa4 !== void 0 ? _layerConfig$binaryDa4 : false,
@@ -20404,13 +20750,13 @@ var Scene3DController = /*#__PURE__*/function () {
20404
20750
  maxZoom: (_layerConfig$maxZoom3 = layerConfig.maxZoom) !== null && _layerConfig$maxZoom3 !== void 0 ? _layerConfig$maxZoom3 : 24,
20405
20751
  renderSubLayers: function renderSubLayers(props) {
20406
20752
  var _layerConfig$defaultH4, _layerConfig$sizeUnit2, _layerConfig$sizeScal2, _layerConfig$billboar2;
20407
- var logoData = buildStoreLogoData(props.data || [], floorKey, _this7.spriteIconMapping, (_layerConfig$defaultH4 = layerConfig.defaultHeight) !== null && _layerConfig$defaultH4 !== void 0 ? _layerConfig$defaultH4 : 5);
20753
+ var logoData = buildStoreLogoData(props.data || [], floorKey, _this8.spriteIconMapping, (_layerConfig$defaultH4 = layerConfig.defaultHeight) !== null && _layerConfig$defaultH4 !== void 0 ? _layerConfig$defaultH4 : 5);
20408
20754
  if (!logoData.length) return null;
20409
20755
  return new deck.IconLayer(scene3DController_objectSpread(scene3DController_objectSpread({}, props), {}, {
20410
20756
  id: "".concat(props.id, "-store-logos"),
20411
20757
  data: logoData,
20412
- iconAtlas: _this7.spriteAtlasImage,
20413
- iconMapping: _this7.spriteIconMapping,
20758
+ iconAtlas: _this8.spriteAtlasImage,
20759
+ iconMapping: _this8.spriteIconMapping,
20414
20760
  getIcon: function getIcon(d) {
20415
20761
  return d.icon;
20416
20762
  },
@@ -20422,7 +20768,7 @@ var Scene3DController = /*#__PURE__*/function () {
20422
20768
  },
20423
20769
  getSize: function getSize(d) {
20424
20770
  var _layerConfig$logoScal;
20425
- return computeStoreLogoSize(_this7.spriteIconMapping, d.icon, (_layerConfig$logoScal = layerConfig.logoScale) !== null && _layerConfig$logoScal !== void 0 ? _layerConfig$logoScal : {});
20771
+ return computeStoreLogoSize(_this8.spriteIconMapping, d.icon, (_layerConfig$logoScal = layerConfig.logoScale) !== null && _layerConfig$logoScal !== void 0 ? _layerConfig$logoScal : {});
20426
20772
  },
20427
20773
  sizeUnits: (_layerConfig$sizeUnit2 = layerConfig.sizeUnits) !== null && _layerConfig$sizeUnit2 !== void 0 ? _layerConfig$sizeUnit2 : "meters",
20428
20774
  sizeScale: (_layerConfig$sizeScal2 = layerConfig.sizeScale) !== null && _layerConfig$sizeScal2 !== void 0 ? _layerConfig$sizeScal2 : 1,
@@ -20433,7 +20779,7 @@ var Scene3DController = /*#__PURE__*/function () {
20433
20779
  updateTriggers: {
20434
20780
  renderSubLayers: [floorKey]
20435
20781
  }
20436
- });
20782
+ }));
20437
20783
  }
20438
20784
  }, {
20439
20785
  key: "updateDeckOverlay",
@@ -20467,19 +20813,19 @@ var Scene3DController = /*#__PURE__*/function () {
20467
20813
  key: "hideLayers",
20468
20814
  value: function hideLayers(layersIds) {
20469
20815
  if (!layersIds) return;
20470
- var _iterator8 = scene3DController_createForOfIteratorHelper(layersIds),
20471
- _step8;
20816
+ var _iterator9 = scene3DController_createForOfIteratorHelper(layersIds),
20817
+ _step9;
20472
20818
  try {
20473
- for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
20474
- var layerId = _step8.value;
20819
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
20820
+ var layerId = _step9.value;
20475
20821
  var layer = this.map.getLayer(layerId);
20476
20822
  if (!layer) continue;
20477
20823
  this.map.setLayoutProperty(layer.id, "visibility", "none");
20478
20824
  }
20479
20825
  } catch (err) {
20480
- _iterator8.e(err);
20826
+ _iterator9.e(err);
20481
20827
  } finally {
20482
- _iterator8.f();
20828
+ _iterator9.f();
20483
20829
  }
20484
20830
  }
20485
20831
  }]);