maplibre-gl-layers 0.18.0 → 0.19.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.
Files changed (38) hide show
  1. package/dist/SpriteLayer.d.ts +3 -3
  2. package/dist/config.d.ts +2 -2
  3. package/dist/const.d.ts +7 -4
  4. package/dist/default.d.ts +2 -2
  5. package/dist/gl/atlas.d.ts +2 -2
  6. package/dist/gl/hitTest.d.ts +3 -3
  7. package/dist/gl/mouseEvents.d.ts +36 -0
  8. package/dist/gl/shader.d.ts +2 -2
  9. package/dist/gl/text.d.ts +2 -2
  10. package/dist/gl/tracking.d.ts +36 -0
  11. package/dist/host/calculationHost.d.ts +15 -13
  12. package/dist/host/mapLibreProjectionHost.d.ts +2 -2
  13. package/dist/host/projectionHost.d.ts +2 -2
  14. package/dist/host/runtime.d.ts +2 -2
  15. package/dist/host/wasmCalculationHost.d.ts +7 -7
  16. package/dist/host/wasmHost.d.ts +2 -2
  17. package/dist/host/wasmProjectionHost.d.ts +2 -2
  18. package/dist/index.cjs +1136 -1102
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.mjs +1136 -1102
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/internalTypes.d.ts +18 -46
  24. package/dist/interpolation/degreeInterpolation.d.ts +8 -40
  25. package/dist/interpolation/distanceInterpolation.d.ts +9 -23
  26. package/dist/interpolation/easing.d.ts +2 -2
  27. package/dist/interpolation/interpolationChannels.d.ts +18 -6
  28. package/dist/interpolation/locationInterpolation.d.ts +30 -0
  29. package/dist/interpolation/rotationInterpolation.d.ts +2 -3
  30. package/dist/types.d.ts +57 -53
  31. package/dist/utils/color.d.ts +2 -2
  32. package/dist/utils/image.d.ts +2 -2
  33. package/dist/utils/looseQuadTree.d.ts +2 -2
  34. package/dist/utils/math.d.ts +38 -58
  35. package/dist/utils/utils.d.ts +2 -2
  36. package/dist/wasm/config.json.d.ts +2 -2
  37. package/package.json +6 -6
  38. package/dist/interpolation/interpolation.d.ts +0 -48
package/dist/index.mjs CHANGED
@@ -3,30 +3,22 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  /*!
5
5
  * name: maplibre-gl-layers
6
- * version: 0.18.0
6
+ * version: 0.19.0
7
7
  * description: MapLibre's layer extension library enabling the display, movement, and modification of large numbers of dynamic sprite images
8
8
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
9
9
  * license: MIT
10
10
  * repository.url: https://github.com/kekyo/maplibre-gl-layers.git
11
- * git.commit.hash: ca8392c8aa3aae7e0e4e3c871e195d49b125e481
11
+ * git.commit.hash: 7bc93c11d7855dedb8d60f140af4e413252c32a7
12
12
  */
13
13
  const UNLIMITED_SPRITE_SCALING_OPTIONS = {
14
14
  metersPerPixel: 1,
15
- zoomMin: 0,
16
- zoomMax: 30,
17
- scaleMin: 1,
18
- scaleMax: 1,
19
- spriteMinPixel: 0,
20
- spriteMaxPixel: 1e5
15
+ minScaleDistanceMeters: 0,
16
+ maxScaleDistanceMeters: Number.POSITIVE_INFINITY
21
17
  };
22
18
  const STANDARD_SPRITE_SCALING_OPTIONS = {
23
19
  metersPerPixel: 1,
24
- zoomMin: 8,
25
- zoomMax: 20,
26
- scaleMin: 0.1,
27
- scaleMax: 1,
28
- spriteMinPixel: 24,
29
- spriteMaxPixel: 100
20
+ minScaleDistanceMeters: 500,
21
+ maxScaleDistanceMeters: 1e4
30
22
  };
31
23
  const DEFAULT_TEXTURE_FILTERING_OPTIONS = {
32
24
  minFilter: "linear",
@@ -22369,6 +22361,13 @@ const __CSS_KEYWORD_COLORS = {
22369
22361
  const CSS_KEYWORD_COLORS = __CSS_KEYWORD_COLORS;
22370
22362
  const DEFAULT_BORDER_COLOR = "red";
22371
22363
  const DEFAULT_BORDER_COLOR_RGBA = CSS_KEYWORD_COLORS.red;
22364
+ const resolveOffsetInput$1 = (offset) => {
22365
+ var _a, _b;
22366
+ return {
22367
+ offsetMeters: (_a = offset == null ? void 0 : offset.offsetMeters) != null ? _a : DEFAULT_IMAGE_OFFSET.offsetMeters,
22368
+ offsetDeg: (_b = offset == null ? void 0 : offset.offsetDeg) != null ? _b : DEFAULT_IMAGE_OFFSET.offsetDeg
22369
+ };
22370
+ };
22372
22371
  const cloneSpriteLocation = (location2) => {
22373
22372
  if (location2.z === void 0) {
22374
22373
  return { lng: location2.lng, lat: location2.lat };
@@ -22468,105 +22467,45 @@ const resolveScalingOptions = (options) => {
22468
22467
  }
22469
22468
  metersPerPixel = fallbackMetersPerPixel;
22470
22469
  }
22471
- const fallbackZoomMin = Number.isFinite(base.zoomMin) ? base.zoomMin : 0;
22472
- let zoomMin = (options == null ? void 0 : options.zoomMin) !== void 0 ? options.zoomMin : fallbackZoomMin;
22473
- if (!Number.isFinite(zoomMin)) {
22474
- if ((options == null ? void 0 : options.zoomMin) !== void 0) {
22475
- warnings.push(
22476
- `zoomMin(${String(options.zoomMin)}) is not finite; using ${fallbackZoomMin}`
22477
- );
22478
- }
22479
- zoomMin = fallbackZoomMin;
22480
- }
22481
- const fallbackZoomMax = Number.isFinite(base.zoomMax) && base.zoomMax > fallbackZoomMin ? base.zoomMax : fallbackZoomMin;
22482
- let zoomMax = (options == null ? void 0 : options.zoomMax) !== void 0 ? options.zoomMax : fallbackZoomMax;
22483
- if (!Number.isFinite(zoomMax)) {
22484
- if ((options == null ? void 0 : options.zoomMax) !== void 0) {
22485
- warnings.push(
22486
- `zoomMax(${String(options.zoomMax)}) is not finite; using ${fallbackZoomMax}`
22487
- );
22488
- }
22489
- zoomMax = fallbackZoomMax;
22490
- }
22491
- if (zoomMax < zoomMin) {
22492
- warnings.push(
22493
- `zoomMax(${zoomMax}) < zoomMin(${zoomMin}); swapped values to maintain ascending order`
22494
- );
22495
- [zoomMin, zoomMax] = [zoomMax, zoomMin];
22496
- }
22497
- const fallbackScaleMin = Number.isFinite(base.scaleMin) ? base.scaleMin : 1;
22498
- let scaleMin = (options == null ? void 0 : options.scaleMin) !== void 0 ? options.scaleMin : fallbackScaleMin;
22499
- if (!Number.isFinite(scaleMin)) {
22500
- if ((options == null ? void 0 : options.scaleMin) !== void 0) {
22501
- warnings.push(
22502
- `scaleMin(${String(options.scaleMin)}) is not finite; using ${fallbackScaleMin}`
22503
- );
22504
- }
22505
- scaleMin = fallbackScaleMin;
22506
- }
22507
- if (scaleMin < 0) {
22508
- warnings.push(`scaleMin(${scaleMin}) is negative; clamped to 0`);
22509
- scaleMin = 0;
22510
- }
22511
- const fallbackScaleMax = Number.isFinite(base.scaleMax) ? base.scaleMax : 1;
22512
- let scaleMax = (options == null ? void 0 : options.scaleMax) !== void 0 ? options.scaleMax : fallbackScaleMax;
22513
- if (!Number.isFinite(scaleMax)) {
22514
- if ((options == null ? void 0 : options.scaleMax) !== void 0) {
22515
- warnings.push(
22516
- `scaleMax(${String(options.scaleMax)}) is not finite; using ${fallbackScaleMax}`
22517
- );
22518
- }
22519
- scaleMax = fallbackScaleMax;
22520
- }
22521
- if (scaleMax < 0) {
22522
- warnings.push(`scaleMax(${scaleMax}) is negative; clamped to 0`);
22523
- scaleMax = 0;
22524
- }
22525
- if (scaleMax < scaleMin) {
22526
- warnings.push(
22527
- `scaleMax(${scaleMax}) < scaleMin(${scaleMin}); swapped values to maintain ascending order`
22528
- );
22529
- [scaleMin, scaleMax] = [scaleMax, scaleMin];
22530
- }
22531
- const fallbackSpriteMin = Number.isFinite(base.spriteMinPixel) && base.spriteMinPixel >= 0 ? base.spriteMinPixel : 0;
22532
- let spriteMinPixel = (options == null ? void 0 : options.spriteMinPixel) !== void 0 ? options.spriteMinPixel : fallbackSpriteMin;
22533
- if (!Number.isFinite(spriteMinPixel)) {
22534
- if ((options == null ? void 0 : options.spriteMinPixel) !== void 0) {
22470
+ const fallbackMinDistance = base.minScaleDistanceMeters !== void 0 && Number.isFinite(base.minScaleDistanceMeters) && base.minScaleDistanceMeters > 0 ? base.minScaleDistanceMeters : 0;
22471
+ let minScaleDistanceMeters = (options == null ? void 0 : options.minScaleDistanceMeters) !== void 0 ? options.minScaleDistanceMeters : fallbackMinDistance;
22472
+ if (!Number.isFinite(minScaleDistanceMeters) || minScaleDistanceMeters < 0) {
22473
+ if ((options == null ? void 0 : options.minScaleDistanceMeters) !== void 0) {
22535
22474
  warnings.push(
22536
- `spriteMinPixel(${String(
22537
- options.spriteMinPixel
22538
- )}) is not finite; using ${fallbackSpriteMin}`
22475
+ `minScaleDistanceMeters(${String(
22476
+ options.minScaleDistanceMeters
22477
+ )}) is invalid; using ${fallbackMinDistance}`
22539
22478
  );
22540
22479
  }
22541
- spriteMinPixel = fallbackSpriteMin;
22542
- } else if (spriteMinPixel < 0) {
22543
- warnings.push(
22544
- `spriteMinPixel(${spriteMinPixel}) is negative; clamped to 0`
22545
- );
22546
- spriteMinPixel = 0;
22480
+ minScaleDistanceMeters = fallbackMinDistance;
22547
22481
  }
22548
- const fallbackSpriteMax = Number.isFinite(base.spriteMaxPixel) && base.spriteMaxPixel >= 0 ? base.spriteMaxPixel : 0;
22549
- let spriteMaxPixel = (options == null ? void 0 : options.spriteMaxPixel) !== void 0 ? options.spriteMaxPixel : fallbackSpriteMax;
22550
- if (!Number.isFinite(spriteMaxPixel)) {
22551
- if ((options == null ? void 0 : options.spriteMaxPixel) !== void 0) {
22482
+ const baseMaxDistance = base.maxScaleDistanceMeters !== void 0 && base.maxScaleDistanceMeters > 0 ? base.maxScaleDistanceMeters : Number.POSITIVE_INFINITY;
22483
+ const fallbackMaxDistance = Number.isFinite(baseMaxDistance) ? baseMaxDistance : Number.POSITIVE_INFINITY;
22484
+ let maxScaleDistanceMeters = (options == null ? void 0 : options.maxScaleDistanceMeters) !== void 0 ? options.maxScaleDistanceMeters : fallbackMaxDistance;
22485
+ const maxIsInfinite = maxScaleDistanceMeters === Number.POSITIVE_INFINITY && (options == null ? void 0 : options.maxScaleDistanceMeters) !== 0;
22486
+ if (!Number.isFinite(maxScaleDistanceMeters) && !maxIsInfinite) {
22487
+ if ((options == null ? void 0 : options.maxScaleDistanceMeters) !== void 0) {
22552
22488
  warnings.push(
22553
- `spriteMaxPixel(${String(
22554
- options.spriteMaxPixel
22555
- )}) is not finite; using ${fallbackSpriteMax}`
22489
+ `maxScaleDistanceMeters(${String(
22490
+ options.maxScaleDistanceMeters
22491
+ )}) is not finite; using ${fallbackMaxDistance}`
22556
22492
  );
22557
22493
  }
22558
- spriteMaxPixel = fallbackSpriteMax;
22559
- } else if (spriteMaxPixel < 0) {
22494
+ maxScaleDistanceMeters = fallbackMaxDistance;
22495
+ } else if (Number.isFinite(maxScaleDistanceMeters) && maxScaleDistanceMeters <= 0) {
22560
22496
  warnings.push(
22561
- `spriteMaxPixel(${spriteMaxPixel}) is negative; clamped to 0`
22497
+ `maxScaleDistanceMeters(${maxScaleDistanceMeters}) is non-positive; treated as unlimited`
22562
22498
  );
22563
- spriteMaxPixel = 0;
22499
+ maxScaleDistanceMeters = fallbackMaxDistance;
22564
22500
  }
22565
- if (spriteMinPixel > 0 && spriteMaxPixel > 0 && spriteMaxPixel < spriteMinPixel) {
22501
+ if (Number.isFinite(maxScaleDistanceMeters) && maxScaleDistanceMeters < minScaleDistanceMeters) {
22566
22502
  warnings.push(
22567
- `spriteMaxPixel(${spriteMaxPixel}) < spriteMinPixel(${spriteMinPixel}); swapped values to maintain ascending order`
22503
+ `maxScaleDistanceMeters(${maxScaleDistanceMeters}) < minScaleDistanceMeters(${minScaleDistanceMeters}); swapped values to maintain ascending order`
22568
22504
  );
22569
- [spriteMinPixel, spriteMaxPixel] = [spriteMaxPixel, spriteMinPixel];
22505
+ [minScaleDistanceMeters, maxScaleDistanceMeters] = [
22506
+ maxScaleDistanceMeters,
22507
+ minScaleDistanceMeters
22508
+ ];
22570
22509
  }
22571
22510
  if (warnings.length > 0 && typeof console !== "undefined") {
22572
22511
  const warn = (_b = console.warn) != null ? _b : null;
@@ -22576,27 +22515,26 @@ const resolveScalingOptions = (options) => {
22576
22515
  }
22577
22516
  return {
22578
22517
  metersPerPixel,
22579
- zoomMin,
22580
- zoomMax,
22581
- scaleMin,
22582
- scaleMax,
22583
- spriteMinPixel,
22584
- spriteMaxPixel
22518
+ minScaleDistanceMeters,
22519
+ maxScaleDistanceMeters
22585
22520
  };
22586
22521
  };
22587
- const calculateZoomScaleFactor = (zoom, scaling) => {
22588
- const { zoomMin, zoomMax, scaleMin, scaleMax } = scaling;
22589
- if (zoomMax <= zoomMin) {
22590
- return scaleMax;
22522
+ const calculateDistanceScaleFactor = (distanceMeters, scaling) => {
22523
+ if (!Number.isFinite(distanceMeters) || distanceMeters <= 0) {
22524
+ return 1;
22591
22525
  }
22592
- if (zoom <= zoomMin) {
22593
- return scaleMin;
22526
+ const minDistance = Math.max(0, scaling.minScaleDistanceMeters);
22527
+ const hasMax = Number.isFinite(scaling.maxScaleDistanceMeters) && scaling.maxScaleDistanceMeters > 0;
22528
+ let clamped = distanceMeters;
22529
+ if (minDistance > 0 && distanceMeters < minDistance) {
22530
+ clamped = minDistance;
22531
+ } else if (hasMax && distanceMeters > scaling.maxScaleDistanceMeters) {
22532
+ clamped = scaling.maxScaleDistanceMeters;
22594
22533
  }
22595
- if (zoom >= zoomMax) {
22596
- return scaleMax;
22534
+ if (clamped === distanceMeters || clamped === 0) {
22535
+ return 1;
22597
22536
  }
22598
- const t = (zoom - zoomMin) / (zoomMax - zoomMin);
22599
- return scaleMin + (scaleMax - scaleMin) * t;
22537
+ return distanceMeters / clamped;
22600
22538
  };
22601
22539
  const calculateMetersPerPixelAtLatitude = (zoom, latitude) => {
22602
22540
  const cosLatitude = Math.cos(latitude * DEG2RAD);
@@ -22639,49 +22577,20 @@ const calculateDistanceAndBearingMeters = (from, to) => {
22639
22577
  }
22640
22578
  return { distanceMeters, bearingDeg };
22641
22579
  };
22642
- const clampSpritePixelSize = (width, height, spriteMinPixel, spriteMaxPixel) => {
22643
- const largest = Math.max(width, height);
22644
- if (!Number.isFinite(largest) || largest <= 0) {
22645
- return { width, height, scaleAdjustment: 1 };
22646
- }
22647
- let nextWidth = width;
22648
- let nextHeight = height;
22649
- let scaleAdjustment = 1;
22650
- let adjustedLargest = largest;
22651
- if (spriteMinPixel > 0 && largest < spriteMinPixel) {
22652
- const factor = spriteMinPixel / largest;
22653
- nextWidth *= factor;
22654
- nextHeight *= factor;
22655
- scaleAdjustment *= factor;
22656
- adjustedLargest *= factor;
22657
- }
22658
- if (spriteMaxPixel > 0 && adjustedLargest > spriteMaxPixel) {
22659
- const factor = spriteMaxPixel / adjustedLargest;
22660
- nextWidth *= factor;
22661
- nextHeight *= factor;
22662
- scaleAdjustment *= factor;
22663
- }
22664
- return { width: nextWidth, height: nextHeight, scaleAdjustment };
22665
- };
22666
- const calculateBillboardPixelDimensions = (imageWidth, imageHeight, baseMetersPerPixel, imageScale, zoomScaleFactor, effectivePixelsPerMeter, spriteMinPixel, spriteMaxPixel) => {
22580
+ const calculateBillboardPixelDimensions = (imageWidth, imageHeight, baseMetersPerPixel, imageScale, distanceScaleFactor, effectivePixelsPerMeter) => {
22667
22581
  if (!imageWidth || !imageHeight || imageWidth <= 0 || imageHeight <= 0 || baseMetersPerPixel <= 0 || effectivePixelsPerMeter <= 0) {
22668
22582
  return { width: 0, height: 0, scaleAdjustment: 1 };
22669
22583
  }
22670
- const scaleFactor = baseMetersPerPixel * imageScale * zoomScaleFactor * effectivePixelsPerMeter;
22671
- const rawWidth = ensureFinite(imageWidth * scaleFactor);
22672
- const rawHeight = ensureFinite(imageHeight * scaleFactor);
22673
- return clampSpritePixelSize(
22674
- rawWidth,
22675
- rawHeight,
22676
- spriteMinPixel,
22677
- spriteMaxPixel
22678
- );
22584
+ const scaleFactor = baseMetersPerPixel * imageScale * distanceScaleFactor * effectivePixelsPerMeter;
22585
+ const width = ensureFinite(imageWidth * scaleFactor);
22586
+ const height = ensureFinite(imageHeight * scaleFactor);
22587
+ return { width, height, scaleAdjustment: 1 };
22679
22588
  };
22680
- const calculateBillboardOffsetPixels = (offset, imageScale, zoomScaleFactor, effectivePixelsPerMeter, sizeScaleAdjustment = 1) => {
22681
- var _a, _b;
22682
- const offsetMeters = ((_a = offset == null ? void 0 : offset.offsetMeters) != null ? _a : 0) * imageScale * zoomScaleFactor;
22589
+ const calculateBillboardOffsetPixels = (offset, imageScale, distanceScaleFactor, effectivePixelsPerMeter, sizeScaleAdjustment = 1) => {
22590
+ const resolved = resolveOffsetInput$1(offset);
22591
+ const offsetMeters = resolved.offsetMeters * imageScale * distanceScaleFactor;
22683
22592
  const offsetPixels = offsetMeters * effectivePixelsPerMeter * sizeScaleAdjustment;
22684
- const offsetRad = ((_b = offset == null ? void 0 : offset.offsetDeg) != null ? _b : 0) * DEG2RAD;
22593
+ const offsetRad = resolved.offsetDeg * DEG2RAD;
22685
22594
  return {
22686
22595
  x: offsetPixels * Math.sin(offsetRad),
22687
22596
  y: offsetPixels * Math.cos(offsetRad)
@@ -22704,40 +22613,14 @@ const calculateBillboardAnchorShiftPixels = (halfWidth, halfHeight, anchor, tota
22704
22613
  const shiftY = -anchorX * sinR - anchorY * cosR;
22705
22614
  return { x: shiftX, y: shiftY };
22706
22615
  };
22707
- const calculateSurfaceWorldDimensions = (imageWidth, imageHeight, baseMetersPerPixel, imageScale, zoomScaleFactor, options) => {
22708
- var _a, _b;
22616
+ const calculateSurfaceWorldDimensions = (imageWidth, imageHeight, baseMetersPerPixel, imageScale, distanceScaleFactor) => {
22709
22617
  if (!imageWidth || !imageHeight || imageWidth <= 0 || imageHeight <= 0 || baseMetersPerPixel <= 0) {
22710
22618
  return { width: 0, height: 0, scaleAdjustment: 1 };
22711
22619
  }
22712
- const scaleFactor = baseMetersPerPixel * imageScale * zoomScaleFactor;
22713
- let width = ensureFinite(imageWidth * scaleFactor);
22714
- let height = ensureFinite(imageHeight * scaleFactor);
22715
- let scaleAdjustment = 1;
22716
- const effectivePixelsPerMeter = (options == null ? void 0 : options.effectivePixelsPerMeter) !== void 0 ? options.effectivePixelsPerMeter : 0;
22717
- const spriteMinPixel = (_a = options == null ? void 0 : options.spriteMinPixel) != null ? _a : 0;
22718
- const spriteMaxPixel = (_b = options == null ? void 0 : options.spriteMaxPixel) != null ? _b : 0;
22719
- if (effectivePixelsPerMeter > 0 && Number.isFinite(effectivePixelsPerMeter) && (spriteMinPixel > 0 || spriteMaxPixel > 0)) {
22720
- const largestMeters = Math.max(width, height);
22721
- if (largestMeters > 0 && Number.isFinite(largestMeters)) {
22722
- const largestPixels = largestMeters * effectivePixelsPerMeter;
22723
- if (Number.isFinite(largestPixels) && largestPixels > 0) {
22724
- let scale2 = 1;
22725
- if (spriteMinPixel > 0 && largestPixels < spriteMinPixel) {
22726
- scale2 = spriteMinPixel / largestPixels;
22727
- }
22728
- const scaledLargest = largestPixels * scale2;
22729
- if (spriteMaxPixel > 0 && scaledLargest > spriteMaxPixel) {
22730
- scale2 = spriteMaxPixel / largestPixels;
22731
- }
22732
- if (scale2 !== 1) {
22733
- width *= scale2;
22734
- height *= scale2;
22735
- scaleAdjustment *= scale2;
22736
- }
22737
- }
22738
- }
22739
- }
22740
- return { width, height, scaleAdjustment };
22620
+ const scaleFactor = baseMetersPerPixel * imageScale * distanceScaleFactor;
22621
+ const width = ensureFinite(imageWidth * scaleFactor);
22622
+ const height = ensureFinite(imageHeight * scaleFactor);
22623
+ return { width, height, scaleAdjustment: 1 };
22741
22624
  };
22742
22625
  const calculateSurfaceAnchorShiftMeters = (halfWidthMeters, halfHeightMeters, anchor, totalRotateDeg) => {
22743
22626
  var _a, _b;
@@ -22756,13 +22639,13 @@ const calculateSurfaceAnchorShiftMeters = (halfWidthMeters, halfHeightMeters, an
22756
22639
  const north = -anchorEast * sinR - anchorNorth * cosR;
22757
22640
  return { east, north };
22758
22641
  };
22759
- const calculateSurfaceOffsetMeters = (offset, imageScale, zoomScaleFactor, sizeScaleAdjustment = 1) => {
22760
- var _a, _b;
22761
- const offsetMeters = ((_a = offset == null ? void 0 : offset.offsetMeters) != null ? _a : 0) * imageScale * zoomScaleFactor;
22642
+ const calculateSurfaceOffsetMeters = (offset, imageScale, distanceScaleFactor, sizeScaleAdjustment = 1) => {
22643
+ const resolved = resolveOffsetInput$1(offset);
22644
+ const offsetMeters = resolved.offsetMeters * imageScale * distanceScaleFactor;
22762
22645
  if (offsetMeters === 0) {
22763
22646
  return { east: 0, north: 0 };
22764
22647
  }
22765
- const rad = ((_b = offset == null ? void 0 : offset.offsetDeg) != null ? _b : 0) * DEG2RAD;
22648
+ const rad = resolved.offsetDeg * DEG2RAD;
22766
22649
  return {
22767
22650
  east: offsetMeters * Math.sin(rad) * sizeScaleAdjustment,
22768
22651
  north: offsetMeters * Math.cos(rad) * sizeScaleAdjustment
@@ -22856,10 +22739,8 @@ const calculateBillboardCenterPosition = (params) => {
22856
22739
  imageHeight,
22857
22740
  baseMetersPerPixel,
22858
22741
  imageScale,
22859
- zoomScaleFactor,
22742
+ distanceScaleFactor,
22860
22743
  effectivePixelsPerMeter,
22861
- spriteMinPixel,
22862
- spriteMaxPixel,
22863
22744
  totalRotateDeg,
22864
22745
  anchor,
22865
22746
  offset
@@ -22869,10 +22750,8 @@ const calculateBillboardCenterPosition = (params) => {
22869
22750
  imageHeight,
22870
22751
  baseMetersPerPixel,
22871
22752
  imageScale,
22872
- zoomScaleFactor,
22873
- effectivePixelsPerMeter,
22874
- spriteMinPixel,
22875
- spriteMaxPixel
22753
+ distanceScaleFactor,
22754
+ effectivePixelsPerMeter
22876
22755
  );
22877
22756
  const halfWidth = pixelDims.width / 2;
22878
22757
  const halfHeight = pixelDims.height / 2;
@@ -22885,7 +22764,7 @@ const calculateBillboardCenterPosition = (params) => {
22885
22764
  const offsetShift = calculateBillboardOffsetPixels(
22886
22765
  offset,
22887
22766
  imageScale,
22888
- zoomScaleFactor,
22767
+ distanceScaleFactor,
22889
22768
  effectivePixelsPerMeter,
22890
22769
  pixelDims.scaleAdjustment
22891
22770
  );
@@ -22998,13 +22877,10 @@ const calculateSurfaceCenterPosition = (params) => {
22998
22877
  imageHeight,
22999
22878
  baseMetersPerPixel,
23000
22879
  imageScale,
23001
- zoomScaleFactor,
22880
+ distanceScaleFactor,
23002
22881
  totalRotateDeg,
23003
22882
  anchor,
23004
22883
  offset,
23005
- effectivePixelsPerMeter = 0,
23006
- spriteMinPixel = 0,
23007
- spriteMaxPixel = 0,
23008
22884
  project,
23009
22885
  projectToClipSpace,
23010
22886
  drawingBufferWidth,
@@ -23035,12 +22911,7 @@ const calculateSurfaceCenterPosition = (params) => {
23035
22911
  imageHeight,
23036
22912
  baseMetersPerPixel,
23037
22913
  imageScale,
23038
- zoomScaleFactor,
23039
- {
23040
- effectivePixelsPerMeter,
23041
- spriteMinPixel,
23042
- spriteMaxPixel
23043
- }
22914
+ distanceScaleFactor
23044
22915
  );
23045
22916
  const halfWidthMeters = worldDims.width / 2;
23046
22917
  const halfHeightMeters = worldDims.height / 2;
@@ -23053,7 +22924,7 @@ const calculateSurfaceCenterPosition = (params) => {
23053
22924
  const offsetMeters = calculateSurfaceOffsetMeters(
23054
22925
  offset,
23055
22926
  imageScale,
23056
- zoomScaleFactor,
22927
+ distanceScaleFactor,
23057
22928
  worldDims.scaleAdjustment
23058
22929
  );
23059
22930
  const totalDisplacement = {
@@ -23148,6 +23019,17 @@ const clampOpacity = (value) => {
23148
23019
  }
23149
23020
  return value;
23150
23021
  };
23022
+ const normalizeDuration$2 = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
23023
+ const normalizeOptions$2 = (options) => {
23024
+ var _a;
23025
+ const resolved = resolveEasing(options.easing);
23026
+ return {
23027
+ durationMs: normalizeDuration$2(options.durationMs),
23028
+ easingFunc: resolved.func,
23029
+ easingParam: resolved.param,
23030
+ mode: (_a = options.mode) != null ? _a : "feedback"
23031
+ };
23032
+ };
23151
23033
  const computeFeedforwardTarget = (previous, next) => {
23152
23034
  var _a, _b;
23153
23035
  if (!previous) {
@@ -23156,27 +23038,16 @@ const computeFeedforwardTarget = (previous, next) => {
23156
23038
  const prevZ = (_a = previous.z) != null ? _a : 0;
23157
23039
  const nextZ = (_b = next.z) != null ? _b : 0;
23158
23040
  const hasZ = previous.z !== void 0 || next.z !== void 0;
23159
- const target = {
23041
+ return {
23160
23042
  lng: next.lng + (next.lng - previous.lng),
23161
23043
  lat: next.lat + (next.lat - previous.lat),
23162
- // Only extrapolate altitude when either point includes z; otherwise we maintain the 2D assumption.
23163
23044
  z: hasZ ? nextZ + (nextZ - prevZ) : void 0
23164
23045
  };
23165
- return target;
23166
23046
  };
23167
- const normalizeOptions$2 = (options) => {
23168
- var _a;
23169
- return {
23170
- durationMs: Math.max(0, options.durationMs),
23171
- mode: (_a = options.mode) != null ? _a : "feedback",
23172
- easing: options.easing
23173
- };
23174
- };
23175
- const createInterpolationState = (params) => {
23047
+ const createLocationInterpolationState = (params) => {
23176
23048
  const { currentLocation, lastCommandLocation, nextCommandLocation } = params;
23177
23049
  const options = normalizeOptions$2(params.options);
23178
23050
  const from = cloneSpriteLocation(currentLocation);
23179
- const resolvedEasing = resolveEasing(options.easing);
23180
23051
  const commandTarget = cloneSpriteLocation(nextCommandLocation);
23181
23052
  let pathTarget;
23182
23053
  if (options.mode === "feedforward") {
@@ -23189,8 +23060,8 @@ const createInterpolationState = (params) => {
23189
23060
  const state = {
23190
23061
  mode: options.mode,
23191
23062
  durationMs: options.durationMs,
23192
- easingFunc: resolvedEasing.func,
23193
- easingParam: resolvedEasing.param,
23063
+ easingFunc: options.easingFunc,
23064
+ easingParam: options.easingParam,
23194
23065
  startTimestamp: -1,
23195
23066
  from,
23196
23067
  to: commandTarget,
@@ -23198,17 +23069,15 @@ const createInterpolationState = (params) => {
23198
23069
  };
23199
23070
  return { state, requiresInterpolation };
23200
23071
  };
23201
- const evaluateInterpolation = (params) => {
23072
+ const evaluateLocationInterpolation = (state, timestamp) => {
23202
23073
  var _a;
23203
- const { state } = params;
23204
23074
  const easingFn = state.easingFunc;
23205
- const timestamp = Number.isFinite(params.timestamp) ? params.timestamp : Date.now();
23206
23075
  const duration = Math.max(0, state.durationMs);
23207
23076
  const effectiveStart = state.startTimestamp >= 0 ? state.startTimestamp : timestamp;
23208
23077
  const target = (_a = state.pathTarget) != null ? _a : state.to;
23209
23078
  if (duration === 0 || spriteLocationsEqual(state.from, target)) {
23210
23079
  return {
23211
- location: cloneSpriteLocation(state.to),
23080
+ value: cloneSpriteLocation(state.to),
23212
23081
  completed: true,
23213
23082
  effectiveStartTimestamp: effectiveStart
23214
23083
  };
@@ -23216,14 +23085,155 @@ const evaluateInterpolation = (params) => {
23216
23085
  const elapsed = timestamp - effectiveStart;
23217
23086
  const rawProgress = duration <= 0 ? 1 : elapsed / duration;
23218
23087
  const eased = easingFn(rawProgress);
23219
- const location2 = lerpSpriteLocation(state.from, target, eased);
23088
+ const value = lerpSpriteLocation(state.from, target, eased);
23220
23089
  const completed = rawProgress >= 1;
23221
23090
  return {
23222
- location: location2,
23091
+ value,
23223
23092
  completed,
23224
23093
  effectiveStartTimestamp: effectiveStart
23225
23094
  };
23226
23095
  };
23096
+ const evaluateLocationInterpolationsBatch = (states, timestamp) => {
23097
+ if (!states.length) {
23098
+ return [];
23099
+ }
23100
+ return states.map((state) => evaluateLocationInterpolation(state, timestamp));
23101
+ };
23102
+ const collectLocationInterpolationWorkItems = (sprite, workItems) => {
23103
+ const state = sprite.location.interpolation.state;
23104
+ if (state) {
23105
+ workItems.push({ ...state, sprite });
23106
+ }
23107
+ };
23108
+ const applyLocationInterpolationEvaluations = (workItems, evaluations, timestamp) => {
23109
+ var _a;
23110
+ let active = false;
23111
+ for (let index = 0; index < workItems.length; index += 1) {
23112
+ const item = workItems[index];
23113
+ const { sprite } = item;
23114
+ const evaluation = (_a = evaluations[index]) != null ? _a : evaluateLocationInterpolation(item, timestamp);
23115
+ if (item.startTimestamp < 0) {
23116
+ const effectiveStart = evaluation.effectiveStartTimestamp;
23117
+ item.startTimestamp = effectiveStart;
23118
+ const interpolationState = sprite.location.interpolation.state;
23119
+ if (interpolationState && interpolationState.startTimestamp < 0) {
23120
+ interpolationState.startTimestamp = effectiveStart;
23121
+ }
23122
+ }
23123
+ sprite.location.current = evaluation.value;
23124
+ if (evaluation.completed) {
23125
+ sprite.location.current = cloneSpriteLocation(item.to);
23126
+ sprite.location.from = void 0;
23127
+ sprite.location.to = void 0;
23128
+ sprite.location.interpolation.state = null;
23129
+ } else {
23130
+ active = true;
23131
+ }
23132
+ }
23133
+ return active;
23134
+ };
23135
+ const clamp01$2 = (value) => Math.min(1, Math.max(0, value));
23136
+ const clamp255 = (value) => Math.min(255, Math.max(0, value));
23137
+ const normalizeRgba = (r, g, b, a) => [
23138
+ clamp255(r) / 255,
23139
+ clamp255(g) / 255,
23140
+ clamp255(b) / 255,
23141
+ clamp01$2(a)
23142
+ ];
23143
+ const tryParseHexColor = (value) => {
23144
+ var _a;
23145
+ const match = /^#([0-9a-f]{3,8})$/i.exec(value.trim());
23146
+ if (!match) {
23147
+ return null;
23148
+ }
23149
+ const hex = (_a = match[1]) != null ? _a : "";
23150
+ if (hex.length === 3) {
23151
+ const [r, g, b] = hex.split("").map((c) => parseInt(c + c, 16));
23152
+ return normalizeRgba(r, g, b, 1);
23153
+ }
23154
+ if (hex.length === 4) {
23155
+ const [r, g, b, a] = hex.split("").map((c) => parseInt(c + c, 16));
23156
+ return normalizeRgba(r, g, b, a / 255);
23157
+ }
23158
+ if (hex.length === 6 || hex.length === 8) {
23159
+ const r = parseInt(hex.slice(0, 2), 16);
23160
+ const g = parseInt(hex.slice(2, 4), 16);
23161
+ const b = parseInt(hex.slice(4, 6), 16);
23162
+ const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) : 255;
23163
+ return normalizeRgba(r, g, b, a / 255);
23164
+ }
23165
+ return null;
23166
+ };
23167
+ const parseChannel = (value) => {
23168
+ if (value.endsWith("%")) {
23169
+ const percent = Number.parseFloat(value.slice(0, -1));
23170
+ if (!Number.isFinite(percent)) {
23171
+ return Number.NaN;
23172
+ }
23173
+ return clamp255(percent / 100 * 255);
23174
+ }
23175
+ const number = Number.parseFloat(value);
23176
+ return Number.isFinite(number) ? clamp255(number) : Number.NaN;
23177
+ };
23178
+ const parseAlpha = (value) => {
23179
+ if (value === void 0) {
23180
+ return 1;
23181
+ }
23182
+ if (value.endsWith("%")) {
23183
+ const percent = Number.parseFloat(value.slice(0, -1));
23184
+ if (!Number.isFinite(percent)) {
23185
+ return Number.NaN;
23186
+ }
23187
+ return clamp01$2(percent / 100);
23188
+ }
23189
+ const number = Number.parseFloat(value);
23190
+ return Number.isFinite(number) ? clamp01$2(number) : Number.NaN;
23191
+ };
23192
+ const tryParseRgbFunction = (value) => {
23193
+ var _a, _b, _c;
23194
+ const match = /^rgba?\(\s*([^,]+?)\s*,\s*([^,]+?)\s*,\s*([^,]+?)(?:\s*,\s*([^,]+?)\s*)?\)$/i.exec(
23195
+ value.trim()
23196
+ );
23197
+ if (!match) {
23198
+ return null;
23199
+ }
23200
+ const r = parseChannel((_a = match[1]) != null ? _a : "");
23201
+ const g = parseChannel((_b = match[2]) != null ? _b : "");
23202
+ const b = parseChannel((_c = match[3]) != null ? _c : "");
23203
+ const a = parseAlpha(match[4]);
23204
+ if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b) || Number.isNaN(a)) {
23205
+ return null;
23206
+ }
23207
+ return normalizeRgba(r, g, b, a);
23208
+ };
23209
+ const parseColorUsingDom = (value) => {
23210
+ var _a;
23211
+ if (typeof document === "undefined") {
23212
+ return null;
23213
+ }
23214
+ const element = document.createElement("div");
23215
+ element.style.color = "";
23216
+ element.style.color = value;
23217
+ if (!element.style.color) {
23218
+ return null;
23219
+ }
23220
+ return (_a = tryParseRgbFunction(element.style.color)) != null ? _a : tryParseHexColor(element.style.color.toLowerCase());
23221
+ };
23222
+ const parseCssColorToRgba = (color, fallback2) => {
23223
+ var _a, _b, _c;
23224
+ if (!color) {
23225
+ return fallback2;
23226
+ }
23227
+ const trimmed = color.trim();
23228
+ if (trimmed.length === 0) {
23229
+ return fallback2;
23230
+ }
23231
+ const keyword = CSS_KEYWORD_COLORS[trimmed.toLowerCase()];
23232
+ if (keyword) {
23233
+ return keyword;
23234
+ }
23235
+ return (_c = (_b = (_a = tryParseHexColor(trimmed)) != null ? _a : tryParseRgbFunction(trimmed)) != null ? _b : parseColorUsingDom(trimmed)) != null ? _c : fallback2;
23236
+ };
23227
23237
  const NUMERIC_EPSILON = 1e-6;
23228
23238
  const normalizeDuration$1 = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
23229
23239
  const normalizeDelta = (delta) => {
@@ -23276,7 +23286,7 @@ const createDegreeInterpolationState = (params) => {
23276
23286
  requiresInterpolation
23277
23287
  };
23278
23288
  };
23279
- const clamp01$2 = (value) => {
23289
+ const clamp01$1 = (value) => {
23280
23290
  if (!Number.isFinite(value)) {
23281
23291
  return 1;
23282
23292
  }
@@ -23288,11 +23298,9 @@ const clamp01$2 = (value) => {
23288
23298
  }
23289
23299
  return value;
23290
23300
  };
23291
- const evaluateDegreeInterpolation = (params) => {
23301
+ const evaluateDegreeInterpolation = (state, timestamp) => {
23292
23302
  var _a;
23293
- const { state } = params;
23294
23303
  const targetValue = (_a = state.pathTarget) != null ? _a : state.to;
23295
- const timestamp = Number.isFinite(params.timestamp) ? params.timestamp : Date.now();
23296
23304
  const duration = Math.max(0, state.durationMs);
23297
23305
  const effectiveStart = state.startTimestamp >= 0 ? state.startTimestamp : timestamp;
23298
23306
  if (duration === 0 || Math.abs(targetValue - state.from) <= NUMERIC_EPSILON) {
@@ -23304,7 +23312,7 @@ const evaluateDegreeInterpolation = (params) => {
23304
23312
  }
23305
23313
  const elapsed = timestamp - effectiveStart;
23306
23314
  const rawProgress = duration <= 0 ? 1 : elapsed / duration;
23307
- const eased = clamp01$2(state.easingFunc(rawProgress));
23315
+ const eased = clamp01$1(state.easingFunc(rawProgress));
23308
23316
  const interpolated = state.from + (targetValue - state.from) * eased;
23309
23317
  const completed = rawProgress >= 1;
23310
23318
  return {
@@ -23315,10 +23323,15 @@ const evaluateDegreeInterpolation = (params) => {
23315
23323
  };
23316
23324
  const DEGREE_INTERPOLATION_CHANNELS = {
23317
23325
  rotation: {
23318
- resolveInterpolation: (image) => image.rotateDeg.interpolation,
23326
+ resolveInterpolation: (image) => image.finalRotateDeg.interpolation,
23319
23327
  normalize: normalizeAngleDeg,
23320
23328
  applyValue: (image, value) => {
23321
- image.displayedRotateDeg = value;
23329
+ image.finalRotateDeg.current = normalizeAngleDeg(value);
23330
+ },
23331
+ applyFinalValue: (image, value) => {
23332
+ image.finalRotateDeg.current = normalizeAngleDeg(value);
23333
+ image.finalRotateDeg.from = void 0;
23334
+ image.finalRotateDeg.to = void 0;
23322
23335
  }
23323
23336
  },
23324
23337
  offsetDeg: {
@@ -23340,17 +23353,17 @@ const collectDegreeInterpolationWorkItems = (image, workItems) => {
23340
23353
  const rotationState = DEGREE_INTERPOLATION_CHANNELS.rotation.resolveInterpolation(image).state;
23341
23354
  if (rotationState) {
23342
23355
  workItems.push({
23356
+ ...rotationState,
23343
23357
  descriptor: DEGREE_INTERPOLATION_CHANNELS.rotation,
23344
- image,
23345
- state: rotationState
23358
+ image
23346
23359
  });
23347
23360
  }
23348
23361
  const offsetState = DEGREE_INTERPOLATION_CHANNELS.offsetDeg.resolveInterpolation(image).state;
23349
23362
  if (offsetState) {
23350
23363
  workItems.push({
23364
+ ...offsetState,
23351
23365
  descriptor: DEGREE_INTERPOLATION_CHANNELS.offsetDeg,
23352
- image,
23353
- state: offsetState
23366
+ image
23354
23367
  });
23355
23368
  }
23356
23369
  };
@@ -23359,158 +23372,25 @@ const applyDegreeInterpolationEvaluations = (workItems, evaluations, timestamp)
23359
23372
  let active = false;
23360
23373
  for (let index = 0; index < workItems.length; index += 1) {
23361
23374
  const item = workItems[index];
23362
- const evaluation = (_a = evaluations[index]) != null ? _a : evaluateDegreeInterpolation({
23363
- state: item.state,
23364
- timestamp
23365
- });
23366
- if (item.state.startTimestamp < 0) {
23367
- item.state.startTimestamp = evaluation.effectiveStartTimestamp;
23375
+ const evaluation = (_a = evaluations[index]) != null ? _a : evaluateDegreeInterpolation(item, timestamp);
23376
+ if (item.startTimestamp < 0) {
23377
+ item.startTimestamp = evaluation.effectiveStartTimestamp;
23368
23378
  }
23369
23379
  const normalize = (_b = item.descriptor.normalize) != null ? _b : ((value) => value);
23370
23380
  const applyFinalValue = (_c = item.descriptor.applyFinalValue) != null ? _c : item.descriptor.applyValue;
23371
23381
  const interpolatedValue = normalize(evaluation.value);
23372
23382
  item.descriptor.applyValue(item.image, interpolatedValue);
23373
23383
  if (evaluation.completed) {
23374
- const finalValue = normalize(item.state.to);
23384
+ const finalValue = normalize(item.to);
23375
23385
  applyFinalValue(item.image, finalValue);
23376
23386
  updateDegreeInterpolationState(item.image, item.descriptor, null);
23377
23387
  } else {
23378
- updateDegreeInterpolationState(item.image, item.descriptor, item.state);
23388
+ updateDegreeInterpolationState(item.image, item.descriptor, item);
23379
23389
  active = true;
23380
23390
  }
23381
23391
  }
23382
23392
  return active;
23383
23393
  };
23384
- const resolveRotationTarget = (params) => {
23385
- const options = params.options;
23386
- const targetAngle = normalizeAngleDeg(params.targetAngleDeg);
23387
- const currentAngle = normalizeAngleDeg(params.currentAngleDeg);
23388
- const previousCommandAngleDeg = params.previousCommandAngleDeg !== void 0 ? normalizeAngleDeg(params.previousCommandAngleDeg) : void 0;
23389
- if (!options || options.durationMs <= 0) {
23390
- return {
23391
- nextAngleDeg: targetAngle,
23392
- interpolationState: null
23393
- };
23394
- }
23395
- const { state, requiresInterpolation } = createDegreeInterpolationState({
23396
- currentValue: currentAngle,
23397
- targetValue: targetAngle,
23398
- previousCommandValue: previousCommandAngleDeg,
23399
- options
23400
- });
23401
- if (!requiresInterpolation) {
23402
- return {
23403
- nextAngleDeg: targetAngle,
23404
- interpolationState: null
23405
- };
23406
- }
23407
- return {
23408
- nextAngleDeg: currentAngle,
23409
- interpolationState: state
23410
- };
23411
- };
23412
- const clamp01$1 = (value) => Math.min(1, Math.max(0, value));
23413
- const clamp255 = (value) => Math.min(255, Math.max(0, value));
23414
- const normalizeRgba = (r, g, b, a) => [
23415
- clamp255(r) / 255,
23416
- clamp255(g) / 255,
23417
- clamp255(b) / 255,
23418
- clamp01$1(a)
23419
- ];
23420
- const tryParseHexColor = (value) => {
23421
- var _a;
23422
- const match = /^#([0-9a-f]{3,8})$/i.exec(value.trim());
23423
- if (!match) {
23424
- return null;
23425
- }
23426
- const hex = (_a = match[1]) != null ? _a : "";
23427
- if (hex.length === 3) {
23428
- const [r, g, b] = hex.split("").map((c) => parseInt(c + c, 16));
23429
- return normalizeRgba(r, g, b, 1);
23430
- }
23431
- if (hex.length === 4) {
23432
- const [r, g, b, a] = hex.split("").map((c) => parseInt(c + c, 16));
23433
- return normalizeRgba(r, g, b, a / 255);
23434
- }
23435
- if (hex.length === 6 || hex.length === 8) {
23436
- const r = parseInt(hex.slice(0, 2), 16);
23437
- const g = parseInt(hex.slice(2, 4), 16);
23438
- const b = parseInt(hex.slice(4, 6), 16);
23439
- const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) : 255;
23440
- return normalizeRgba(r, g, b, a / 255);
23441
- }
23442
- return null;
23443
- };
23444
- const parseChannel = (value) => {
23445
- if (value.endsWith("%")) {
23446
- const percent = Number.parseFloat(value.slice(0, -1));
23447
- if (!Number.isFinite(percent)) {
23448
- return Number.NaN;
23449
- }
23450
- return clamp255(percent / 100 * 255);
23451
- }
23452
- const number = Number.parseFloat(value);
23453
- return Number.isFinite(number) ? clamp255(number) : Number.NaN;
23454
- };
23455
- const parseAlpha = (value) => {
23456
- if (value === void 0) {
23457
- return 1;
23458
- }
23459
- if (value.endsWith("%")) {
23460
- const percent = Number.parseFloat(value.slice(0, -1));
23461
- if (!Number.isFinite(percent)) {
23462
- return Number.NaN;
23463
- }
23464
- return clamp01$1(percent / 100);
23465
- }
23466
- const number = Number.parseFloat(value);
23467
- return Number.isFinite(number) ? clamp01$1(number) : Number.NaN;
23468
- };
23469
- const tryParseRgbFunction = (value) => {
23470
- var _a, _b, _c;
23471
- const match = /^rgba?\(\s*([^,]+?)\s*,\s*([^,]+?)\s*,\s*([^,]+?)(?:\s*,\s*([^,]+?)\s*)?\)$/i.exec(
23472
- value.trim()
23473
- );
23474
- if (!match) {
23475
- return null;
23476
- }
23477
- const r = parseChannel((_a = match[1]) != null ? _a : "");
23478
- const g = parseChannel((_b = match[2]) != null ? _b : "");
23479
- const b = parseChannel((_c = match[3]) != null ? _c : "");
23480
- const a = parseAlpha(match[4]);
23481
- if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b) || Number.isNaN(a)) {
23482
- return null;
23483
- }
23484
- return normalizeRgba(r, g, b, a);
23485
- };
23486
- const parseColorUsingDom = (value) => {
23487
- var _a;
23488
- if (typeof document === "undefined") {
23489
- return null;
23490
- }
23491
- const element = document.createElement("div");
23492
- element.style.color = "";
23493
- element.style.color = value;
23494
- if (!element.style.color) {
23495
- return null;
23496
- }
23497
- return (_a = tryParseRgbFunction(element.style.color)) != null ? _a : tryParseHexColor(element.style.color.toLowerCase());
23498
- };
23499
- const parseCssColorToRgba = (color, fallback2) => {
23500
- var _a, _b, _c;
23501
- if (!color) {
23502
- return fallback2;
23503
- }
23504
- const trimmed = color.trim();
23505
- if (trimmed.length === 0) {
23506
- return fallback2;
23507
- }
23508
- const keyword = CSS_KEYWORD_COLORS[trimmed.toLowerCase()];
23509
- if (keyword) {
23510
- return keyword;
23511
- }
23512
- return (_c = (_b = (_a = tryParseHexColor(trimmed)) != null ? _a : tryParseRgbFunction(trimmed)) != null ? _b : parseColorUsingDom(trimmed)) != null ? _c : fallback2;
23513
- };
23514
23394
  const DISTANCE_EPSILON = 1e-6;
23515
23395
  const normalizeDuration = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
23516
23396
  const normalizeOptions = (options) => {
@@ -23563,11 +23443,9 @@ const clamp01 = (value) => {
23563
23443
  }
23564
23444
  return value;
23565
23445
  };
23566
- const evaluateDistanceInterpolation = (params) => {
23446
+ const evaluateDistanceInterpolation = (state, timestamp) => {
23567
23447
  var _a;
23568
- const { state } = params;
23569
23448
  const targetValue = (_a = state.pathTarget) != null ? _a : state.to;
23570
- const timestamp = Number.isFinite(params.timestamp) ? params.timestamp : Date.now();
23571
23449
  const duration = Math.max(0, state.durationMs);
23572
23450
  const effectiveStart = state.startTimestamp >= 0 ? state.startTimestamp : timestamp;
23573
23451
  if (duration === 0 || Math.abs(targetValue - state.from) <= DISTANCE_EPSILON) {
@@ -23601,80 +23479,105 @@ const DISTANCE_INTERPOLATION_CHANNELS = {
23601
23479
  }
23602
23480
  },
23603
23481
  opacity: {
23604
- resolveInterpolation: (image) => image.opacity.interpolation,
23482
+ resolveInterpolation: (image) => image.finalOpacity.interpolation,
23605
23483
  normalize: clampOpacity,
23606
23484
  applyValue: (image, value) => {
23607
- image.opacity.current = value;
23485
+ image.finalOpacity.current = value;
23608
23486
  },
23609
23487
  applyFinalValue: (image, value) => {
23610
- image.opacity.current = value;
23611
- image.opacity.from = void 0;
23612
- image.opacity.to = void 0;
23488
+ image.finalOpacity.current = value;
23489
+ image.finalOpacity.from = void 0;
23490
+ image.finalOpacity.to = void 0;
23613
23491
  }
23614
23492
  }
23615
23493
  };
23616
- const collectDistanceInterpolationWorkItems = (image, workItems, options) => {
23617
- var _a, _b;
23618
- const includeOffsetMeters = (_a = options == null ? void 0 : options.includeOffsetMeters) != null ? _a : true;
23619
- const includeOpacity = (_b = options == null ? void 0 : options.includeOpacity) != null ? _b : true;
23494
+ const updateDistanceInterpolationState = (image, descriptor, nextState) => {
23495
+ descriptor.resolveInterpolation(image).state = nextState;
23496
+ };
23497
+ const collectDistanceInterpolationWorkItems = (image, workItems, includeOffsetMeters, includeOpacity) => {
23620
23498
  const offsetMetersState = DISTANCE_INTERPOLATION_CHANNELS.offsetMeters.resolveInterpolation(
23621
23499
  image
23622
23500
  ).state;
23623
23501
  if (includeOffsetMeters && offsetMetersState) {
23624
23502
  workItems.push({
23503
+ ...offsetMetersState,
23625
23504
  descriptor: DISTANCE_INTERPOLATION_CHANNELS.offsetMeters,
23626
- image,
23627
- state: offsetMetersState
23505
+ image
23628
23506
  });
23629
23507
  }
23630
23508
  const opacityState = DISTANCE_INTERPOLATION_CHANNELS.opacity.resolveInterpolation(image).state;
23631
23509
  if (includeOpacity && opacityState) {
23632
23510
  workItems.push({
23511
+ ...opacityState,
23633
23512
  descriptor: DISTANCE_INTERPOLATION_CHANNELS.opacity,
23634
- image,
23635
- state: opacityState
23513
+ image
23636
23514
  });
23637
23515
  }
23638
23516
  };
23639
- const updateDistanceInterpolationState = (image, descriptor, nextState) => {
23640
- descriptor.resolveInterpolation(image).state = nextState;
23641
- };
23642
23517
  const applyDistanceInterpolationEvaluations = (workItems, evaluations, timestamp) => {
23643
23518
  var _a, _b, _c;
23644
23519
  let active = false;
23645
23520
  for (let index = 0; index < workItems.length; index += 1) {
23646
23521
  const item = workItems[index];
23647
- const evaluation = (_a = evaluations[index]) != null ? _a : evaluateDistanceInterpolation({
23648
- state: item.state,
23649
- timestamp
23650
- });
23651
- if (item.state.startTimestamp < 0) {
23652
- item.state.startTimestamp = evaluation.effectiveStartTimestamp;
23522
+ const evaluation = (_a = evaluations[index]) != null ? _a : evaluateDistanceInterpolation(item, timestamp);
23523
+ const interpolationState = item.descriptor.resolveInterpolation(
23524
+ item.image
23525
+ ).state;
23526
+ if (interpolationState && interpolationState.startTimestamp < 0) {
23527
+ interpolationState.startTimestamp = evaluation.effectiveStartTimestamp;
23528
+ }
23529
+ if (item.startTimestamp < 0) {
23530
+ item.startTimestamp = evaluation.effectiveStartTimestamp;
23653
23531
  }
23654
23532
  const normalize = (_b = item.descriptor.normalize) != null ? _b : ((value) => value);
23655
23533
  const applyFinalValue = (_c = item.descriptor.applyFinalValue) != null ? _c : item.descriptor.applyValue;
23656
23534
  const interpolatedValue = normalize(evaluation.value);
23657
23535
  item.descriptor.applyValue(item.image, interpolatedValue);
23658
23536
  if (evaluation.completed) {
23659
- const finalValue = normalize(item.state.to);
23537
+ const finalValue = normalize(item.to);
23660
23538
  applyFinalValue(item.image, finalValue);
23661
23539
  updateDistanceInterpolationState(item.image, item.descriptor, null);
23662
23540
  } else {
23663
- updateDistanceInterpolationState(item.image, item.descriptor, item.state);
23541
+ updateDistanceInterpolationState(item.image, item.descriptor, item);
23664
23542
  active = true;
23665
23543
  }
23666
23544
  }
23667
23545
  return active;
23668
23546
  };
23547
+ const resolveRotationTarget = (params) => {
23548
+ const options = params.options;
23549
+ const targetAngle = normalizeAngleDeg(params.targetAngleDeg);
23550
+ const currentAngle = normalizeAngleDeg(params.currentAngleDeg);
23551
+ const previousCommandAngleDeg = params.previousCommandAngleDeg !== void 0 ? normalizeAngleDeg(params.previousCommandAngleDeg) : void 0;
23552
+ if (!options || options.durationMs <= 0) {
23553
+ return {
23554
+ nextAngleDeg: targetAngle,
23555
+ interpolationState: null
23556
+ };
23557
+ }
23558
+ const { state, requiresInterpolation } = createDegreeInterpolationState({
23559
+ currentValue: currentAngle,
23560
+ targetValue: targetAngle,
23561
+ previousCommandValue: previousCommandAngleDeg,
23562
+ options
23563
+ });
23564
+ if (!requiresInterpolation) {
23565
+ return {
23566
+ nextAngleDeg: targetAngle,
23567
+ interpolationState: null
23568
+ };
23569
+ }
23570
+ return {
23571
+ nextAngleDeg: currentAngle,
23572
+ interpolationState: state
23573
+ };
23574
+ };
23669
23575
  const stepDegreeInterpolationState = (interpolationState, timestamp, applyValue, options) => {
23670
23576
  var _a, _b;
23671
23577
  if (!interpolationState) {
23672
23578
  return { state: null, active: false };
23673
23579
  }
23674
- const evaluation = evaluateDegreeInterpolation({
23675
- state: interpolationState,
23676
- timestamp
23677
- });
23580
+ const evaluation = evaluateDegreeInterpolation(interpolationState, timestamp);
23678
23581
  if (interpolationState.startTimestamp < 0) {
23679
23582
  interpolationState.startTimestamp = evaluation.effectiveStartTimestamp;
23680
23583
  }
@@ -23689,59 +23592,80 @@ const stepDegreeInterpolationState = (interpolationState, timestamp, applyValue,
23689
23592
  }
23690
23593
  return { state: interpolationState, active: true };
23691
23594
  };
23692
- const resolveManualRotationFromDisplayed = (image) => {
23693
- var _a;
23694
- const baseRotation = (_a = image.resolvedBaseRotateDeg) != null ? _a : 0;
23695
- const fallbackRotation = normalizeAngleDeg(
23696
- baseRotation + image.rotationCommandDeg
23595
+ const resolveAutoRotationDeg$2 = (image, spriteAutoRotationDeg) => {
23596
+ return image.autoRotation ? spriteAutoRotationDeg : 0;
23597
+ };
23598
+ const resolveCurrentRotation = (image, spriteAutoRotationDeg) => {
23599
+ const targetAngle = normalizeAngleDeg(
23600
+ resolveAutoRotationDeg$2(image, spriteAutoRotationDeg) + image.rotateDeg
23697
23601
  );
23698
- const displayedRotation = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : fallbackRotation;
23699
- return normalizeAngleDeg(displayedRotation - baseRotation);
23602
+ const current = image.finalRotateDeg.current;
23603
+ return Number.isFinite(current) ? normalizeAngleDeg(current) : targetAngle;
23700
23604
  };
23701
- const refreshRotateDegInterpolatedValues = (image) => {
23702
- image.rotateDeg.current = resolveManualRotationFromDisplayed(image);
23703
- if (!image.rotateDeg.interpolation.state) {
23704
- image.rotateDeg.from = void 0;
23705
- image.rotateDeg.to = void 0;
23605
+ const refreshRotateDegInterpolatedValues = (image, spriteAutoRotationDeg) => {
23606
+ image.finalRotateDeg.current = resolveCurrentRotation(
23607
+ image,
23608
+ spriteAutoRotationDeg
23609
+ );
23610
+ if (!image.finalRotateDeg.interpolation.state) {
23611
+ image.finalRotateDeg.from = void 0;
23612
+ image.finalRotateDeg.to = void 0;
23706
23613
  }
23707
23614
  };
23708
- const updateImageDisplayedRotation = (image, optionsOverride) => {
23615
+ const updateImageDisplayedRotation = (image, spriteAutoRotationDeg, optionsOverride) => {
23709
23616
  const targetAngle = normalizeAngleDeg(
23710
- image.resolvedBaseRotateDeg + image.rotationCommandDeg
23617
+ resolveAutoRotationDeg$2(image, spriteAutoRotationDeg) + image.rotateDeg
23711
23618
  );
23712
- const currentAngle = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : targetAngle;
23713
- const previousCommandAngle = image.rotateDeg.interpolation.lastCommandValue;
23714
- const options = optionsOverride === void 0 ? image.rotateDeg.interpolation.options : optionsOverride;
23619
+ const currentAngle = resolveCurrentRotation(image, spriteAutoRotationDeg);
23620
+ const previousCommandAngle = image.finalRotateDeg.interpolation.lastCommandValue;
23621
+ const options = optionsOverride === void 0 ? image.finalRotateDeg.interpolation.options : optionsOverride;
23715
23622
  const { nextAngleDeg, interpolationState } = resolveRotationTarget({
23716
23623
  currentAngleDeg: currentAngle,
23717
23624
  targetAngleDeg: targetAngle,
23718
23625
  previousCommandAngleDeg: previousCommandAngle,
23719
23626
  options: options != null ? options : void 0
23720
23627
  });
23721
- image.displayedRotateDeg = nextAngleDeg;
23722
- image.rotateDeg.interpolation.state = interpolationState;
23628
+ image.finalRotateDeg.current = normalizeAngleDeg(
23629
+ Number.isFinite(nextAngleDeg) ? nextAngleDeg : targetAngle
23630
+ );
23631
+ image.finalRotateDeg.interpolation.state = interpolationState;
23723
23632
  if (!interpolationState) {
23724
- image.displayedRotateDeg = targetAngle;
23633
+ image.finalRotateDeg.current = targetAngle;
23634
+ image.finalRotateDeg.from = void 0;
23635
+ image.finalRotateDeg.to = void 0;
23636
+ } else {
23637
+ image.finalRotateDeg.from = normalizeAngleDeg(currentAngle);
23638
+ image.finalRotateDeg.to = normalizeAngleDeg(targetAngle);
23725
23639
  }
23726
- image.rotateDeg.interpolation.lastCommandValue = targetAngle;
23640
+ image.finalRotateDeg.interpolation.lastCommandValue = targetAngle;
23727
23641
  };
23728
- const syncImageRotationChannel = (image, optionsOverride) => {
23729
- updateImageDisplayedRotation(image, optionsOverride);
23730
- refreshRotateDegInterpolatedValues(image);
23642
+ const syncImageRotationChannel = (image, spriteAutoRotationDeg, optionsOverride) => {
23643
+ updateImageDisplayedRotation(image, spriteAutoRotationDeg, optionsOverride);
23644
+ refreshRotateDegInterpolatedValues(image, spriteAutoRotationDeg);
23731
23645
  };
23732
- const stepRotationInterpolation = (image, timestamp) => {
23646
+ const stepRotationInterpolation = (image, spriteAutoRotationDeg, timestamp) => {
23733
23647
  const { state, active } = stepDegreeInterpolationState(
23734
- image.rotateDeg.interpolation.state,
23648
+ image.finalRotateDeg.interpolation.state,
23735
23649
  timestamp,
23736
23650
  (value) => {
23737
- image.displayedRotateDeg = value;
23651
+ const fallback2 = normalizeAngleDeg(
23652
+ resolveAutoRotationDeg$2(image, spriteAutoRotationDeg) + image.rotateDeg
23653
+ );
23654
+ image.finalRotateDeg.current = normalizeAngleDeg(
23655
+ Number.isFinite(value) ? value : fallback2
23656
+ );
23738
23657
  },
23739
23658
  {
23740
- normalize: normalizeAngleDeg
23659
+ normalize: (value) => {
23660
+ const fallback2 = normalizeAngleDeg(
23661
+ resolveAutoRotationDeg$2(image, spriteAutoRotationDeg) + image.rotateDeg
23662
+ );
23663
+ return normalizeAngleDeg(Number.isFinite(value) ? value : fallback2);
23664
+ }
23741
23665
  }
23742
23666
  );
23743
- image.rotateDeg.interpolation.state = state;
23744
- refreshRotateDegInterpolatedValues(image);
23667
+ image.finalRotateDeg.interpolation.state = state;
23668
+ refreshRotateDegInterpolatedValues(image, spriteAutoRotationDeg);
23745
23669
  return active;
23746
23670
  };
23747
23671
  const stepOffsetDegInterpolation = (image, timestamp) => {
@@ -23769,10 +23693,10 @@ const stepDistanceInterpolationState = (interpolationState, timestamp, applyValu
23769
23693
  if (!interpolationState) {
23770
23694
  return { state: null, active: false };
23771
23695
  }
23772
- const evaluation = evaluateDistanceInterpolation({
23773
- state: interpolationState,
23696
+ const evaluation = evaluateDistanceInterpolation(
23697
+ interpolationState,
23774
23698
  timestamp
23775
- });
23699
+ );
23776
23700
  if (interpolationState.startTimestamp < 0) {
23777
23701
  interpolationState.startTimestamp = evaluation.effectiveStartTimestamp;
23778
23702
  }
@@ -23793,7 +23717,9 @@ const clearOffsetMetersInterpolation = (image) => {
23793
23717
  image.offset.offsetMeters.to = void 0;
23794
23718
  };
23795
23719
  const clearOpacityInterpolation = (image) => {
23796
- image.opacity.interpolation.state = null;
23720
+ image.finalOpacity.interpolation.state = null;
23721
+ image.finalOpacity.from = void 0;
23722
+ image.finalOpacity.to = void 0;
23797
23723
  };
23798
23724
  const applyOffsetDegUpdate = (image, nextOffset, interpolationOptions) => {
23799
23725
  const options = interpolationOptions;
@@ -23870,35 +23796,36 @@ const runOpacityTargetTransition = (image, targetOpacity, interpolationOptions)
23870
23796
  const clampedTarget = clampOpacity(targetOpacity);
23871
23797
  const options = interpolationOptions;
23872
23798
  if (!options || options.durationMs <= 0) {
23873
- image.opacity.current = clampedTarget;
23874
- image.opacity.from = void 0;
23875
- image.opacity.to = void 0;
23876
- image.opacity.interpolation.state = null;
23799
+ image.finalOpacity.current = clampedTarget;
23800
+ image.finalOpacity.from = void 0;
23801
+ image.finalOpacity.to = void 0;
23802
+ image.finalOpacity.interpolation.state = null;
23877
23803
  } else {
23878
23804
  const { state, requiresInterpolation } = createDistanceInterpolationState({
23879
- currentValue: clampOpacity(image.opacity.current),
23805
+ currentValue: clampOpacity(image.finalOpacity.current),
23880
23806
  targetValue: clampedTarget,
23881
- previousCommandValue: image.opacity.interpolation.lastCommandValue,
23807
+ previousCommandValue: image.finalOpacity.interpolation.lastCommandValue,
23882
23808
  options
23883
23809
  });
23884
23810
  if (requiresInterpolation) {
23885
- image.opacity.interpolation.state = state;
23886
- image.opacity.from = image.opacity.current;
23887
- image.opacity.to = clampedTarget;
23811
+ image.finalOpacity.interpolation.state = state;
23812
+ image.finalOpacity.from = image.finalOpacity.current;
23813
+ image.finalOpacity.to = clampedTarget;
23888
23814
  } else {
23889
- image.opacity.current = clampedTarget;
23890
- image.opacity.from = void 0;
23891
- image.opacity.to = void 0;
23892
- image.opacity.interpolation.state = null;
23815
+ image.finalOpacity.current = clampedTarget;
23816
+ image.finalOpacity.from = void 0;
23817
+ image.finalOpacity.to = void 0;
23818
+ image.finalOpacity.interpolation.state = null;
23893
23819
  }
23894
23820
  }
23895
- image.opacity.interpolation.lastCommandValue = clampedTarget;
23896
- image.opacity.interpolation.targetValue = clampedTarget;
23821
+ image.finalOpacity.interpolation.lastCommandValue = clampedTarget;
23822
+ image.finalOpacity.interpolation.targetValue = clampedTarget;
23897
23823
  };
23898
23824
  const applyOpacityUpdate = (image, nextOpacity, interpolationOptions, spriteOpacityMultiplier = 1) => {
23899
23825
  const clampedBase = clampOpacity(nextOpacity);
23900
23826
  const lodMultiplier = typeof image.lodOpacity === "number" ? image.lodOpacity : 1;
23901
- image.opacity.interpolation.baseValue = clampedBase;
23827
+ image.finalOpacity.interpolation.baseValue = clampedBase;
23828
+ image.opacity = clampedBase;
23902
23829
  runOpacityTargetTransition(
23903
23830
  image,
23904
23831
  clampedBase * spriteOpacityMultiplier * lodMultiplier,
@@ -23914,48 +23841,64 @@ const applyResolvedOpacityTarget = (image, resolvedTarget, interpolationOptions)
23914
23841
  };
23915
23842
  const stepOpacityInterpolation = (image, timestamp) => {
23916
23843
  const { state, active } = stepDistanceInterpolationState(
23917
- image.opacity.interpolation.state,
23844
+ image.finalOpacity.interpolation.state,
23918
23845
  timestamp,
23919
23846
  (value) => {
23920
- image.opacity.current = value;
23847
+ image.finalOpacity.current = value;
23921
23848
  },
23922
23849
  {
23923
23850
  normalize: clampOpacity
23924
23851
  }
23925
23852
  );
23926
- image.opacity.interpolation.state = state;
23853
+ image.finalOpacity.interpolation.state = state;
23927
23854
  if (!state) {
23928
- image.opacity.from = void 0;
23929
- image.opacity.to = void 0;
23855
+ image.finalOpacity.from = void 0;
23856
+ image.finalOpacity.to = void 0;
23930
23857
  }
23931
23858
  return active;
23932
23859
  };
23933
23860
  const IMAGE_INTERPOLATION_STEPPERS = [
23934
23861
  { id: "rotation", step: stepRotationInterpolation },
23935
- { id: "offsetDeg", step: stepOffsetDegInterpolation },
23936
- { id: "offsetMeters", step: stepOffsetMetersInterpolation },
23937
- { id: "opacity", step: stepOpacityInterpolation }
23862
+ {
23863
+ id: "offsetDeg",
23864
+ step: (image, timestamp, _autoRotationDeg) => stepOffsetDegInterpolation(image, timestamp)
23865
+ },
23866
+ {
23867
+ id: "offsetMeters",
23868
+ step: (image, timestamp, _autoRotationDeg) => stepOffsetMetersInterpolation(image, timestamp)
23869
+ },
23870
+ {
23871
+ id: "opacity",
23872
+ step: (image, timestamp, _autoRotationDeg) => stepOpacityInterpolation(image, timestamp)
23873
+ }
23938
23874
  ];
23939
23875
  const stepSpriteImageInterpolations = (image, timestamp, options) => {
23940
- var _a;
23876
+ var _a, _b;
23941
23877
  let active = false;
23942
23878
  const skipChannels = (_a = options == null ? void 0 : options.skipChannels) != null ? _a : null;
23879
+ const autoRotationDeg = (_b = options == null ? void 0 : options.autoRotationDeg) != null ? _b : 0;
23943
23880
  for (const { id, step } of IMAGE_INTERPOLATION_STEPPERS) {
23944
23881
  if (skipChannels && skipChannels[id]) {
23945
23882
  continue;
23946
23883
  }
23947
- if (step(image, timestamp)) {
23884
+ if (step(image, timestamp, autoRotationDeg)) {
23948
23885
  active = true;
23949
23886
  }
23950
23887
  }
23951
23888
  return active;
23952
23889
  };
23953
23890
  const hasActiveImageInterpolations = (image) => {
23954
- return image.rotateDeg.interpolation.state !== null || image.offset.offsetDeg.interpolation.state !== null || image.offset.offsetMeters.interpolation.state !== null || image.opacity.interpolation.state !== null;
23891
+ return image.finalRotateDeg.interpolation.state !== null || image.offset.offsetDeg.interpolation.state !== null || image.offset.offsetMeters.interpolation.state !== null || image.finalOpacity.interpolation.state !== null;
23955
23892
  };
23956
23893
  const applyOffsetUpdate = (image, nextOffset, options = {}) => {
23957
- applyOffsetDegUpdate(image, nextOffset, options.deg);
23958
- applyOffsetMetersUpdate(image, nextOffset, options.meters);
23894
+ const shouldUpdateMeters = options.meters !== void 0 || nextOffset.offsetMeters !== image.offset.offsetMeters.current;
23895
+ if (shouldUpdateMeters) {
23896
+ applyOffsetMetersUpdate(image, nextOffset, options.meters);
23897
+ }
23898
+ const shouldUpdateDeg = options.deg !== void 0 || nextOffset.offsetDeg !== image.offset.offsetDeg.current;
23899
+ if (shouldUpdateDeg) {
23900
+ applyOffsetDegUpdate(image, nextOffset, options.deg);
23901
+ }
23959
23902
  };
23960
23903
  const VERTEX_COMPONENT_COUNT = 6;
23961
23904
  const POSITION_COMPONENT_COUNT = 4;
@@ -26017,14 +25960,17 @@ const resolveImageOffset$2 = (image) => {
26017
25960
  offsetDeg: offset.offsetDeg.current
26018
25961
  };
26019
25962
  };
26020
- const calculateBorderWidthPixels = (widthMeters, imageScale, zoomScaleFactor, effectivePixelsPerMeter, sizeScaleAdjustment) => {
25963
+ const resolveAutoRotationDeg$1 = (sprite, image) => {
25964
+ return image.autoRotation ? sprite.currentAutoRotateDeg : 0;
25965
+ };
25966
+ const calculateBorderWidthPixels = (widthMeters, imageScale, distanceScaleFactor, effectivePixelsPerMeter, sizeScaleAdjustment) => {
26021
25967
  if (widthMeters === void 0 || !Number.isFinite(widthMeters) || widthMeters <= 0) {
26022
25968
  return 0;
26023
25969
  }
26024
25970
  if (!Number.isFinite(effectivePixelsPerMeter) || effectivePixelsPerMeter <= 0) {
26025
25971
  return 0;
26026
25972
  }
26027
- const scaledWidthMeters = widthMeters * imageScale * zoomScaleFactor * sizeScaleAdjustment;
25973
+ const scaledWidthMeters = widthMeters * imageScale * distanceScaleFactor * sizeScaleAdjustment;
26028
25974
  if (!Number.isFinite(scaledWidthMeters) || scaledWidthMeters <= 0) {
26029
25975
  return 0;
26030
25976
  }
@@ -26063,14 +26009,13 @@ const ensureHitTestCorners$1 = (imageEntry) => {
26063
26009
  }
26064
26010
  return imageEntry.hitTestCorners;
26065
26011
  };
26066
- const collectDepthSortedItemsInternal = (projectionHost, zoom, zoomScaleFactor, originCenterCache, {
26012
+ const collectDepthSortedItemsInternal = (projectionHost, zoom, originCenterCache, {
26067
26013
  bucket,
26068
26014
  bucketBuffers,
26069
26015
  imageResources,
26016
+ resolvedScaling,
26070
26017
  clipContext,
26071
26018
  baseMetersPerPixel,
26072
- spriteMinPixel,
26073
- spriteMaxPixel,
26074
26019
  drawingBufferWidth,
26075
26020
  drawingBufferHeight,
26076
26021
  pixelRatio
@@ -26085,6 +26030,7 @@ const collectDepthSortedItemsInternal = (projectionHost, zoom, zoomScaleFactor,
26085
26030
  throw new Error("bucketBuffers length mismatch");
26086
26031
  }
26087
26032
  const resolveOrigin = createBucketOriginResolver(bucket);
26033
+ const cameraLocation = projectionHost.getCameraLocation();
26088
26034
  for (const [spriteEntry, imageEntry] of bucket) {
26089
26035
  const imageResource = imageResources[imageEntry.imageHandle];
26090
26036
  if (!imageResource || !imageResource.texture) {
@@ -26113,23 +26059,35 @@ const collectDepthSortedItemsInternal = (projectionHost, zoom, zoomScaleFactor,
26113
26059
  if (effectivePixelsPerMeter <= 0) {
26114
26060
  continue;
26115
26061
  }
26062
+ const spriteBaseLocation = spriteEntry.location.current;
26063
+ const spriteDistanceLocation = {
26064
+ lng: spriteBaseLocation.lng,
26065
+ lat: spriteBaseLocation.lat,
26066
+ z: (_a = spriteBaseLocation.z) != null ? _a : 0
26067
+ };
26068
+ const cameraDistanceMeters = cameraLocation !== void 0 ? calculateCartesianDistanceMeters(
26069
+ cameraLocation,
26070
+ spriteDistanceLocation
26071
+ ) : Number.POSITIVE_INFINITY;
26072
+ const distanceScaleFactor = calculateDistanceScaleFactor(
26073
+ cameraDistanceMeters,
26074
+ resolvedScaling
26075
+ );
26116
26076
  const centerParams = {
26117
26077
  projectionHost,
26118
26078
  imageResources,
26119
26079
  originCenterCache,
26120
26080
  projected,
26121
26081
  baseMetersPerPixel,
26122
- spriteMinPixel,
26123
- spriteMaxPixel,
26124
26082
  effectivePixelsPerMeter,
26125
- zoomScaleFactor,
26083
+ distanceScaleFactor,
26126
26084
  drawingBufferWidth,
26127
26085
  drawingBufferHeight,
26128
26086
  pixelRatio,
26129
26087
  clipContext,
26130
26088
  resolveOrigin
26131
26089
  };
26132
- const anchorResolved = (_a = imageEntry.anchor) != null ? _a : DEFAULT_ANCHOR;
26090
+ const anchorResolved = (_b = imageEntry.anchor) != null ? _b : DEFAULT_ANCHOR;
26133
26091
  const offsetResolved = resolveImageOffset$2(imageEntry);
26134
26092
  const depthCenter = computeImageCenterXY(
26135
26093
  spriteEntry,
@@ -26139,26 +26097,22 @@ const collectDepthSortedItemsInternal = (projectionHost, zoom, zoomScaleFactor,
26139
26097
  );
26140
26098
  let depthKey;
26141
26099
  if (imageEntry.mode === "surface") {
26142
- const imageScale = (_b = imageEntry.scale) != null ? _b : 1;
26100
+ const imageScale = (_c = imageEntry.scale) != null ? _c : 1;
26143
26101
  const worldDims = calculateSurfaceWorldDimensions(
26144
26102
  imageResource.width,
26145
26103
  imageResource.height,
26146
26104
  baseMetersPerPixel,
26147
26105
  imageScale,
26148
- zoomScaleFactor,
26149
- {
26150
- effectivePixelsPerMeter,
26151
- spriteMinPixel,
26152
- spriteMaxPixel
26153
- }
26106
+ distanceScaleFactor
26154
26107
  );
26155
- const totalRotateDeg = Number.isFinite(imageEntry.displayedRotateDeg) ? imageEntry.displayedRotateDeg : normalizeAngleDeg(
26156
- ((_c = imageEntry.resolvedBaseRotateDeg) != null ? _c : 0) + imageEntry.rotationCommandDeg
26108
+ const autoRotationDeg = resolveAutoRotationDeg$1(spriteEntry, imageEntry);
26109
+ const totalRotateDeg = normalizeAngleDeg(
26110
+ Number.isFinite(imageEntry.finalRotateDeg.current) ? imageEntry.finalRotateDeg.current : autoRotationDeg + imageEntry.rotateDeg
26157
26111
  );
26158
26112
  const offsetMeters = calculateSurfaceOffsetMeters(
26159
26113
  offsetResolved,
26160
26114
  imageScale,
26161
- zoomScaleFactor,
26115
+ distanceScaleFactor,
26162
26116
  worldDims.scaleAdjustment
26163
26117
  );
26164
26118
  const cornerDisplacements = calculateSurfaceCornerDisplacements({
@@ -26225,6 +26179,8 @@ const collectDepthSortedItemsInternal = (projectionHost, zoom, zoomScaleFactor,
26225
26179
  image: imageEntry,
26226
26180
  resource: imageResource,
26227
26181
  depthKey,
26182
+ cameraDistanceMeters,
26183
+ distanceScaleFactor,
26228
26184
  resolveOrigin
26229
26185
  });
26230
26186
  }
@@ -26262,15 +26218,13 @@ const projectLngLatToClipSpace = (projectionHost, location2, context) => {
26262
26218
  return [clipX, clipY, clipZ, clipW];
26263
26219
  };
26264
26220
  const computeImageCenterXY = (sprite, image, params, useResolvedAnchor) => {
26265
- var _a, _b, _c, _d, _e;
26221
+ var _a, _b, _c, _d;
26266
26222
  const {
26267
26223
  originCenterCache,
26268
26224
  projected,
26269
26225
  baseMetersPerPixel,
26270
- spriteMinPixel,
26271
- spriteMaxPixel,
26272
26226
  effectivePixelsPerMeter,
26273
- zoomScaleFactor,
26227
+ distanceScaleFactor,
26274
26228
  imageResources,
26275
26229
  projectionHost,
26276
26230
  drawingBufferWidth,
@@ -26305,10 +26259,11 @@ const computeImageCenterXY = (sprite, image, params, useResolvedAnchor) => {
26305
26259
  base = refCenter;
26306
26260
  }
26307
26261
  }
26308
- const totalRotDeg = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : normalizeAngleDeg(
26309
- ((_a = image.resolvedBaseRotateDeg) != null ? _a : 0) + image.rotationCommandDeg
26262
+ const autoRotationDeg = resolveAutoRotationDeg$1(sprite, image);
26263
+ const totalRotDeg = normalizeAngleDeg(
26264
+ Number.isFinite(image.finalRotateDeg.current) ? image.finalRotateDeg.current : autoRotationDeg + image.rotateDeg
26310
26265
  );
26311
- const imageScaleLocal = (_b = image.scale) != null ? _b : 1;
26266
+ const imageScaleLocal = (_a = image.scale) != null ? _a : 1;
26312
26267
  const imageResourceRef = imageResources[image.imageHandle];
26313
26268
  if (image.mode === "billboard") {
26314
26269
  const placement = calculateBillboardCenterPosition({
@@ -26317,10 +26272,8 @@ const computeImageCenterXY = (sprite, image, params, useResolvedAnchor) => {
26317
26272
  imageHeight: imageResourceRef == null ? void 0 : imageResourceRef.height,
26318
26273
  baseMetersPerPixel,
26319
26274
  imageScale: imageScaleLocal,
26320
- zoomScaleFactor,
26275
+ distanceScaleFactor,
26321
26276
  effectivePixelsPerMeter,
26322
- spriteMinPixel,
26323
- spriteMaxPixel,
26324
26277
  totalRotateDeg: totalRotDeg,
26325
26278
  anchor: image.anchor,
26326
26279
  offset: resolveImageOffset$2(image)
@@ -26336,7 +26289,7 @@ const computeImageCenterXY = (sprite, image, params, useResolvedAnchor) => {
26336
26289
  }
26337
26290
  const baseLngLat = image.originLocation !== void 0 ? (
26338
26291
  // When anchored to another image, reproject the 2D reference point back to geographic space.
26339
- (_c = projectionHost.unproject(base)) != null ? _c : sprite.location.current
26292
+ (_b = projectionHost.unproject(base)) != null ? _b : sprite.location.current
26340
26293
  ) : (
26341
26294
  // Otherwise use the sprite's own interpolated geographic location.
26342
26295
  sprite.location.current
@@ -26348,13 +26301,10 @@ const computeImageCenterXY = (sprite, image, params, useResolvedAnchor) => {
26348
26301
  imageHeight: imageResourceRef == null ? void 0 : imageResourceRef.height,
26349
26302
  baseMetersPerPixel,
26350
26303
  imageScale: imageScaleLocal,
26351
- zoomScaleFactor,
26304
+ distanceScaleFactor,
26352
26305
  totalRotateDeg: totalRotDeg,
26353
26306
  anchor: image.anchor,
26354
26307
  offset: resolveImageOffset$2(image),
26355
- effectivePixelsPerMeter,
26356
- spriteMinPixel,
26357
- spriteMaxPixel,
26358
26308
  projectToClipSpace,
26359
26309
  drawingBufferWidth,
26360
26310
  drawingBufferHeight,
@@ -26362,8 +26312,8 @@ const computeImageCenterXY = (sprite, image, params, useResolvedAnchor) => {
26362
26312
  resolveAnchorless: true,
26363
26313
  project: projectToClipSpace ? void 0 : projectionHost.project
26364
26314
  });
26365
- const anchorlessCenter = (_d = surfacePlacement.anchorlessCenter) != null ? _d : base;
26366
- const anchorAppliedCenter = (_e = surfacePlacement.center) != null ? _e : anchorlessCenter;
26315
+ const anchorlessCenter = (_c = surfacePlacement.anchorlessCenter) != null ? _c : base;
26316
+ const anchorAppliedCenter = (_d = surfacePlacement.center) != null ? _d : anchorlessCenter;
26367
26317
  const entry = cachedEntry != null ? cachedEntry : {
26368
26318
  anchorless: anchorlessCenter,
26369
26319
  anchorApplied: anchorAppliedCenter
@@ -26455,11 +26405,9 @@ const prepareSurfaceShaderInputs = (projectionHost, params) => {
26455
26405
  clipCorners: []
26456
26406
  };
26457
26407
  };
26458
- const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFactor, originCenterCache, {
26408
+ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, originCenterCache, {
26459
26409
  imageResources,
26460
26410
  baseMetersPerPixel,
26461
- spriteMinPixel,
26462
- spriteMaxPixel,
26463
26411
  drawingBufferWidth,
26464
26412
  drawingBufferHeight,
26465
26413
  pixelRatio,
@@ -26473,7 +26421,7 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26473
26421
  screenToClipOffsetX,
26474
26422
  screenToClipOffsetY
26475
26423
  }) => {
26476
- var _a, _b, _c, _d, _e, _f, _g, _h;
26424
+ var _a, _b, _c, _d, _e, _f;
26477
26425
  const spriteEntry = item.sprite;
26478
26426
  const imageEntry = item.image;
26479
26427
  const imageResource = item.resource;
@@ -26485,6 +26433,8 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26485
26433
  const atlasUSpan = atlasU1 - atlasU0;
26486
26434
  const atlasVSpan = atlasV1 - atlasV0;
26487
26435
  const spriteMercator = resolveSpriteMercator(projectionHost, item.sprite);
26436
+ const distanceScaleFactor = item.distanceScaleFactor;
26437
+ const cameraDistanceMeters = item.cameraDistanceMeters;
26488
26438
  imageEntry.surfaceShaderInputs = void 0;
26489
26439
  imageEntry.borderPixelWidth = 0;
26490
26440
  let screenCornerBuffer = null;
@@ -26502,8 +26452,9 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26502
26452
  let borderSizeScaleAdjustment = 1;
26503
26453
  const anchor = (_a = imageEntry.anchor) != null ? _a : DEFAULT_ANCHOR;
26504
26454
  const offsetDef = resolveImageOffset$2(imageEntry);
26505
- const totalRotateDeg = Number.isFinite(imageEntry.displayedRotateDeg) ? imageEntry.displayedRotateDeg : normalizeAngleDeg(
26506
- ((_b = imageEntry.resolvedBaseRotateDeg) != null ? _b : 0) + imageEntry.rotationCommandDeg
26455
+ const autoRotationDeg = resolveAutoRotationDeg$1(spriteEntry, imageEntry);
26456
+ const totalRotateDeg = normalizeAngleDeg(
26457
+ Number.isFinite(imageEntry.finalRotateDeg.current) ? imageEntry.finalRotateDeg.current : autoRotationDeg + imageEntry.rotateDeg
26507
26458
  );
26508
26459
  const projected = projectionHost.project(spriteEntry.location.current);
26509
26460
  if (!projected) {
@@ -26527,17 +26478,15 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26527
26478
  if (effectivePixelsPerMeter <= 0) {
26528
26479
  return null;
26529
26480
  }
26530
- const imageScale = (_c = imageEntry.scale) != null ? _c : 1;
26481
+ const imageScale = (_b = imageEntry.scale) != null ? _b : 1;
26531
26482
  const centerParams = {
26532
26483
  projectionHost,
26533
26484
  imageResources,
26534
26485
  originCenterCache,
26535
26486
  projected,
26536
26487
  baseMetersPerPixel,
26537
- spriteMinPixel,
26538
- spriteMaxPixel,
26539
26488
  effectivePixelsPerMeter,
26540
- zoomScaleFactor,
26489
+ distanceScaleFactor,
26541
26490
  drawingBufferWidth,
26542
26491
  drawingBufferHeight,
26543
26492
  pixelRatio,
@@ -26552,7 +26501,7 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26552
26501
  spriteEntry,
26553
26502
  refImg,
26554
26503
  centerParams,
26555
- (_d = imageEntry.originLocation.useResolvedAnchor) != null ? _d : false
26504
+ (_c = imageEntry.originLocation.useResolvedAnchor) != null ? _c : false
26556
26505
  );
26557
26506
  }
26558
26507
  }
@@ -26576,14 +26525,6 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26576
26525
  };
26577
26526
  };
26578
26527
  const baseLocation = resolveBaseLocation();
26579
- const cameraLocation = projectionHost.getCameraLocation();
26580
- const spriteBaseLocation = spriteEntry.location.current;
26581
- const spriteDistanceLocation = {
26582
- lng: spriteBaseLocation.lng,
26583
- lat: spriteBaseLocation.lat,
26584
- z: (_e = spriteBaseLocation.z) != null ? _e : 0
26585
- };
26586
- const cameraDistanceMeters = cameraLocation !== void 0 ? calculateCartesianDistanceMeters(cameraLocation, spriteDistanceLocation) : Number.POSITIVE_INFINITY;
26587
26528
  if (imageEntry.mode === "surface") {
26588
26529
  screenToClipUniforms = {
26589
26530
  scaleX: identityScaleX,
@@ -26598,13 +26539,10 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26598
26539
  imageHeight: imageResource.height,
26599
26540
  baseMetersPerPixel,
26600
26541
  imageScale,
26601
- zoomScaleFactor,
26542
+ distanceScaleFactor,
26602
26543
  totalRotateDeg,
26603
26544
  anchor,
26604
26545
  offset: offsetDef,
26605
- effectivePixelsPerMeter,
26606
- spriteMinPixel,
26607
- spriteMaxPixel,
26608
26546
  projectToClipSpace: (location2) => projectLngLatToClipSpace(projectionHost, location2, clipContext),
26609
26547
  drawingBufferWidth,
26610
26548
  drawingBufferHeight,
@@ -26618,7 +26556,7 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26618
26556
  const offsetMeters = calculateSurfaceOffsetMeters(
26619
26557
  offsetDef,
26620
26558
  imageScale,
26621
- zoomScaleFactor,
26559
+ distanceScaleFactor,
26622
26560
  surfaceCenter.worldDimensions.scaleAdjustment
26623
26561
  );
26624
26562
  const cornerDisplacements = calculateSurfaceCornerDisplacements({
@@ -26630,7 +26568,7 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26630
26568
  });
26631
26569
  const orderIndex = Math.min(imageEntry.order, ORDER_MAX - 1);
26632
26570
  const depthBiasNdc = -((imageEntry.subLayer * ORDER_BUCKET + orderIndex) * EPS_NDC);
26633
- const displacedCenter = (_f = surfaceCenter.displacedLngLat) != null ? _f : baseLngLat;
26571
+ const displacedCenter = (_d = surfaceCenter.displacedLngLat) != null ? _d : baseLngLat;
26634
26572
  const surfaceShaderInputs = prepareSurfaceShaderInputs(projectionHost, {
26635
26573
  baseLngLat,
26636
26574
  worldWidthMeters: surfaceCenter.worldDimensions.width,
@@ -26816,10 +26754,8 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26816
26754
  imageHeight: imageResource.height,
26817
26755
  baseMetersPerPixel,
26818
26756
  imageScale,
26819
- zoomScaleFactor,
26757
+ distanceScaleFactor,
26820
26758
  effectivePixelsPerMeter,
26821
- spriteMinPixel,
26822
- spriteMaxPixel,
26823
26759
  totalRotateDeg,
26824
26760
  anchor,
26825
26761
  offset: offsetDef
@@ -26887,19 +26823,19 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26887
26823
  }
26888
26824
  writeBillboardCorners(resolvedCorners, useShaderBillboard);
26889
26825
  }
26890
- const borderWidthMeters = (_g = imageEntry.border) == null ? void 0 : _g.widthMeters;
26826
+ const borderWidthMeters = (_e = imageEntry.border) == null ? void 0 : _e.widthMeters;
26891
26827
  imageEntry.borderPixelWidth = calculateBorderWidthPixels(
26892
26828
  borderWidthMeters,
26893
26829
  imageScale,
26894
- zoomScaleFactor,
26830
+ distanceScaleFactor,
26895
26831
  effectivePixelsPerMeter,
26896
26832
  borderSizeScaleAdjustment
26897
26833
  );
26898
- const leaderLineWidthMeters = (_h = imageEntry.leaderLine) == null ? void 0 : _h.widthMeters;
26834
+ const leaderLineWidthMeters = (_f = imageEntry.leaderLine) == null ? void 0 : _f.widthMeters;
26899
26835
  imageEntry.leaderLinePixelWidth = calculateBorderWidthPixels(
26900
26836
  leaderLineWidthMeters,
26901
26837
  imageScale,
26902
- zoomScaleFactor,
26838
+ distanceScaleFactor,
26903
26839
  effectivePixelsPerMeter,
26904
26840
  borderSizeScaleAdjustment
26905
26841
  );
@@ -26909,7 +26845,7 @@ const prepareDrawSpriteImageInternal = (projectionHost, item, zoom, zoomScaleFac
26909
26845
  imageEntry,
26910
26846
  imageResource,
26911
26847
  vertexData: new Float32Array(QUAD_VERTEX_SCRATCH),
26912
- opacity: imageEntry.opacity.current,
26848
+ opacity: imageEntry.finalOpacity.current,
26913
26849
  hitTestCorners,
26914
26850
  screenToClip: screenToClipUniforms,
26915
26851
  useShaderSurface,
@@ -26925,19 +26861,17 @@ const prepareDrawSpriteImages = (projectionHost, params) => {
26925
26861
  const originCenterCache = /* @__PURE__ */ new Map();
26926
26862
  const zoom = projectionHost.getZoom();
26927
26863
  const resolvedScaling = (_a = params.resolvedScaling) != null ? _a : resolveScalingOptions({
26928
- metersPerPixel: params.baseMetersPerPixel,
26929
- spriteMinPixel: params.spriteMinPixel,
26930
- spriteMaxPixel: params.spriteMaxPixel,
26931
- zoomMin: zoom,
26932
- zoomMax: zoom
26864
+ metersPerPixel: params.baseMetersPerPixel
26933
26865
  });
26934
- const zoomScaleFactor = calculateZoomScaleFactor(zoom, resolvedScaling);
26866
+ const preparedParams = {
26867
+ ...params,
26868
+ resolvedScaling
26869
+ };
26935
26870
  const itemsWithDepth = collectDepthSortedItemsInternal(
26936
26871
  projectionHost,
26937
26872
  zoom,
26938
- zoomScaleFactor,
26939
26873
  originCenterCache,
26940
- params
26874
+ preparedParams
26941
26875
  );
26942
26876
  const preparedItems = [];
26943
26877
  for (const item of itemsWithDepth) {
@@ -26945,9 +26879,8 @@ const prepareDrawSpriteImages = (projectionHost, params) => {
26945
26879
  projectionHost,
26946
26880
  item,
26947
26881
  zoom,
26948
- zoomScaleFactor,
26949
26882
  originCenterCache,
26950
- params
26883
+ preparedParams
26951
26884
  );
26952
26885
  if (prepared) {
26953
26886
  preparedItems.push(prepared);
@@ -26981,14 +26914,14 @@ const applyVisibilityDistanceLod = (preparedItems) => {
26981
26914
  continue;
26982
26915
  }
26983
26916
  image.lodOpacity = lodMultiplier;
26984
- const baseOpacity = (_b = image.opacity.interpolation.baseValue) != null ? _b : image.opacity.current;
26917
+ const baseOpacity = (_b = image.finalOpacity.interpolation.baseValue) != null ? _b : image.finalOpacity.current;
26985
26918
  const combinedTarget = clampOpacity(
26986
26919
  baseOpacity * ((_c = sprite.opacityMultiplier) != null ? _c : 1) * lodMultiplier
26987
26920
  );
26988
26921
  applyResolvedOpacityTarget(
26989
26922
  image,
26990
26923
  combinedTarget,
26991
- (_d = image.opacity.interpolation.options) != null ? _d : null
26924
+ (_d = image.finalOpacity.interpolation.options) != null ? _d : null
26992
26925
  );
26993
26926
  }
26994
26927
  };
@@ -26997,7 +26930,7 @@ const syncPreparedOpacities = (preparedItems) => {
26997
26930
  return;
26998
26931
  }
26999
26932
  for (const prepared of preparedItems) {
27000
- prepared.opacity = prepared.imageEntry.opacity.current;
26933
+ prepared.opacity = prepared.imageEntry.finalOpacity.current;
27001
26934
  }
27002
26935
  };
27003
26936
  const filterVisiblePreparedItems = (preparedItems) => {
@@ -27012,93 +26945,61 @@ const filterVisiblePreparedItems = (preparedItems) => {
27012
26945
  }
27013
26946
  return visibleItems;
27014
26947
  };
27015
- const evaluateDistanceInterpolationsBatch = (requests) => {
27016
- if (!requests.length) {
27017
- return [];
27018
- }
27019
- return requests.map((request) => evaluateDistanceInterpolation(request));
27020
- };
27021
- const evaluateDegreeInterpolationsBatch = (requests) => {
27022
- if (!requests.length) {
26948
+ const evaluateDistanceInterpolationsBatch = (states, timestamp) => {
26949
+ if (!states.length) {
27023
26950
  return [];
27024
26951
  }
27025
- return requests.map((request) => evaluateDegreeInterpolation(request));
26952
+ return states.map((state) => evaluateDistanceInterpolation(state, timestamp));
27026
26953
  };
27027
- const evaluateSpriteInterpolationsBatch = (requests) => {
27028
- if (!requests.length) {
26954
+ const evaluateDegreeInterpolationsBatch = (states, timestamp) => {
26955
+ if (!states.length) {
27029
26956
  return [];
27030
26957
  }
27031
- return requests.map((request) => evaluateInterpolation(request));
27032
- };
27033
- const defaultInterpolationEvaluationHandlers = {
27034
- evaluateDistance: (requests) => evaluateDistanceInterpolationsBatch(requests),
27035
- evaluateDegree: (requests) => evaluateDegreeInterpolationsBatch(requests),
27036
- evaluateSprite: (requests) => evaluateSpriteInterpolationsBatch(requests)
27037
- };
27038
- const applySpriteInterpolationEvaluations$1 = (workItems, evaluations, timestamp) => {
27039
- var _a;
27040
- let active = false;
27041
- for (let index = 0; index < workItems.length; index += 1) {
27042
- const item = workItems[index];
27043
- const { sprite, state } = item;
27044
- const evaluation = (_a = evaluations[index]) != null ? _a : evaluateInterpolation({
27045
- state,
27046
- timestamp
27047
- });
27048
- if (state.startTimestamp < 0) {
27049
- state.startTimestamp = evaluation.effectiveStartTimestamp;
27050
- }
27051
- sprite.location.current = evaluation.location;
27052
- if (evaluation.completed) {
27053
- sprite.location.current = cloneSpriteLocation(state.to);
27054
- sprite.location.from = void 0;
27055
- sprite.location.to = void 0;
27056
- sprite.location.interpolation.state = null;
27057
- } else {
27058
- active = true;
27059
- }
27060
- }
27061
- return active;
26958
+ return states.map((state) => evaluateDegreeInterpolation(state, timestamp));
27062
26959
  };
27063
26960
  const ensureOpacityInterpolationTarget = (sprite, image) => {
27064
26961
  var _a, _b, _c, _d;
27065
26962
  const target = clampOpacity(
27066
- ((_a = image.opacity.interpolation.baseValue) != null ? _a : image.opacity.current) * ((_b = sprite.opacityMultiplier) != null ? _b : 1) * ((_c = image.lodOpacity) != null ? _c : 1)
26963
+ ((_a = image.finalOpacity.interpolation.baseValue) != null ? _a : image.finalOpacity.current) * ((_b = sprite.opacityMultiplier) != null ? _b : 1) * ((_c = image.lodOpacity) != null ? _c : 1)
27067
26964
  );
27068
- const interpolationState = image.opacity.interpolation.state;
27069
- const currentStateTarget = interpolationState ? clampOpacity((_d = interpolationState.pathTarget) != null ? _d : interpolationState.to) : image.opacity.current;
26965
+ const interpolationState = image.finalOpacity.interpolation.state;
26966
+ const currentStateTarget = interpolationState ? clampOpacity((_d = interpolationState.pathTarget) != null ? _d : interpolationState.to) : image.finalOpacity.current;
27070
26967
  if (interpolationState) {
27071
26968
  if (Math.abs(currentStateTarget - target) <= OPACITY_TARGET_EPSILON) {
27072
26969
  return;
27073
26970
  }
27074
- } else if (Math.abs(image.opacity.current - target) <= OPACITY_TARGET_EPSILON) {
26971
+ } else if (Math.abs(image.finalOpacity.current - target) <= OPACITY_TARGET_EPSILON) {
27075
26972
  return;
27076
26973
  }
27077
- const options = image.opacity.interpolation.options;
26974
+ const options = image.finalOpacity.interpolation.options;
27078
26975
  if (options && options.durationMs > 0) {
27079
26976
  const { state, requiresInterpolation } = createDistanceInterpolationState({
27080
- currentValue: clampOpacity(image.opacity.current),
26977
+ currentValue: clampOpacity(image.finalOpacity.current),
27081
26978
  targetValue: target,
27082
- previousCommandValue: image.opacity.interpolation.lastCommandValue,
26979
+ previousCommandValue: image.finalOpacity.interpolation.lastCommandValue,
27083
26980
  options
27084
26981
  });
27085
26982
  if (requiresInterpolation) {
27086
- image.opacity.interpolation.state = state;
27087
- image.opacity.from = image.opacity.current;
27088
- image.opacity.to = target;
26983
+ image.finalOpacity.interpolation.state = state;
26984
+ image.finalOpacity.from = image.finalOpacity.current;
26985
+ image.finalOpacity.to = target;
27089
26986
  return;
27090
26987
  }
27091
26988
  }
27092
- image.opacity.current = target;
27093
- image.opacity.from = void 0;
27094
- image.opacity.to = void 0;
27095
- image.opacity.interpolation.state = null;
27096
- image.opacity.interpolation.lastCommandValue = target;
27097
- image.opacity.interpolation.targetValue = target;
26989
+ image.finalOpacity.current = target;
26990
+ image.finalOpacity.from = void 0;
26991
+ image.finalOpacity.to = void 0;
26992
+ image.finalOpacity.interpolation.state = null;
26993
+ image.finalOpacity.interpolation.lastCommandValue = target;
26994
+ image.finalOpacity.interpolation.targetValue = target;
26995
+ };
26996
+ const DEFAULT_INTERPOLATION_EVALUATION_HANDLERS = {
26997
+ evaluateDistance: evaluateDistanceInterpolationsBatch,
26998
+ evaluateDegree: evaluateDegreeInterpolationsBatch,
26999
+ evaluateSprite: evaluateLocationInterpolationsBatch
27098
27000
  };
27099
- const processInterpolationsInternal = (params, handlers = defaultInterpolationEvaluationHandlers) => {
27001
+ const processInterpolationsInternal = (params, handlers = DEFAULT_INTERPOLATION_EVALUATION_HANDLERS) => {
27100
27002
  var _a;
27101
- const evaluationHandlers = handlers != null ? handlers : defaultInterpolationEvaluationHandlers;
27102
27003
  const { sprites, timestamp } = params;
27103
27004
  if (!sprites.length) {
27104
27005
  return {
@@ -27108,14 +27009,13 @@ const processInterpolationsInternal = (params, handlers = defaultInterpolationEv
27108
27009
  }
27109
27010
  const distanceInterpolationWorkItems = [];
27110
27011
  const degreeInterpolationWorkItems = [];
27111
- const spriteInterpolationWorkItems = [];
27012
+ const locationInterpolationWorkItems = [];
27112
27013
  let hasActiveInterpolation = false;
27113
27014
  for (const sprite of sprites) {
27114
- const locationInterpolation = sprite.location.interpolation;
27115
- const state = locationInterpolation.state;
27116
- if (state) {
27117
- spriteInterpolationWorkItems.push({ sprite, state });
27118
- }
27015
+ collectLocationInterpolationWorkItems(
27016
+ sprite,
27017
+ locationInterpolationWorkItems
27018
+ );
27119
27019
  sprite.images.forEach((orderMap) => {
27120
27020
  orderMap.forEach((image) => {
27121
27021
  const hasOffsetMetersInterpolation = image.offset.offsetMeters.interpolation.state !== null;
@@ -27123,14 +27023,14 @@ const processInterpolationsInternal = (params, handlers = defaultInterpolationEv
27123
27023
  collectDistanceInterpolationWorkItems(
27124
27024
  image,
27125
27025
  distanceInterpolationWorkItems,
27126
- {
27127
- includeOpacity: false
27128
- }
27026
+ true,
27027
+ // includeOffsetMeters
27028
+ false
27129
27029
  );
27130
27030
  }
27131
27031
  ensureOpacityInterpolationTarget(sprite, image);
27132
- const hasOpacityInterpolation = image.opacity.interpolation.state !== null;
27133
- const hasDegreeInterpolation = image.rotateDeg.interpolation.state !== null || image.offset.offsetDeg.interpolation.state !== null;
27032
+ const hasOpacityInterpolation = image.finalOpacity.interpolation.state !== null;
27033
+ const hasDegreeInterpolation = image.finalRotateDeg.interpolation.state !== null || image.offset.offsetDeg.interpolation.state !== null;
27134
27034
  if (hasDegreeInterpolation) {
27135
27035
  collectDegreeInterpolationWorkItems(
27136
27036
  image,
@@ -27152,38 +27052,33 @@ const processInterpolationsInternal = (params, handlers = defaultInterpolationEv
27152
27052
  skipChannels.offsetDeg = true;
27153
27053
  shouldSkipChannels = true;
27154
27054
  }
27155
- if (stepSpriteImageInterpolations(
27156
- image,
27157
- timestamp,
27158
- shouldSkipChannels ? { skipChannels } : void 0
27159
- )) {
27055
+ const interpolationOptions = shouldSkipChannels ? {
27056
+ skipChannels,
27057
+ autoRotationDeg: resolveAutoRotationDeg$1(sprite, image)
27058
+ } : { autoRotationDeg: resolveAutoRotationDeg$1(sprite, image) };
27059
+ if (stepSpriteImageInterpolations(image, timestamp, interpolationOptions)) {
27160
27060
  hasActiveInterpolation = true;
27161
27061
  }
27162
27062
  });
27163
27063
  });
27164
27064
  }
27165
- const distanceRequests = distanceInterpolationWorkItems.length > 0 ? distanceInterpolationWorkItems.map(({ state }) => ({
27166
- state,
27167
- timestamp
27168
- })) : [];
27169
- const degreeRequests = degreeInterpolationWorkItems.length > 0 ? degreeInterpolationWorkItems.map(({ state }) => ({
27170
- state,
27171
- timestamp
27172
- })) : [];
27173
- const spriteRequests = spriteInterpolationWorkItems.length > 0 ? spriteInterpolationWorkItems.map(({ state }) => ({
27174
- state,
27175
- timestamp
27176
- })) : [];
27177
- const hasRequests = distanceRequests.length > 0 || degreeRequests.length > 0 || spriteRequests.length > 0;
27065
+ const hasRequests = distanceInterpolationWorkItems.length > 0 || degreeInterpolationWorkItems.length > 0 || locationInterpolationWorkItems.length > 0;
27178
27066
  if (hasRequests) {
27179
- (_a = evaluationHandlers.prepare) == null ? void 0 : _a.call(evaluationHandlers, {
27180
- distance: distanceRequests,
27181
- degree: degreeRequests,
27182
- sprite: spriteRequests
27183
- });
27067
+ (_a = handlers.prepare) == null ? void 0 : _a.call(
27068
+ handlers,
27069
+ {
27070
+ distance: distanceInterpolationWorkItems,
27071
+ degree: degreeInterpolationWorkItems,
27072
+ sprite: locationInterpolationWorkItems
27073
+ },
27074
+ timestamp
27075
+ );
27184
27076
  }
27185
- if (distanceRequests.length > 0) {
27186
- const evaluations = evaluationHandlers.evaluateDistance(distanceRequests);
27077
+ if (distanceInterpolationWorkItems.length > 0) {
27078
+ const evaluations = handlers.evaluateDistance(
27079
+ distanceInterpolationWorkItems,
27080
+ timestamp
27081
+ );
27187
27082
  if (applyDistanceInterpolationEvaluations(
27188
27083
  distanceInterpolationWorkItems,
27189
27084
  evaluations,
@@ -27192,8 +27087,11 @@ const processInterpolationsInternal = (params, handlers = defaultInterpolationEv
27192
27087
  hasActiveInterpolation = true;
27193
27088
  }
27194
27089
  }
27195
- if (degreeRequests.length > 0) {
27196
- const evaluations = evaluationHandlers.evaluateDegree(degreeRequests);
27090
+ if (degreeInterpolationWorkItems.length > 0) {
27091
+ const evaluations = handlers.evaluateDegree(
27092
+ degreeInterpolationWorkItems,
27093
+ timestamp
27094
+ );
27197
27095
  if (applyDegreeInterpolationEvaluations(
27198
27096
  degreeInterpolationWorkItems,
27199
27097
  evaluations,
@@ -27202,10 +27100,13 @@ const processInterpolationsInternal = (params, handlers = defaultInterpolationEv
27202
27100
  hasActiveInterpolation = true;
27203
27101
  }
27204
27102
  }
27205
- if (spriteRequests.length > 0) {
27206
- const evaluations = evaluationHandlers.evaluateSprite(spriteRequests);
27207
- if (applySpriteInterpolationEvaluations$1(
27208
- spriteInterpolationWorkItems,
27103
+ if (locationInterpolationWorkItems.length > 0) {
27104
+ const evaluations = handlers.evaluateSprite(
27105
+ locationInterpolationWorkItems,
27106
+ timestamp
27107
+ );
27108
+ if (applyLocationInterpolationEvaluations(
27109
+ locationInterpolationWorkItems,
27209
27110
  evaluations,
27210
27111
  timestamp
27211
27112
  )) {
@@ -27217,9 +27118,8 @@ const processInterpolationsInternal = (params, handlers = defaultInterpolationEv
27217
27118
  hasActiveInterpolation
27218
27119
  };
27219
27120
  };
27220
- const processOpacityInterpolationsAfterPreparation = (params, preparedItems, handlers = defaultInterpolationEvaluationHandlers) => {
27121
+ const processOpacityInterpolationsAfterPreparation = (params, preparedItems, handlers = DEFAULT_INTERPOLATION_EVALUATION_HANDLERS) => {
27221
27122
  var _a;
27222
- const evaluationHandlers = handlers != null ? handlers : defaultInterpolationEvaluationHandlers;
27223
27123
  const { sprites, timestamp } = params;
27224
27124
  if (!sprites.length) {
27225
27125
  return {
@@ -27232,10 +27132,14 @@ const processOpacityInterpolationsAfterPreparation = (params, preparedItems, han
27232
27132
  sprite.images.forEach((orderMap) => {
27233
27133
  orderMap.forEach((image) => {
27234
27134
  ensureOpacityInterpolationTarget(sprite, image);
27235
- if (image.opacity.interpolation.state !== null) {
27236
- collectDistanceInterpolationWorkItems(image, opacityWorkItems, {
27237
- includeOffsetMeters: false
27238
- });
27135
+ if (image.finalOpacity.interpolation.state !== null) {
27136
+ collectDistanceInterpolationWorkItems(
27137
+ image,
27138
+ opacityWorkItems,
27139
+ false,
27140
+ true
27141
+ // includeOpacity
27142
+ );
27239
27143
  }
27240
27144
  });
27241
27145
  });
@@ -27246,20 +27150,20 @@ const processOpacityInterpolationsAfterPreparation = (params, preparedItems, han
27246
27150
  hasActiveInterpolation: false
27247
27151
  };
27248
27152
  }
27249
- const opacityRequests = opacityWorkItems.length > 0 ? opacityWorkItems.map(({ state }) => ({
27250
- state,
27251
- timestamp
27252
- })) : [];
27253
- if (opacityRequests.length > 0) {
27254
- (_a = evaluationHandlers.prepare) == null ? void 0 : _a.call(evaluationHandlers, {
27255
- distance: opacityRequests,
27256
- degree: [],
27257
- sprite: []
27258
- });
27153
+ if (opacityWorkItems.length > 0) {
27154
+ (_a = handlers.prepare) == null ? void 0 : _a.call(
27155
+ handlers,
27156
+ {
27157
+ distance: opacityWorkItems,
27158
+ degree: [],
27159
+ sprite: []
27160
+ },
27161
+ timestamp
27162
+ );
27259
27163
  }
27260
27164
  let hasActiveInterpolation = false;
27261
- if (opacityRequests.length > 0) {
27262
- const evaluations = evaluationHandlers.evaluateDistance(opacityRequests);
27165
+ if (opacityWorkItems.length > 0) {
27166
+ const evaluations = handlers.evaluateDistance(opacityWorkItems, timestamp);
27263
27167
  if (applyDistanceInterpolationEvaluations(
27264
27168
  opacityWorkItems,
27265
27169
  evaluations,
@@ -27396,9 +27300,11 @@ const resolveImageOffset$1 = (image) => {
27396
27300
  offsetDeg: offset.offsetDeg.current
27397
27301
  };
27398
27302
  };
27399
- const encodeDistanceInterpolationRequest = (buffer, cursor, request) => {
27303
+ const resolveAutoRotationDeg = (sprite, image) => {
27304
+ return image.autoRotation ? sprite.currentAutoRotateDeg : 0;
27305
+ };
27306
+ const encodeDistanceInterpolationRequest = (buffer, cursor, state, timestamp) => {
27400
27307
  var _a;
27401
- const { state, timestamp } = request;
27402
27308
  const preset = encodeEasingPreset(state.easingParam);
27403
27309
  if (preset.id < 0) {
27404
27310
  throw new Error(
@@ -27417,9 +27323,8 @@ const encodeDistanceInterpolationRequest = (buffer, cursor, request) => {
27417
27323
  buffer[cursor++] = preset.param2;
27418
27324
  return cursor;
27419
27325
  };
27420
- const encodeDegreeInterpolationRequest = (buffer, cursor, request) => {
27326
+ const encodeDegreeInterpolationRequest = (buffer, cursor, state, timestamp) => {
27421
27327
  var _a;
27422
- const { state, timestamp } = request;
27423
27328
  const preset = encodeEasingPreset(state.easingParam);
27424
27329
  if (preset.id < 0) {
27425
27330
  throw new Error(
@@ -27438,9 +27343,8 @@ const encodeDegreeInterpolationRequest = (buffer, cursor, request) => {
27438
27343
  buffer[cursor++] = preset.param2;
27439
27344
  return cursor;
27440
27345
  };
27441
- const encodeSpriteInterpolationRequest = (buffer, cursor, request) => {
27346
+ const encodeSpriteInterpolationRequest = (buffer, cursor, state, timestamp) => {
27442
27347
  var _a, _b;
27443
- const { state, timestamp } = request;
27444
27348
  const preset = encodeEasingPreset(state.easingParam);
27445
27349
  if (preset.id < 0) {
27446
27350
  throw new Error(
@@ -27471,17 +27375,17 @@ const decodeSpriteInterpolationResult = (buffer, cursor) => {
27471
27375
  const hasZ = buffer[cursor++] !== 0;
27472
27376
  const completed = buffer[cursor++] !== 0;
27473
27377
  const effectiveStartTimestamp = buffer[cursor++];
27474
- const location2 = hasZ ? { lng, lat, z } : { lng, lat };
27378
+ const value = hasZ ? { lng, lat, z } : { lng, lat };
27475
27379
  return {
27476
27380
  nextCursor: cursor,
27477
27381
  result: {
27478
- location: location2,
27382
+ value,
27479
27383
  completed,
27480
27384
  effectiveStartTimestamp
27481
27385
  }
27482
27386
  };
27483
27387
  };
27484
- const processInterpolationsViaWasm = (wasm, requests) => {
27388
+ const processInterpolationsViaWasm = (wasm, requests, timestamp) => {
27485
27389
  const distanceCount = requests.distance.length;
27486
27390
  const degreeCount = requests.degree.length;
27487
27391
  const spriteCount = requests.sprite.length;
@@ -27510,14 +27414,25 @@ const processInterpolationsViaWasm = (wasm, requests) => {
27510
27414
  cursor = encodeDistanceInterpolationRequest(
27511
27415
  paramsBuffer,
27512
27416
  cursor,
27513
- request
27417
+ request,
27418
+ timestamp
27514
27419
  );
27515
27420
  }
27516
27421
  for (const request of requests.degree) {
27517
- cursor = encodeDegreeInterpolationRequest(paramsBuffer, cursor, request);
27422
+ cursor = encodeDegreeInterpolationRequest(
27423
+ paramsBuffer,
27424
+ cursor,
27425
+ request,
27426
+ timestamp
27427
+ );
27518
27428
  }
27519
27429
  for (const request of requests.sprite) {
27520
- cursor = encodeSpriteInterpolationRequest(paramsBuffer, cursor, request);
27430
+ cursor = encodeSpriteInterpolationRequest(
27431
+ paramsBuffer,
27432
+ cursor,
27433
+ request,
27434
+ timestamp
27435
+ );
27521
27436
  }
27522
27437
  const resultPrepared = resultHolder.prepare();
27523
27438
  const success = wasm.processInterpolations(
@@ -27529,9 +27444,7 @@ const processInterpolationsViaWasm = (wasm, requests) => {
27529
27444
  }
27530
27445
  const resultBuffer = resultPrepared.buffer;
27531
27446
  let read = WASM_PROCESS_INTERPOLATIONS_HEADER_LENGTH;
27532
- const distanceResults = new Array(
27533
- distanceCount
27534
- );
27447
+ const distanceResults = new Array(distanceCount);
27535
27448
  for (let i = 0; i < distanceCount; i += 1) {
27536
27449
  const value = resultBuffer[read++];
27537
27450
  const completed = resultBuffer[read++] !== 0;
@@ -27542,9 +27455,7 @@ const processInterpolationsViaWasm = (wasm, requests) => {
27542
27455
  effectiveStartTimestamp
27543
27456
  };
27544
27457
  }
27545
- const degreeResults = new Array(
27546
- degreeCount
27547
- );
27458
+ const degreeResults = new Array(degreeCount);
27548
27459
  for (let i = 0; i < degreeCount; i += 1) {
27549
27460
  const value = resultBuffer[read++];
27550
27461
  const completed = resultBuffer[read++] !== 0;
@@ -27555,9 +27466,7 @@ const processInterpolationsViaWasm = (wasm, requests) => {
27555
27466
  effectiveStartTimestamp
27556
27467
  };
27557
27468
  }
27558
- const spriteResults = new Array(
27559
- spriteCount
27560
- );
27469
+ const spriteResults = new Array(spriteCount);
27561
27470
  for (let i = 0; i < spriteCount; i += 1) {
27562
27471
  const decoded = decodeSpriteInterpolationResult(resultBuffer, read);
27563
27472
  spriteResults[i] = decoded.result;
@@ -27573,31 +27482,6 @@ const processInterpolationsViaWasm = (wasm, requests) => {
27573
27482
  paramsHolder.release();
27574
27483
  }
27575
27484
  };
27576
- const applySpriteInterpolationEvaluations = (workItems, evaluations, timestamp) => {
27577
- var _a;
27578
- let active = false;
27579
- for (let index = 0; index < workItems.length; index += 1) {
27580
- const item = workItems[index];
27581
- const { sprite, state } = item;
27582
- const evaluation = (_a = evaluations[index]) != null ? _a : evaluateInterpolation({
27583
- state,
27584
- timestamp
27585
- });
27586
- if (state.startTimestamp < 0) {
27587
- state.startTimestamp = evaluation.effectiveStartTimestamp;
27588
- }
27589
- sprite.location.current = evaluation.location;
27590
- if (evaluation.completed) {
27591
- sprite.location.current = cloneSpriteLocation(state.to);
27592
- sprite.location.from = void 0;
27593
- sprite.location.to = void 0;
27594
- sprite.location.interpolation.state = null;
27595
- } else {
27596
- active = true;
27597
- }
27598
- }
27599
- return active;
27600
- };
27601
27485
  const processInterpolationsWithWasm = (wasm, params) => {
27602
27486
  const { sprites, timestamp } = params;
27603
27487
  if (!sprites.length) {
@@ -27608,7 +27492,7 @@ const processInterpolationsWithWasm = (wasm, params) => {
27608
27492
  }
27609
27493
  const distanceInterpolationWorkItems = [];
27610
27494
  const degreeInterpolationWorkItems = [];
27611
- const spriteInterpolationWorkItems = [];
27495
+ const locationInterpolationWorkItems = [];
27612
27496
  const processedSprites = [];
27613
27497
  let hasActiveInterpolation = false;
27614
27498
  for (const sprite of sprites) {
@@ -27618,9 +27502,10 @@ const processInterpolationsWithWasm = (wasm, params) => {
27618
27502
  if (!hasSpriteInterpolation && !sprite.interpolationDirty) {
27619
27503
  continue;
27620
27504
  }
27621
- if (state) {
27622
- spriteInterpolationWorkItems.push({ sprite, state });
27623
- }
27505
+ collectLocationInterpolationWorkItems(
27506
+ sprite,
27507
+ locationInterpolationWorkItems
27508
+ );
27624
27509
  const touchedImages = [];
27625
27510
  sprite.images.forEach((orderMap) => {
27626
27511
  orderMap.forEach((image) => {
@@ -27637,13 +27522,13 @@ const processInterpolationsWithWasm = (wasm, params) => {
27637
27522
  collectDistanceInterpolationWorkItems(
27638
27523
  image,
27639
27524
  distanceInterpolationWorkItems,
27640
- {
27641
- includeOpacity: false
27642
- }
27525
+ true,
27526
+ // includeOffsetMeters
27527
+ false
27643
27528
  );
27644
27529
  }
27645
- const hasOpacityInterpolation = image.opacity.interpolation.state !== null;
27646
- const hasDegreeInterpolation = image.rotateDeg.interpolation.state !== null || image.offset.offsetDeg.interpolation.state !== null;
27530
+ const hasOpacityInterpolation = image.finalOpacity.interpolation.state !== null;
27531
+ const hasDegreeInterpolation = image.finalRotateDeg.interpolation.state !== null || image.offset.offsetDeg.interpolation.state !== null;
27647
27532
  if (hasDegreeInterpolation) {
27648
27533
  collectDegreeInterpolationWorkItems(
27649
27534
  image,
@@ -27665,11 +27550,11 @@ const processInterpolationsWithWasm = (wasm, params) => {
27665
27550
  skipChannels.offsetDeg = true;
27666
27551
  shouldSkipChannels = true;
27667
27552
  }
27668
- if (stepSpriteImageInterpolations(
27669
- image,
27670
- timestamp,
27671
- shouldSkipChannels ? { skipChannels } : void 0
27672
- )) {
27553
+ const interpolationOptions = shouldSkipChannels ? {
27554
+ skipChannels,
27555
+ autoRotationDeg: resolveAutoRotationDeg(sprite, image)
27556
+ } : { autoRotationDeg: resolveAutoRotationDeg(sprite, image) };
27557
+ if (stepSpriteImageInterpolations(image, timestamp, interpolationOptions)) {
27673
27558
  hasActiveInterpolation = true;
27674
27559
  }
27675
27560
  });
@@ -27680,29 +27565,21 @@ const processInterpolationsWithWasm = (wasm, params) => {
27680
27565
  }
27681
27566
  processedSprites.push({ sprite, touchedImages });
27682
27567
  }
27683
- const distanceRequests = distanceInterpolationWorkItems.length > 0 ? distanceInterpolationWorkItems.map(({ state }) => ({
27684
- state,
27685
- timestamp
27686
- })) : [];
27687
- const degreeRequests = degreeInterpolationWorkItems.length > 0 ? degreeInterpolationWorkItems.map(({ state }) => ({
27688
- state,
27689
- timestamp
27690
- })) : [];
27691
- const spriteRequests = spriteInterpolationWorkItems.length > 0 ? spriteInterpolationWorkItems.map(({ state }) => ({
27692
- state,
27568
+ const hasPresetRequests = distanceInterpolationWorkItems.length > 0 || degreeInterpolationWorkItems.length > 0 || locationInterpolationWorkItems.length > 0;
27569
+ const wasmResults = hasPresetRequests ? processInterpolationsViaWasm(
27570
+ wasm,
27571
+ {
27572
+ distance: distanceInterpolationWorkItems,
27573
+ degree: degreeInterpolationWorkItems,
27574
+ sprite: locationInterpolationWorkItems
27575
+ },
27693
27576
  timestamp
27694
- })) : [];
27695
- const hasPresetRequests = distanceRequests.length > 0 || degreeRequests.length > 0 || spriteRequests.length > 0;
27696
- const wasmResults = hasPresetRequests ? processInterpolationsViaWasm(wasm, {
27697
- distance: distanceRequests,
27698
- degree: degreeRequests,
27699
- sprite: spriteRequests
27700
- }) : {
27577
+ ) : {
27701
27578
  distance: [],
27702
27579
  degree: [],
27703
27580
  sprite: []
27704
27581
  };
27705
- if (distanceRequests.length > 0) {
27582
+ if (distanceInterpolationWorkItems.length > 0) {
27706
27583
  if (applyDistanceInterpolationEvaluations(
27707
27584
  distanceInterpolationWorkItems,
27708
27585
  wasmResults.distance,
@@ -27711,7 +27588,7 @@ const processInterpolationsWithWasm = (wasm, params) => {
27711
27588
  hasActiveInterpolation = true;
27712
27589
  }
27713
27590
  }
27714
- if (degreeRequests.length > 0) {
27591
+ if (degreeInterpolationWorkItems.length > 0) {
27715
27592
  if (applyDegreeInterpolationEvaluations(
27716
27593
  degreeInterpolationWorkItems,
27717
27594
  wasmResults.degree,
@@ -27720,9 +27597,9 @@ const processInterpolationsWithWasm = (wasm, params) => {
27720
27597
  hasActiveInterpolation = true;
27721
27598
  }
27722
27599
  }
27723
- if (spriteRequests.length > 0) {
27724
- if (applySpriteInterpolationEvaluations(
27725
- spriteInterpolationWorkItems,
27600
+ if (locationInterpolationWorkItems.length > 0) {
27601
+ if (applyLocationInterpolationEvaluations(
27602
+ locationInterpolationWorkItems,
27726
27603
  wasmResults.sprite,
27727
27604
  timestamp
27728
27605
  )) {
@@ -28245,6 +28122,9 @@ const convertToWasmProjectionState = (wasm, params, deps) => {
28245
28122
  9
28246
28123
  /* FLAGS */
28247
28124
  ] = inputFlags;
28125
+ const zoomScaleFactor = 1;
28126
+ const spriteMinPixel = 0;
28127
+ const spriteMaxPixel = 0;
28248
28128
  const frameConstView = parameterBuffer.subarray(
28249
28129
  frameConstOffset,
28250
28130
  frameConstOffset + INPUT_FRAME_CONSTANT_LENGTH
@@ -28261,12 +28141,12 @@ const convertToWasmProjectionState = (wasm, params, deps) => {
28261
28141
  0
28262
28142
  );
28263
28143
  frameConstView[fcCursor++] = callParams.baseMetersPerPixel;
28264
- frameConstView[fcCursor++] = callParams.spriteMinPixel;
28265
- frameConstView[fcCursor++] = callParams.spriteMaxPixel;
28144
+ frameConstView[fcCursor++] = spriteMinPixel;
28145
+ frameConstView[fcCursor++] = spriteMaxPixel;
28266
28146
  frameConstView[fcCursor++] = callParams.drawingBufferWidth;
28267
28147
  frameConstView[fcCursor++] = callParams.drawingBufferHeight;
28268
28148
  frameConstView[fcCursor++] = callParams.pixelRatio;
28269
- frameConstView[fcCursor++] = toFiniteOr(callParams.zoomScaleFactor, 1);
28149
+ frameConstView[fcCursor++] = zoomScaleFactor;
28270
28150
  frameConstView[fcCursor++] = callParams.identityScaleX;
28271
28151
  frameConstView[fcCursor++] = callParams.identityScaleY;
28272
28152
  frameConstView[fcCursor++] = callParams.identityOffsetX;
@@ -28286,7 +28166,7 @@ const convertToWasmProjectionState = (wasm, params, deps) => {
28286
28166
  frameConstView[fcCursor++] = (_c = cameraLocation == null ? void 0 : cameraLocation.z) != null ? _c : 0;
28287
28167
  state.lastFrameParams = {
28288
28168
  baseMetersPerPixel: callParams.baseMetersPerPixel,
28289
- zoomScaleFactor: toFiniteOr(callParams.zoomScaleFactor, 1)
28169
+ zoomScaleFactor
28290
28170
  };
28291
28171
  writeMatrix(
28292
28172
  parameterBuffer,
@@ -28347,7 +28227,7 @@ const convertToWasmProjectionState = (wasm, params, deps) => {
28347
28227
  const originTargetIndices = (_g = (_f = callParams.bucketBuffers) == null ? void 0 : _f.originTargetIndices) != null ? _g : null;
28348
28228
  cursor = itemOffset;
28349
28229
  bucket.forEach(([sprite, image], index) => {
28350
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h, _i, _j, _k;
28230
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h, _i, _j, _k, _l;
28351
28231
  const imageHandle = image.imageHandle;
28352
28232
  const spriteHandle = sprite.handle;
28353
28233
  const originKeyCandidate = (_a2 = originReferenceKeys == null ? void 0 : originReferenceKeys[index]) != null ? _a2 : image.originReferenceKey;
@@ -28355,37 +28235,52 @@ const convertToWasmProjectionState = (wasm, params, deps) => {
28355
28235
  const originIndex = (_b2 = originTargetIndices == null ? void 0 : originTargetIndices[index]) != null ? _b2 : image.originRenderTargetIndex;
28356
28236
  const originLocation = image.originLocation;
28357
28237
  const currentLocation = sprite.location.current;
28238
+ const cameraLocation2 = preparedProjection.cameraLocation;
28239
+ const cameraDistanceMeters = cameraLocation2 !== void 0 ? calculateCartesianDistanceMeters(cameraLocation2, {
28240
+ lng: currentLocation.lng,
28241
+ lat: currentLocation.lat,
28242
+ z: (_c2 = currentLocation.z) != null ? _c2 : 0
28243
+ }) : Number.POSITIVE_INFINITY;
28244
+ const distanceScaleFactor = calculateDistanceScaleFactor(
28245
+ cameraDistanceMeters,
28246
+ callParams.resolvedScaling
28247
+ );
28248
+ const scaledImageScale = ((_d2 = image.scale) != null ? _d2 : 1) * distanceScaleFactor;
28358
28249
  parameterBuffer[cursor++] = spriteHandle;
28359
28250
  parameterBuffer[cursor++] = imageHandle;
28360
28251
  parameterBuffer[cursor++] = originIndex != null ? originIndex : SPRITE_ORIGIN_REFERENCE_INDEX_NONE;
28361
28252
  parameterBuffer[cursor++] = boolToNumber(
28362
- (_c2 = originLocation == null ? void 0 : originLocation.useResolvedAnchor) != null ? _c2 : false
28253
+ (_e2 = originLocation == null ? void 0 : originLocation.useResolvedAnchor) != null ? _e2 : false
28363
28254
  );
28364
28255
  parameterBuffer[cursor++] = modeToNumber(image.mode);
28365
- parameterBuffer[cursor++] = (_d2 = image.scale) != null ? _d2 : 1;
28366
- parameterBuffer[cursor++] = image.opacity.current;
28367
- const anchor = (_e2 = image.anchor) != null ? _e2 : { x: 0, y: 0 };
28256
+ parameterBuffer[cursor++] = scaledImageScale;
28257
+ parameterBuffer[cursor++] = image.finalOpacity.current;
28258
+ const anchor = (_f2 = image.anchor) != null ? _f2 : { x: 0, y: 0 };
28368
28259
  parameterBuffer[cursor++] = anchor.x;
28369
28260
  parameterBuffer[cursor++] = anchor.y;
28370
28261
  const offset = resolveImageOffset$1(image);
28371
28262
  parameterBuffer[cursor++] = offset.offsetMeters;
28372
28263
  parameterBuffer[cursor++] = offset.offsetDeg;
28373
- parameterBuffer[cursor++] = toFiniteOr(image.displayedRotateDeg, 0);
28374
- parameterBuffer[cursor++] = toFiniteOr(image.resolvedBaseRotateDeg, 0);
28375
- parameterBuffer[cursor++] = toFiniteOr(image.rotationCommandDeg, 0);
28264
+ const autoRotationDeg = resolveAutoRotationDeg(sprite, image);
28265
+ const resolvedRotation = normalizeAngleDeg(
28266
+ toFiniteOr(image.finalRotateDeg.current, 0)
28267
+ );
28268
+ parameterBuffer[cursor++] = resolvedRotation;
28269
+ parameterBuffer[cursor++] = toFiniteOr(autoRotationDeg, 0);
28270
+ parameterBuffer[cursor++] = toFiniteOr(image.rotateDeg, 0);
28376
28271
  parameterBuffer[cursor++] = image.order;
28377
28272
  parameterBuffer[cursor++] = image.subLayer;
28378
28273
  parameterBuffer[cursor++] = originKey != null ? originKey : SPRITE_ORIGIN_REFERENCE_KEY_NONE;
28379
- parameterBuffer[cursor++] = (_f2 = originReferenceKeys == null ? void 0 : originReferenceKeys[index]) != null ? _f2 : SPRITE_ORIGIN_REFERENCE_KEY_NONE;
28380
- parameterBuffer[cursor++] = (_g2 = originTargetIndices == null ? void 0 : originTargetIndices[index]) != null ? _g2 : SPRITE_ORIGIN_REFERENCE_INDEX_NONE;
28274
+ parameterBuffer[cursor++] = (_g2 = originReferenceKeys == null ? void 0 : originReferenceKeys[index]) != null ? _g2 : SPRITE_ORIGIN_REFERENCE_KEY_NONE;
28275
+ parameterBuffer[cursor++] = (_h = originTargetIndices == null ? void 0 : originTargetIndices[index]) != null ? _h : SPRITE_ORIGIN_REFERENCE_INDEX_NONE;
28381
28276
  parameterBuffer[cursor++] = image.imageHandle;
28382
28277
  parameterBuffer[cursor++] = currentLocation.lng;
28383
28278
  parameterBuffer[cursor++] = currentLocation.lat;
28384
- parameterBuffer[cursor++] = (_h = currentLocation.z) != null ? _h : 0;
28385
- parameterBuffer[cursor++] = (_i = originLocation == null ? void 0 : originLocation.subLayer) != null ? _i : -1;
28386
- parameterBuffer[cursor++] = (_j = originLocation == null ? void 0 : originLocation.order) != null ? _j : -1;
28279
+ parameterBuffer[cursor++] = (_i = currentLocation.z) != null ? _i : 0;
28280
+ parameterBuffer[cursor++] = (_j = originLocation == null ? void 0 : originLocation.subLayer) != null ? _j : -1;
28281
+ parameterBuffer[cursor++] = (_k = originLocation == null ? void 0 : originLocation.order) != null ? _k : -1;
28387
28282
  parameterBuffer[cursor++] = boolToNumber(
28388
- (_k = originLocation == null ? void 0 : originLocation.useResolvedAnchor) != null ? _k : false
28283
+ (_l = originLocation == null ? void 0 : originLocation.useResolvedAnchor) != null ? _l : false
28389
28284
  );
28390
28285
  parameterBuffer[cursor++] = index;
28391
28286
  });
@@ -28435,39 +28330,306 @@ const createWasmCalculationHost = (params, deps) => {
28435
28330
  }
28436
28331
  };
28437
28332
  return {
28438
- processDrawSpriteImages: (params2) => runWithFallback(
28439
- () => {
28440
- let interpolationResult = params2.interpolationParams ? processInterpolationsWithWasm(wasm, params2.interpolationParams) : DEFAULT_RENDER_INTERPOLATION_RESULT;
28441
- const preparedItems = params2.prepareParams ? prepareDrawSpriteImagesInternal(
28442
- wasm,
28443
- wasmState,
28444
- deps,
28445
- params2.prepareParams
28446
- ) : [];
28447
- if (preparedItems.length > 0) {
28448
- applyVisibilityDistanceLod(preparedItems);
28449
- }
28450
- if (params2.interpolationParams) {
28451
- const opacityResult = processOpacityInterpolationsAfterPreparation(
28452
- params2.interpolationParams,
28453
- preparedItems
28454
- );
28455
- interpolationResult = {
28456
- handled: interpolationResult.handled || opacityResult.handled,
28457
- hasActiveInterpolation: interpolationResult.hasActiveInterpolation || opacityResult.hasActiveInterpolation
28458
- };
28459
- }
28460
- syncPreparedOpacities(preparedItems);
28461
- const visiblePreparedItems = filterVisiblePreparedItems(preparedItems);
28462
- return {
28463
- interpolationResult,
28464
- preparedItems: visiblePreparedItems
28465
- };
28466
- },
28467
- () => ensureFallbackHost().processDrawSpriteImages(params2)
28468
- ),
28333
+ processDrawSpriteImages: (params2) => runWithFallback(
28334
+ () => {
28335
+ let interpolationResult = params2.interpolationParams ? processInterpolationsWithWasm(wasm, params2.interpolationParams) : DEFAULT_RENDER_INTERPOLATION_RESULT;
28336
+ const preparedItems = params2.prepareParams ? prepareDrawSpriteImagesInternal(
28337
+ wasm,
28338
+ wasmState,
28339
+ deps,
28340
+ params2.prepareParams
28341
+ ) : [];
28342
+ if (preparedItems.length > 0) {
28343
+ applyVisibilityDistanceLod(preparedItems);
28344
+ }
28345
+ if (params2.interpolationParams) {
28346
+ const opacityResult = processOpacityInterpolationsAfterPreparation(
28347
+ params2.interpolationParams,
28348
+ preparedItems
28349
+ );
28350
+ interpolationResult = {
28351
+ handled: interpolationResult.handled || opacityResult.handled,
28352
+ hasActiveInterpolation: interpolationResult.hasActiveInterpolation || opacityResult.hasActiveInterpolation
28353
+ };
28354
+ }
28355
+ syncPreparedOpacities(preparedItems);
28356
+ const visiblePreparedItems = filterVisiblePreparedItems(preparedItems);
28357
+ return {
28358
+ interpolationResult,
28359
+ preparedItems: visiblePreparedItems
28360
+ };
28361
+ },
28362
+ () => ensureFallbackHost().processDrawSpriteImages(params2)
28363
+ ),
28364
+ release: () => {
28365
+ releaseFallbackHost();
28366
+ }
28367
+ };
28368
+ };
28369
+ const createSpriteTrackingController = (mapInstance) => {
28370
+ let trackedSpriteTrackRotation = true;
28371
+ let trackedSprite;
28372
+ let trackedSpriteFrameId = null;
28373
+ const cancelTrackedSpriteFrame = () => {
28374
+ if (trackedSpriteFrameId === null) {
28375
+ return;
28376
+ }
28377
+ if (typeof window !== "undefined") {
28378
+ window.cancelAnimationFrame(trackedSpriteFrameId);
28379
+ }
28380
+ trackedSpriteFrameId = null;
28381
+ };
28382
+ const untrackSpriteInternal = () => {
28383
+ cancelTrackedSpriteFrame();
28384
+ };
28385
+ const applyTrackedSpriteRotation = (sprite) => {
28386
+ let targetBearing = null;
28387
+ for (const orderMap of sprite.images.values()) {
28388
+ const iterator = orderMap.values().next();
28389
+ if (!iterator.done) {
28390
+ targetBearing = normalizeAngleDeg(
28391
+ iterator.value.finalRotateDeg.current
28392
+ );
28393
+ break;
28394
+ }
28395
+ }
28396
+ if (targetBearing === null) {
28397
+ return false;
28398
+ }
28399
+ const currentBearing = normalizeAngleDeg(mapInstance.getBearing());
28400
+ if (currentBearing === targetBearing) {
28401
+ return false;
28402
+ }
28403
+ mapInstance.setBearing(targetBearing);
28404
+ return true;
28405
+ };
28406
+ const stepTrackedSprite = () => {
28407
+ trackedSpriteFrameId = null;
28408
+ if (!mapInstance || !trackedSprite || typeof window === "undefined") {
28409
+ return;
28410
+ }
28411
+ mapInstance.setCenter(trackedSprite.location.current);
28412
+ if (trackedSpriteTrackRotation) {
28413
+ applyTrackedSpriteRotation(trackedSprite);
28414
+ }
28415
+ trackedSpriteFrameId = window.requestAnimationFrame(stepTrackedSprite);
28416
+ };
28417
+ const trackSprite = (sprite, trackRotation) => {
28418
+ if (typeof window === "undefined") {
28419
+ return;
28420
+ }
28421
+ trackedSpriteTrackRotation = trackRotation !== false;
28422
+ trackedSprite = sprite;
28423
+ cancelTrackedSpriteFrame();
28424
+ trackedSpriteFrameId = window.requestAnimationFrame(stepTrackedSprite);
28425
+ };
28426
+ const untrackSprite = () => {
28427
+ trackedSpriteTrackRotation = true;
28428
+ trackedSprite = void 0;
28429
+ untrackSpriteInternal();
28430
+ };
28431
+ return {
28432
+ trackSprite,
28433
+ untrackSprite,
28434
+ release: () => {
28435
+ untrackSpriteInternal();
28436
+ trackedSprite = void 0;
28437
+ }
28438
+ };
28439
+ };
28440
+ const createSpriteMouseEventsController = ({
28441
+ resolveHitTestResult,
28442
+ resolveSpriteEventPayload,
28443
+ updateVisibilityState
28444
+ }) => {
28445
+ const eventListeners = /* @__PURE__ */ new Map();
28446
+ const inputListenerDisposers = [];
28447
+ let boundCanvasElement;
28448
+ const registerDisposer = (disposer) => {
28449
+ inputListenerDisposers.push(disposer);
28450
+ };
28451
+ const clearDomListeners = () => {
28452
+ inputListenerDisposers.forEach((dispose) => dispose());
28453
+ inputListenerDisposers.length = 0;
28454
+ };
28455
+ const getListenerSet = (type) => {
28456
+ let set = eventListeners.get(type);
28457
+ if (!set) {
28458
+ set = /* @__PURE__ */ new Set();
28459
+ eventListeners.set(type, set);
28460
+ }
28461
+ return set;
28462
+ };
28463
+ const addEventListener2 = (type, listener) => {
28464
+ getListenerSet(type).add(listener);
28465
+ };
28466
+ const removeEventListener2 = (type, listener) => {
28467
+ const listeners = eventListeners.get(type);
28468
+ if (!listeners) {
28469
+ return;
28470
+ }
28471
+ listeners.delete(listener);
28472
+ if (listeners.size === 0) {
28473
+ eventListeners.delete(type);
28474
+ }
28475
+ };
28476
+ const hasSpriteListeners = (type) => {
28477
+ var _a, _b;
28478
+ return ((_b = (_a = eventListeners.get(type)) == null ? void 0 : _a.size) != null ? _b : 0) > 0;
28479
+ };
28480
+ const hasSpriteClickListeners = () => hasSpriteListeners("spriteclick");
28481
+ const hasSpriteHoverListeners = () => hasSpriteListeners("spritehover");
28482
+ const dispatchSpriteClick = (hitEntry, screenPoint, originalEvent) => {
28483
+ const listeners = eventListeners.get("spriteclick");
28484
+ if (!listeners || listeners.size === 0) {
28485
+ return;
28486
+ }
28487
+ const payload = resolveSpriteEventPayload(hitEntry);
28488
+ const clickEvent = {
28489
+ type: "spriteclick",
28490
+ sprite: payload.sprite,
28491
+ image: payload.image,
28492
+ screenPoint,
28493
+ originalEvent
28494
+ };
28495
+ listeners.forEach((listener) => {
28496
+ listener(clickEvent);
28497
+ });
28498
+ };
28499
+ const dispatchSpriteHover = (hitEntry, screenPoint, originalEvent) => {
28500
+ const listeners = eventListeners.get("spritehover");
28501
+ if (!listeners || listeners.size === 0) {
28502
+ return;
28503
+ }
28504
+ const payload = resolveSpriteEventPayload(hitEntry);
28505
+ const hoverEvent = {
28506
+ type: "spritehover",
28507
+ sprite: payload.sprite,
28508
+ image: payload.image,
28509
+ screenPoint,
28510
+ originalEvent
28511
+ };
28512
+ listeners.forEach((listener) => {
28513
+ listener(hoverEvent);
28514
+ });
28515
+ };
28516
+ const processClickEvent = (nativeEvent) => {
28517
+ if (!hasSpriteClickListeners()) {
28518
+ return;
28519
+ }
28520
+ const hitResult = resolveHitTestResult(nativeEvent);
28521
+ if (!hitResult || !hitResult.hitEntry) {
28522
+ return;
28523
+ }
28524
+ dispatchSpriteClick(hitResult.hitEntry, hitResult.screenPoint, nativeEvent);
28525
+ };
28526
+ const processHoverEvent = (nativeEvent) => {
28527
+ if (!hasSpriteHoverListeners()) {
28528
+ return;
28529
+ }
28530
+ const hitResult = resolveHitTestResult(nativeEvent);
28531
+ if (!hitResult) {
28532
+ return;
28533
+ }
28534
+ dispatchSpriteHover(hitResult.hitEntry, hitResult.screenPoint, nativeEvent);
28535
+ };
28536
+ const bindCanvas = (canvasElement) => {
28537
+ var _a;
28538
+ clearDomListeners();
28539
+ boundCanvasElement = canvasElement;
28540
+ const supportsPointerEvents = typeof window !== "undefined" && "PointerEvent" in window;
28541
+ if (canvasElement) {
28542
+ if (supportsPointerEvents) {
28543
+ const pointerUpListener = (event) => {
28544
+ if (event.pointerType === "mouse" && event.button !== 0) {
28545
+ return;
28546
+ }
28547
+ processClickEvent(event);
28548
+ };
28549
+ canvasElement.addEventListener("pointerup", pointerUpListener, {
28550
+ passive: true
28551
+ });
28552
+ registerDisposer(() => {
28553
+ canvasElement.removeEventListener("pointerup", pointerUpListener);
28554
+ });
28555
+ const pointerMoveListener = (event) => {
28556
+ if (!event.isPrimary) {
28557
+ return;
28558
+ }
28559
+ if (event.pointerType === "touch") {
28560
+ return;
28561
+ }
28562
+ processHoverEvent(event);
28563
+ };
28564
+ canvasElement.addEventListener("pointermove", pointerMoveListener, {
28565
+ passive: true
28566
+ });
28567
+ registerDisposer(() => {
28568
+ canvasElement.removeEventListener("pointermove", pointerMoveListener);
28569
+ });
28570
+ } else {
28571
+ const clickListener = (event) => {
28572
+ if (event.button !== 0) {
28573
+ return;
28574
+ }
28575
+ processClickEvent(event);
28576
+ };
28577
+ canvasElement.addEventListener("click", clickListener, {
28578
+ passive: true
28579
+ });
28580
+ registerDisposer(() => {
28581
+ canvasElement.removeEventListener("click", clickListener);
28582
+ });
28583
+ const touchListener = (event) => {
28584
+ processClickEvent(event);
28585
+ };
28586
+ canvasElement.addEventListener("touchend", touchListener, {
28587
+ passive: true
28588
+ });
28589
+ registerDisposer(() => {
28590
+ canvasElement.removeEventListener("touchend", touchListener);
28591
+ });
28592
+ const mouseMoveListener = (event) => {
28593
+ processHoverEvent(event);
28594
+ };
28595
+ canvasElement.addEventListener("mousemove", mouseMoveListener, {
28596
+ passive: true
28597
+ });
28598
+ registerDisposer(() => {
28599
+ canvasElement.removeEventListener("mousemove", mouseMoveListener);
28600
+ });
28601
+ }
28602
+ const visibilityTarget = (_a = canvasElement.ownerDocument) != null ? _a : typeof document !== "undefined" ? document : void 0;
28603
+ if (visibilityTarget) {
28604
+ const visibilityListener = () => updateVisibilityState();
28605
+ visibilityTarget.addEventListener(
28606
+ "visibilitychange",
28607
+ visibilityListener
28608
+ );
28609
+ registerDisposer(() => {
28610
+ visibilityTarget.removeEventListener(
28611
+ "visibilitychange",
28612
+ visibilityListener
28613
+ );
28614
+ });
28615
+ updateVisibilityState();
28616
+ }
28617
+ }
28618
+ };
28619
+ return {
28620
+ get canvasElement() {
28621
+ return boundCanvasElement;
28622
+ },
28623
+ addEventListener: addEventListener2,
28624
+ removeEventListener: removeEventListener2,
28625
+ hasSpriteClickListeners,
28626
+ hasSpriteHoverListeners,
28627
+ bindCanvas,
28469
28628
  release: () => {
28470
- releaseFallbackHost();
28629
+ clearDomListeners();
28630
+ eventListeners.forEach((set) => set.clear());
28631
+ eventListeners.clear();
28632
+ boundCanvasElement = void 0;
28471
28633
  }
28472
28634
  };
28473
28635
  };
@@ -29268,6 +29430,9 @@ const resolveImageOffset = (image) => {
29268
29430
  offsetDeg: offset.offsetDeg.current
29269
29431
  };
29270
29432
  };
29433
+ const resolveImageAutoRotationDeg$1 = (sprite, image) => {
29434
+ return image.autoRotation ? sprite.currentAutoRotateDeg : 0;
29435
+ };
29271
29436
  const createHitTestController = ({
29272
29437
  images,
29273
29438
  getResolvedScaling
@@ -29338,7 +29503,6 @@ const createHitTestController = ({
29338
29503
  const scaling = getResolvedScaling();
29339
29504
  const baseLocation = sprite.location.current;
29340
29505
  const zoom = projectionHost.getZoom();
29341
- const zoomScaleFactor = calculateZoomScaleFactor(zoom, scaling);
29342
29506
  const metersPerPixelAtLat = calculateMetersPerPixelAtLatitude(
29343
29507
  zoom,
29344
29508
  baseLocation.lat
@@ -29358,35 +29522,39 @@ const createHitTestController = ({
29358
29522
  if (!Number.isFinite(effectivePixelsPerMeter) || effectivePixelsPerMeter <= 0) {
29359
29523
  return null;
29360
29524
  }
29361
- const imageScale = (_a = image.scale) != null ? _a : 1;
29525
+ const cameraLocation = projectionHost.getCameraLocation();
29526
+ const cameraDistanceMeters = cameraLocation !== void 0 ? calculateCartesianDistanceMeters(cameraLocation, {
29527
+ lng: baseLocation.lng,
29528
+ lat: baseLocation.lat,
29529
+ z: (_a = baseLocation.z) != null ? _a : 0
29530
+ }) : Number.POSITIVE_INFINITY;
29531
+ const distanceScaleFactor = calculateDistanceScaleFactor(
29532
+ cameraDistanceMeters,
29533
+ scaling
29534
+ );
29535
+ const imageScale = (_b = image.scale) != null ? _b : 1;
29362
29536
  const baseMetersPerPixel = scaling.metersPerPixel;
29363
- const spriteMinPixel = scaling.spriteMinPixel;
29364
- const spriteMaxPixel = scaling.spriteMaxPixel;
29365
29537
  const worldDims = calculateSurfaceWorldDimensions(
29366
29538
  imageResource.width,
29367
29539
  imageResource.height,
29368
29540
  baseMetersPerPixel,
29369
29541
  imageScale,
29370
- zoomScaleFactor,
29371
- {
29372
- effectivePixelsPerMeter,
29373
- spriteMinPixel,
29374
- spriteMaxPixel
29375
- }
29542
+ distanceScaleFactor
29376
29543
  );
29377
29544
  if (worldDims.width <= 0 || worldDims.height <= 0) {
29378
29545
  return null;
29379
29546
  }
29380
- const anchor = (_b = image.anchor) != null ? _b : DEFAULT_ANCHOR;
29547
+ const anchor = (_c = image.anchor) != null ? _c : DEFAULT_ANCHOR;
29381
29548
  const offsetDef = resolveImageOffset(image);
29382
29549
  const offsetMetersVec = calculateSurfaceOffsetMeters(
29383
29550
  offsetDef,
29384
29551
  imageScale,
29385
- zoomScaleFactor,
29552
+ distanceScaleFactor,
29386
29553
  worldDims.scaleAdjustment
29387
29554
  );
29388
- const totalRotateDeg = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : normalizeAngleDeg(
29389
- ((_c = image.resolvedBaseRotateDeg) != null ? _c : 0) + image.rotationCommandDeg
29555
+ const autoRotationDeg = resolveImageAutoRotationDeg$1(sprite, image);
29556
+ const totalRotateDeg = normalizeAngleDeg(
29557
+ Number.isFinite(image.finalRotateDeg.current) ? image.finalRotateDeg.current : autoRotationDeg + image.rotateDeg
29390
29558
  );
29391
29559
  const cornerDisplacements = calculateSurfaceCornerDisplacements({
29392
29560
  worldWidthMeters: worldDims.width,
@@ -29409,7 +29577,6 @@ const createHitTestController = ({
29409
29577
  const scaling = getResolvedScaling();
29410
29578
  const baseLocation = sprite.location.current;
29411
29579
  const zoom = projectionHost.getZoom();
29412
- const zoomScaleFactor = calculateZoomScaleFactor(zoom, scaling);
29413
29580
  const metersPerPixelAtLat = calculateMetersPerPixelAtLatitude(
29414
29581
  zoom,
29415
29582
  baseLocation.lat
@@ -29429,22 +29596,29 @@ const createHitTestController = ({
29429
29596
  if (!Number.isFinite(effectivePixelsPerMeter) || effectivePixelsPerMeter <= 0) {
29430
29597
  return null;
29431
29598
  }
29599
+ const cameraLocation = projectionHost.getCameraLocation();
29600
+ const cameraDistanceMeters = cameraLocation !== void 0 ? calculateCartesianDistanceMeters(cameraLocation, {
29601
+ lng: baseLocation.lng,
29602
+ lat: baseLocation.lat,
29603
+ z: (_a = baseLocation.z) != null ? _a : 0
29604
+ }) : Number.POSITIVE_INFINITY;
29605
+ const distanceScaleFactor = calculateDistanceScaleFactor(
29606
+ cameraDistanceMeters,
29607
+ scaling
29608
+ );
29432
29609
  const baseMetersPerPixel = scaling.metersPerPixel;
29433
- const spriteMinPixel = scaling.spriteMinPixel;
29434
- const spriteMaxPixel = scaling.spriteMaxPixel;
29435
- const imageScale = (_a = image.scale) != null ? _a : 1;
29436
- const totalRotateDeg = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : normalizeAngleDeg(
29437
- ((_b = image.resolvedBaseRotateDeg) != null ? _b : 0) + image.rotationCommandDeg
29610
+ const imageScale = (_b = image.scale) != null ? _b : 1;
29611
+ const autoRotationDeg = resolveImageAutoRotationDeg$1(sprite, image);
29612
+ const totalRotateDeg = normalizeAngleDeg(
29613
+ Number.isFinite(image.finalRotateDeg.current) ? image.finalRotateDeg.current : autoRotationDeg + image.rotateDeg
29438
29614
  );
29439
29615
  const pixelDims = calculateBillboardPixelDimensions(
29440
29616
  imageResource.width,
29441
29617
  imageResource.height,
29442
29618
  baseMetersPerPixel,
29443
29619
  imageScale,
29444
- zoomScaleFactor,
29445
- effectivePixelsPerMeter,
29446
- spriteMinPixel,
29447
- spriteMaxPixel
29620
+ distanceScaleFactor,
29621
+ effectivePixelsPerMeter
29448
29622
  );
29449
29623
  const halfWidthMeters = pixelDims.width / 2 / effectivePixelsPerMeter;
29450
29624
  const halfHeightMeters = pixelDims.height / 2 / effectivePixelsPerMeter;
@@ -29457,7 +29631,7 @@ const createHitTestController = ({
29457
29631
  const offsetShift = calculateBillboardOffsetPixels(
29458
29632
  resolveImageOffset(image),
29459
29633
  imageScale,
29460
- zoomScaleFactor,
29634
+ distanceScaleFactor,
29461
29635
  effectivePixelsPerMeter
29462
29636
  );
29463
29637
  const anchorShiftMeters = Math.hypot(anchorShift.x, anchorShift.y) / effectivePixelsPerMeter;
@@ -29466,7 +29640,7 @@ const createHitTestController = ({
29466
29640
  return rectFromRadiusMeters(baseLocation, safetyRadius);
29467
29641
  };
29468
29642
  const estimateImageBounds = (projectionHost, sprite, image) => {
29469
- if (image.opacity.current <= 0 || !sprite.isEnabled) {
29643
+ if (image.finalOpacity.current <= 0 || !sprite.isEnabled) {
29470
29644
  return null;
29471
29645
  }
29472
29646
  if (image.mode === "surface") {
@@ -29746,7 +29920,7 @@ const createHitTestController = ({
29746
29920
  hitTestTree.clear();
29747
29921
  hitTestTreeItems = /* @__PURE__ */ new WeakMap();
29748
29922
  };
29749
- const setHitTestEnabled = (enabled) => {
29923
+ const setHitTestDetection = (enabled) => {
29750
29924
  if (isHitTestEnabled === enabled) {
29751
29925
  return false;
29752
29926
  }
@@ -29765,7 +29939,7 @@ const createHitTestController = ({
29765
29939
  refreshSpriteHitTestBounds,
29766
29940
  findTopmostHitEntry,
29767
29941
  resolveHitTestResult,
29768
- setHitTestEnabled,
29942
+ setHitTestDetection,
29769
29943
  isHitTestEnabled: isHitTestEnabledFn
29770
29944
  };
29771
29945
  };
@@ -30267,12 +30441,15 @@ const reapplySpriteOpacityMultiplier = (sprite) => {
30267
30441
  sprite.images.forEach((orderMap) => {
30268
30442
  orderMap.forEach((image) => {
30269
30443
  var _a2, _b;
30270
- const baseOpacity = (_a2 = image.opacity.interpolation.baseValue) != null ? _a2 : image.opacity.current;
30271
- const interpolationOption = (_b = image.opacity.interpolation.options) != null ? _b : null;
30444
+ const baseOpacity = (_a2 = image.finalOpacity.interpolation.baseValue) != null ? _a2 : image.finalOpacity.current;
30445
+ const interpolationOption = (_b = image.finalOpacity.interpolation.options) != null ? _b : null;
30272
30446
  applyOpacityUpdate(image, baseOpacity, interpolationOption, multiplier);
30273
30447
  });
30274
30448
  });
30275
30449
  };
30450
+ const resolveImageAutoRotationDeg = (sprite, image) => {
30451
+ return image.autoRotation ? sprite.currentAutoRotateDeg : 0;
30452
+ };
30276
30453
  const applyAutoRotation = (sprite, nextLocation, forceAutoRotation) => {
30277
30454
  let hasAutoRotation = false;
30278
30455
  let requiredDistance = 0;
@@ -30305,20 +30482,19 @@ const applyAutoRotation = (sprite, nextLocation, forceAutoRotation) => {
30305
30482
  if (distanceMeters < requiredDistance) {
30306
30483
  return false;
30307
30484
  }
30308
- const resolvedAngleRaw = isFiniteNumber(bearingDeg) ? bearingDeg : sprite.lastAutoRotationAngleDeg;
30485
+ const resolvedAngleRaw = isFiniteNumber(bearingDeg) ? bearingDeg : sprite.currentAutoRotateDeg;
30309
30486
  const resolvedAngle = normalizeAngleDeg(resolvedAngleRaw);
30487
+ sprite.currentAutoRotateDeg = resolvedAngle;
30310
30488
  sprite.images.forEach((orderMap) => {
30311
30489
  orderMap.forEach((image) => {
30312
30490
  if (!image.autoRotation) {
30313
30491
  return;
30314
30492
  }
30315
- image.resolvedBaseRotateDeg = resolvedAngle;
30316
- syncImageRotationChannel(image);
30493
+ syncImageRotationChannel(image, resolvedAngle);
30317
30494
  updateImageInterpolationDirtyState(sprite, image);
30318
30495
  });
30319
30496
  });
30320
30497
  sprite.lastAutoRotationLocation = cloneSpriteLocation(nextLocation);
30321
- sprite.lastAutoRotationAngleDeg = resolvedAngle;
30322
30498
  return true;
30323
30499
  };
30324
30500
  const cloneOriginLocation = (origin) => {
@@ -30340,17 +30516,15 @@ const cloneAnchor = (anchor) => {
30340
30516
  }
30341
30517
  return { x: anchor.x, y: anchor.y };
30342
30518
  };
30343
- const cloneOffset = (offset) => {
30344
- if (!offset) {
30345
- return { ...DEFAULT_IMAGE_OFFSET };
30346
- }
30519
+ const resolveOffsetInput = (offset) => {
30520
+ var _a, _b;
30347
30521
  return {
30348
- offsetMeters: offset.offsetMeters,
30349
- offsetDeg: offset.offsetDeg
30522
+ offsetMeters: (_a = offset == null ? void 0 : offset.offsetMeters) != null ? _a : DEFAULT_IMAGE_OFFSET.offsetMeters,
30523
+ offsetDeg: (_b = offset == null ? void 0 : offset.offsetDeg) != null ? _b : DEFAULT_IMAGE_OFFSET.offsetDeg
30350
30524
  };
30351
30525
  };
30352
30526
  const createInterpolatedOffsetState = (offset, invalidated) => {
30353
- const base = offset ? cloneOffset(offset) : { ...DEFAULT_IMAGE_OFFSET };
30527
+ const base = resolveOffsetInput(offset);
30354
30528
  return {
30355
30529
  offsetMeters: {
30356
30530
  current: base.offsetMeters,
@@ -30424,11 +30598,14 @@ const sanitizeOpacityMultiplier = (value) => {
30424
30598
  }
30425
30599
  return value;
30426
30600
  };
30427
- const createImageStateFromInit = (imageInit, subLayer, order, originReference, invalidated) => {
30428
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
30601
+ const createImageStateFromInit = (imageInit, subLayer, order, originReference, invalidated, spriteAutoRotationDeg = 0) => {
30602
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
30429
30603
  const mode = (_a = imageInit.mode) != null ? _a : "surface";
30430
30604
  const autoRotationDefault = mode === "surface";
30431
- const initialOffset = cloneOffset(imageInit.offset);
30605
+ const initialOffset = resolveOffsetInput({
30606
+ offsetMeters: imageInit.offsetMeters,
30607
+ offsetDeg: imageInit.offsetDeg
30608
+ });
30432
30609
  const initialOpacity = clampOpacity((_b = imageInit.opacity) != null ? _b : 1);
30433
30610
  const initialRotateDeg = normalizeAngleDeg((_c = imageInit.rotateDeg) != null ? _c : 0);
30434
30611
  const originLocation = cloneOriginLocation(imageInit.originLocation);
@@ -30439,7 +30616,9 @@ const createImageStateFromInit = (imageInit, subLayer, order, originReference, i
30439
30616
  imageId: imageInit.imageId,
30440
30617
  imageHandle: 0,
30441
30618
  mode,
30442
- opacity: {
30619
+ rotateDeg: initialRotateDeg,
30620
+ opacity: initialOpacity,
30621
+ finalOpacity: {
30443
30622
  current: initialOpacity,
30444
30623
  from: void 0,
30445
30624
  to: void 0,
@@ -30460,7 +30639,7 @@ const createImageStateFromInit = (imageInit, subLayer, order, originReference, i
30460
30639
  leaderLine: resolveSpriteImageLineAttribute(imageInit.leaderLine),
30461
30640
  leaderLinePixelWidth: 0,
30462
30641
  offset: createInterpolatedOffsetState(initialOffset, invalidated),
30463
- rotateDeg: {
30642
+ finalRotateDeg: {
30464
30643
  current: initialRotateDeg,
30465
30644
  from: void 0,
30466
30645
  to: void 0,
@@ -30473,25 +30652,28 @@ const createImageStateFromInit = (imageInit, subLayer, order, originReference, i
30473
30652
  targetValue: void 0
30474
30653
  }
30475
30654
  },
30476
- rotationCommandDeg: initialRotateDeg,
30477
- displayedRotateDeg: initialRotateDeg,
30478
30655
  autoRotation: (_e = imageInit.autoRotation) != null ? _e : autoRotationDefault,
30479
30656
  autoRotationMinDistanceMeters: (_f = imageInit.autoRotationMinDistanceMeters) != null ? _f : DEFAULT_AUTO_ROTATION_MIN_DISTANCE_METERS,
30480
- resolvedBaseRotateDeg: 0,
30481
30657
  originLocation,
30482
30658
  originReferenceKey,
30483
30659
  originRenderTargetIndex: SPRITE_ORIGIN_REFERENCE_INDEX_NONE,
30484
- interpolationDirty: false
30660
+ interpolationDirty: false,
30661
+ surfaceShaderInputs: void 0,
30662
+ hitTestCorners: void 0
30485
30663
  };
30486
- const rotateInitOption = (_h = (_g = imageInit.interpolation) == null ? void 0 : _g.rotateDeg) != null ? _h : null;
30664
+ const rotateInitOption = (_h = (_g = imageInit.interpolation) == null ? void 0 : _g.finalRotateDeg) != null ? _h : null;
30487
30665
  if (rotateInitOption) {
30488
- state.rotateDeg.interpolation.options = cloneInterpolationOptions(rotateInitOption);
30666
+ state.finalRotateDeg.interpolation.options = cloneInterpolationOptions(rotateInitOption);
30489
30667
  }
30490
- const opacityInitOption = (_j = (_i = imageInit.interpolation) == null ? void 0 : _i.opacity) != null ? _j : null;
30668
+ const opacityInitOption = (_j = (_i = imageInit.interpolation) == null ? void 0 : _i.finalOpacity) != null ? _j : null;
30491
30669
  if (opacityInitOption) {
30492
- state.opacity.interpolation.options = cloneInterpolationOptions(opacityInitOption);
30670
+ state.finalOpacity.interpolation.options = cloneInterpolationOptions(opacityInitOption);
30493
30671
  }
30494
- syncImageRotationChannel(state);
30672
+ syncImageRotationChannel(
30673
+ state,
30674
+ spriteAutoRotationDeg,
30675
+ (_k = state.finalRotateDeg.interpolation.options) != null ? _k : void 0
30676
+ );
30495
30677
  return state;
30496
30678
  };
30497
30679
  const createSpriteLayer = (options) => {
@@ -30734,6 +30916,7 @@ const createSpriteLayer = (options) => {
30734
30916
  images,
30735
30917
  getResolvedScaling: () => resolvedScaling
30736
30918
  });
30919
+ let trackingController;
30737
30920
  const syncAtlasPlacementsFromManager = () => {
30738
30921
  let placementsChanged = false;
30739
30922
  images.forEach((image, imageId) => {
@@ -30768,14 +30951,14 @@ const createSpriteLayer = (options) => {
30768
30951
  const sprites = /* @__PURE__ */ new Map();
30769
30952
  const invalidateImageInterpolationState = (sprite, image) => {
30770
30953
  var _a2;
30771
- image.rotateDeg.interpolation.state = null;
30954
+ image.finalRotateDeg.interpolation.state = null;
30772
30955
  image.offset.offsetDeg.interpolation.state = null;
30773
30956
  image.offset.offsetMeters.interpolation.state = null;
30774
- image.opacity.interpolation.state = null;
30775
- image.rotateDeg.from = void 0;
30776
- image.rotateDeg.to = void 0;
30777
- image.rotateDeg.invalidated = true;
30778
- image.rotateDeg.interpolation.lastCommandValue = image.rotateDeg.current;
30957
+ image.finalOpacity.interpolation.state = null;
30958
+ image.finalRotateDeg.from = void 0;
30959
+ image.finalRotateDeg.to = void 0;
30960
+ image.finalRotateDeg.invalidated = true;
30961
+ image.finalRotateDeg.interpolation.lastCommandValue = image.finalRotateDeg.current;
30779
30962
  image.offset.offsetDeg.from = void 0;
30780
30963
  image.offset.offsetDeg.to = void 0;
30781
30964
  image.offset.offsetDeg.invalidated = true;
@@ -30784,16 +30967,16 @@ const createSpriteLayer = (options) => {
30784
30967
  image.offset.offsetMeters.to = void 0;
30785
30968
  image.offset.offsetMeters.invalidated = true;
30786
30969
  image.offset.offsetMeters.interpolation.lastCommandValue = image.offset.offsetMeters.current;
30787
- image.opacity.from = void 0;
30788
- image.opacity.to = void 0;
30789
- image.opacity.invalidated = true;
30790
- image.opacity.interpolation.targetValue = image.opacity.current;
30791
- image.opacity.interpolation.lastCommandValue = image.opacity.current;
30970
+ image.finalOpacity.from = void 0;
30971
+ image.finalOpacity.to = void 0;
30972
+ image.finalOpacity.invalidated = true;
30973
+ image.finalOpacity.interpolation.targetValue = image.finalOpacity.current;
30974
+ image.finalOpacity.interpolation.lastCommandValue = image.finalOpacity.current;
30792
30975
  const spriteOpacityMultiplier = (_a2 = sprite.opacityMultiplier) != null ? _a2 : 1;
30793
30976
  const lodMultiplier = image.lodOpacity || 1;
30794
30977
  if (spriteOpacityMultiplier > 0 && lodMultiplier > 0) {
30795
- image.opacity.interpolation.baseValue = clampOpacity(
30796
- image.opacity.current / (spriteOpacityMultiplier * lodMultiplier)
30978
+ image.finalOpacity.interpolation.baseValue = clampOpacity(
30979
+ image.finalOpacity.current / (spriteOpacityMultiplier * lodMultiplier)
30797
30980
  );
30798
30981
  }
30799
30982
  updateImageInterpolationDirtyState(sprite, image);
@@ -30812,7 +30995,8 @@ const createSpriteLayer = (options) => {
30812
30995
  sprite.images.forEach((orderMap) => {
30813
30996
  orderMap.forEach((image) => {
30814
30997
  invalidateImageInterpolationState(sprite, image);
30815
- image.displayedRotateDeg = image.resolvedBaseRotateDeg + image.rotationCommandDeg;
30998
+ const autoRotationDeg = resolveImageAutoRotationDeg(sprite, image);
30999
+ image.finalRotateDeg.current = autoRotationDeg + image.rotateDeg;
30816
31000
  });
30817
31001
  });
30818
31002
  };
@@ -30885,30 +31069,7 @@ const createSpriteLayer = (options) => {
30885
31069
  return Array.from(buckets.keys()).sort((a, b) => a - b).map((subLayer) => [subLayer, buckets.get(subLayer)]);
30886
31070
  };
30887
31071
  const renderTargetEntries = [];
30888
- const eventListeners = /* @__PURE__ */ new Map();
30889
- const getListenerSet = (type) => {
30890
- let set = eventListeners.get(type);
30891
- if (!set) {
30892
- set = /* @__PURE__ */ new Set();
30893
- eventListeners.set(type, set);
30894
- }
30895
- return set;
30896
- };
30897
- const addEventListener2 = (type, listener) => {
30898
- getListenerSet(type).add(listener);
30899
- };
30900
- const removeEventListener2 = (type, listener) => {
30901
- const listeners = eventListeners.get(type);
30902
- if (!listeners) {
30903
- return;
30904
- }
30905
- listeners.delete(listener);
30906
- if (listeners.size === 0) {
30907
- eventListeners.delete(type);
30908
- }
30909
- };
30910
31072
  let canvasElement;
30911
- const inputListenerDisposers = [];
30912
31073
  let mapVisible = typeof document !== "undefined" ? document.visibilityState !== "hidden" : true;
30913
31074
  const resolveDocumentVisibility = () => {
30914
31075
  var _a2;
@@ -30916,15 +31077,6 @@ const createSpriteLayer = (options) => {
30916
31077
  return doc ? doc.visibilityState !== "hidden" : true;
30917
31078
  };
30918
31079
  const isLayerVisible = () => mapVisible;
30919
- const hasSpriteListeners = (type) => {
30920
- var _a2, _b;
30921
- return (
30922
- // Treat missing listener sets as zero, otherwise check the registered count.
30923
- ((_b = (_a2 = eventListeners.get(type)) == null ? void 0 : _a2.size) != null ? _b : 0) > 0
30924
- );
30925
- };
30926
- const hasSpriteClickListeners = () => hasSpriteListeners("spriteclick");
30927
- const hasSpriteHoverListeners = () => hasSpriteListeners("spritehover");
30928
31080
  const resolveSpriteEventPayload = (hitEntry) => {
30929
31081
  var _a2, _b;
30930
31082
  if (!hitEntry) {
@@ -30940,40 +31092,6 @@ const createSpriteLayer = (options) => {
30940
31092
  image: imageState
30941
31093
  };
30942
31094
  };
30943
- const dispatchSpriteClick = (hitEntry, screenPoint, originalEvent) => {
30944
- const listeners = eventListeners.get("spriteclick");
30945
- if (!listeners || listeners.size === 0) {
30946
- return;
30947
- }
30948
- const payload = resolveSpriteEventPayload(hitEntry);
30949
- const clickEvent = {
30950
- type: "spriteclick",
30951
- sprite: payload.sprite,
30952
- image: payload.image,
30953
- screenPoint,
30954
- originalEvent
30955
- };
30956
- listeners.forEach((listener) => {
30957
- listener(clickEvent);
30958
- });
30959
- };
30960
- const dispatchSpriteHover = (hitEntry, screenPoint, originalEvent) => {
30961
- const listeners = eventListeners.get("spritehover");
30962
- if (!listeners || listeners.size === 0) {
30963
- return;
30964
- }
30965
- const payload = resolveSpriteEventPayload(hitEntry);
30966
- const hoverEvent = {
30967
- type: "spritehover",
30968
- sprite: payload.sprite,
30969
- image: payload.image,
30970
- screenPoint,
30971
- originalEvent
30972
- };
30973
- listeners.forEach((listener) => {
30974
- listener(hoverEvent);
30975
- });
30976
- };
30977
31095
  const resolveHitTestResult = (nativeEvent) => {
30978
31096
  return hitTestController.resolveHitTestResult(
30979
31097
  nativeEvent,
@@ -30981,26 +31099,11 @@ const createSpriteLayer = (options) => {
30981
31099
  map
30982
31100
  );
30983
31101
  };
30984
- const processClickEvent = (nativeEvent) => {
30985
- if (!hasSpriteClickListeners()) {
30986
- return;
30987
- }
30988
- const hitResult = resolveHitTestResult(nativeEvent);
30989
- if (!hitResult || !hitResult.hitEntry) {
30990
- return;
30991
- }
30992
- dispatchSpriteClick(hitResult.hitEntry, hitResult.screenPoint, nativeEvent);
30993
- };
30994
- const processHoverEvent = (nativeEvent) => {
30995
- if (!hasSpriteHoverListeners()) {
30996
- return;
30997
- }
30998
- const hitResult = resolveHitTestResult(nativeEvent);
30999
- if (!hitResult) {
31000
- return;
31001
- }
31002
- dispatchSpriteHover(hitResult.hitEntry, hitResult.screenPoint, nativeEvent);
31003
- };
31102
+ const mouseEventsController = createSpriteMouseEventsController({
31103
+ resolveHitTestResult,
31104
+ resolveSpriteEventPayload,
31105
+ updateVisibilityState
31106
+ });
31004
31107
  let isRenderScheduled = false;
31005
31108
  const scheduleRender = () => {
31006
31109
  if (!map || isRenderScheduled) {
@@ -31026,9 +31129,10 @@ const createSpriteLayer = (options) => {
31026
31129
  sprite.images.forEach((orderMap) => {
31027
31130
  orderMap.forEach((image) => {
31028
31131
  var _a3;
31029
- const baseOpacity = (_a3 = image.opacity.interpolation.baseValue) != null ? _a3 : image.opacity.interpolation.lastCommandValue;
31132
+ const isOpacityInterpolating = image.finalOpacity.interpolation.state !== null;
31133
+ const baseOpacity = (_a3 = image.finalOpacity.interpolation.baseValue) != null ? _a3 : image.finalOpacity.interpolation.lastCommandValue;
31030
31134
  const shouldForceVisibilityCheck = sprite.visibilityDistanceMeters !== void 0 && (baseOpacity != null ? baseOpacity : 0) > OPACITY_VISIBILITY_EPSILON;
31031
- if (image.opacity.current <= 0 && !shouldForceVisibilityCheck) {
31135
+ if (image.finalOpacity.current <= 0 && !isOpacityInterpolating && !shouldForceVisibilityCheck) {
31032
31136
  image.originRenderTargetIndex = SPRITE_ORIGIN_REFERENCE_INDEX_NONE;
31033
31137
  image.originReferenceKey = SPRITE_ORIGIN_REFERENCE_KEY_NONE;
31034
31138
  return;
@@ -31086,9 +31190,20 @@ const createSpriteLayer = (options) => {
31086
31190
  image.originRenderTargetIndex = targetIndex;
31087
31191
  }
31088
31192
  };
31193
+ const trackSprite = (spriteId, trackRotation) => {
31194
+ const sprite = sprites.get(spriteId);
31195
+ if (!sprite) {
31196
+ trackingController == null ? void 0 : trackingController.untrackSprite();
31197
+ return;
31198
+ }
31199
+ trackingController == null ? void 0 : trackingController.trackSprite(sprite, trackRotation != null ? trackRotation : true);
31200
+ };
31201
+ const untrackSprite = () => {
31202
+ trackingController == null ? void 0 : trackingController.untrackSprite();
31203
+ };
31089
31204
  const onAdd = (mapInstance, glContext) => {
31090
- var _a2;
31091
31205
  map = mapInstance;
31206
+ trackingController = createSpriteTrackingController(mapInstance);
31092
31207
  gl = glContext;
31093
31208
  anisotropyExtension = resolveAnisotropyExtension(glContext);
31094
31209
  if (anisotropyExtension) {
@@ -31105,96 +31220,15 @@ const createSpriteLayer = (options) => {
31105
31220
  maxSupportedAnisotropy = 1;
31106
31221
  }
31107
31222
  canvasElement = mapInstance.getCanvas();
31108
- const registerDisposer = (disposer) => {
31109
- inputListenerDisposers.push(disposer);
31110
- };
31111
- const supportsPointerEvents = typeof window !== "undefined" && "PointerEvent" in window;
31112
- if (canvasElement) {
31113
- if (supportsPointerEvents) {
31114
- const pointerUpListener = (event) => {
31115
- if (event.pointerType === "mouse" && event.button !== 0) {
31116
- return;
31117
- }
31118
- processClickEvent(event);
31119
- };
31120
- canvasElement.addEventListener("pointerup", pointerUpListener, {
31121
- passive: true
31122
- });
31123
- registerDisposer(() => {
31124
- canvasElement == null ? void 0 : canvasElement.removeEventListener("pointerup", pointerUpListener);
31125
- });
31126
- const pointerMoveListener = (event) => {
31127
- if (!event.isPrimary) {
31128
- return;
31129
- }
31130
- if (event.pointerType === "touch") {
31131
- return;
31132
- }
31133
- processHoverEvent(event);
31134
- };
31135
- canvasElement.addEventListener("pointermove", pointerMoveListener, {
31136
- passive: true
31137
- });
31138
- registerDisposer(() => {
31139
- canvasElement == null ? void 0 : canvasElement.removeEventListener(
31140
- "pointermove",
31141
- pointerMoveListener
31142
- );
31143
- });
31144
- } else {
31145
- const clickListener = (event) => {
31146
- if (event.button !== 0) {
31147
- return;
31148
- }
31149
- processClickEvent(event);
31150
- };
31151
- canvasElement.addEventListener("click", clickListener, {
31152
- passive: true
31153
- });
31154
- registerDisposer(() => {
31155
- canvasElement == null ? void 0 : canvasElement.removeEventListener("click", clickListener);
31156
- });
31157
- const touchListener = (event) => {
31158
- processClickEvent(event);
31159
- };
31160
- canvasElement.addEventListener("touchend", touchListener, {
31161
- passive: true
31162
- });
31163
- registerDisposer(() => {
31164
- canvasElement == null ? void 0 : canvasElement.removeEventListener("touchend", touchListener);
31165
- });
31166
- const mouseMoveListener = (event) => {
31167
- processHoverEvent(event);
31168
- };
31169
- canvasElement.addEventListener("mousemove", mouseMoveListener, {
31170
- passive: true
31171
- });
31172
- registerDisposer(() => {
31173
- canvasElement == null ? void 0 : canvasElement.removeEventListener("mousemove", mouseMoveListener);
31174
- });
31175
- }
31176
- const visibilityTarget = (_a2 = canvasElement.ownerDocument) != null ? _a2 : typeof document !== "undefined" ? document : void 0;
31177
- if (visibilityTarget) {
31178
- const visibilityListener = () => updateVisibilityState();
31179
- visibilityTarget.addEventListener(
31180
- "visibilitychange",
31181
- visibilityListener
31182
- );
31183
- registerDisposer(() => {
31184
- visibilityTarget.removeEventListener(
31185
- "visibilitychange",
31186
- visibilityListener
31187
- );
31188
- });
31189
- updateVisibilityState();
31190
- }
31191
- }
31223
+ mouseEventsController.bindCanvas(canvasElement);
31224
+ canvasElement = mouseEventsController.canvasElement;
31192
31225
  spriteDrawProgram = createSpriteDrawProgram(glContext);
31193
31226
  scheduleRender();
31194
31227
  };
31195
31228
  const onRemove = () => {
31196
- inputListenerDisposers.forEach((dispose) => dispose());
31197
- inputListenerDisposers.length = 0;
31229
+ trackingController == null ? void 0 : trackingController.release();
31230
+ trackingController = void 0;
31231
+ mouseEventsController.release();
31198
31232
  canvasElement = void 0;
31199
31233
  hitTestController.clearAll();
31200
31234
  const glContext = gl;
@@ -31220,8 +31254,6 @@ const createSpriteLayer = (options) => {
31220
31254
  leaderLineRenderer = void 0;
31221
31255
  }
31222
31256
  }
31223
- eventListeners.forEach((set) => set.clear());
31224
- eventListeners.clear();
31225
31257
  gl = void 0;
31226
31258
  map = void 0;
31227
31259
  borderOutlineRenderer = void 0;
@@ -31258,9 +31290,7 @@ const createSpriteLayer = (options) => {
31258
31290
  sprites: spriteStateArray,
31259
31291
  timestamp: interpolationTimestamp2,
31260
31292
  frameContext: {
31261
- baseMetersPerPixel: resolvedScaling.metersPerPixel,
31262
- spriteMinPixel: resolvedScaling.spriteMinPixel,
31263
- spriteMaxPixel: resolvedScaling.spriteMaxPixel
31293
+ baseMetersPerPixel: resolvedScaling.metersPerPixel
31264
31294
  }
31265
31295
  } : null;
31266
31296
  let hasActiveInterpolation = false;
@@ -31299,16 +31329,12 @@ const createSpriteLayer = (options) => {
31299
31329
  const identityOffsetX = 0;
31300
31330
  const identityOffsetY = 0;
31301
31331
  const baseMetersPerPixel = resolvedScaling.metersPerPixel;
31302
- const spriteMinPixel = resolvedScaling.spriteMinPixel;
31303
- const spriteMaxPixel = resolvedScaling.spriteMaxPixel;
31304
31332
  const projectionHost = createProjectionHostForMap(mapInstance);
31305
31333
  try {
31306
31334
  const clipContext = projectionHost.getClipContext();
31307
31335
  if (!clipContext) {
31308
31336
  return;
31309
31337
  }
31310
- const zoom = projectionHost.getZoom();
31311
- const zoomScaleFactor = calculateZoomScaleFactor(zoom, resolvedScaling);
31312
31338
  glContext.enable(glContext.BLEND);
31313
31339
  glContext.blendFunc(glContext.SRC_ALPHA, glContext.ONE_MINUS_SRC_ALPHA);
31314
31340
  glContext.disable(glContext.DEPTH_TEST);
@@ -31353,12 +31379,9 @@ const createSpriteLayer = (options) => {
31353
31379
  resolvedScaling,
31354
31380
  clipContext,
31355
31381
  baseMetersPerPixel,
31356
- spriteMinPixel,
31357
- spriteMaxPixel,
31358
31382
  drawingBufferWidth,
31359
31383
  drawingBufferHeight,
31360
31384
  pixelRatio,
31361
- zoomScaleFactor,
31362
31385
  identityScaleX,
31363
31386
  identityScaleY,
31364
31387
  identityOffsetX,
@@ -31511,7 +31534,7 @@ const createSpriteLayer = (options) => {
31511
31534
  continue;
31512
31535
  }
31513
31536
  const effectiveAlpha = clampOpacity(
31514
- border.rgba[3] * entry.image.opacity.current
31537
+ border.rgba[3] * entry.image.finalOpacity.current
31515
31538
  );
31516
31539
  if (effectiveAlpha <= 0) {
31517
31540
  continue;
@@ -31708,6 +31731,7 @@ const createSpriteLayer = (options) => {
31708
31731
  scheduleRender();
31709
31732
  };
31710
31733
  const getAllImageIds = () => Array.from(images.keys());
31734
+ const getAllSpriteIds = () => Array.from(sprites.keys());
31711
31735
  const addSpriteInternal = (projectionHost, spriteId, init) => {
31712
31736
  var _a2, _b, _c, _d, _e, _f;
31713
31737
  if (sprites.get(spriteId)) {
@@ -31805,7 +31829,7 @@ const createSpriteLayer = (options) => {
31805
31829
  // Tags default to null to simplify downstream comparisons.
31806
31830
  tag: (_f = init.tag) != null ? _f : null,
31807
31831
  lastAutoRotationLocation: cloneSpriteLocation(currentLocation),
31808
- lastAutoRotationAngleDeg: 0,
31832
+ currentAutoRotateDeg: 0,
31809
31833
  autoRotationInvalidated: false,
31810
31834
  interpolationDirty: false,
31811
31835
  cachedMercator: initialMercator,
@@ -31946,7 +31970,8 @@ const createSpriteLayer = (options) => {
31946
31970
  subLayer,
31947
31971
  order,
31948
31972
  originReference,
31949
- !isLayerVisible() || sprite.location.invalidated === true
31973
+ !isLayerVisible() || sprite.location.invalidated === true,
31974
+ sprite.currentAutoRotateDeg
31950
31975
  );
31951
31976
  state.imageHandle = resolveImageHandle(state.imageId);
31952
31977
  if (state.originLocation !== void 0) {
@@ -31980,10 +32005,8 @@ const createSpriteLayer = (options) => {
31980
32005
  curMaybe = getRef(cur);
31981
32006
  }
31982
32007
  }
31983
- if (state.autoRotation) {
31984
- state.resolvedBaseRotateDeg = sprite.lastAutoRotationAngleDeg;
31985
- }
31986
- syncImageRotationChannel(state);
32008
+ const autoRotationDeg = resolveImageAutoRotationDeg(sprite, state);
32009
+ syncImageRotationChannel(state, autoRotationDeg);
31987
32010
  updateImageInterpolationDirtyState(sprite, state);
31988
32011
  setImageState(sprite, state);
31989
32012
  hitTestController.refreshSpriteHitTestBounds(projectionHost, sprite);
@@ -32020,11 +32043,12 @@ const createSpriteLayer = (options) => {
32020
32043
  }
32021
32044
  };
32022
32045
  const updateSpriteImageInternal = (projectionHost, sprite, subLayer, order, imageUpdate, resultOut) => {
32023
- var _a2;
32046
+ var _a2, _b, _c;
32024
32047
  const state = getImageState(sprite, subLayer, order);
32025
32048
  if (!state) return false;
32026
32049
  const mapCurrentlyVisible = isLayerVisible();
32027
32050
  const interpolationAllowed = interpolationCalculationEnabled && mapCurrentlyVisible;
32051
+ const resolveAutoRotationDeg2 = () => resolveImageAutoRotationDeg(sprite, state);
32028
32052
  if (imageUpdate.imageId !== void 0) {
32029
32053
  state.imageId = imageUpdate.imageId;
32030
32054
  state.imageHandle = resolveImageHandle(imageUpdate.imageId);
@@ -32033,12 +32057,12 @@ const createSpriteLayer = (options) => {
32033
32057
  state.mode = imageUpdate.mode;
32034
32058
  }
32035
32059
  const interpolationOptions = imageUpdate.interpolation;
32036
- const opacityInterpolationOption = interpolationOptions == null ? void 0 : interpolationOptions.opacity;
32060
+ const opacityInterpolationOption = interpolationOptions == null ? void 0 : interpolationOptions.finalOpacity;
32037
32061
  if (opacityInterpolationOption !== void 0) {
32038
- state.opacity.interpolation.options = opacityInterpolationOption === null ? null : cloneInterpolationOptions(opacityInterpolationOption);
32062
+ state.finalOpacity.interpolation.options = opacityInterpolationOption === null ? null : cloneInterpolationOptions(opacityInterpolationOption);
32039
32063
  }
32040
- const allowOpacityInterpolation = interpolationAllowed && !state.opacity.invalidated;
32041
- const resolvedOpacityInterpolationOption = allowOpacityInterpolation ? opacityInterpolationOption === void 0 ? (_a2 = state.opacity.interpolation.options) != null ? _a2 : null : opacityInterpolationOption : null;
32064
+ const allowOpacityInterpolation = interpolationAllowed && !state.finalOpacity.invalidated;
32065
+ const resolvedOpacityInterpolationOption = allowOpacityInterpolation ? opacityInterpolationOption === void 0 ? (_a2 = state.finalOpacity.interpolation.options) != null ? _a2 : null : opacityInterpolationOption : null;
32042
32066
  if (imageUpdate.opacity !== void 0) {
32043
32067
  applyOpacityUpdate(
32044
32068
  state,
@@ -32046,8 +32070,8 @@ const createSpriteLayer = (options) => {
32046
32070
  resolvedOpacityInterpolationOption,
32047
32071
  sprite.opacityMultiplier
32048
32072
  );
32049
- if (mapCurrentlyVisible && state.opacity.invalidated) {
32050
- state.opacity.invalidated = false;
32073
+ if (mapCurrentlyVisible && state.finalOpacity.invalidated) {
32074
+ state.finalOpacity.invalidated = false;
32051
32075
  }
32052
32076
  } else if (opacityInterpolationOption === null) {
32053
32077
  clearOpacityInterpolation(state);
@@ -32076,13 +32100,18 @@ const createSpriteLayer = (options) => {
32076
32100
  const allowOffsetMetersInterpolation = interpolationAllowed && !state.offset.offsetMeters.invalidated;
32077
32101
  const offsetDegInterpolationOption = allowOffsetDegInterpolation ? interpolationOptions == null ? void 0 : interpolationOptions.offsetDeg : null;
32078
32102
  const offsetMetersInterpolationOption = allowOffsetMetersInterpolation ? interpolationOptions == null ? void 0 : interpolationOptions.offsetMeters : null;
32079
- const allowRotateInterpolation = interpolationAllowed && !state.rotateDeg.invalidated;
32080
- const rotateInterpolationOption = allowRotateInterpolation ? interpolationOptions == null ? void 0 : interpolationOptions.rotateDeg : null;
32103
+ const allowRotateInterpolation = interpolationAllowed && !state.finalRotateDeg.invalidated;
32104
+ const rotateInterpolationOption = allowRotateInterpolation ? interpolationOptions == null ? void 0 : interpolationOptions.finalRotateDeg : null;
32081
32105
  let rotationOverride;
32082
32106
  let hasRotationOverride = false;
32083
- if (imageUpdate.offset !== void 0) {
32084
- const clonedOffset = cloneOffset(imageUpdate.offset);
32085
- applyOffsetUpdate(state, clonedOffset, {
32107
+ const hasOffsetMetersUpdate = imageUpdate.offsetMeters !== void 0;
32108
+ const hasOffsetDegUpdate = imageUpdate.offsetDeg !== void 0;
32109
+ if (hasOffsetMetersUpdate || hasOffsetDegUpdate) {
32110
+ const nextOffset = {
32111
+ offsetMeters: (_b = imageUpdate.offsetMeters) != null ? _b : state.offset.offsetMeters.current,
32112
+ offsetDeg: (_c = imageUpdate.offsetDeg) != null ? _c : state.offset.offsetDeg.current
32113
+ };
32114
+ applyOffsetUpdate(state, nextOffset, {
32086
32115
  deg: allowOffsetDegInterpolation ? offsetDegInterpolationOption : null,
32087
32116
  meters: allowOffsetMetersInterpolation ? offsetMetersInterpolationOption : null
32088
32117
  });
@@ -32104,11 +32133,11 @@ const createSpriteLayer = (options) => {
32104
32133
  }
32105
32134
  if (rotateInterpolationOption !== void 0) {
32106
32135
  if (rotateInterpolationOption === null) {
32107
- state.rotateDeg.interpolation.options = null;
32136
+ state.finalRotateDeg.interpolation.options = null;
32108
32137
  rotationOverride = null;
32109
32138
  } else {
32110
32139
  const cloned = cloneInterpolationOptions(rotateInterpolationOption);
32111
- state.rotateDeg.interpolation.options = cloned;
32140
+ state.finalRotateDeg.interpolation.options = cloned;
32112
32141
  rotationOverride = cloned;
32113
32142
  }
32114
32143
  hasRotationOverride = true;
@@ -32116,9 +32145,12 @@ const createSpriteLayer = (options) => {
32116
32145
  let requireRotationSync = false;
32117
32146
  if (imageUpdate.rotateDeg !== void 0) {
32118
32147
  const nextRotation = normalizeAngleDeg(imageUpdate.rotateDeg);
32119
- state.rotateDeg.from = state.rotateDeg.current;
32120
- state.rotateDeg.to = nextRotation;
32121
- state.rotationCommandDeg = nextRotation;
32148
+ const targetDisplayed = normalizeAngleDeg(
32149
+ resolveAutoRotationDeg2() + nextRotation
32150
+ );
32151
+ state.finalRotateDeg.from = state.finalRotateDeg.current;
32152
+ state.finalRotateDeg.to = targetDisplayed;
32153
+ state.rotateDeg = nextRotation;
32122
32154
  requireRotationSync = true;
32123
32155
  } else if (hasRotationOverride) {
32124
32156
  requireRotationSync = true;
@@ -32127,7 +32159,6 @@ const createSpriteLayer = (options) => {
32127
32159
  state.autoRotation = imageUpdate.autoRotation;
32128
32160
  if (imageUpdate.autoRotation) {
32129
32161
  if (!prevAutoRotation) {
32130
- state.resolvedBaseRotateDeg = sprite.lastAutoRotationAngleDeg;
32131
32162
  shouldReapplyAutoRotation = true;
32132
32163
  }
32133
32164
  } else if (prevAutoRotation) {
@@ -32141,24 +32172,24 @@ const createSpriteLayer = (options) => {
32141
32172
  }
32142
32173
  }
32143
32174
  if (shouldResetResolvedAngle) {
32144
- state.resolvedBaseRotateDeg = 0;
32145
32175
  requireRotationSync = true;
32146
32176
  }
32147
32177
  if (shouldReapplyAutoRotation) {
32148
32178
  const applied = applyAutoRotation(sprite, sprite.location.current, true);
32149
32179
  if (!applied && state.autoRotation) {
32150
- state.resolvedBaseRotateDeg = sprite.lastAutoRotationAngleDeg;
32151
32180
  requireRotationSync = true;
32152
32181
  }
32153
32182
  }
32154
32183
  if (requireRotationSync) {
32184
+ const autoRotationDeg = resolveAutoRotationDeg2();
32155
32185
  syncImageRotationChannel(
32156
32186
  state,
32187
+ autoRotationDeg,
32157
32188
  // When a rotation override has been computed, pass it along (null clears interpolation); otherwise leave undefined.
32158
32189
  interpolationAllowed ? hasRotationOverride ? rotationOverride != null ? rotationOverride : null : void 0 : null
32159
32190
  );
32160
- if (mapCurrentlyVisible && state.rotateDeg.invalidated) {
32161
- state.rotateDeg.invalidated = false;
32191
+ if (mapCurrentlyVisible && state.finalRotateDeg.invalidated) {
32192
+ state.finalRotateDeg.invalidated = false;
32162
32193
  }
32163
32194
  }
32164
32195
  updateImageInterpolationDirtyState(sprite, state);
@@ -32251,18 +32282,18 @@ const createSpriteLayer = (options) => {
32251
32282
  sprite.images.forEach((orderMap) => {
32252
32283
  orderMap.forEach((image) => {
32253
32284
  var _a3;
32254
- const baseOpacity = (_a3 = image.opacity.interpolation.baseValue) != null ? _a3 : image.opacity.current;
32285
+ const baseOpacity = (_a3 = image.finalOpacity.interpolation.baseValue) != null ? _a3 : image.finalOpacity.current;
32255
32286
  if (!(Number.isFinite(baseOpacity) && baseOpacity > 0)) {
32256
32287
  return;
32257
32288
  }
32258
- if (image.opacity.current > 0) {
32289
+ if (image.finalOpacity.current > 0) {
32259
32290
  return;
32260
32291
  }
32261
32292
  image.lodOpacity = 1;
32262
32293
  applyOpacityUpdate(
32263
32294
  image,
32264
32295
  baseOpacity,
32265
- image.opacity.interpolation.options,
32296
+ image.finalOpacity.interpolation.options,
32266
32297
  sprite.opacityMultiplier
32267
32298
  );
32268
32299
  });
@@ -32326,7 +32357,7 @@ const createSpriteLayer = (options) => {
32326
32357
  );
32327
32358
  let handledByInterpolation = false;
32328
32359
  if (effectiveOptions && effectiveOptions.durationMs > 0) {
32329
- const { state, requiresInterpolation } = createInterpolationState({
32360
+ const { state, requiresInterpolation } = createLocationInterpolationState({
32330
32361
  currentLocation: locationState.current,
32331
32362
  lastCommandLocation: locationInterpolation.lastCommandValue,
32332
32363
  nextCommandLocation: newCommandLocation,
@@ -32638,9 +32669,9 @@ const createSpriteLayer = (options) => {
32638
32669
  scheduleRender();
32639
32670
  }
32640
32671
  };
32641
- const setHitTestEnabled = (enabled) => {
32642
- const changed = hitTestController.setHitTestEnabled(enabled);
32643
- if (!changed || !enabled || !map) {
32672
+ const setHitTestDetection = (detect) => {
32673
+ const changed = hitTestController.setHitTestDetection(detect);
32674
+ if (!changed || !detect || !map) {
32644
32675
  return;
32645
32676
  }
32646
32677
  const projectionHost = createProjectionHostForMap(map);
@@ -32664,6 +32695,7 @@ const createSpriteLayer = (options) => {
32664
32695
  unregisterImage,
32665
32696
  unregisterAllImages,
32666
32697
  getAllImageIds,
32698
+ getAllSpriteIds,
32667
32699
  addSprite,
32668
32700
  addSprites,
32669
32701
  removeSprite,
@@ -32678,9 +32710,11 @@ const createSpriteLayer = (options) => {
32678
32710
  mutateSprites,
32679
32711
  updateForEach,
32680
32712
  setInterpolationCalculation,
32681
- setHitTestEnabled,
32682
- on: addEventListener2,
32683
- off: removeEventListener2
32713
+ setHitTestDetection,
32714
+ trackSprite,
32715
+ untrackSprite,
32716
+ on: mouseEventsController.addEventListener,
32717
+ off: mouseEventsController.removeEventListener
32684
32718
  };
32685
32719
  return spriteLayout;
32686
32720
  };