@mapvx/web-js 3.3.0-dev.2 → 3.3.0-dev.3

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
@@ -11240,7 +11240,7 @@ const extractSafariExtensionDetails = (func, filename) => {
11240
11240
  // exists only for the type-checker, so in the ES/CJS builds the identifier is
11241
11241
  // genuinely absent and a direct comparison throws ReferenceError at module load.
11242
11242
  // `typeof` is the only safe way to probe a possibly-undeclared global.
11243
- var sentry_SDK_VERSION = false ? 0 : "3.3.0-dev.2";
11243
+ var sentry_SDK_VERSION = false ? 0 : "3.3.0-dev.3";
11244
11244
  var DSN = false ? 0 : "https://872f598f020e3cd73a0933b562d24c81@sentry.mapvx.app/5";
11245
11245
 
11246
11246
  /**
@@ -19327,6 +19327,89 @@ function addScene3DLights(three, scene, lights) {
19327
19327
  }
19328
19328
  return count;
19329
19329
  }
19330
+
19331
+ /** Every material texture-slot property name across three.js's built-in material types. */
19332
+ var MATERIAL_TEXTURE_KEYS = ["map", "alphaMap", "aoMap", "bumpMap", "displacementMap", "emissiveMap", "envMap", "lightMap", "metalnessMap", "normalMap", "roughnessMap", "specularMap", "gradientMap", "clearcoatMap", "clearcoatNormalMap", "clearcoatRoughnessMap", "sheenColorMap", "sheenRoughnessMap", "transmissionMap", "thicknessMap", "iridescenceMap", "iridescenceThicknessMap", "anisotropyMap"];
19333
+ function disposeMaterial(three, material, disposeTextures) {
19334
+ if (disposeTextures) {
19335
+ var record = material;
19336
+ var _iterator2 = threeScene_createForOfIteratorHelper(MATERIAL_TEXTURE_KEYS),
19337
+ _step2;
19338
+ try {
19339
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
19340
+ var key = _step2.value;
19341
+ var value = record[key];
19342
+ if (value instanceof three.Texture) {
19343
+ value.dispose();
19344
+ }
19345
+ }
19346
+ } catch (err) {
19347
+ _iterator2.e(err);
19348
+ } finally {
19349
+ _iterator2.f();
19350
+ }
19351
+ }
19352
+ material.dispose();
19353
+ }
19354
+
19355
+ /**
19356
+ * Disposes every mesh's material(s) under `root`, releasing each one's GPU-side program reference,
19357
+ * without touching geometries or textures. Use this for a group whose geometries/textures are
19358
+ * shared with a still-live cache (e.g. a GLB template reused by future placements via `.clone(true)`)
19359
+ * and only its per-placement material clones (made so each placement's opacity is independent) are
19360
+ * exclusively owned by the group.
19361
+ *
19362
+ * @param three - The resolved Three.js module (from `loadThree()`).
19363
+ */
19364
+ function disposeMaterialsOnly(three, root) {
19365
+ root.traverse(function (obj) {
19366
+ var mesh = obj;
19367
+ if (!mesh.isMesh) return;
19368
+ var materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
19369
+ var _iterator3 = threeScene_createForOfIteratorHelper(materials),
19370
+ _step3;
19371
+ try {
19372
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
19373
+ var material = _step3.value;
19374
+ disposeMaterial(three, material, false);
19375
+ }
19376
+ } catch (err) {
19377
+ _iterator3.e(err);
19378
+ } finally {
19379
+ _iterator3.f();
19380
+ }
19381
+ });
19382
+ }
19383
+
19384
+ /**
19385
+ * Fully disposes every mesh's geometry, material(s), and textures under `root`. Use this only for
19386
+ * an object that exclusively owns its GPU resources — e.g. a loaded GLB template root being evicted
19387
+ * from cache — never for a placement group whose geometries/textures came from a shared template
19388
+ * (use {@link disposeMaterialsOnly} for that instead).
19389
+ *
19390
+ * @param three - The resolved Three.js module (from `loadThree()`).
19391
+ */
19392
+ function disposeObject3D(three, root) {
19393
+ root.traverse(function (obj) {
19394
+ var _mesh$geometry;
19395
+ var mesh = obj;
19396
+ if (!mesh.isMesh) return;
19397
+ (_mesh$geometry = mesh.geometry) === null || _mesh$geometry === void 0 || _mesh$geometry.dispose();
19398
+ var materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
19399
+ var _iterator4 = threeScene_createForOfIteratorHelper(materials),
19400
+ _step4;
19401
+ try {
19402
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
19403
+ var material = _step4.value;
19404
+ disposeMaterial(three, material, true);
19405
+ }
19406
+ } catch (err) {
19407
+ _iterator4.e(err);
19408
+ } finally {
19409
+ _iterator4.f();
19410
+ }
19411
+ });
19412
+ }
19330
19413
  ;// ./src/map/scene3DController.ts
19331
19414
  function scene3DController_typeof(o) { "@babel/helpers - typeof"; return scene3DController_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, scene3DController_typeof(o); }
19332
19415
  function scene3DController_ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
@@ -19335,12 +19418,12 @@ function scene3DController_slicedToArray(r, e) { return scene3DController_arrayW
19335
19418
  function scene3DController_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
19336
19419
  function scene3DController_iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
19337
19420
  function scene3DController_arrayWithHoles(r) { if (Array.isArray(r)) return r; }
19338
- function scene3DController_createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = scene3DController_unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
19339
19421
  function scene3DController_toConsumableArray(r) { return scene3DController_arrayWithoutHoles(r) || scene3DController_iterableToArray(r) || scene3DController_unsupportedIterableToArray(r) || scene3DController_nonIterableSpread(); }
19340
19422
  function scene3DController_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
19341
- function scene3DController_unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return scene3DController_arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? scene3DController_arrayLikeToArray(r, a) : void 0; } }
19342
19423
  function scene3DController_iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
19343
19424
  function scene3DController_arrayWithoutHoles(r) { if (Array.isArray(r)) return scene3DController_arrayLikeToArray(r); }
19425
+ function scene3DController_createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = scene3DController_unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
19426
+ function scene3DController_unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return scene3DController_arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? scene3DController_arrayLikeToArray(r, a) : void 0; } }
19344
19427
  function scene3DController_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; }
19345
19428
  function scene3DController_regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return scene3DController_regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (scene3DController_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, scene3DController_regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, scene3DController_regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), scene3DController_regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", scene3DController_regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), scene3DController_regeneratorDefine2(u), scene3DController_regeneratorDefine2(u, o, "Generator"), scene3DController_regeneratorDefine2(u, n, function () { return this; }), scene3DController_regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (scene3DController_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
19346
19429
  function scene3DController_regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } scene3DController_regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { scene3DController_regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, scene3DController_regeneratorDefine2(e, r, n, t); }
@@ -19393,6 +19476,8 @@ var Scene3DController = /*#__PURE__*/function () {
19393
19476
  scene3DController_defineProperty(this, "scene3DGlbLightCount", 0);
19394
19477
  /** Container group holding all placed GLB pivots; rebuilt on each floor change. */
19395
19478
  scene3DController_defineProperty(this, "scene3DModelsGroup", undefined);
19479
+ /** The GLB custom layer's renderer, stored so {@link dispose} can release it; see `createGlbCustomLayer`. */
19480
+ scene3DController_defineProperty(this, "glbRenderer", undefined);
19396
19481
  /**
19397
19482
  * Route points currently used for GLB route-transparency collision, tagged with the floor on
19398
19483
  * which each point's route segment is visible. Stored as coordinates (not pivot references) so
@@ -19500,11 +19585,20 @@ var Scene3DController = /*#__PURE__*/function () {
19500
19585
  this.applyModelOpacity();
19501
19586
  }
19502
19587
 
19503
- /** Rebuilds the deck overlay and GLB placements for the given floor. */
19588
+ /**
19589
+ * Rebuilds the deck overlay and GLB placements for the given floor. Host apps call this on every
19590
+ * floor/place-changing navigation, including many that leave the floor unchanged (e.g. re-entering
19591
+ * a screen, tapping the already-active floor selector); a no-op floor is skipped so those don't
19592
+ * trigger a full, wasteful GLB rebuild.
19593
+ */
19504
19594
  }, {
19505
19595
  key: "onFloorChange",
19506
19596
  value: function onFloorChange(currentFloor) {
19507
- this.currentFloor = currentFloor !== null && currentFloor !== void 0 ? currentFloor : "";
19597
+ var nextFloor = currentFloor !== null && currentFloor !== void 0 ? currentFloor : "";
19598
+ if (nextFloor === this.currentFloor) {
19599
+ return;
19600
+ }
19601
+ this.currentFloor = nextFloor;
19508
19602
  this.updateDeckOverlay();
19509
19603
  this.placeScene3DModels();
19510
19604
  }
@@ -19517,6 +19611,48 @@ var Scene3DController = /*#__PURE__*/function () {
19517
19611
  this.updateDeckOverlay();
19518
19612
  }
19519
19613
 
19614
+ /**
19615
+ * Releases every GPU resource this controller owns: the placed models group's material clones,
19616
+ * the cached GLB templates' geometries/materials/textures, and the `WebGLRenderer` created for the
19617
+ * declarative GLB layer. Idempotent — safe to call more than once (e.g. once via the custom
19618
+ * layer's own `onRemove` and again explicitly).
19619
+ *
19620
+ * Callers must invoke this themselves before tearing down the map: MapLibre's `map.remove()` does
19621
+ * not call a custom layer's `onRemove`, so without an explicit call here nothing ever frees these
19622
+ * resources, and every context-loss recovery cycle (destroy + recreate the map) leaks a full scene.
19623
+ */
19624
+ }, {
19625
+ key: "dispose",
19626
+ value: function dispose() {
19627
+ var _this$threeMod, _this$glbRenderer;
19628
+ var three = (_this$threeMod = this.threeMod) === null || _this$threeMod === void 0 ? void 0 : _this$threeMod.THREE;
19629
+ if (three) {
19630
+ if (this.scene3DModelsGroup) {
19631
+ disposeMaterialsOnly(three, this.scene3DModelsGroup);
19632
+ this.scene3DModelsGroup = undefined;
19633
+ }
19634
+ // Iterate the deduplicated-by-URL roots (not `scene3DGlbTemplateById`, which may map several
19635
+ // asset ids to the same root) so a shared root is never disposed more than once.
19636
+ var _iterator = scene3DController_createForOfIteratorHelper(this.scene3DGlbRootByUrl.values()),
19637
+ _step;
19638
+ try {
19639
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
19640
+ var root = _step.value;
19641
+ disposeObject3D(three, root);
19642
+ }
19643
+ } catch (err) {
19644
+ _iterator.e(err);
19645
+ } finally {
19646
+ _iterator.f();
19647
+ }
19648
+ }
19649
+ this.scene3DGlbRootByUrl.clear();
19650
+ this.scene3DGlbTemplateById.clear();
19651
+ this.scene3DGlbScene = undefined;
19652
+ (_this$glbRenderer = this.glbRenderer) === null || _this$glbRenderer === void 0 || _this$glbRenderer.dispose();
19653
+ this.glbRenderer = undefined;
19654
+ }
19655
+
19520
19656
  // Internal implementation -----------------------------------------------------------------
19521
19657
 
19522
19658
  /**
@@ -19527,15 +19663,15 @@ var Scene3DController = /*#__PURE__*/function () {
19527
19663
  key: "ensure3DLibs",
19528
19664
  value: function () {
19529
19665
  var _ensure3DLibs = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee2() {
19530
- var _this$threeMod, _this$deckMod;
19666
+ var _this$threeMod2, _this$deckMod;
19531
19667
  return scene3DController_regenerator().w(function (_context2) {
19532
19668
  while (1) switch (_context2.n) {
19533
19669
  case 0:
19534
- if (!((_this$threeMod = this.threeMod) !== null && _this$threeMod !== void 0)) {
19670
+ if (!((_this$threeMod2 = this.threeMod) !== null && _this$threeMod2 !== void 0)) {
19535
19671
  _context2.n = 1;
19536
19672
  break;
19537
19673
  }
19538
- _this$threeMod;
19674
+ _this$threeMod2;
19539
19675
  _context2.n = 3;
19540
19676
  break;
19541
19677
  case 1:
@@ -19606,6 +19742,13 @@ var Scene3DController = /*#__PURE__*/function () {
19606
19742
  renderer.setSize = function (width, height) {
19607
19743
  this.setViewport(0, 0, width, height);
19608
19744
  };
19745
+ // Stored on the controller (not just this closure) so `dispose()` can release it — MapLibre
19746
+ // does not call a custom layer's `onRemove` when the whole map/style is torn down via
19747
+ // `map.remove()`, so callers must dispose this controller explicitly before that happens.
19748
+ _this.glbRenderer = renderer;
19749
+ },
19750
+ onRemove: function onRemove() {
19751
+ _this.dispose();
19609
19752
  },
19610
19753
  render: function render(_gl, args) {
19611
19754
  var _args$defaultProjecti;
@@ -19635,13 +19778,13 @@ var Scene3DController = /*#__PURE__*/function () {
19635
19778
  key: "loadScene3DGlbTemplates",
19636
19779
  value: function () {
19637
19780
  var _loadScene3DGlbTemplates = scene3DController_asyncToGenerator(/*#__PURE__*/scene3DController_regenerator().m(function _callee4() {
19638
- var _this$threeMod2,
19781
+ var _this$threeMod3,
19639
19782
  _this2 = this;
19640
- var three, models, uniqueUrls, errorByUrl, semaphore, loadedBytesByUrl, totalBytesByUrl, settledAssets, totalAssets, reportProgress, _iterator2, _step2, asset, root, center, _t5;
19783
+ var three, models, uniqueUrls, errorByUrl, semaphore, loadedBytesByUrl, totalBytesByUrl, settledAssets, totalAssets, reportProgress, _iterator3, _step3, asset, root, center, _t5;
19641
19784
  return scene3DController_regenerator().w(function (_context4) {
19642
19785
  while (1) switch (_context4.p = _context4.n) {
19643
19786
  case 0:
19644
- three = (_this$threeMod2 = this.threeMod) === null || _this$threeMod2 === void 0 ? void 0 : _this$threeMod2.THREE;
19787
+ three = (_this$threeMod3 = this.threeMod) === null || _this$threeMod3 === void 0 ? void 0 : _this$threeMod3.THREE;
19645
19788
  models = this.scene3DConfig.models;
19646
19789
  if (!(!three || !models || models.enabled === false || models.assets.length === 0)) {
19647
19790
  _context4.n = 1;
@@ -19671,20 +19814,20 @@ var Scene3DController = /*#__PURE__*/function () {
19671
19814
  if (!_this2.onModelsProgress) return;
19672
19815
  var loadedBytes = 0;
19673
19816
  var totalBytes = 0;
19674
- var _iterator = scene3DController_createForOfIteratorHelper(uniqueUrls),
19675
- _step;
19817
+ var _iterator2 = scene3DController_createForOfIteratorHelper(uniqueUrls),
19818
+ _step2;
19676
19819
  try {
19677
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
19820
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
19678
19821
  var _loadedBytesByUrl$get;
19679
- var url = _step.value;
19822
+ var url = _step2.value;
19680
19823
  loadedBytes += (_loadedBytesByUrl$get = loadedBytesByUrl.get(url)) !== null && _loadedBytesByUrl$get !== void 0 ? _loadedBytesByUrl$get : 0;
19681
19824
  var total = totalBytesByUrl.get(url);
19682
19825
  totalBytes = total == null || totalBytes === null ? null : totalBytes + total;
19683
19826
  }
19684
19827
  } catch (err) {
19685
- _iterator.e(err);
19828
+ _iterator2.e(err);
19686
19829
  } finally {
19687
- _iterator.f();
19830
+ _iterator2.f();
19688
19831
  }
19689
19832
  try {
19690
19833
  _this2.onModelsProgress({
@@ -19752,15 +19895,15 @@ var Scene3DController = /*#__PURE__*/function () {
19752
19895
  }()));
19753
19896
  case 2:
19754
19897
  reportProgress(true);
19755
- _iterator2 = scene3DController_createForOfIteratorHelper(models.assets);
19898
+ _iterator3 = scene3DController_createForOfIteratorHelper(models.assets);
19756
19899
  _context4.p = 3;
19757
- _iterator2.s();
19900
+ _iterator3.s();
19758
19901
  case 4:
19759
- if ((_step2 = _iterator2.n()).done) {
19902
+ if ((_step3 = _iterator3.n()).done) {
19760
19903
  _context4.n = 7;
19761
19904
  break;
19762
19905
  }
19763
- asset = _step2.value;
19906
+ asset = _step3.value;
19764
19907
  root = this.scene3DGlbRootByUrl.get(asset.url);
19765
19908
  if (root) {
19766
19909
  _context4.n = 5;
@@ -19783,10 +19926,10 @@ var Scene3DController = /*#__PURE__*/function () {
19783
19926
  case 8:
19784
19927
  _context4.p = 8;
19785
19928
  _t5 = _context4.v;
19786
- _iterator2.e(_t5);
19929
+ _iterator3.e(_t5);
19787
19930
  case 9:
19788
19931
  _context4.p = 9;
19789
- _iterator2.f();
19932
+ _iterator3.f();
19790
19933
  return _context4.f(9);
19791
19934
  case 10:
19792
19935
  return _context4.a(2);
@@ -19801,7 +19944,7 @@ var Scene3DController = /*#__PURE__*/function () {
19801
19944
  }, {
19802
19945
  key: "placeScene3DModels",
19803
19946
  value: function placeScene3DModels() {
19804
- var _this$threeMod3,
19947
+ var _this$threeMod4,
19805
19948
  _models$globalOffset$,
19806
19949
  _models$globalOffset,
19807
19950
  _models$globalOffset$2,
@@ -19809,7 +19952,7 @@ var Scene3DController = /*#__PURE__*/function () {
19809
19952
  _models$globalOffset$3,
19810
19953
  _models$globalOffset3,
19811
19954
  _this3 = this;
19812
- var three = (_this$threeMod3 = this.threeMod) === null || _this$threeMod3 === void 0 ? void 0 : _this$threeMod3.THREE;
19955
+ var three = (_this$threeMod4 = this.threeMod) === null || _this$threeMod4 === void 0 ? void 0 : _this$threeMod4.THREE;
19813
19956
  if (!three || !this.scene3DGlbScene) {
19814
19957
  return;
19815
19958
  }
@@ -19818,6 +19961,10 @@ var Scene3DController = /*#__PURE__*/function () {
19818
19961
  return;
19819
19962
  }
19820
19963
  if (this.scene3DModelsGroup) {
19964
+ // Only the per-placement material clones (made below so each placement's zoom-based opacity
19965
+ // is independent) are exclusively owned by this group — geometries/textures come from the
19966
+ // cached templates and stay alive for the next rebuild, so they must not be disposed here.
19967
+ disposeMaterialsOnly(three, this.scene3DModelsGroup);
19821
19968
  this.scene3DGlbScene.remove(this.scene3DModelsGroup);
19822
19969
  this.scene3DModelsGroup = undefined;
19823
19970
  }
@@ -19829,12 +19976,12 @@ var Scene3DController = /*#__PURE__*/function () {
19829
19976
  var floorKey = this.currentFloor;
19830
19977
  var modelsGroup = new three.Group();
19831
19978
  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);
19832
- var _iterator3 = scene3DController_createForOfIteratorHelper(models.placements),
19833
- _step3;
19979
+ var _iterator4 = scene3DController_createForOfIteratorHelper(models.placements),
19980
+ _step4;
19834
19981
  try {
19835
19982
  var _loop = function _loop() {
19836
19983
  var _placement$position$a;
19837
- var placement = _step3.value;
19984
+ var placement = _step4.value;
19838
19985
  if (!isPlacementVisibleOnFloor(placement, floorKey)) {
19839
19986
  return 0; // continue
19840
19987
  }
@@ -19900,14 +20047,14 @@ var Scene3DController = /*#__PURE__*/function () {
19900
20047
  modelsGroup.add(pivot);
19901
20048
  },
19902
20049
  _ret;
19903
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
20050
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
19904
20051
  _ret = _loop();
19905
20052
  if (_ret === 0) continue;
19906
20053
  }
19907
20054
  } catch (err) {
19908
- _iterator3.e(err);
20055
+ _iterator4.e(err);
19909
20056
  } finally {
19910
- _iterator3.f();
20057
+ _iterator4.f();
19911
20058
  }
19912
20059
  this.scene3DModelsGroup = modelsGroup;
19913
20060
  this.scene3DGlbScene.add(modelsGroup);
@@ -19927,9 +20074,9 @@ var Scene3DController = /*#__PURE__*/function () {
19927
20074
  }, {
19928
20075
  key: "recomputeRouteAffectedModels",
19929
20076
  value: function recomputeRouteAffectedModels() {
19930
- var _this$threeMod4,
20077
+ var _this$threeMod5,
19931
20078
  _this4 = this;
19932
- var three = (_this$threeMod4 = this.threeMod) === null || _this$threeMod4 === void 0 ? void 0 : _this$threeMod4.THREE;
20079
+ var three = (_this$threeMod5 = this.threeMod) === null || _this$threeMod5 === void 0 ? void 0 : _this$threeMod5.THREE;
19933
20080
  var modelsGroup = this.scene3DModelsGroup;
19934
20081
  if (!three || !modelsGroup) {
19935
20082
  return;
@@ -19952,11 +20099,11 @@ var Scene3DController = /*#__PURE__*/function () {
19952
20099
  });
19953
20100
  modelsGroup.updateMatrixWorld(true);
19954
20101
  var local = new three.Vector3();
19955
- var _iterator4 = scene3DController_createForOfIteratorHelper(modelsGroup.children),
19956
- _step4;
20102
+ var _iterator5 = scene3DController_createForOfIteratorHelper(modelsGroup.children),
20103
+ _step5;
19957
20104
  try {
19958
20105
  var _loop2 = function _loop2() {
19959
- var pivot = _step4.value;
20106
+ var pivot = _step5.value;
19960
20107
  var routeCfg = pivot.userData.routeTransparency;
19961
20108
  var footprint = pivot.userData.footprint;
19962
20109
  // Only models with a route-transparency config participate (feature activation gate).
@@ -19973,13 +20120,13 @@ var Scene3DController = /*#__PURE__*/function () {
19973
20120
  return pointInFootprint(footprint, local.x, local.z);
19974
20121
  });
19975
20122
  };
19976
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
20123
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
19977
20124
  if (_loop2()) continue;
19978
20125
  }
19979
20126
  } catch (err) {
19980
- _iterator4.e(err);
20127
+ _iterator5.e(err);
19981
20128
  } finally {
19982
- _iterator4.f();
20129
+ _iterator5.f();
19983
20130
  }
19984
20131
  }
19985
20132
 
@@ -19999,11 +20146,11 @@ var Scene3DController = /*#__PURE__*/function () {
19999
20146
  }
20000
20147
  var zoom = this.map.getZoom();
20001
20148
  var changed = false;
20002
- var _iterator5 = scene3DController_createForOfIteratorHelper(this.scene3DModelsGroup.children),
20003
- _step5;
20149
+ var _iterator6 = scene3DController_createForOfIteratorHelper(this.scene3DModelsGroup.children),
20150
+ _step6;
20004
20151
  try {
20005
20152
  var _loop3 = function _loop3() {
20006
- var pivot = _step5.value;
20153
+ var pivot = _step6.value;
20007
20154
  var zoomCfg = pivot.userData.zoomTransparency;
20008
20155
  var routeCfg = pivot.userData.routeTransparency;
20009
20156
  var routeAffected = pivot.userData.routeAffected === true;
@@ -20014,11 +20161,11 @@ var Scene3DController = /*#__PURE__*/function () {
20014
20161
  return;
20015
20162
  }
20016
20163
  var materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
20017
- var _iterator6 = scene3DController_createForOfIteratorHelper(materials),
20018
- _step6;
20164
+ var _iterator7 = scene3DController_createForOfIteratorHelper(materials),
20165
+ _step7;
20019
20166
  try {
20020
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
20021
- var material = _step6.value;
20167
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
20168
+ var material = _step7.value;
20022
20169
  if (material.opacity !== opacity) {
20023
20170
  material.transparent = opacity < 1;
20024
20171
  material.opacity = opacity;
@@ -20028,19 +20175,19 @@ var Scene3DController = /*#__PURE__*/function () {
20028
20175
  }
20029
20176
  }
20030
20177
  } catch (err) {
20031
- _iterator6.e(err);
20178
+ _iterator7.e(err);
20032
20179
  } finally {
20033
- _iterator6.f();
20180
+ _iterator7.f();
20034
20181
  }
20035
20182
  });
20036
20183
  };
20037
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
20184
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
20038
20185
  _loop3();
20039
20186
  }
20040
20187
  } catch (err) {
20041
- _iterator5.e(err);
20188
+ _iterator6.e(err);
20042
20189
  } finally {
20043
- _iterator5.f();
20190
+ _iterator6.f();
20044
20191
  }
20045
20192
  if (changed) {
20046
20193
  this.map.triggerRepaint();
@@ -20292,19 +20439,19 @@ var Scene3DController = /*#__PURE__*/function () {
20292
20439
  key: "hideLayers",
20293
20440
  value: function hideLayers(layersIds) {
20294
20441
  if (!layersIds) return;
20295
- var _iterator7 = scene3DController_createForOfIteratorHelper(layersIds),
20296
- _step7;
20442
+ var _iterator8 = scene3DController_createForOfIteratorHelper(layersIds),
20443
+ _step8;
20297
20444
  try {
20298
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
20299
- var layerId = _step7.value;
20445
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
20446
+ var layerId = _step8.value;
20300
20447
  var layer = this.map.getLayer(layerId);
20301
20448
  if (!layer) continue;
20302
20449
  this.map.setLayoutProperty(layer.id, "visibility", "none");
20303
20450
  }
20304
20451
  } catch (err) {
20305
- _iterator7.e(err);
20452
+ _iterator8.e(err);
20306
20453
  } finally {
20307
- _iterator7.f();
20454
+ _iterator8.f();
20308
20455
  }
20309
20456
  }
20310
20457
  }]);
@@ -21129,8 +21276,12 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
21129
21276
  }, {
21130
21277
  key: "destroyMap",
21131
21278
  value: function destroyMap() {
21279
+ var _this$scene3D;
21132
21280
  this.circles = [];
21133
21281
  this.markerLayoutController.destroy();
21282
+ // Dispose the 3D scene's GPU resources before the map (and its shared WebGL context) go away —
21283
+ // MapLibre's own teardown never calls the custom GLB layer's `onRemove`.
21284
+ (_this$scene3D = this.scene3D) === null || _this$scene3D === void 0 || _this$scene3D.dispose();
21134
21285
  this.map.remove();
21135
21286
  this.unsubscribeFromFailedTiles();
21136
21287
  }
@@ -21183,11 +21334,11 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
21183
21334
  }, {
21184
21335
  key: "setRouteCollisionPath",
21185
21336
  value: function setRouteCollisionPath(points) {
21186
- var _this$scene3D;
21337
+ var _this$scene3D2;
21187
21338
  if (!this.is3DSceneActive()) {
21188
21339
  return;
21189
21340
  }
21190
- (_this$scene3D = this.scene3D) === null || _this$scene3D === void 0 || _this$scene3D.setRouteCollisionPath(points);
21341
+ (_this$scene3D2 = this.scene3D) === null || _this$scene3D2 === void 0 || _this$scene3D2.setRouteCollisionPath(points);
21191
21342
  }
21192
21343
 
21193
21344
  /**
@@ -21204,7 +21355,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
21204
21355
  _this$innerFloors$fin,
21205
21356
  _this$innerFloors$fin2,
21206
21357
  _this$innerFloors$,
21207
- _this$scene3D2,
21358
+ _this$scene3D3,
21208
21359
  _this9 = this;
21209
21360
  var updateStyle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
21210
21361
  var onStyleReady = arguments.length > 2 ? arguments[2] : undefined;
@@ -21219,7 +21370,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
21219
21370
  if (place) {
21220
21371
  this.subPlacesLoad(place.mapvxId);
21221
21372
  }
21222
- (_this$scene3D2 = this.scene3D) === null || _this$scene3D2 === void 0 || _this$scene3D2.onFloorChange(this.currentFloor);
21373
+ (_this$scene3D3 = this.scene3D) === null || _this$scene3D3 === void 0 || _this$scene3D3.onFloorChange(this.currentFloor);
21223
21374
  if (updateStyle) {
21224
21375
  this.repository.fetchAndParseMapStyle(place === null || place === void 0 ? void 0 : place.mapvxId).then(function (style) {
21225
21376
  var useServiceWorkerCaching = _this9.tileCacheConfig.enabled && _this9.tileCacheConfig.persistToServiceWorker;
@@ -21241,7 +21392,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
21241
21392
  }, {
21242
21393
  key: "updatePlaceAndFloor",
21243
21394
  value: function updatePlaceAndFloor(parentPlaceId, floorId) {
21244
- var _place$innerFloors$so2, _ref2, _ref3, _this$innerFloors$fin3, _this$innerFloors$2, _this$scene3D3;
21395
+ var _place$innerFloors$so2, _ref2, _ref3, _this$innerFloors$fin3, _this$innerFloors$2, _this$scene3D4;
21245
21396
  var place = this.potentialParentPlaces.find(function (place) {
21246
21397
  return place.mapvxId === parentPlaceId;
21247
21398
  });
@@ -21253,7 +21404,7 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
21253
21404
  this.currentFloor = (_ref2 = (_ref3 = floorId !== null && floorId !== void 0 ? floorId : (_this$innerFloors$fin3 = this.innerFloors.find(function (floor) {
21254
21405
  return floor.defaultFloor;
21255
21406
  })) === null || _this$innerFloors$fin3 === void 0 ? void 0 : _this$innerFloors$fin3.key) !== null && _ref3 !== void 0 ? _ref3 : (_this$innerFloors$2 = this.innerFloors[0]) === null || _this$innerFloors$2 === void 0 ? void 0 : _this$innerFloors$2.key) !== null && _ref2 !== void 0 ? _ref2 : "";
21256
- (_this$scene3D3 = this.scene3D) === null || _this$scene3D3 === void 0 || _this$scene3D3.onFloorChange(this.currentFloor);
21407
+ (_this$scene3D4 = this.scene3D) === null || _this$scene3D4 === void 0 || _this$scene3D4.onFloorChange(this.currentFloor);
21257
21408
  }
21258
21409
  }, {
21259
21410
  key: "updateParentPlaceAndFloor",
@@ -21313,14 +21464,14 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
21313
21464
  }, {
21314
21465
  key: "whenStyleUpdates",
21315
21466
  value: function whenStyleUpdates(newStyle) {
21316
- var _this$scene3D4;
21467
+ var _this$scene3D5;
21317
21468
  if (newStyle) {
21318
21469
  this.setBaseFilters(newStyle);
21319
21470
  }
21320
21471
  this.routeController.addSourcesAndLayers();
21321
21472
  this.refreshCircles();
21322
21473
  this.filterByFloorKey(this.currentFloor);
21323
- (_this$scene3D4 = this.scene3D) === null || _this$scene3D4 === void 0 || _this$scene3D4.refreshOverlay(this.currentFloor);
21474
+ (_this$scene3D5 = this.scene3D) === null || _this$scene3D5 === void 0 || _this$scene3D5.refreshOverlay(this.currentFloor);
21324
21475
  }
21325
21476
 
21326
21477
  /**
@@ -22234,9 +22385,9 @@ var InternalMapVXMap = /*#__PURE__*/function (_Loggeable) {
22234
22385
  key: "updateFloor",
22235
22386
  value: function updateFloor(floorId, options) {
22236
22387
  try {
22237
- var _this$scene3D5, _this$onFloorChange2, _options$onComplete6;
22388
+ var _this$scene3D6, _this$onFloorChange2, _options$onComplete6;
22238
22389
  this.filterByFloorKey(floorId);
22239
- (_this$scene3D5 = this.scene3D) === null || _this$scene3D5 === void 0 || _this$scene3D5.onFloorChange(this.currentFloor);
22390
+ (_this$scene3D6 = this.scene3D) === null || _this$scene3D6 === void 0 || _this$scene3D6.onFloorChange(this.currentFloor);
22240
22391
  (_this$onFloorChange2 = this.onFloorChange) === null || _this$onFloorChange2 === void 0 || _this$onFloorChange2.call(this, floorId);
22241
22392
  this.logEvent("updateFloor", {
22242
22393
  floorId: floorId