maplibre-gl-layers 0.6.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/SpriteLayer.d.ts +8 -173
- package/dist/const.d.ts +29 -0
- package/dist/degreeInterpolation.d.ts +66 -0
- package/dist/distanceInterpolation.d.ts +33 -0
- package/dist/easing.d.ts +2 -2
- package/dist/index.cjs +2378 -404
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.mjs +2379 -405
- package/dist/index.mjs.map +1 -1
- package/dist/internalTypes.d.ts +265 -0
- package/dist/interpolation.d.ts +4 -22
- package/dist/interpolationChannels.d.ts +37 -0
- package/dist/location.d.ts +2 -2
- package/dist/looseQuadTree.d.ts +34 -0
- package/dist/math.d.ts +15 -2
- package/dist/rotationInterpolation.d.ts +11 -9
- package/dist/types.d.ts +100 -68
- package/dist/utils.d.ts +19 -3
- package/package.json +6 -6
- package/dist/numericInterpolation.d.ts +0 -80
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
2
5
|
/*!
|
|
3
6
|
* name: maplibre-gl-layers
|
|
4
|
-
* version: 0.
|
|
7
|
+
* version: 0.11.0
|
|
5
8
|
* description: MapLibre's layer extension library enabling the display, movement, and modification of large numbers of dynamic sprite images
|
|
6
9
|
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
7
10
|
* license: MIT
|
|
8
11
|
* repository.url: https://github.com/kekyo/maplibre-gl-layers.git
|
|
9
|
-
* git.commit.hash:
|
|
12
|
+
* git.commit.hash: 371efb126f281333d59ec75cfe788d45f3b1482e
|
|
10
13
|
*/
|
|
11
14
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
12
15
|
const UNLIMITED_SPRITE_SCALING_OPTIONS = {
|
|
@@ -39,6 +42,270 @@ const BETTER_TEXTURE_FILTERING_OPTIONS = {
|
|
|
39
42
|
generateMipmaps: true,
|
|
40
43
|
maxAnisotropy: 8
|
|
41
44
|
};
|
|
45
|
+
class SvgSizeResolutionError extends Error {
|
|
46
|
+
constructor(message, code) {
|
|
47
|
+
super(message);
|
|
48
|
+
__publicField(this, "code");
|
|
49
|
+
this.name = "SvgSizeResolutionError";
|
|
50
|
+
this.code = code;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const parseNumericLength = (value) => {
|
|
54
|
+
if (!value) {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
const trimmed = value.trim();
|
|
58
|
+
if (trimmed.length === 0) {
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
const parsed = Number.parseFloat(trimmed);
|
|
62
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
};
|
|
67
|
+
const extractStyleLength = (styleValue, property) => {
|
|
68
|
+
if (!styleValue) {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
const declarations = styleValue.split(";").map((decl) => decl.trim()).filter((decl) => decl.length > 0);
|
|
72
|
+
for (const declaration of declarations) {
|
|
73
|
+
const [prop, rawValue] = declaration.split(":");
|
|
74
|
+
if (!prop || !rawValue) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (prop.trim().toLowerCase() === property) {
|
|
78
|
+
return parseNumericLength(rawValue);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return void 0;
|
|
82
|
+
};
|
|
83
|
+
const parseSvgSize = (svgText) => {
|
|
84
|
+
try {
|
|
85
|
+
const doc = new DOMParser().parseFromString(svgText, "image/svg+xml");
|
|
86
|
+
const svg = doc.documentElement;
|
|
87
|
+
if (!svg || svg.tagName.toLowerCase() !== "svg") {
|
|
88
|
+
return { hasViewBox: false };
|
|
89
|
+
}
|
|
90
|
+
const attrWidth = parseNumericLength(svg.getAttribute("width"));
|
|
91
|
+
const attrHeight = parseNumericLength(svg.getAttribute("height"));
|
|
92
|
+
const styleWidth = extractStyleLength(svg.getAttribute("style"), "width");
|
|
93
|
+
const styleHeight = extractStyleLength(svg.getAttribute("style"), "height");
|
|
94
|
+
const width = attrWidth != null ? attrWidth : styleWidth;
|
|
95
|
+
const height = attrHeight != null ? attrHeight : styleHeight;
|
|
96
|
+
let viewBoxWidth;
|
|
97
|
+
let viewBoxHeight;
|
|
98
|
+
let hasViewBox = false;
|
|
99
|
+
const viewBox = svg.getAttribute("viewBox");
|
|
100
|
+
if (viewBox) {
|
|
101
|
+
const parts = viewBox.split(/[\s,]+/).map((part) => Number.parseFloat(part)).filter((part) => Number.isFinite(part));
|
|
102
|
+
if (parts.length === 4) {
|
|
103
|
+
viewBoxWidth = parts[2];
|
|
104
|
+
viewBoxHeight = parts[3];
|
|
105
|
+
if (viewBoxWidth > 0 && viewBoxHeight > 0) {
|
|
106
|
+
hasViewBox = true;
|
|
107
|
+
} else {
|
|
108
|
+
viewBoxWidth = void 0;
|
|
109
|
+
viewBoxHeight = void 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
width: width !== void 0 && width > 0 ? width : void 0,
|
|
115
|
+
height: height !== void 0 && height > 0 ? height : void 0,
|
|
116
|
+
viewBoxWidth,
|
|
117
|
+
viewBoxHeight,
|
|
118
|
+
hasViewBox
|
|
119
|
+
};
|
|
120
|
+
} catch (e) {
|
|
121
|
+
return { hasViewBox: false };
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const determineSvgRasterDimensions = (parsed, options) => {
|
|
125
|
+
var _a, _b;
|
|
126
|
+
const overrideWidth = options == null ? void 0 : options.width;
|
|
127
|
+
const overrideHeight = options == null ? void 0 : options.height;
|
|
128
|
+
if (overrideWidth !== void 0 && overrideHeight !== void 0 && overrideWidth > 0 && overrideHeight > 0) {
|
|
129
|
+
return {
|
|
130
|
+
width: Math.max(1, Math.round(overrideWidth)),
|
|
131
|
+
height: Math.max(1, Math.round(overrideHeight))
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const intrinsicWidth = parsed == null ? void 0 : parsed.width;
|
|
135
|
+
const intrinsicHeight = parsed == null ? void 0 : parsed.height;
|
|
136
|
+
const hasValidViewBox = Boolean(
|
|
137
|
+
(parsed == null ? void 0 : parsed.hasViewBox) && parsed.viewBoxWidth !== void 0 && parsed.viewBoxHeight !== void 0 && parsed.viewBoxWidth > 0 && parsed.viewBoxHeight > 0
|
|
138
|
+
);
|
|
139
|
+
const viewBoxAspect = hasValidViewBox ? parsed.viewBoxWidth / parsed.viewBoxHeight : void 0;
|
|
140
|
+
let baseWidth;
|
|
141
|
+
let baseHeight;
|
|
142
|
+
let aspect = intrinsicWidth !== void 0 && intrinsicHeight !== void 0 && intrinsicHeight > 0 ? intrinsicWidth / intrinsicHeight : viewBoxAspect;
|
|
143
|
+
if (intrinsicWidth !== void 0 && intrinsicWidth > 0 && intrinsicHeight !== void 0 && intrinsicHeight > 0) {
|
|
144
|
+
baseWidth = intrinsicWidth;
|
|
145
|
+
baseHeight = intrinsicHeight;
|
|
146
|
+
} else if (intrinsicWidth !== void 0 && intrinsicWidth > 0 && aspect !== void 0) {
|
|
147
|
+
baseWidth = intrinsicWidth;
|
|
148
|
+
baseHeight = intrinsicWidth / aspect;
|
|
149
|
+
} else if (intrinsicHeight !== void 0 && intrinsicHeight > 0 && aspect !== void 0) {
|
|
150
|
+
baseHeight = intrinsicHeight;
|
|
151
|
+
baseWidth = intrinsicHeight * aspect;
|
|
152
|
+
} else if (hasValidViewBox && ((_a = options == null ? void 0 : options.svg) == null ? void 0 : _a.useViewBoxDimensions)) {
|
|
153
|
+
baseWidth = parsed.viewBoxWidth;
|
|
154
|
+
baseHeight = parsed.viewBoxHeight;
|
|
155
|
+
aspect = baseWidth / baseHeight;
|
|
156
|
+
}
|
|
157
|
+
if ((baseWidth === void 0 || baseHeight === void 0) && hasValidViewBox && !((_b = options == null ? void 0 : options.svg) == null ? void 0 : _b.useViewBoxDimensions)) {
|
|
158
|
+
throw new SvgSizeResolutionError(
|
|
159
|
+
"SVG width/height attributes are missing and useViewBoxDimensions option is disabled.",
|
|
160
|
+
"viewbox-disabled"
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (baseWidth === void 0 || baseHeight === void 0) {
|
|
164
|
+
throw new SvgSizeResolutionError(
|
|
165
|
+
"SVG image lacks sufficient sizing information.",
|
|
166
|
+
"size-missing"
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
aspect = aspect != null ? aspect : baseWidth / baseHeight;
|
|
170
|
+
let finalWidth = baseWidth;
|
|
171
|
+
let finalHeight = baseHeight;
|
|
172
|
+
if (overrideWidth !== void 0 && overrideWidth > 0) {
|
|
173
|
+
finalWidth = overrideWidth;
|
|
174
|
+
if (overrideHeight === void 0) {
|
|
175
|
+
if (aspect === void 0) {
|
|
176
|
+
throw new SvgSizeResolutionError(
|
|
177
|
+
"Unable to infer SVG height from width; aspect ratio is undefined.",
|
|
178
|
+
"invalid-dimensions"
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
finalHeight = finalWidth / aspect;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (overrideHeight !== void 0 && overrideHeight > 0) {
|
|
185
|
+
finalHeight = overrideHeight;
|
|
186
|
+
if (overrideWidth === void 0) {
|
|
187
|
+
if (aspect === void 0) {
|
|
188
|
+
throw new SvgSizeResolutionError(
|
|
189
|
+
"Unable to infer SVG width from height; aspect ratio is undefined.",
|
|
190
|
+
"invalid-dimensions"
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
finalWidth = finalHeight * aspect;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (!Number.isFinite(finalWidth) || !Number.isFinite(finalHeight) || finalWidth <= 0 || finalHeight <= 0) {
|
|
197
|
+
throw new SvgSizeResolutionError(
|
|
198
|
+
"Resolved SVG dimensions are invalid.",
|
|
199
|
+
"invalid-dimensions"
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
width: Math.max(1, Math.round(finalWidth)),
|
|
204
|
+
height: Math.max(1, Math.round(finalHeight))
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
const isSvgMimeType = (mimeType) => {
|
|
208
|
+
if (!mimeType) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
return mimeType.toLowerCase().includes("image/svg");
|
|
212
|
+
};
|
|
213
|
+
const rasterizeSvgWithCanvas = async (blob, width, height, options) => {
|
|
214
|
+
if (typeof document === "undefined") {
|
|
215
|
+
throw new Error(
|
|
216
|
+
"SVG rasterization fallback requires a browser environment"
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
220
|
+
try {
|
|
221
|
+
const image = await new Promise((resolve, reject) => {
|
|
222
|
+
const element = new Image();
|
|
223
|
+
element.onload = () => resolve(element);
|
|
224
|
+
element.onerror = () => reject(new Error("Failed to load SVG for rasterization"));
|
|
225
|
+
element.src = blobUrl;
|
|
226
|
+
});
|
|
227
|
+
const canvas = document.createElement("canvas");
|
|
228
|
+
canvas.width = width;
|
|
229
|
+
canvas.height = height;
|
|
230
|
+
const ctx = canvas.getContext("2d");
|
|
231
|
+
if (!ctx) {
|
|
232
|
+
throw new Error("Failed to acquire 2D context for SVG rasterization");
|
|
233
|
+
}
|
|
234
|
+
ctx.clearRect(0, 0, width, height);
|
|
235
|
+
ctx.imageSmoothingEnabled = true;
|
|
236
|
+
if ((options == null ? void 0 : options.resizeQuality) === "pixelated") {
|
|
237
|
+
ctx.imageSmoothingEnabled = false;
|
|
238
|
+
} else if (options == null ? void 0 : options.resizeQuality) {
|
|
239
|
+
ctx.imageSmoothingQuality = options.resizeQuality;
|
|
240
|
+
}
|
|
241
|
+
ctx.drawImage(image, 0, 0, width, height);
|
|
242
|
+
try {
|
|
243
|
+
return await createImageBitmap(canvas);
|
|
244
|
+
} catch (e) {
|
|
245
|
+
const canvasBlob = await new Promise((resolve, reject) => {
|
|
246
|
+
canvas.toBlob((result) => {
|
|
247
|
+
if (result) {
|
|
248
|
+
resolve(result);
|
|
249
|
+
} else {
|
|
250
|
+
reject(
|
|
251
|
+
new Error("Failed to convert canvas to blob during rasterization")
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
return await createImageBitmap(canvasBlob);
|
|
257
|
+
}
|
|
258
|
+
} finally {
|
|
259
|
+
URL.revokeObjectURL(blobUrl);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
const resolveSvgBitmapWithFallback = async (blob, width, height, options) => {
|
|
263
|
+
const bitmapOptions = {
|
|
264
|
+
resizeWidth: width,
|
|
265
|
+
resizeHeight: height
|
|
266
|
+
};
|
|
267
|
+
if (options == null ? void 0 : options.resizeQuality) {
|
|
268
|
+
bitmapOptions.resizeQuality = options.resizeQuality;
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
return await createImageBitmap(blob, bitmapOptions);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
return await rasterizeSvgWithCanvas(blob, width, height, options);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const internalReadImageBitmap = async (blob, shouldTreatAsSvg, options) => {
|
|
277
|
+
const svgOptions = options == null ? void 0 : options.svg;
|
|
278
|
+
if (shouldTreatAsSvg) {
|
|
279
|
+
let parsed = null;
|
|
280
|
+
if ((svgOptions == null ? void 0 : svgOptions.inspectSize) !== false) {
|
|
281
|
+
const text = await blob.text();
|
|
282
|
+
parsed = parseSvgSize(text);
|
|
283
|
+
}
|
|
284
|
+
const { width, height } = determineSvgRasterDimensions(parsed, options);
|
|
285
|
+
return await resolveSvgBitmapWithFallback(blob, width, height, options);
|
|
286
|
+
}
|
|
287
|
+
return await createImageBitmap(blob, {
|
|
288
|
+
resizeWidth: options == null ? void 0 : options.width,
|
|
289
|
+
resizeHeight: options == null ? void 0 : options.height,
|
|
290
|
+
resizeQuality: options == null ? void 0 : options.resizeQuality
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
const readImageBitmap = (blob, options) => {
|
|
294
|
+
const svgOptions = options == null ? void 0 : options.svg;
|
|
295
|
+
const shouldTreatAsSvg = (svgOptions == null ? void 0 : svgOptions.assumeSvg) === true;
|
|
296
|
+
return internalReadImageBitmap(blob, shouldTreatAsSvg, options);
|
|
297
|
+
};
|
|
298
|
+
const loadImageBitmap = async (url, options) => {
|
|
299
|
+
var _a;
|
|
300
|
+
const response = await fetch(url);
|
|
301
|
+
if (!response.ok) {
|
|
302
|
+
throw new Error(`Failed to fetch image from ${url}`);
|
|
303
|
+
}
|
|
304
|
+
const mimeType = response.headers.get("content-type");
|
|
305
|
+
const blob = await response.blob();
|
|
306
|
+
const shouldTreatAsSvg = ((_a = options == null ? void 0 : options.svg) == null ? void 0 : _a.assumeSvg) === true || isSvgMimeType(mimeType);
|
|
307
|
+
return await internalReadImageBitmap(blob, shouldTreatAsSvg, options);
|
|
308
|
+
};
|
|
42
309
|
var maplibreGl$1 = { exports: {} };
|
|
43
310
|
/**
|
|
44
311
|
* MapLibre GL JS
|
|
@@ -21113,14 +21380,6 @@ function transformMat4(out, a, m) {
|
|
|
21113
21380
|
return a;
|
|
21114
21381
|
};
|
|
21115
21382
|
})();
|
|
21116
|
-
const loadImageBitmap = async (url) => {
|
|
21117
|
-
const response = await fetch(url);
|
|
21118
|
-
if (!response.ok) {
|
|
21119
|
-
throw new Error(`Failed to fetch image from ${url}`);
|
|
21120
|
-
}
|
|
21121
|
-
const blob = await response.blob();
|
|
21122
|
-
return await createImageBitmap(blob);
|
|
21123
|
-
};
|
|
21124
21383
|
const cloneSpriteLocation = (location2) => {
|
|
21125
21384
|
if (location2.z === void 0) {
|
|
21126
21385
|
return { lng: location2.lng, lat: location2.lat };
|
|
@@ -21177,7 +21436,7 @@ const computeFeedforwardTarget = (previous, next) => {
|
|
|
21177
21436
|
}
|
|
21178
21437
|
return target;
|
|
21179
21438
|
};
|
|
21180
|
-
const
|
|
21439
|
+
const normalizeOptions$2 = (options) => {
|
|
21181
21440
|
var _a;
|
|
21182
21441
|
return {
|
|
21183
21442
|
durationMs: Math.max(0, options.durationMs),
|
|
@@ -21187,7 +21446,7 @@ const normaliseOptions$1 = (options) => {
|
|
|
21187
21446
|
};
|
|
21188
21447
|
const createInterpolationState = (params) => {
|
|
21189
21448
|
const { currentLocation, lastCommandLocation, nextCommandLocation } = params;
|
|
21190
|
-
const options =
|
|
21449
|
+
const options = normalizeOptions$2(params.options);
|
|
21191
21450
|
const from = cloneSpriteLocation(currentLocation);
|
|
21192
21451
|
const easing = resolveEasing(options.easing);
|
|
21193
21452
|
let to;
|
|
@@ -21232,8 +21491,8 @@ const evaluateInterpolation = (params) => {
|
|
|
21232
21491
|
};
|
|
21233
21492
|
};
|
|
21234
21493
|
const NUMERIC_EPSILON = 1e-6;
|
|
21235
|
-
const
|
|
21236
|
-
const
|
|
21494
|
+
const normalizeDuration$1 = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
|
|
21495
|
+
const normalizeDelta = (delta) => {
|
|
21237
21496
|
if (!Number.isFinite(delta)) {
|
|
21238
21497
|
return 0;
|
|
21239
21498
|
}
|
|
@@ -21245,16 +21504,24 @@ const normaliseDelta = (delta) => {
|
|
|
21245
21504
|
}
|
|
21246
21505
|
return adjusted;
|
|
21247
21506
|
};
|
|
21248
|
-
const
|
|
21507
|
+
const normalizeOptions$1 = (options) => {
|
|
21508
|
+
var _a;
|
|
21249
21509
|
return {
|
|
21250
|
-
durationMs:
|
|
21251
|
-
easing: resolveEasing(options.easing)
|
|
21510
|
+
durationMs: normalizeDuration$1(options.durationMs),
|
|
21511
|
+
easing: resolveEasing(options.easing),
|
|
21512
|
+
mode: (_a = options.mode) != null ? _a : "feedback"
|
|
21252
21513
|
};
|
|
21253
21514
|
};
|
|
21254
|
-
const
|
|
21515
|
+
const createDegreeInterpolationState = (params) => {
|
|
21255
21516
|
const { currentValue, targetValue } = params;
|
|
21256
|
-
const options =
|
|
21257
|
-
|
|
21517
|
+
const options = normalizeOptions$1(params.options);
|
|
21518
|
+
let effectiveTarget = targetValue;
|
|
21519
|
+
const previousCommand = params.previousCommandValue;
|
|
21520
|
+
if (options.mode === "feedforward" && previousCommand !== void 0 && Number.isFinite(previousCommand)) {
|
|
21521
|
+
const commandDelta = normalizeDelta(targetValue - previousCommand);
|
|
21522
|
+
effectiveTarget = targetValue + commandDelta;
|
|
21523
|
+
}
|
|
21524
|
+
const delta = normalizeDelta(effectiveTarget - currentValue);
|
|
21258
21525
|
const pathTarget = currentValue + delta;
|
|
21259
21526
|
const requiresInterpolation = options.durationMs > 0 && Math.abs(delta) > NUMERIC_EPSILON;
|
|
21260
21527
|
const state = {
|
|
@@ -21262,7 +21529,7 @@ const createNumericInterpolationState = (params) => {
|
|
|
21262
21529
|
easing: options.easing,
|
|
21263
21530
|
from: currentValue,
|
|
21264
21531
|
to: pathTarget,
|
|
21265
|
-
finalValue:
|
|
21532
|
+
finalValue: effectiveTarget,
|
|
21266
21533
|
startTimestamp: -1
|
|
21267
21534
|
};
|
|
21268
21535
|
return {
|
|
@@ -21270,7 +21537,7 @@ const createNumericInterpolationState = (params) => {
|
|
|
21270
21537
|
requiresInterpolation
|
|
21271
21538
|
};
|
|
21272
21539
|
};
|
|
21273
|
-
const clamp01 = (value) => {
|
|
21540
|
+
const clamp01$1 = (value) => {
|
|
21274
21541
|
if (!Number.isFinite(value)) {
|
|
21275
21542
|
return 1;
|
|
21276
21543
|
}
|
|
@@ -21282,7 +21549,7 @@ const clamp01 = (value) => {
|
|
|
21282
21549
|
}
|
|
21283
21550
|
return value;
|
|
21284
21551
|
};
|
|
21285
|
-
const
|
|
21552
|
+
const evaluateDegreeInterpolation = (params) => {
|
|
21286
21553
|
const { state } = params;
|
|
21287
21554
|
const timestamp = Number.isFinite(params.timestamp) ? params.timestamp : Date.now();
|
|
21288
21555
|
const duration = Math.max(0, state.durationMs);
|
|
@@ -21296,7 +21563,7 @@ const evaluateNumericInterpolation = (params) => {
|
|
|
21296
21563
|
}
|
|
21297
21564
|
const elapsed = timestamp - effectiveStart;
|
|
21298
21565
|
const rawProgress = duration <= 0 ? 1 : elapsed / duration;
|
|
21299
|
-
const eased = clamp01(state.easing(rawProgress));
|
|
21566
|
+
const eased = clamp01$1(state.easing(rawProgress));
|
|
21300
21567
|
const interpolated = state.from + (state.to - state.from) * eased;
|
|
21301
21568
|
const completed = rawProgress >= 1;
|
|
21302
21569
|
return {
|
|
@@ -21305,7 +21572,7 @@ const evaluateNumericInterpolation = (params) => {
|
|
|
21305
21572
|
effectiveStartTimestamp: effectiveStart
|
|
21306
21573
|
};
|
|
21307
21574
|
};
|
|
21308
|
-
const
|
|
21575
|
+
const normalizeAngleDeg = (angle) => {
|
|
21309
21576
|
if (!Number.isFinite(angle)) {
|
|
21310
21577
|
return 0;
|
|
21311
21578
|
}
|
|
@@ -21315,17 +21582,19 @@ const normaliseAngleDeg = (angle) => {
|
|
|
21315
21582
|
};
|
|
21316
21583
|
const resolveRotationTarget = (params) => {
|
|
21317
21584
|
const options = params.options;
|
|
21318
|
-
const targetAngle =
|
|
21319
|
-
const currentAngle =
|
|
21585
|
+
const targetAngle = normalizeAngleDeg(params.targetAngleDeg);
|
|
21586
|
+
const currentAngle = normalizeAngleDeg(params.currentAngleDeg);
|
|
21587
|
+
const previousCommandAngleDeg = params.previousCommandAngleDeg !== void 0 ? normalizeAngleDeg(params.previousCommandAngleDeg) : void 0;
|
|
21320
21588
|
if (!options || options.durationMs <= 0) {
|
|
21321
21589
|
return {
|
|
21322
21590
|
nextAngleDeg: targetAngle,
|
|
21323
21591
|
interpolationState: null
|
|
21324
21592
|
};
|
|
21325
21593
|
}
|
|
21326
|
-
const { state, requiresInterpolation } =
|
|
21594
|
+
const { state, requiresInterpolation } = createDegreeInterpolationState({
|
|
21327
21595
|
currentValue: currentAngle,
|
|
21328
21596
|
targetValue: targetAngle,
|
|
21597
|
+
previousCommandValue: previousCommandAngleDeg,
|
|
21329
21598
|
options
|
|
21330
21599
|
});
|
|
21331
21600
|
if (!requiresInterpolation) {
|
|
@@ -21667,13 +21936,6 @@ const applySurfaceDisplacement = (baseLng, baseLat, east, north) => {
|
|
|
21667
21936
|
lat: baseLat + deltaLat
|
|
21668
21937
|
};
|
|
21669
21938
|
};
|
|
21670
|
-
const screenToClip = (x, y, drawingBufferWidth, drawingBufferHeight, pixelRatio) => {
|
|
21671
|
-
const deviceX = x * pixelRatio;
|
|
21672
|
-
const deviceY = y * pixelRatio;
|
|
21673
|
-
const clipX = deviceX / drawingBufferWidth * 2 - 1;
|
|
21674
|
-
const clipY = 1 - deviceY / drawingBufferHeight * 2;
|
|
21675
|
-
return [clipX, clipY];
|
|
21676
|
-
};
|
|
21677
21939
|
const clipToScreen = (clipPosition, drawingBufferWidth, drawingBufferHeight, pixelRatio) => {
|
|
21678
21940
|
const [clipX, clipY, , clipW] = clipPosition;
|
|
21679
21941
|
if (!Number.isFinite(clipW) || clipW === 0) {
|
|
@@ -21818,41 +22080,55 @@ const calculateBillboardCenterPosition = (params) => {
|
|
|
21818
22080
|
offsetShift
|
|
21819
22081
|
};
|
|
21820
22082
|
};
|
|
21821
|
-
const
|
|
21822
|
-
[-1, 1],
|
|
21823
|
-
[1, 1],
|
|
21824
|
-
[-1, -1],
|
|
21825
|
-
[1, -1]
|
|
21826
|
-
];
|
|
21827
|
-
const calculateBillboardCornerScreenPositions = (params) => {
|
|
22083
|
+
const computeSurfaceCornerShaderModel = (params) => {
|
|
21828
22084
|
var _a, _b;
|
|
21829
|
-
const {
|
|
22085
|
+
const {
|
|
22086
|
+
baseLngLat,
|
|
22087
|
+
worldWidthMeters,
|
|
22088
|
+
worldHeightMeters,
|
|
22089
|
+
anchor,
|
|
22090
|
+
totalRotateDeg,
|
|
22091
|
+
offsetMeters
|
|
22092
|
+
} = params;
|
|
22093
|
+
const halfWidth = worldWidthMeters / 2;
|
|
22094
|
+
const halfHeight = worldHeightMeters / 2;
|
|
21830
22095
|
if (halfWidth <= 0 || halfHeight <= 0) {
|
|
21831
|
-
|
|
22096
|
+
const cosLat2 = Math.cos(baseLngLat.lat * DEG2RAD);
|
|
22097
|
+
const cosLatClamped2 = Math.max(cosLat2, MIN_COS_LAT);
|
|
22098
|
+
const deltaLat = offsetMeters.north / EARTH_RADIUS_METERS * RAD2DEG;
|
|
22099
|
+
const deltaLng = offsetMeters.east / (EARTH_RADIUS_METERS * cosLatClamped2) * RAD2DEG;
|
|
22100
|
+
return SURFACE_BASE_CORNERS$1.map(() => ({
|
|
22101
|
+
east: offsetMeters.east,
|
|
22102
|
+
north: offsetMeters.north,
|
|
22103
|
+
lng: baseLngLat.lng + deltaLng,
|
|
22104
|
+
lat: baseLngLat.lat + deltaLat
|
|
22105
|
+
}));
|
|
21832
22106
|
}
|
|
21833
|
-
const
|
|
21834
|
-
const
|
|
22107
|
+
const anchorEast = ((_a = anchor == null ? void 0 : anchor.x) != null ? _a : 0) * halfWidth;
|
|
22108
|
+
const anchorNorth = ((_b = anchor == null ? void 0 : anchor.y) != null ? _b : 0) * halfHeight;
|
|
21835
22109
|
const rad = -totalRotateDeg * DEG2RAD;
|
|
21836
|
-
const cosR = Math.cos(rad);
|
|
21837
22110
|
const sinR = Math.sin(rad);
|
|
21838
|
-
const
|
|
21839
|
-
|
|
21840
|
-
|
|
21841
|
-
|
|
21842
|
-
const
|
|
21843
|
-
const
|
|
21844
|
-
const
|
|
21845
|
-
const
|
|
21846
|
-
const
|
|
21847
|
-
const
|
|
21848
|
-
|
|
21849
|
-
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
21853
|
-
|
|
21854
|
-
|
|
21855
|
-
|
|
22111
|
+
const cosR = Math.cos(rad);
|
|
22112
|
+
const cosLat = Math.cos(baseLngLat.lat * DEG2RAD);
|
|
22113
|
+
const cosLatClamped = Math.max(cosLat, MIN_COS_LAT);
|
|
22114
|
+
return SURFACE_BASE_CORNERS$1.map(([eastNorm, northNorm]) => {
|
|
22115
|
+
const cornerEast = eastNorm * halfWidth;
|
|
22116
|
+
const cornerNorth = northNorm * halfHeight;
|
|
22117
|
+
const localEast = cornerEast - anchorEast;
|
|
22118
|
+
const localNorth = cornerNorth - anchorNorth;
|
|
22119
|
+
const rotatedEast = localEast * cosR - localNorth * sinR;
|
|
22120
|
+
const rotatedNorth = localEast * sinR + localNorth * cosR;
|
|
22121
|
+
const east = rotatedEast + offsetMeters.east;
|
|
22122
|
+
const north = rotatedNorth + offsetMeters.north;
|
|
22123
|
+
const deltaLat = north / EARTH_RADIUS_METERS * RAD2DEG;
|
|
22124
|
+
const deltaLng = east / (EARTH_RADIUS_METERS * cosLatClamped) * RAD2DEG;
|
|
22125
|
+
return {
|
|
22126
|
+
east,
|
|
22127
|
+
north,
|
|
22128
|
+
lng: baseLngLat.lng + deltaLng,
|
|
22129
|
+
lat: baseLngLat.lat + deltaLat
|
|
22130
|
+
};
|
|
22131
|
+
});
|
|
21856
22132
|
};
|
|
21857
22133
|
const calculateSurfaceCenterPosition = (params) => {
|
|
21858
22134
|
var _a, _b;
|
|
@@ -21962,7 +22238,7 @@ const calculateSurfaceCenterPosition = (params) => {
|
|
|
21962
22238
|
anchorlessLngLat
|
|
21963
22239
|
};
|
|
21964
22240
|
};
|
|
21965
|
-
const SURFACE_BASE_CORNERS = [
|
|
22241
|
+
const SURFACE_BASE_CORNERS$1 = [
|
|
21966
22242
|
[-1, 1],
|
|
21967
22243
|
[1, 1],
|
|
21968
22244
|
[-1, -1],
|
|
@@ -21978,7 +22254,7 @@ const calculateSurfaceCornerDisplacements = (params) => {
|
|
|
21978
22254
|
offsetMeters
|
|
21979
22255
|
} = params;
|
|
21980
22256
|
if (worldWidthMeters <= 0 || worldHeightMeters <= 0) {
|
|
21981
|
-
return SURFACE_BASE_CORNERS.map(() => ({
|
|
22257
|
+
return SURFACE_BASE_CORNERS$1.map(() => ({
|
|
21982
22258
|
east: offsetMeters.east,
|
|
21983
22259
|
north: offsetMeters.north
|
|
21984
22260
|
}));
|
|
@@ -21991,7 +22267,7 @@ const calculateSurfaceCornerDisplacements = (params) => {
|
|
|
21991
22267
|
const cosR = Math.cos(rad);
|
|
21992
22268
|
const sinR = Math.sin(rad);
|
|
21993
22269
|
const corners = [];
|
|
21994
|
-
for (const [eastNorm, northNorm] of SURFACE_BASE_CORNERS) {
|
|
22270
|
+
for (const [eastNorm, northNorm] of SURFACE_BASE_CORNERS$1) {
|
|
21995
22271
|
const cornerEast = eastNorm * halfWidth;
|
|
21996
22272
|
const cornerNorth = northNorm * halfHeight;
|
|
21997
22273
|
const localEast = cornerEast - anchorEast;
|
|
@@ -22005,115 +22281,602 @@ const calculateSurfaceCornerDisplacements = (params) => {
|
|
|
22005
22281
|
}
|
|
22006
22282
|
return corners;
|
|
22007
22283
|
};
|
|
22008
|
-
const
|
|
22009
|
-
const
|
|
22010
|
-
const
|
|
22011
|
-
|
|
22012
|
-
offsetDeg: 0
|
|
22013
|
-
};
|
|
22014
|
-
const MIN_CLIP_W = 1e-6;
|
|
22015
|
-
const MIN_CLIP_Z_EPSILON = 1e-7;
|
|
22016
|
-
const EPS_NDC = 1e-6;
|
|
22017
|
-
const ORDER_MAX = 16;
|
|
22018
|
-
const ORDER_BUCKET = 16;
|
|
22019
|
-
const MIN_FILTER_VALUES = [
|
|
22020
|
-
"nearest",
|
|
22021
|
-
"linear",
|
|
22022
|
-
"nearest-mipmap-nearest",
|
|
22023
|
-
"nearest-mipmap-linear",
|
|
22024
|
-
"linear-mipmap-nearest",
|
|
22025
|
-
"linear-mipmap-linear"
|
|
22026
|
-
];
|
|
22027
|
-
const MAG_FILTER_VALUES = [
|
|
22028
|
-
"nearest",
|
|
22029
|
-
"linear"
|
|
22030
|
-
];
|
|
22031
|
-
const MIPMAP_MIN_FILTERS = /* @__PURE__ */ new Set([
|
|
22032
|
-
"nearest-mipmap-nearest",
|
|
22033
|
-
"nearest-mipmap-linear",
|
|
22034
|
-
"linear-mipmap-nearest",
|
|
22035
|
-
"linear-mipmap-linear"
|
|
22036
|
-
]);
|
|
22037
|
-
const filterRequiresMipmaps = (filter) => MIPMAP_MIN_FILTERS.has(filter);
|
|
22038
|
-
const resolveTextureFilteringOptions = (options) => {
|
|
22039
|
-
var _a, _b;
|
|
22040
|
-
const minCandidate = options == null ? void 0 : options.minFilter;
|
|
22041
|
-
const minFilter = MIN_FILTER_VALUES.includes(
|
|
22042
|
-
minCandidate
|
|
22043
|
-
) ? minCandidate : DEFAULT_TEXTURE_FILTERING_OPTIONS.minFilter;
|
|
22044
|
-
const magCandidate = options == null ? void 0 : options.magFilter;
|
|
22045
|
-
const magFilter = MAG_FILTER_VALUES.includes(
|
|
22046
|
-
magCandidate
|
|
22047
|
-
) ? magCandidate : DEFAULT_TEXTURE_FILTERING_OPTIONS.magFilter;
|
|
22048
|
-
let generateMipmaps = (_a = options == null ? void 0 : options.generateMipmaps) != null ? _a : DEFAULT_TEXTURE_FILTERING_OPTIONS.generateMipmaps;
|
|
22049
|
-
if (filterRequiresMipmaps(minFilter)) {
|
|
22050
|
-
generateMipmaps = true;
|
|
22051
|
-
}
|
|
22052
|
-
let maxAnisotropy = (_b = options == null ? void 0 : options.maxAnisotropy) != null ? _b : DEFAULT_TEXTURE_FILTERING_OPTIONS.maxAnisotropy;
|
|
22053
|
-
if (!Number.isFinite(maxAnisotropy) || maxAnisotropy < 1) {
|
|
22054
|
-
maxAnisotropy = 1;
|
|
22055
|
-
}
|
|
22284
|
+
const DISTANCE_EPSILON = 1e-6;
|
|
22285
|
+
const normalizeDuration = (durationMs) => Number.isFinite(durationMs) && durationMs > 0 ? durationMs : 0;
|
|
22286
|
+
const normalizeOptions = (options) => {
|
|
22287
|
+
var _a;
|
|
22056
22288
|
return {
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
maxAnisotropy
|
|
22289
|
+
durationMs: normalizeDuration(options.durationMs),
|
|
22290
|
+
easing: resolveEasing(options.easing),
|
|
22291
|
+
mode: (_a = options.mode) != null ? _a : "feedback"
|
|
22061
22292
|
};
|
|
22062
22293
|
};
|
|
22063
|
-
const
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22067
|
-
|
|
22068
|
-
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
if (extension) {
|
|
22072
|
-
return extension;
|
|
22073
|
-
}
|
|
22294
|
+
const createDistanceInterpolationState = (params) => {
|
|
22295
|
+
const { currentValue, targetValue } = params;
|
|
22296
|
+
const options = normalizeOptions(params.options);
|
|
22297
|
+
let effectiveTarget = targetValue;
|
|
22298
|
+
const previousCommand = params.previousCommandValue;
|
|
22299
|
+
if (options.mode === "feedforward" && previousCommand !== void 0 && Number.isFinite(previousCommand)) {
|
|
22300
|
+
const commandDelta = targetValue - previousCommand;
|
|
22301
|
+
effectiveTarget = targetValue + commandDelta;
|
|
22074
22302
|
}
|
|
22075
|
-
|
|
22303
|
+
const delta = effectiveTarget - currentValue;
|
|
22304
|
+
const requiresInterpolation = options.durationMs > 0 && Math.abs(delta) > DISTANCE_EPSILON;
|
|
22305
|
+
const state = {
|
|
22306
|
+
durationMs: options.durationMs,
|
|
22307
|
+
easing: options.easing,
|
|
22308
|
+
from: currentValue,
|
|
22309
|
+
to: currentValue + delta,
|
|
22310
|
+
finalValue: effectiveTarget,
|
|
22311
|
+
startTimestamp: -1
|
|
22312
|
+
};
|
|
22313
|
+
return {
|
|
22314
|
+
state,
|
|
22315
|
+
requiresInterpolation
|
|
22316
|
+
};
|
|
22076
22317
|
};
|
|
22077
|
-
const
|
|
22078
|
-
|
|
22079
|
-
|
|
22080
|
-
case "nearest":
|
|
22081
|
-
return glContext.NEAREST;
|
|
22082
|
-
case "nearest-mipmap-nearest":
|
|
22083
|
-
return glContext.NEAREST_MIPMAP_NEAREST;
|
|
22084
|
-
case "nearest-mipmap-linear":
|
|
22085
|
-
return glContext.NEAREST_MIPMAP_LINEAR;
|
|
22086
|
-
case "linear-mipmap-nearest":
|
|
22087
|
-
return glContext.LINEAR_MIPMAP_NEAREST;
|
|
22088
|
-
case "linear-mipmap-linear":
|
|
22089
|
-
return glContext.LINEAR_MIPMAP_LINEAR;
|
|
22090
|
-
case "linear":
|
|
22091
|
-
default:
|
|
22092
|
-
return glContext.LINEAR;
|
|
22318
|
+
const clamp01 = (value) => {
|
|
22319
|
+
if (!Number.isFinite(value)) {
|
|
22320
|
+
return 1;
|
|
22093
22321
|
}
|
|
22094
|
-
|
|
22095
|
-
|
|
22096
|
-
switch (filter) {
|
|
22097
|
-
case "nearest":
|
|
22098
|
-
return glContext.NEAREST;
|
|
22099
|
-
case "linear":
|
|
22100
|
-
default:
|
|
22101
|
-
return glContext.LINEAR;
|
|
22322
|
+
if (value <= 0) {
|
|
22323
|
+
return 0;
|
|
22102
22324
|
}
|
|
22103
|
-
|
|
22104
|
-
const calculatePerspectiveRatio = (mapInstance, location2) => {
|
|
22105
|
-
var _a, _b, _c;
|
|
22106
|
-
const transform = mapInstance.transform;
|
|
22107
|
-
if (!transform) {
|
|
22325
|
+
if (value >= 1) {
|
|
22108
22326
|
return 1;
|
|
22109
22327
|
}
|
|
22110
|
-
|
|
22328
|
+
return value;
|
|
22329
|
+
};
|
|
22330
|
+
const evaluateDistanceInterpolation = (params) => {
|
|
22331
|
+
const { state } = params;
|
|
22332
|
+
const timestamp = Number.isFinite(params.timestamp) ? params.timestamp : Date.now();
|
|
22333
|
+
const duration = Math.max(0, state.durationMs);
|
|
22334
|
+
const effectiveStart = state.startTimestamp >= 0 ? state.startTimestamp : timestamp;
|
|
22335
|
+
if (duration === 0 || Math.abs(state.to - state.from) <= DISTANCE_EPSILON) {
|
|
22336
|
+
return {
|
|
22337
|
+
value: state.finalValue,
|
|
22338
|
+
completed: true,
|
|
22339
|
+
effectiveStartTimestamp: effectiveStart
|
|
22340
|
+
};
|
|
22341
|
+
}
|
|
22342
|
+
const elapsed = timestamp - effectiveStart;
|
|
22343
|
+
const rawProgress = duration <= 0 ? 1 : elapsed / duration;
|
|
22344
|
+
const eased = clamp01(state.easing(rawProgress));
|
|
22345
|
+
const interpolated = state.from + (state.to - state.from) * eased;
|
|
22346
|
+
const completed = rawProgress >= 1;
|
|
22347
|
+
return {
|
|
22348
|
+
value: completed ? state.finalValue : interpolated,
|
|
22349
|
+
completed,
|
|
22350
|
+
effectiveStartTimestamp: effectiveStart
|
|
22351
|
+
};
|
|
22352
|
+
};
|
|
22353
|
+
const stepDegreeInterpolationState = (interpolationState, timestamp, applyValue, options) => {
|
|
22354
|
+
var _a, _b;
|
|
22355
|
+
if (!interpolationState) {
|
|
22356
|
+
return { state: null, active: false };
|
|
22357
|
+
}
|
|
22358
|
+
const evaluation = evaluateDegreeInterpolation({
|
|
22359
|
+
state: interpolationState,
|
|
22360
|
+
timestamp
|
|
22361
|
+
});
|
|
22362
|
+
if (interpolationState.startTimestamp < 0) {
|
|
22363
|
+
interpolationState.startTimestamp = evaluation.effectiveStartTimestamp;
|
|
22364
|
+
}
|
|
22365
|
+
const normalizeValue = (_a = options == null ? void 0 : options.normalize) != null ? _a : ((value) => value);
|
|
22366
|
+
const applyFinalValue = (_b = options == null ? void 0 : options.applyFinalValue) != null ? _b : applyValue;
|
|
22367
|
+
const interpolatedValue = normalizeValue(evaluation.value);
|
|
22368
|
+
applyValue(interpolatedValue);
|
|
22369
|
+
if (evaluation.completed) {
|
|
22370
|
+
const finalValue = normalizeValue(interpolationState.finalValue);
|
|
22371
|
+
applyFinalValue(finalValue);
|
|
22372
|
+
return { state: null, active: false };
|
|
22373
|
+
}
|
|
22374
|
+
return { state: interpolationState, active: true };
|
|
22375
|
+
};
|
|
22376
|
+
const updateImageDisplayedRotation = (image, optionsOverride) => {
|
|
22377
|
+
const targetAngle = normalizeAngleDeg(
|
|
22378
|
+
image.resolvedBaseRotateDeg + image.rotateDeg
|
|
22379
|
+
);
|
|
22380
|
+
const currentAngle = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : targetAngle;
|
|
22381
|
+
const previousCommandAngle = image.lastCommandRotateDeg;
|
|
22382
|
+
const options = optionsOverride === void 0 ? image.rotationInterpolationOptions : optionsOverride;
|
|
22383
|
+
const { nextAngleDeg, interpolationState } = resolveRotationTarget({
|
|
22384
|
+
currentAngleDeg: currentAngle,
|
|
22385
|
+
targetAngleDeg: targetAngle,
|
|
22386
|
+
previousCommandAngleDeg: previousCommandAngle,
|
|
22387
|
+
options: options != null ? options : void 0
|
|
22388
|
+
});
|
|
22389
|
+
image.displayedRotateDeg = nextAngleDeg;
|
|
22390
|
+
image.rotationInterpolationState = interpolationState;
|
|
22391
|
+
if (!interpolationState) {
|
|
22392
|
+
image.displayedRotateDeg = targetAngle;
|
|
22393
|
+
}
|
|
22394
|
+
image.lastCommandRotateDeg = targetAngle;
|
|
22395
|
+
};
|
|
22396
|
+
const syncImageRotationChannel = (image, optionsOverride) => {
|
|
22397
|
+
updateImageDisplayedRotation(image, optionsOverride);
|
|
22398
|
+
};
|
|
22399
|
+
const stepRotationInterpolation = (image, timestamp) => {
|
|
22400
|
+
const { state, active } = stepDegreeInterpolationState(
|
|
22401
|
+
image.rotationInterpolationState,
|
|
22402
|
+
timestamp,
|
|
22403
|
+
(value) => {
|
|
22404
|
+
image.displayedRotateDeg = value;
|
|
22405
|
+
},
|
|
22406
|
+
{
|
|
22407
|
+
normalize: normalizeAngleDeg
|
|
22408
|
+
}
|
|
22409
|
+
);
|
|
22410
|
+
image.rotationInterpolationState = state;
|
|
22411
|
+
return active;
|
|
22412
|
+
};
|
|
22413
|
+
const stepOffsetDegInterpolation = (image, timestamp) => {
|
|
22414
|
+
const { state, active } = stepDegreeInterpolationState(
|
|
22415
|
+
image.offsetDegInterpolationState,
|
|
22416
|
+
timestamp,
|
|
22417
|
+
(value) => {
|
|
22418
|
+
image.offset.offsetDeg = value;
|
|
22419
|
+
}
|
|
22420
|
+
);
|
|
22421
|
+
image.offsetDegInterpolationState = state;
|
|
22422
|
+
return active;
|
|
22423
|
+
};
|
|
22424
|
+
const clearOffsetDegInterpolation = (image) => {
|
|
22425
|
+
image.offsetDegInterpolationState = null;
|
|
22426
|
+
};
|
|
22427
|
+
const stepDistanceInterpolationState = (interpolationState, timestamp, applyValue) => {
|
|
22428
|
+
if (!interpolationState) {
|
|
22429
|
+
return { state: null, active: false };
|
|
22430
|
+
}
|
|
22431
|
+
const evaluation = evaluateDistanceInterpolation({
|
|
22432
|
+
state: interpolationState,
|
|
22433
|
+
timestamp
|
|
22434
|
+
});
|
|
22435
|
+
if (interpolationState.startTimestamp < 0) {
|
|
22436
|
+
interpolationState.startTimestamp = evaluation.effectiveStartTimestamp;
|
|
22437
|
+
}
|
|
22438
|
+
applyValue(evaluation.value);
|
|
22439
|
+
if (evaluation.completed) {
|
|
22440
|
+
applyValue(interpolationState.finalValue);
|
|
22441
|
+
return { state: null, active: false };
|
|
22442
|
+
}
|
|
22443
|
+
return { state: interpolationState, active: true };
|
|
22444
|
+
};
|
|
22445
|
+
const clearOffsetMetersInterpolation = (image) => {
|
|
22446
|
+
image.offsetMetersInterpolationState = null;
|
|
22447
|
+
};
|
|
22448
|
+
const applyOffsetDegUpdate = (image, nextOffset, interpolationOptions) => {
|
|
22449
|
+
const options = interpolationOptions;
|
|
22450
|
+
if (!options || options.durationMs <= 0) {
|
|
22451
|
+
image.offset.offsetDeg = nextOffset.offsetDeg;
|
|
22452
|
+
image.offsetDegInterpolationState = null;
|
|
22453
|
+
image.lastCommandOffsetDeg = nextOffset.offsetDeg;
|
|
22454
|
+
return;
|
|
22455
|
+
}
|
|
22456
|
+
const { state, requiresInterpolation } = createDegreeInterpolationState({
|
|
22457
|
+
currentValue: image.offset.offsetDeg,
|
|
22458
|
+
targetValue: nextOffset.offsetDeg,
|
|
22459
|
+
previousCommandValue: image.lastCommandOffsetDeg,
|
|
22460
|
+
options
|
|
22461
|
+
});
|
|
22462
|
+
image.lastCommandOffsetDeg = nextOffset.offsetDeg;
|
|
22463
|
+
if (requiresInterpolation) {
|
|
22464
|
+
image.offsetDegInterpolationState = state;
|
|
22465
|
+
} else {
|
|
22466
|
+
image.offset.offsetDeg = nextOffset.offsetDeg;
|
|
22467
|
+
image.offsetDegInterpolationState = null;
|
|
22468
|
+
}
|
|
22469
|
+
};
|
|
22470
|
+
const applyOffsetMetersUpdate = (image, nextOffset, interpolationOptions) => {
|
|
22471
|
+
const options = interpolationOptions;
|
|
22472
|
+
if (!options || options.durationMs <= 0) {
|
|
22473
|
+
image.offset.offsetMeters = nextOffset.offsetMeters;
|
|
22474
|
+
image.offsetMetersInterpolationState = null;
|
|
22475
|
+
image.lastCommandOffsetMeters = nextOffset.offsetMeters;
|
|
22476
|
+
return;
|
|
22477
|
+
}
|
|
22478
|
+
const { state, requiresInterpolation } = createDistanceInterpolationState({
|
|
22479
|
+
currentValue: image.offset.offsetMeters,
|
|
22480
|
+
targetValue: nextOffset.offsetMeters,
|
|
22481
|
+
previousCommandValue: image.lastCommandOffsetMeters,
|
|
22482
|
+
options
|
|
22483
|
+
});
|
|
22484
|
+
image.lastCommandOffsetMeters = nextOffset.offsetMeters;
|
|
22485
|
+
if (requiresInterpolation) {
|
|
22486
|
+
image.offsetMetersInterpolationState = state;
|
|
22487
|
+
} else {
|
|
22488
|
+
image.offset.offsetMeters = nextOffset.offsetMeters;
|
|
22489
|
+
image.offsetMetersInterpolationState = null;
|
|
22490
|
+
}
|
|
22491
|
+
};
|
|
22492
|
+
const stepOffsetMetersInterpolation = (image, timestamp) => {
|
|
22493
|
+
const { state, active } = stepDistanceInterpolationState(
|
|
22494
|
+
image.offsetMetersInterpolationState,
|
|
22495
|
+
timestamp,
|
|
22496
|
+
(value) => {
|
|
22497
|
+
image.offset.offsetMeters = value;
|
|
22498
|
+
}
|
|
22499
|
+
);
|
|
22500
|
+
image.offsetMetersInterpolationState = state;
|
|
22501
|
+
return active;
|
|
22502
|
+
};
|
|
22503
|
+
const IMAGE_INTERPOLATION_STEPPERS = [
|
|
22504
|
+
stepRotationInterpolation,
|
|
22505
|
+
stepOffsetDegInterpolation,
|
|
22506
|
+
stepOffsetMetersInterpolation
|
|
22507
|
+
];
|
|
22508
|
+
const stepSpriteImageInterpolations = (image, timestamp) => {
|
|
22509
|
+
let active = false;
|
|
22510
|
+
for (const stepper of IMAGE_INTERPOLATION_STEPPERS) {
|
|
22511
|
+
if (stepper(image, timestamp)) {
|
|
22512
|
+
active = true;
|
|
22513
|
+
}
|
|
22514
|
+
}
|
|
22515
|
+
return active;
|
|
22516
|
+
};
|
|
22517
|
+
const applyOffsetUpdate = (image, nextOffset, options = {}) => {
|
|
22518
|
+
applyOffsetDegUpdate(image, nextOffset, options.deg);
|
|
22519
|
+
applyOffsetMetersUpdate(image, nextOffset, options.meters);
|
|
22520
|
+
};
|
|
22521
|
+
const DEFAULT_MAX_ITEMS_PER_NODE = 16;
|
|
22522
|
+
const DEFAULT_MAX_DEPTH = 8;
|
|
22523
|
+
const DEFAULT_LOOSENESS = 1.5;
|
|
22524
|
+
const createNode = (bounds, looseness, depth) => ({
|
|
22525
|
+
bounds,
|
|
22526
|
+
looseBounds: expandRect(bounds, looseness),
|
|
22527
|
+
items: [],
|
|
22528
|
+
children: null,
|
|
22529
|
+
depth
|
|
22530
|
+
});
|
|
22531
|
+
const normalizeRect = (rect) => {
|
|
22532
|
+
const x0 = Math.min(rect.x0, rect.x1);
|
|
22533
|
+
const y0 = Math.min(rect.y0, rect.y1);
|
|
22534
|
+
const x1 = Math.max(rect.x0, rect.x1);
|
|
22535
|
+
const y1 = Math.max(rect.y0, rect.y1);
|
|
22536
|
+
return { x0, y0, x1, y1 };
|
|
22537
|
+
};
|
|
22538
|
+
const isFiniteRect = (rect) => Number.isFinite(rect.x0) && Number.isFinite(rect.y0) && Number.isFinite(rect.x1) && Number.isFinite(rect.y1);
|
|
22539
|
+
const expandRect = (rect, looseness) => {
|
|
22540
|
+
if (looseness === 1) {
|
|
22541
|
+
return rect;
|
|
22542
|
+
}
|
|
22543
|
+
const width = rect.x1 - rect.x0;
|
|
22544
|
+
const height = rect.y1 - rect.y0;
|
|
22545
|
+
const halfWidth = width * looseness / 2;
|
|
22546
|
+
const halfHeight = height * looseness / 2;
|
|
22547
|
+
const centerX = rect.x0 + width / 2;
|
|
22548
|
+
const centerY = rect.y0 + height / 2;
|
|
22549
|
+
return {
|
|
22550
|
+
x0: centerX - halfWidth,
|
|
22551
|
+
y0: centerY - halfHeight,
|
|
22552
|
+
x1: centerX + halfWidth,
|
|
22553
|
+
y1: centerY + halfHeight
|
|
22554
|
+
};
|
|
22555
|
+
};
|
|
22556
|
+
const rectContainsRectInclusive = (container, target) => container.x0 <= target.x0 && container.y0 <= target.y0 && container.x1 >= target.x1 && container.y1 >= target.y1;
|
|
22557
|
+
const rectsOverlapInclusive = (a, b) => !(a.x1 < b.x0 || a.x0 > b.x1 || a.y1 < b.y0 || a.y0 > b.y1);
|
|
22558
|
+
const rectEquals = (a, b) => a.x0 === b.x0 && a.y0 === b.y0 && a.x1 === b.x1 && a.y1 === b.y1;
|
|
22559
|
+
const createLooseQuadTree = (options) => {
|
|
22560
|
+
var _a, _b, _c;
|
|
22561
|
+
const maxItemsPerNode = (_a = options.maxItemsPerNode) != null ? _a : DEFAULT_MAX_ITEMS_PER_NODE;
|
|
22562
|
+
const maxDepth = (_b = options.maxDepth) != null ? _b : DEFAULT_MAX_DEPTH;
|
|
22563
|
+
const looseness = (_c = options.looseness) != null ? _c : DEFAULT_LOOSENESS;
|
|
22564
|
+
if (maxItemsPerNode <= 0) {
|
|
22565
|
+
throw new Error("maxItemsPerNode must be greater than 0.");
|
|
22566
|
+
}
|
|
22567
|
+
if (maxDepth < 0) {
|
|
22568
|
+
throw new Error("maxDepth must be 0 or greater.");
|
|
22569
|
+
}
|
|
22570
|
+
if (!(looseness >= 1)) {
|
|
22571
|
+
throw new Error("looseness must be greater than or equal to 1.");
|
|
22572
|
+
}
|
|
22573
|
+
const normalizedBounds = normalizeRect(options.bounds);
|
|
22574
|
+
if (!isFiniteRect(normalizedBounds)) {
|
|
22575
|
+
throw new Error("Bounds must have finite coordinates.");
|
|
22576
|
+
}
|
|
22577
|
+
let root = createNode(normalizedBounds, looseness, 0);
|
|
22578
|
+
let count = 0;
|
|
22579
|
+
let registry = /* @__PURE__ */ new WeakMap();
|
|
22580
|
+
const insertIntoNode = (node, quadItem) => {
|
|
22581
|
+
if (node.children) {
|
|
22582
|
+
const childIndex = findChildIndex(node.children, quadItem.rect);
|
|
22583
|
+
if (childIndex !== -1) {
|
|
22584
|
+
insertIntoNode(node.children[childIndex], quadItem);
|
|
22585
|
+
return;
|
|
22586
|
+
}
|
|
22587
|
+
}
|
|
22588
|
+
quadItem.node = node;
|
|
22589
|
+
quadItem.index = node.items.length;
|
|
22590
|
+
node.items.push(quadItem);
|
|
22591
|
+
if (node.items.length > maxItemsPerNode && node.depth < maxDepth) {
|
|
22592
|
+
if (!node.children) {
|
|
22593
|
+
subdivide(node);
|
|
22594
|
+
}
|
|
22595
|
+
const children = node.children;
|
|
22596
|
+
if (!children) {
|
|
22597
|
+
return;
|
|
22598
|
+
}
|
|
22599
|
+
let i = 0;
|
|
22600
|
+
while (i < node.items.length) {
|
|
22601
|
+
const candidate = node.items[i];
|
|
22602
|
+
const childIndex = findChildIndex(children, candidate.rect);
|
|
22603
|
+
if (childIndex !== -1) {
|
|
22604
|
+
detachFromNode(candidate);
|
|
22605
|
+
insertIntoNode(children[childIndex], candidate);
|
|
22606
|
+
} else {
|
|
22607
|
+
i += 1;
|
|
22608
|
+
}
|
|
22609
|
+
}
|
|
22610
|
+
}
|
|
22611
|
+
};
|
|
22612
|
+
const removeQuadItem = (quadItem) => {
|
|
22613
|
+
detachFromNode(quadItem);
|
|
22614
|
+
registry.delete(quadItem.item);
|
|
22615
|
+
};
|
|
22616
|
+
const detachFromNode = (quadItem) => {
|
|
22617
|
+
const node = quadItem.node;
|
|
22618
|
+
const index = quadItem.index;
|
|
22619
|
+
if (index < 0 || index >= node.items.length) {
|
|
22620
|
+
return;
|
|
22621
|
+
}
|
|
22622
|
+
const lastIndex = node.items.length - 1;
|
|
22623
|
+
if (index !== lastIndex) {
|
|
22624
|
+
const moved = node.items[lastIndex];
|
|
22625
|
+
node.items[index] = moved;
|
|
22626
|
+
moved.index = index;
|
|
22627
|
+
}
|
|
22628
|
+
node.items.pop();
|
|
22629
|
+
quadItem.index = -1;
|
|
22630
|
+
quadItem.node = node;
|
|
22631
|
+
};
|
|
22632
|
+
const reassignIfPossible = (quadItem) => {
|
|
22633
|
+
const node = quadItem.node;
|
|
22634
|
+
if (!node.children) {
|
|
22635
|
+
return;
|
|
22636
|
+
}
|
|
22637
|
+
const childIndex = findChildIndex(node.children, quadItem.rect);
|
|
22638
|
+
if (childIndex === -1) {
|
|
22639
|
+
return;
|
|
22640
|
+
}
|
|
22641
|
+
detachFromNode(quadItem);
|
|
22642
|
+
insertIntoNode(node.children[childIndex], quadItem);
|
|
22643
|
+
};
|
|
22644
|
+
const add = (item) => {
|
|
22645
|
+
const rect = normalizeRect(item);
|
|
22646
|
+
if (!rectContainsRectInclusive(root.bounds, rect)) {
|
|
22647
|
+
throw new Error("Item rectangle is outside of quadtree bounds.");
|
|
22648
|
+
}
|
|
22649
|
+
const quadItem = {
|
|
22650
|
+
item,
|
|
22651
|
+
rect,
|
|
22652
|
+
node: root,
|
|
22653
|
+
index: -1
|
|
22654
|
+
};
|
|
22655
|
+
insertIntoNode(root, quadItem);
|
|
22656
|
+
registry.set(item, quadItem);
|
|
22657
|
+
count += 1;
|
|
22658
|
+
};
|
|
22659
|
+
const remove = (x0, y0, x1, y1, item) => {
|
|
22660
|
+
const quadItem = registry.get(item);
|
|
22661
|
+
if (!quadItem) {
|
|
22662
|
+
return false;
|
|
22663
|
+
}
|
|
22664
|
+
const rect = normalizeRect({ x0, y0, x1, y1 });
|
|
22665
|
+
if (!rectEquals(rect, quadItem.rect)) {
|
|
22666
|
+
return false;
|
|
22667
|
+
}
|
|
22668
|
+
removeQuadItem(quadItem);
|
|
22669
|
+
count -= 1;
|
|
22670
|
+
return true;
|
|
22671
|
+
};
|
|
22672
|
+
const update = (oldX0, oldY0, oldX1, oldY1, newX0, newY0, newX1, newY1, item) => {
|
|
22673
|
+
const quadItem = registry.get(item);
|
|
22674
|
+
if (!quadItem) {
|
|
22675
|
+
return false;
|
|
22676
|
+
}
|
|
22677
|
+
const currentRect = quadItem.rect;
|
|
22678
|
+
const expectedOldRect = normalizeRect({
|
|
22679
|
+
x0: oldX0,
|
|
22680
|
+
y0: oldY0,
|
|
22681
|
+
x1: oldX1,
|
|
22682
|
+
y1: oldY1
|
|
22683
|
+
});
|
|
22684
|
+
if (!rectEquals(currentRect, expectedOldRect)) {
|
|
22685
|
+
return false;
|
|
22686
|
+
}
|
|
22687
|
+
const newRect = normalizeRect({
|
|
22688
|
+
x0: newX0,
|
|
22689
|
+
y0: newY0,
|
|
22690
|
+
x1: newX1,
|
|
22691
|
+
y1: newY1
|
|
22692
|
+
});
|
|
22693
|
+
if (!rectContainsRectInclusive(root.bounds, newRect)) {
|
|
22694
|
+
throw new Error("Updated rectangle is outside of quadtree bounds.");
|
|
22695
|
+
}
|
|
22696
|
+
if (rectContainsRectInclusive(quadItem.node.looseBounds, newRect)) {
|
|
22697
|
+
quadItem.rect = newRect;
|
|
22698
|
+
reassignIfPossible(quadItem);
|
|
22699
|
+
return true;
|
|
22700
|
+
}
|
|
22701
|
+
detachFromNode(quadItem);
|
|
22702
|
+
quadItem.rect = newRect;
|
|
22703
|
+
insertIntoNode(root, quadItem);
|
|
22704
|
+
return true;
|
|
22705
|
+
};
|
|
22706
|
+
const lookup = (x0, y0, x1, y1) => {
|
|
22707
|
+
const rect = normalizeRect({ x0, y0, x1, y1 });
|
|
22708
|
+
const results = [];
|
|
22709
|
+
collectFromNode(root, rect, results);
|
|
22710
|
+
return results;
|
|
22711
|
+
};
|
|
22712
|
+
const clear = () => {
|
|
22713
|
+
root = createNode(normalizedBounds, looseness, 0);
|
|
22714
|
+
registry = /* @__PURE__ */ new WeakMap();
|
|
22715
|
+
count = 0;
|
|
22716
|
+
};
|
|
22717
|
+
const collectFromNode = (node, rect, results) => {
|
|
22718
|
+
if (!rectsOverlapInclusive(node.looseBounds, rect)) {
|
|
22719
|
+
return;
|
|
22720
|
+
}
|
|
22721
|
+
for (const quadItem of node.items) {
|
|
22722
|
+
if (rectsOverlapInclusive(quadItem.rect, rect)) {
|
|
22723
|
+
results.push(quadItem.item);
|
|
22724
|
+
}
|
|
22725
|
+
}
|
|
22726
|
+
if (!node.children) {
|
|
22727
|
+
return;
|
|
22728
|
+
}
|
|
22729
|
+
for (const child of node.children) {
|
|
22730
|
+
collectFromNode(child, rect, results);
|
|
22731
|
+
}
|
|
22732
|
+
};
|
|
22733
|
+
const findChildIndex = (children, rect) => {
|
|
22734
|
+
for (let i = 0; i < children.length; i += 1) {
|
|
22735
|
+
const child = children[i];
|
|
22736
|
+
if (rectContainsRectInclusive(child.looseBounds, rect)) {
|
|
22737
|
+
return i;
|
|
22738
|
+
}
|
|
22739
|
+
}
|
|
22740
|
+
return -1;
|
|
22741
|
+
};
|
|
22742
|
+
const subdivide = (node) => {
|
|
22743
|
+
if (node.children) {
|
|
22744
|
+
return;
|
|
22745
|
+
}
|
|
22746
|
+
const { bounds } = node;
|
|
22747
|
+
const splitX = bounds.x0 + (bounds.x1 - bounds.x0) / 2;
|
|
22748
|
+
const splitY = bounds.y0 + (bounds.y1 - bounds.y0) / 2;
|
|
22749
|
+
const childrenBounds = [
|
|
22750
|
+
normalizeRect({ x0: bounds.x0, y0: bounds.y0, x1: splitX, y1: splitY }),
|
|
22751
|
+
normalizeRect({ x0: splitX, y0: bounds.y0, x1: bounds.x1, y1: splitY }),
|
|
22752
|
+
normalizeRect({ x0: bounds.x0, y0: splitY, x1: splitX, y1: bounds.y1 }),
|
|
22753
|
+
normalizeRect({ x0: splitX, y0: splitY, x1: bounds.x1, y1: bounds.y1 })
|
|
22754
|
+
];
|
|
22755
|
+
node.children = childrenBounds.map(
|
|
22756
|
+
(childBounds) => createNode(childBounds, looseness, node.depth + 1)
|
|
22757
|
+
);
|
|
22758
|
+
};
|
|
22759
|
+
return {
|
|
22760
|
+
get size() {
|
|
22761
|
+
return count;
|
|
22762
|
+
},
|
|
22763
|
+
add,
|
|
22764
|
+
remove,
|
|
22765
|
+
update,
|
|
22766
|
+
lookup,
|
|
22767
|
+
clear
|
|
22768
|
+
};
|
|
22769
|
+
};
|
|
22770
|
+
const DEFAULT_ANCHOR = { x: 0, y: 0 };
|
|
22771
|
+
const DEFAULT_AUTO_ROTATION_MIN_DISTANCE_METERS = 20;
|
|
22772
|
+
const DEFAULT_IMAGE_OFFSET = {
|
|
22773
|
+
offsetMeters: 0,
|
|
22774
|
+
offsetDeg: 0
|
|
22775
|
+
};
|
|
22776
|
+
const HIT_TEST_QUERY_RADIUS_PIXELS = 32;
|
|
22777
|
+
const MIN_CLIP_W = 1e-6;
|
|
22778
|
+
const MIN_CLIP_Z_EPSILON = 1e-7;
|
|
22779
|
+
const EPS_NDC = 1e-6;
|
|
22780
|
+
const ORDER_MAX = 16;
|
|
22781
|
+
const ORDER_BUCKET = 16;
|
|
22782
|
+
const MIN_FILTER_VALUES = [
|
|
22783
|
+
"nearest",
|
|
22784
|
+
"linear",
|
|
22785
|
+
"nearest-mipmap-nearest",
|
|
22786
|
+
"nearest-mipmap-linear",
|
|
22787
|
+
"linear-mipmap-nearest",
|
|
22788
|
+
"linear-mipmap-linear"
|
|
22789
|
+
];
|
|
22790
|
+
const MAG_FILTER_VALUES = [
|
|
22791
|
+
"nearest",
|
|
22792
|
+
"linear"
|
|
22793
|
+
];
|
|
22794
|
+
const MIPMAP_MIN_FILTERS = /* @__PURE__ */ new Set([
|
|
22795
|
+
"nearest-mipmap-nearest",
|
|
22796
|
+
"nearest-mipmap-linear",
|
|
22797
|
+
"linear-mipmap-nearest",
|
|
22798
|
+
"linear-mipmap-linear"
|
|
22799
|
+
]);
|
|
22800
|
+
const filterRequiresMipmaps = (filter) => MIPMAP_MIN_FILTERS.has(filter);
|
|
22801
|
+
const resolveTextureFilteringOptions = (options) => {
|
|
22802
|
+
var _a, _b;
|
|
22803
|
+
const minCandidate = options == null ? void 0 : options.minFilter;
|
|
22804
|
+
const minFilter = MIN_FILTER_VALUES.includes(
|
|
22805
|
+
minCandidate
|
|
22806
|
+
) ? minCandidate : DEFAULT_TEXTURE_FILTERING_OPTIONS.minFilter;
|
|
22807
|
+
const magCandidate = options == null ? void 0 : options.magFilter;
|
|
22808
|
+
const magFilter = MAG_FILTER_VALUES.includes(
|
|
22809
|
+
magCandidate
|
|
22810
|
+
) ? magCandidate : DEFAULT_TEXTURE_FILTERING_OPTIONS.magFilter;
|
|
22811
|
+
let generateMipmaps = (_a = options == null ? void 0 : options.generateMipmaps) != null ? _a : DEFAULT_TEXTURE_FILTERING_OPTIONS.generateMipmaps;
|
|
22812
|
+
if (filterRequiresMipmaps(minFilter)) {
|
|
22813
|
+
generateMipmaps = true;
|
|
22814
|
+
}
|
|
22815
|
+
let maxAnisotropy = (_b = options == null ? void 0 : options.maxAnisotropy) != null ? _b : DEFAULT_TEXTURE_FILTERING_OPTIONS.maxAnisotropy;
|
|
22816
|
+
if (!Number.isFinite(maxAnisotropy) || maxAnisotropy < 1) {
|
|
22817
|
+
maxAnisotropy = 1;
|
|
22818
|
+
}
|
|
22819
|
+
return {
|
|
22820
|
+
minFilter,
|
|
22821
|
+
magFilter,
|
|
22822
|
+
generateMipmaps,
|
|
22823
|
+
maxAnisotropy
|
|
22824
|
+
};
|
|
22825
|
+
};
|
|
22826
|
+
const ANISOTROPY_EXTENSION_NAMES = [
|
|
22827
|
+
"EXT_texture_filter_anisotropic",
|
|
22828
|
+
"WEBKIT_EXT_texture_filter_anisotropic",
|
|
22829
|
+
"MOZ_EXT_texture_filter_anisotropic"
|
|
22830
|
+
];
|
|
22831
|
+
const resolveAnisotropyExtension = (glContext) => {
|
|
22832
|
+
for (const name of ANISOTROPY_EXTENSION_NAMES) {
|
|
22833
|
+
const extension = glContext.getExtension(name);
|
|
22834
|
+
if (extension) {
|
|
22835
|
+
return extension;
|
|
22836
|
+
}
|
|
22837
|
+
}
|
|
22838
|
+
return null;
|
|
22839
|
+
};
|
|
22840
|
+
const isPowerOfTwo = (value) => value > 0 && (value & value - 1) === 0;
|
|
22841
|
+
const resolveGlMinFilter = (glContext, filter) => {
|
|
22842
|
+
switch (filter) {
|
|
22843
|
+
case "nearest":
|
|
22844
|
+
return glContext.NEAREST;
|
|
22845
|
+
case "nearest-mipmap-nearest":
|
|
22846
|
+
return glContext.NEAREST_MIPMAP_NEAREST;
|
|
22847
|
+
case "nearest-mipmap-linear":
|
|
22848
|
+
return glContext.NEAREST_MIPMAP_LINEAR;
|
|
22849
|
+
case "linear-mipmap-nearest":
|
|
22850
|
+
return glContext.LINEAR_MIPMAP_NEAREST;
|
|
22851
|
+
case "linear-mipmap-linear":
|
|
22852
|
+
return glContext.LINEAR_MIPMAP_LINEAR;
|
|
22853
|
+
case "linear":
|
|
22854
|
+
default:
|
|
22855
|
+
return glContext.LINEAR;
|
|
22856
|
+
}
|
|
22857
|
+
};
|
|
22858
|
+
const resolveGlMagFilter = (glContext, filter) => {
|
|
22859
|
+
switch (filter) {
|
|
22860
|
+
case "nearest":
|
|
22861
|
+
return glContext.NEAREST;
|
|
22862
|
+
case "linear":
|
|
22863
|
+
default:
|
|
22864
|
+
return glContext.LINEAR;
|
|
22865
|
+
}
|
|
22866
|
+
};
|
|
22867
|
+
const calculatePerspectiveRatio = (mapInstance, location2, cachedMercator) => {
|
|
22868
|
+
var _a, _b, _c;
|
|
22869
|
+
const transform = mapInstance.transform;
|
|
22870
|
+
if (!transform) {
|
|
22871
|
+
return 1;
|
|
22872
|
+
}
|
|
22873
|
+
const mercatorMatrix = (_a = transform.mercatorMatrix) != null ? _a : transform._mercatorMatrix;
|
|
22111
22874
|
const cameraToCenterDistance = transform.cameraToCenterDistance;
|
|
22112
22875
|
if (!mercatorMatrix || typeof cameraToCenterDistance !== "number" || !Number.isFinite(cameraToCenterDistance)) {
|
|
22113
22876
|
return 1;
|
|
22114
22877
|
}
|
|
22115
22878
|
try {
|
|
22116
|
-
const mercator = maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
22879
|
+
const mercator = cachedMercator != null ? cachedMercator : maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
22117
22880
|
{ lng: location2.lng, lat: location2.lat },
|
|
22118
22881
|
(_b = location2.z) != null ? _b : 0
|
|
22119
22882
|
);
|
|
@@ -22222,14 +22985,14 @@ const applyAutoRotation = (sprite, nextLocation) => {
|
|
|
22222
22985
|
return false;
|
|
22223
22986
|
}
|
|
22224
22987
|
const resolvedAngleRaw = isFiniteNumber(bearingDeg) ? bearingDeg : sprite.lastAutoRotationAngleDeg;
|
|
22225
|
-
const resolvedAngle =
|
|
22988
|
+
const resolvedAngle = normalizeAngleDeg(resolvedAngleRaw);
|
|
22226
22989
|
sprite.images.forEach((orderMap) => {
|
|
22227
22990
|
orderMap.forEach((image) => {
|
|
22228
22991
|
if (!image.autoRotation) {
|
|
22229
22992
|
return;
|
|
22230
22993
|
}
|
|
22231
22994
|
image.resolvedBaseRotateDeg = resolvedAngle;
|
|
22232
|
-
|
|
22995
|
+
syncImageRotationChannel(image);
|
|
22233
22996
|
});
|
|
22234
22997
|
});
|
|
22235
22998
|
sprite.lastAutoRotationLocation = cloneSpriteLocation(nextLocation);
|
|
@@ -22246,10 +23009,59 @@ const QUAD_VERTEX_COUNT = 6;
|
|
|
22246
23009
|
const VERTEX_SHADER_SOURCE = `
|
|
22247
23010
|
attribute vec4 a_position;
|
|
22248
23011
|
attribute vec2 a_uv;
|
|
23012
|
+
uniform vec2 u_screenToClipScale;
|
|
23013
|
+
uniform vec2 u_screenToClipOffset;
|
|
23014
|
+
uniform float u_billboardMode;
|
|
23015
|
+
uniform float u_surfaceMode;
|
|
23016
|
+
uniform vec2 u_billboardCenter;
|
|
23017
|
+
uniform vec2 u_billboardHalfSize;
|
|
23018
|
+
uniform vec2 u_billboardAnchor;
|
|
23019
|
+
uniform vec2 u_billboardSinCos;
|
|
23020
|
+
uniform float u_surfaceClipEnabled;
|
|
23021
|
+
uniform vec4 u_surfaceClipCenter;
|
|
23022
|
+
uniform vec4 u_surfaceClipBasisEast;
|
|
23023
|
+
uniform vec4 u_surfaceClipBasisNorth;
|
|
23024
|
+
uniform float u_surfaceDepthBias;
|
|
22249
23025
|
varying vec2 v_uv;
|
|
23026
|
+
vec2 computeBillboardCorner(vec2 uv) {
|
|
23027
|
+
vec2 base = vec2(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0);
|
|
23028
|
+
vec2 anchorShift = vec2(u_billboardAnchor.x * u_billboardHalfSize.x, u_billboardAnchor.y * u_billboardHalfSize.y);
|
|
23029
|
+
vec2 shifted = vec2(base.x * u_billboardHalfSize.x, base.y * u_billboardHalfSize.y) - anchorShift;
|
|
23030
|
+
float sinR = u_billboardSinCos.x;
|
|
23031
|
+
float cosR = u_billboardSinCos.y;
|
|
23032
|
+
vec2 rotated = vec2(
|
|
23033
|
+
shifted.x * cosR - shifted.y * sinR,
|
|
23034
|
+
shifted.x * sinR + shifted.y * cosR
|
|
23035
|
+
);
|
|
23036
|
+
return vec2(
|
|
23037
|
+
u_billboardCenter.x + rotated.x,
|
|
23038
|
+
u_billboardCenter.y - rotated.y
|
|
23039
|
+
);
|
|
23040
|
+
}
|
|
23041
|
+
vec4 computeSurfaceCorner(vec2 corner) {
|
|
23042
|
+
if (u_surfaceClipEnabled < 0.5) {
|
|
23043
|
+
return vec4(0.0, 0.0, 0.0, 1.0);
|
|
23044
|
+
}
|
|
23045
|
+
vec4 clip = u_surfaceClipCenter
|
|
23046
|
+
+ (corner.x * u_surfaceClipBasisEast)
|
|
23047
|
+
+ (corner.y * u_surfaceClipBasisNorth);
|
|
23048
|
+
clip.z += u_surfaceDepthBias * clip.w;
|
|
23049
|
+
return clip;
|
|
23050
|
+
}
|
|
22250
23051
|
void main() {
|
|
22251
23052
|
v_uv = a_uv;
|
|
22252
|
-
|
|
23053
|
+
vec4 position;
|
|
23054
|
+
if (u_billboardMode > 0.5) {
|
|
23055
|
+
vec2 screenPosition = computeBillboardCorner(a_uv);
|
|
23056
|
+
position = vec4(screenPosition, 0.0, 1.0);
|
|
23057
|
+
} else if (u_surfaceMode > 0.5) {
|
|
23058
|
+
vec2 baseCorner = vec2(a_position.x, a_position.y);
|
|
23059
|
+
position = computeSurfaceCorner(baseCorner);
|
|
23060
|
+
} else {
|
|
23061
|
+
position = a_position;
|
|
23062
|
+
}
|
|
23063
|
+
position.xy = position.xy * u_screenToClipScale + u_screenToClipOffset;
|
|
23064
|
+
gl_Position = position;
|
|
22253
23065
|
}
|
|
22254
23066
|
`;
|
|
22255
23067
|
const FRAGMENT_SHADER_SOURCE = `
|
|
@@ -22268,6 +23080,175 @@ const INITIAL_QUAD_VERTICES = new Float32Array(
|
|
|
22268
23080
|
const QUAD_VERTEX_SCRATCH = new Float32Array(
|
|
22269
23081
|
QUAD_VERTEX_COUNT * VERTEX_COMPONENT_COUNT
|
|
22270
23082
|
);
|
|
23083
|
+
const DEBUG_OUTLINE_VERTEX_SHADER_SOURCE = `
|
|
23084
|
+
attribute vec4 a_position;
|
|
23085
|
+
uniform vec2 u_screenToClipScale;
|
|
23086
|
+
uniform vec2 u_screenToClipOffset;
|
|
23087
|
+
void main() {
|
|
23088
|
+
vec4 position = a_position;
|
|
23089
|
+
position.xy = position.xy * u_screenToClipScale + u_screenToClipOffset;
|
|
23090
|
+
gl_Position = position;
|
|
23091
|
+
}
|
|
23092
|
+
`;
|
|
23093
|
+
const DEBUG_OUTLINE_FRAGMENT_SHADER_SOURCE = `
|
|
23094
|
+
precision mediump float;
|
|
23095
|
+
uniform vec4 u_color;
|
|
23096
|
+
void main() {
|
|
23097
|
+
gl_FragColor = u_color;
|
|
23098
|
+
}
|
|
23099
|
+
`;
|
|
23100
|
+
const DEBUG_OUTLINE_VERTEX_COUNT = 4;
|
|
23101
|
+
const DEBUG_OUTLINE_POSITION_COMPONENT_COUNT = 4;
|
|
23102
|
+
const DEBUG_OUTLINE_VERTEX_STRIDE = DEBUG_OUTLINE_POSITION_COMPONENT_COUNT * FLOAT_SIZE;
|
|
23103
|
+
const DEBUG_OUTLINE_VERTEX_SCRATCH = new Float32Array(
|
|
23104
|
+
DEBUG_OUTLINE_VERTEX_COUNT * DEBUG_OUTLINE_POSITION_COMPONENT_COUNT
|
|
23105
|
+
);
|
|
23106
|
+
const DEBUG_OUTLINE_COLOR = [
|
|
23107
|
+
1,
|
|
23108
|
+
0,
|
|
23109
|
+
0,
|
|
23110
|
+
1
|
|
23111
|
+
];
|
|
23112
|
+
const DEBUG_OUTLINE_CORNER_ORDER = [0, 1, 3, 2];
|
|
23113
|
+
const BILLBOARD_BASE_CORNERS = [
|
|
23114
|
+
[-1, 1],
|
|
23115
|
+
[1, 1],
|
|
23116
|
+
[-1, -1],
|
|
23117
|
+
[1, -1]
|
|
23118
|
+
];
|
|
23119
|
+
const SURFACE_BASE_CORNERS = [
|
|
23120
|
+
[-1, 1],
|
|
23121
|
+
[1, 1],
|
|
23122
|
+
[-1, -1],
|
|
23123
|
+
[1, -1]
|
|
23124
|
+
];
|
|
23125
|
+
const computeBillboardCornersShaderModel = ({
|
|
23126
|
+
centerX,
|
|
23127
|
+
centerY,
|
|
23128
|
+
halfWidth,
|
|
23129
|
+
halfHeight,
|
|
23130
|
+
anchor,
|
|
23131
|
+
rotationDeg
|
|
23132
|
+
}) => {
|
|
23133
|
+
var _a, _b;
|
|
23134
|
+
const anchorX = (_a = anchor == null ? void 0 : anchor.x) != null ? _a : 0;
|
|
23135
|
+
const anchorY = (_b = anchor == null ? void 0 : anchor.y) != null ? _b : 0;
|
|
23136
|
+
const rad = -rotationDeg * DEG2RAD;
|
|
23137
|
+
const cosR = Math.cos(rad);
|
|
23138
|
+
const sinR = Math.sin(rad);
|
|
23139
|
+
return BILLBOARD_BASE_CORNERS.map(([cornerXNorm, cornerYNorm], index) => {
|
|
23140
|
+
const cornerX = cornerXNorm * halfWidth;
|
|
23141
|
+
const cornerY = cornerYNorm * halfHeight;
|
|
23142
|
+
const shiftedX = cornerX - anchorX * halfWidth;
|
|
23143
|
+
const shiftedY = cornerY - anchorY * halfHeight;
|
|
23144
|
+
const rotatedX = shiftedX * cosR - shiftedY * sinR;
|
|
23145
|
+
const rotatedY = shiftedX * sinR + shiftedY * cosR;
|
|
23146
|
+
const [u, v] = UV_CORNERS[index];
|
|
23147
|
+
return {
|
|
23148
|
+
x: centerX + rotatedX,
|
|
23149
|
+
y: centerY - rotatedY,
|
|
23150
|
+
u,
|
|
23151
|
+
v
|
|
23152
|
+
};
|
|
23153
|
+
});
|
|
23154
|
+
};
|
|
23155
|
+
const calculateWorldToMercatorScale = (base, altitudeMeters) => {
|
|
23156
|
+
const origin = maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
23157
|
+
{ lng: base.lng, lat: base.lat },
|
|
23158
|
+
altitudeMeters
|
|
23159
|
+
);
|
|
23160
|
+
const eastLngLat = applySurfaceDisplacement(base.lng, base.lat, 1, 0);
|
|
23161
|
+
const eastCoord = maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
23162
|
+
{ lng: eastLngLat.lng, lat: eastLngLat.lat },
|
|
23163
|
+
altitudeMeters
|
|
23164
|
+
);
|
|
23165
|
+
const northLngLat = applySurfaceDisplacement(base.lng, base.lat, 0, 1);
|
|
23166
|
+
const northCoord = maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
23167
|
+
{ lng: northLngLat.lng, lat: northLngLat.lat },
|
|
23168
|
+
altitudeMeters
|
|
23169
|
+
);
|
|
23170
|
+
return {
|
|
23171
|
+
east: eastCoord.x - origin.x,
|
|
23172
|
+
north: northCoord.y - origin.y
|
|
23173
|
+
};
|
|
23174
|
+
};
|
|
23175
|
+
const prepareSurfaceShaderInputs = (params) => {
|
|
23176
|
+
var _a, _b;
|
|
23177
|
+
const {
|
|
23178
|
+
baseLngLat,
|
|
23179
|
+
worldWidthMeters,
|
|
23180
|
+
worldHeightMeters,
|
|
23181
|
+
anchor,
|
|
23182
|
+
totalRotateDeg,
|
|
23183
|
+
offsetMeters,
|
|
23184
|
+
displacedCenter,
|
|
23185
|
+
altitudeMeters,
|
|
23186
|
+
depthBiasNdc,
|
|
23187
|
+
scaleAdjustment,
|
|
23188
|
+
centerDisplacement
|
|
23189
|
+
} = params;
|
|
23190
|
+
const halfSizeMeters = {
|
|
23191
|
+
east: worldWidthMeters / 2,
|
|
23192
|
+
north: worldHeightMeters / 2
|
|
23193
|
+
};
|
|
23194
|
+
const rotationRad = -totalRotateDeg * DEG2RAD;
|
|
23195
|
+
const sinR = Math.sin(rotationRad);
|
|
23196
|
+
const cosR = Math.cos(rotationRad);
|
|
23197
|
+
const mercatorCenter = maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
23198
|
+
{ lng: displacedCenter.lng, lat: displacedCenter.lat },
|
|
23199
|
+
altitudeMeters
|
|
23200
|
+
);
|
|
23201
|
+
const worldToMercatorScale = calculateWorldToMercatorScale(
|
|
23202
|
+
displacedCenter,
|
|
23203
|
+
altitudeMeters
|
|
23204
|
+
);
|
|
23205
|
+
const cornerModel = computeSurfaceCornerShaderModel({
|
|
23206
|
+
baseLngLat,
|
|
23207
|
+
worldWidthMeters,
|
|
23208
|
+
worldHeightMeters,
|
|
23209
|
+
anchor,
|
|
23210
|
+
totalRotateDeg,
|
|
23211
|
+
offsetMeters
|
|
23212
|
+
});
|
|
23213
|
+
return {
|
|
23214
|
+
mercatorCenter: {
|
|
23215
|
+
x: mercatorCenter.x,
|
|
23216
|
+
y: mercatorCenter.y,
|
|
23217
|
+
z: (_a = mercatorCenter.z) != null ? _a : 0
|
|
23218
|
+
},
|
|
23219
|
+
worldToMercatorScale,
|
|
23220
|
+
halfSizeMeters,
|
|
23221
|
+
anchor,
|
|
23222
|
+
offsetMeters: {
|
|
23223
|
+
east: offsetMeters.east,
|
|
23224
|
+
north: offsetMeters.north
|
|
23225
|
+
},
|
|
23226
|
+
sinCos: { sin: sinR, cos: cosR },
|
|
23227
|
+
totalRotateDeg,
|
|
23228
|
+
depthBiasNdc,
|
|
23229
|
+
centerDisplacement: {
|
|
23230
|
+
east: centerDisplacement.east,
|
|
23231
|
+
north: centerDisplacement.north
|
|
23232
|
+
},
|
|
23233
|
+
baseLngLat,
|
|
23234
|
+
displacedCenter: {
|
|
23235
|
+
lng: displacedCenter.lng,
|
|
23236
|
+
lat: displacedCenter.lat,
|
|
23237
|
+
z: (_b = displacedCenter.z) != null ? _b : altitudeMeters
|
|
23238
|
+
},
|
|
23239
|
+
scaleAdjustment,
|
|
23240
|
+
corners: cornerModel.map((corner) => ({
|
|
23241
|
+
east: corner.east,
|
|
23242
|
+
north: corner.north,
|
|
23243
|
+
lng: corner.lng,
|
|
23244
|
+
lat: corner.lat
|
|
23245
|
+
})),
|
|
23246
|
+
clipCenter: { x: 0, y: 0, z: 0, w: 1 },
|
|
23247
|
+
clipBasisEast: { x: 0, y: 0, z: 0, w: 0 },
|
|
23248
|
+
clipBasisNorth: { x: 0, y: 0, z: 0, w: 0 },
|
|
23249
|
+
clipCorners: []
|
|
23250
|
+
};
|
|
23251
|
+
};
|
|
22271
23252
|
const compileShader = (glContext, type, source) => {
|
|
22272
23253
|
var _a;
|
|
22273
23254
|
const shader = glContext.createShader(type);
|
|
@@ -22665,23 +23646,6 @@ const cloneOffset = (offset) => {
|
|
|
22665
23646
|
offsetDeg: offset.offsetDeg
|
|
22666
23647
|
};
|
|
22667
23648
|
};
|
|
22668
|
-
const updateImageDisplayedRotation = (image, optionsOverride) => {
|
|
22669
|
-
const targetAngle = normaliseAngleDeg(
|
|
22670
|
-
image.resolvedBaseRotateDeg + image.rotateDeg
|
|
22671
|
-
);
|
|
22672
|
-
const currentAngle = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : targetAngle;
|
|
22673
|
-
const options = optionsOverride === void 0 ? image.rotationInterpolationOptions : optionsOverride;
|
|
22674
|
-
const { nextAngleDeg, interpolationState } = resolveRotationTarget({
|
|
22675
|
-
currentAngleDeg: currentAngle,
|
|
22676
|
-
targetAngleDeg: targetAngle,
|
|
22677
|
-
options: options != null ? options : void 0
|
|
22678
|
-
});
|
|
22679
|
-
image.displayedRotateDeg = nextAngleDeg;
|
|
22680
|
-
image.rotationInterpolationState = interpolationState;
|
|
22681
|
-
if (!interpolationState) {
|
|
22682
|
-
image.displayedRotateDeg = targetAngle;
|
|
22683
|
-
}
|
|
22684
|
-
};
|
|
22685
23649
|
const cloneInterpolationOptions = (options) => {
|
|
22686
23650
|
return {
|
|
22687
23651
|
mode: options.mode,
|
|
@@ -22689,40 +23653,40 @@ const cloneInterpolationOptions = (options) => {
|
|
|
22689
23653
|
easing: options.easing
|
|
22690
23654
|
};
|
|
22691
23655
|
};
|
|
22692
|
-
const cloneNumericInterpolationOptions = (options) => {
|
|
22693
|
-
return {
|
|
22694
|
-
durationMs: options.durationMs,
|
|
22695
|
-
easing: options.easing
|
|
22696
|
-
};
|
|
22697
|
-
};
|
|
22698
23656
|
const createImageStateFromInit = (imageInit, subLayer, order) => {
|
|
22699
23657
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
22700
23658
|
const mode = (_a = imageInit.mode) != null ? _a : "surface";
|
|
22701
23659
|
const autoRotationDefault = mode === "surface";
|
|
23660
|
+
const initialOffset = cloneOffset(imageInit.offset);
|
|
23661
|
+
const initialRotateDeg = normalizeAngleDeg((_b = imageInit.rotateDeg) != null ? _b : 0);
|
|
22702
23662
|
const state = {
|
|
22703
23663
|
subLayer,
|
|
22704
23664
|
order,
|
|
22705
23665
|
imageId: imageInit.imageId,
|
|
22706
23666
|
mode,
|
|
22707
|
-
opacity: (
|
|
22708
|
-
scale: (
|
|
23667
|
+
opacity: (_c = imageInit.opacity) != null ? _c : 1,
|
|
23668
|
+
scale: (_d = imageInit.scale) != null ? _d : 1,
|
|
22709
23669
|
anchor: cloneAnchor(imageInit.anchor),
|
|
22710
|
-
offset:
|
|
22711
|
-
rotateDeg: (
|
|
22712
|
-
displayedRotateDeg:
|
|
23670
|
+
offset: initialOffset,
|
|
23671
|
+
rotateDeg: (_e = imageInit.rotateDeg) != null ? _e : 0,
|
|
23672
|
+
displayedRotateDeg: initialRotateDeg,
|
|
22713
23673
|
autoRotation: (_f = imageInit.autoRotation) != null ? _f : autoRotationDefault,
|
|
22714
23674
|
autoRotationMinDistanceMeters: (_g = imageInit.autoRotationMinDistanceMeters) != null ? _g : DEFAULT_AUTO_ROTATION_MIN_DISTANCE_METERS,
|
|
22715
23675
|
resolvedBaseRotateDeg: 0,
|
|
22716
23676
|
originLocation: cloneOriginLocation(imageInit.originLocation),
|
|
22717
23677
|
rotationInterpolationState: null,
|
|
22718
23678
|
rotationInterpolationOptions: null,
|
|
22719
|
-
|
|
23679
|
+
offsetDegInterpolationState: null,
|
|
23680
|
+
offsetMetersInterpolationState: null,
|
|
23681
|
+
lastCommandRotateDeg: initialRotateDeg,
|
|
23682
|
+
lastCommandOffsetDeg: initialOffset.offsetDeg,
|
|
23683
|
+
lastCommandOffsetMeters: initialOffset.offsetMeters
|
|
22720
23684
|
};
|
|
22721
|
-
const rotateInitOption = (_i = (_h = imageInit.
|
|
23685
|
+
const rotateInitOption = (_i = (_h = imageInit.interpolation) == null ? void 0 : _h.rotateDeg) != null ? _i : null;
|
|
22722
23686
|
if (rotateInitOption) {
|
|
22723
|
-
state.rotationInterpolationOptions =
|
|
23687
|
+
state.rotationInterpolationOptions = cloneInterpolationOptions(rotateInitOption);
|
|
22724
23688
|
}
|
|
22725
|
-
|
|
23689
|
+
syncImageRotationChannel(state);
|
|
22726
23690
|
return state;
|
|
22727
23691
|
};
|
|
22728
23692
|
const createSpriteLayer = (options) => {
|
|
@@ -22732,6 +23696,7 @@ const createSpriteLayer = (options) => {
|
|
|
22732
23696
|
const resolvedTextureFiltering = resolveTextureFilteringOptions(
|
|
22733
23697
|
options == null ? void 0 : options.textureFiltering
|
|
22734
23698
|
);
|
|
23699
|
+
const showDebugBounds = (options == null ? void 0 : options.showDebugBounds) === true;
|
|
22735
23700
|
let gl = null;
|
|
22736
23701
|
let map = null;
|
|
22737
23702
|
let program = null;
|
|
@@ -22740,8 +23705,27 @@ const createSpriteLayer = (options) => {
|
|
|
22740
23705
|
let attribUvLocation = -1;
|
|
22741
23706
|
let uniformTextureLocation = null;
|
|
22742
23707
|
let uniformOpacityLocation = null;
|
|
23708
|
+
let uniformScreenToClipScaleLocation = null;
|
|
23709
|
+
let uniformScreenToClipOffsetLocation = null;
|
|
23710
|
+
let uniformBillboardModeLocation = null;
|
|
23711
|
+
let uniformBillboardCenterLocation = null;
|
|
23712
|
+
let uniformBillboardHalfSizeLocation = null;
|
|
23713
|
+
let uniformBillboardAnchorLocation = null;
|
|
23714
|
+
let uniformBillboardSinCosLocation = null;
|
|
23715
|
+
let uniformSurfaceModeLocation = null;
|
|
23716
|
+
let uniformSurfaceDepthBiasLocation = null;
|
|
23717
|
+
let uniformSurfaceClipEnabledLocation = null;
|
|
23718
|
+
let uniformSurfaceClipCenterLocation = null;
|
|
23719
|
+
let uniformSurfaceClipBasisEastLocation = null;
|
|
23720
|
+
let uniformSurfaceClipBasisNorthLocation = null;
|
|
22743
23721
|
let anisotropyExtension = null;
|
|
22744
23722
|
let maxSupportedAnisotropy = 1;
|
|
23723
|
+
let debugProgram = null;
|
|
23724
|
+
let debugVertexBuffer = null;
|
|
23725
|
+
let debugAttribPositionLocation = -1;
|
|
23726
|
+
let debugUniformColorLocation = null;
|
|
23727
|
+
let debugUniformScreenToClipScaleLocation = null;
|
|
23728
|
+
let debugUniformScreenToClipOffsetLocation = null;
|
|
22745
23729
|
const images = /* @__PURE__ */ new Map();
|
|
22746
23730
|
const queuedTextureIds = /* @__PURE__ */ new Set();
|
|
22747
23731
|
const queueTextureUpload = (image) => {
|
|
@@ -22754,6 +23738,347 @@ const createSpriteLayer = (options) => {
|
|
|
22754
23738
|
queuedTextureIds.clear();
|
|
22755
23739
|
};
|
|
22756
23740
|
const sprites = /* @__PURE__ */ new Map();
|
|
23741
|
+
const resolveSpriteMercator = (sprite) => {
|
|
23742
|
+
var _a2;
|
|
23743
|
+
const location2 = sprite.currentLocation;
|
|
23744
|
+
const altitude = (_a2 = location2.z) != null ? _a2 : 0;
|
|
23745
|
+
if (sprite.cachedMercator && sprite.cachedMercatorLng === location2.lng && sprite.cachedMercatorLat === location2.lat && sprite.cachedMercatorZ === altitude) {
|
|
23746
|
+
return sprite.cachedMercator;
|
|
23747
|
+
}
|
|
23748
|
+
const mercator = maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
23749
|
+
{ lng: location2.lng, lat: location2.lat },
|
|
23750
|
+
altitude
|
|
23751
|
+
);
|
|
23752
|
+
sprite.cachedMercator = mercator;
|
|
23753
|
+
sprite.cachedMercatorLng = location2.lng;
|
|
23754
|
+
sprite.cachedMercatorLat = location2.lat;
|
|
23755
|
+
sprite.cachedMercatorZ = altitude;
|
|
23756
|
+
return mercator;
|
|
23757
|
+
};
|
|
23758
|
+
const HIT_TEST_WORLD_BOUNDS = {
|
|
23759
|
+
x0: -180,
|
|
23760
|
+
y0: -90,
|
|
23761
|
+
x1: 180,
|
|
23762
|
+
y1: 90
|
|
23763
|
+
};
|
|
23764
|
+
const hitTestTree = createLooseQuadTree({
|
|
23765
|
+
bounds: HIT_TEST_WORLD_BOUNDS
|
|
23766
|
+
});
|
|
23767
|
+
let hitTestTreeItems = /* @__PURE__ */ new WeakMap();
|
|
23768
|
+
let isHitTestEnabled = true;
|
|
23769
|
+
const rectFromLngLatPoints = (points) => {
|
|
23770
|
+
let minLng = Number.POSITIVE_INFINITY;
|
|
23771
|
+
let maxLng = Number.NEGATIVE_INFINITY;
|
|
23772
|
+
let minLat = Number.POSITIVE_INFINITY;
|
|
23773
|
+
let maxLat = Number.NEGATIVE_INFINITY;
|
|
23774
|
+
for (const point of points) {
|
|
23775
|
+
if (!point || !Number.isFinite(point.lng) || !Number.isFinite(point.lat)) {
|
|
23776
|
+
continue;
|
|
23777
|
+
}
|
|
23778
|
+
if (point.lng < minLng) minLng = point.lng;
|
|
23779
|
+
if (point.lng > maxLng) maxLng = point.lng;
|
|
23780
|
+
if (point.lat < minLat) minLat = point.lat;
|
|
23781
|
+
if (point.lat > maxLat) maxLat = point.lat;
|
|
23782
|
+
}
|
|
23783
|
+
if (minLng === Number.POSITIVE_INFINITY || maxLng === Number.NEGATIVE_INFINITY || minLat === Number.POSITIVE_INFINITY || maxLat === Number.NEGATIVE_INFINITY) {
|
|
23784
|
+
return null;
|
|
23785
|
+
}
|
|
23786
|
+
return {
|
|
23787
|
+
x0: Math.max(
|
|
23788
|
+
HIT_TEST_WORLD_BOUNDS.x0,
|
|
23789
|
+
Math.min(minLng, HIT_TEST_WORLD_BOUNDS.x1)
|
|
23790
|
+
),
|
|
23791
|
+
y0: Math.max(
|
|
23792
|
+
HIT_TEST_WORLD_BOUNDS.y0,
|
|
23793
|
+
Math.min(minLat, HIT_TEST_WORLD_BOUNDS.y1)
|
|
23794
|
+
),
|
|
23795
|
+
x1: Math.max(
|
|
23796
|
+
HIT_TEST_WORLD_BOUNDS.x0,
|
|
23797
|
+
Math.min(maxLng, HIT_TEST_WORLD_BOUNDS.x1)
|
|
23798
|
+
),
|
|
23799
|
+
y1: Math.max(
|
|
23800
|
+
HIT_TEST_WORLD_BOUNDS.y0,
|
|
23801
|
+
Math.min(maxLat, HIT_TEST_WORLD_BOUNDS.y1)
|
|
23802
|
+
)
|
|
23803
|
+
};
|
|
23804
|
+
};
|
|
23805
|
+
const rectFromRadiusMeters = (base, radiusMeters) => {
|
|
23806
|
+
if (!Number.isFinite(base.lng) || !Number.isFinite(base.lat) || !Number.isFinite(radiusMeters) || radiusMeters <= 0) {
|
|
23807
|
+
return null;
|
|
23808
|
+
}
|
|
23809
|
+
const cornerNE = applySurfaceDisplacement(
|
|
23810
|
+
base.lng,
|
|
23811
|
+
base.lat,
|
|
23812
|
+
radiusMeters,
|
|
23813
|
+
radiusMeters
|
|
23814
|
+
);
|
|
23815
|
+
const cornerSW = applySurfaceDisplacement(
|
|
23816
|
+
base.lng,
|
|
23817
|
+
base.lat,
|
|
23818
|
+
-radiusMeters,
|
|
23819
|
+
-radiusMeters
|
|
23820
|
+
);
|
|
23821
|
+
return rectFromLngLatPoints([cornerNE, cornerSW]);
|
|
23822
|
+
};
|
|
23823
|
+
const estimateSurfaceImageBounds = (sprite, image) => {
|
|
23824
|
+
var _a2, _b, _c, _d, _e;
|
|
23825
|
+
const mapInstance = map;
|
|
23826
|
+
if (!mapInstance) {
|
|
23827
|
+
return null;
|
|
23828
|
+
}
|
|
23829
|
+
const imageResource = images.get(image.imageId);
|
|
23830
|
+
if (!imageResource) {
|
|
23831
|
+
return null;
|
|
23832
|
+
}
|
|
23833
|
+
const baseLocation = sprite.currentLocation;
|
|
23834
|
+
const zoom = mapInstance.getZoom();
|
|
23835
|
+
const zoomScaleFactor = calculateZoomScaleFactor(zoom, resolvedScaling);
|
|
23836
|
+
const metersPerPixelAtLat = calculateMetersPerPixelAtLatitude(
|
|
23837
|
+
zoom,
|
|
23838
|
+
baseLocation.lat
|
|
23839
|
+
);
|
|
23840
|
+
if (!Number.isFinite(metersPerPixelAtLat) || metersPerPixelAtLat <= 0) {
|
|
23841
|
+
return null;
|
|
23842
|
+
}
|
|
23843
|
+
const spriteMercator = resolveSpriteMercator(sprite);
|
|
23844
|
+
const perspectiveRatio = calculatePerspectiveRatio(
|
|
23845
|
+
mapInstance,
|
|
23846
|
+
baseLocation,
|
|
23847
|
+
spriteMercator
|
|
23848
|
+
);
|
|
23849
|
+
const effectivePixelsPerMeter = calculateEffectivePixelsPerMeter(
|
|
23850
|
+
metersPerPixelAtLat,
|
|
23851
|
+
perspectiveRatio
|
|
23852
|
+
);
|
|
23853
|
+
if (!Number.isFinite(effectivePixelsPerMeter) || effectivePixelsPerMeter <= 0) {
|
|
23854
|
+
return null;
|
|
23855
|
+
}
|
|
23856
|
+
const imageScale = (_a2 = image.scale) != null ? _a2 : 1;
|
|
23857
|
+
const baseMetersPerPixel = resolvedScaling.metersPerPixel;
|
|
23858
|
+
const spriteMinPixel = resolvedScaling.spriteMinPixel;
|
|
23859
|
+
const spriteMaxPixel = resolvedScaling.spriteMaxPixel;
|
|
23860
|
+
const worldDims = calculateSurfaceWorldDimensions(
|
|
23861
|
+
imageResource.width,
|
|
23862
|
+
imageResource.height,
|
|
23863
|
+
baseMetersPerPixel,
|
|
23864
|
+
imageScale,
|
|
23865
|
+
zoomScaleFactor,
|
|
23866
|
+
{
|
|
23867
|
+
effectivePixelsPerMeter,
|
|
23868
|
+
spriteMinPixel,
|
|
23869
|
+
spriteMaxPixel
|
|
23870
|
+
}
|
|
23871
|
+
);
|
|
23872
|
+
if (worldDims.width <= 0 || worldDims.height <= 0) {
|
|
23873
|
+
return null;
|
|
23874
|
+
}
|
|
23875
|
+
const anchor = (_b = image.anchor) != null ? _b : DEFAULT_ANCHOR;
|
|
23876
|
+
const offsetDef = (_c = image.offset) != null ? _c : DEFAULT_IMAGE_OFFSET;
|
|
23877
|
+
const offsetMetersVec = calculateSurfaceOffsetMeters(
|
|
23878
|
+
offsetDef,
|
|
23879
|
+
imageScale,
|
|
23880
|
+
zoomScaleFactor,
|
|
23881
|
+
worldDims.scaleAdjustment
|
|
23882
|
+
);
|
|
23883
|
+
const totalRotateDeg = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : normalizeAngleDeg(
|
|
23884
|
+
((_d = image.resolvedBaseRotateDeg) != null ? _d : 0) + ((_e = image.rotateDeg) != null ? _e : 0)
|
|
23885
|
+
);
|
|
23886
|
+
const cornerDisplacements = calculateSurfaceCornerDisplacements({
|
|
23887
|
+
worldWidthMeters: worldDims.width,
|
|
23888
|
+
worldHeightMeters: worldDims.height,
|
|
23889
|
+
anchor,
|
|
23890
|
+
totalRotateDeg,
|
|
23891
|
+
offsetMeters: offsetMetersVec
|
|
23892
|
+
});
|
|
23893
|
+
const corners = cornerDisplacements.map(
|
|
23894
|
+
(corner) => applySurfaceDisplacement(
|
|
23895
|
+
baseLocation.lng,
|
|
23896
|
+
baseLocation.lat,
|
|
23897
|
+
corner.east,
|
|
23898
|
+
corner.north
|
|
23899
|
+
)
|
|
23900
|
+
);
|
|
23901
|
+
return rectFromLngLatPoints(corners);
|
|
23902
|
+
};
|
|
23903
|
+
const estimateBillboardImageBounds = (sprite, image) => {
|
|
23904
|
+
var _a2, _b, _c, _d;
|
|
23905
|
+
const mapInstance = map;
|
|
23906
|
+
if (!mapInstance) {
|
|
23907
|
+
return null;
|
|
23908
|
+
}
|
|
23909
|
+
const imageResource = images.get(image.imageId);
|
|
23910
|
+
if (!imageResource) {
|
|
23911
|
+
return null;
|
|
23912
|
+
}
|
|
23913
|
+
const baseLocation = sprite.currentLocation;
|
|
23914
|
+
const zoom = mapInstance.getZoom();
|
|
23915
|
+
const zoomScaleFactor = calculateZoomScaleFactor(zoom, resolvedScaling);
|
|
23916
|
+
const metersPerPixelAtLat = calculateMetersPerPixelAtLatitude(
|
|
23917
|
+
zoom,
|
|
23918
|
+
baseLocation.lat
|
|
23919
|
+
);
|
|
23920
|
+
if (!Number.isFinite(metersPerPixelAtLat) || metersPerPixelAtLat <= 0) {
|
|
23921
|
+
return null;
|
|
23922
|
+
}
|
|
23923
|
+
const spriteMercator = resolveSpriteMercator(sprite);
|
|
23924
|
+
const perspectiveRatio = calculatePerspectiveRatio(
|
|
23925
|
+
mapInstance,
|
|
23926
|
+
baseLocation,
|
|
23927
|
+
spriteMercator
|
|
23928
|
+
);
|
|
23929
|
+
const effectivePixelsPerMeter = calculateEffectivePixelsPerMeter(
|
|
23930
|
+
metersPerPixelAtLat,
|
|
23931
|
+
perspectiveRatio
|
|
23932
|
+
);
|
|
23933
|
+
if (!Number.isFinite(effectivePixelsPerMeter) || effectivePixelsPerMeter <= 0) {
|
|
23934
|
+
return null;
|
|
23935
|
+
}
|
|
23936
|
+
const baseMetersPerPixel = resolvedScaling.metersPerPixel;
|
|
23937
|
+
const spriteMinPixel = resolvedScaling.spriteMinPixel;
|
|
23938
|
+
const spriteMaxPixel = resolvedScaling.spriteMaxPixel;
|
|
23939
|
+
const imageScale = (_a2 = image.scale) != null ? _a2 : 1;
|
|
23940
|
+
const totalRotateDeg = Number.isFinite(image.displayedRotateDeg) ? image.displayedRotateDeg : normalizeAngleDeg(
|
|
23941
|
+
((_b = image.resolvedBaseRotateDeg) != null ? _b : 0) + ((_c = image.rotateDeg) != null ? _c : 0)
|
|
23942
|
+
);
|
|
23943
|
+
const pixelDims = calculateBillboardPixelDimensions(
|
|
23944
|
+
imageResource.width,
|
|
23945
|
+
imageResource.height,
|
|
23946
|
+
baseMetersPerPixel,
|
|
23947
|
+
imageScale,
|
|
23948
|
+
zoomScaleFactor,
|
|
23949
|
+
effectivePixelsPerMeter,
|
|
23950
|
+
spriteMinPixel,
|
|
23951
|
+
spriteMaxPixel
|
|
23952
|
+
);
|
|
23953
|
+
const halfWidthMeters = pixelDims.width / 2 / effectivePixelsPerMeter;
|
|
23954
|
+
const halfHeightMeters = pixelDims.height / 2 / effectivePixelsPerMeter;
|
|
23955
|
+
const anchorShift = calculateBillboardAnchorShiftPixels(
|
|
23956
|
+
pixelDims.width / 2,
|
|
23957
|
+
pixelDims.height / 2,
|
|
23958
|
+
image.anchor,
|
|
23959
|
+
totalRotateDeg
|
|
23960
|
+
);
|
|
23961
|
+
const offsetShift = calculateBillboardOffsetPixels(
|
|
23962
|
+
(_d = image.offset) != null ? _d : DEFAULT_IMAGE_OFFSET,
|
|
23963
|
+
imageScale,
|
|
23964
|
+
zoomScaleFactor,
|
|
23965
|
+
effectivePixelsPerMeter
|
|
23966
|
+
);
|
|
23967
|
+
const anchorShiftMeters = Math.hypot(anchorShift.x, anchorShift.y) / effectivePixelsPerMeter;
|
|
23968
|
+
const offsetShiftMeters = Math.hypot(offsetShift.x, offsetShift.y) / effectivePixelsPerMeter;
|
|
23969
|
+
const safetyRadius = Math.hypot(halfWidthMeters, halfHeightMeters) + anchorShiftMeters + offsetShiftMeters;
|
|
23970
|
+
return rectFromRadiusMeters(baseLocation, safetyRadius);
|
|
23971
|
+
};
|
|
23972
|
+
const estimateImageBounds = (sprite, image) => {
|
|
23973
|
+
if (image.opacity <= 0 || !sprite.isEnabled) {
|
|
23974
|
+
return null;
|
|
23975
|
+
}
|
|
23976
|
+
if (image.mode === "surface") {
|
|
23977
|
+
return estimateSurfaceImageBounds(sprite, image);
|
|
23978
|
+
}
|
|
23979
|
+
return estimateBillboardImageBounds(sprite, image);
|
|
23980
|
+
};
|
|
23981
|
+
const removeImageBoundsFromHitTestTree = (image) => {
|
|
23982
|
+
const handle = hitTestTreeItems.get(image);
|
|
23983
|
+
if (!handle) {
|
|
23984
|
+
return;
|
|
23985
|
+
}
|
|
23986
|
+
hitTestTree.remove(
|
|
23987
|
+
handle.rect.x0,
|
|
23988
|
+
handle.rect.y0,
|
|
23989
|
+
handle.rect.x1,
|
|
23990
|
+
handle.rect.y1,
|
|
23991
|
+
handle.item
|
|
23992
|
+
);
|
|
23993
|
+
hitTestTreeItems.delete(image);
|
|
23994
|
+
};
|
|
23995
|
+
const setItemRect = (item, rect) => {
|
|
23996
|
+
const mutable = item;
|
|
23997
|
+
mutable.x0 = rect.x0;
|
|
23998
|
+
mutable.y0 = rect.y0;
|
|
23999
|
+
mutable.x1 = rect.x1;
|
|
24000
|
+
mutable.y1 = rect.y1;
|
|
24001
|
+
};
|
|
24002
|
+
const registerImageBoundsInHitTestTree = (sprite, image) => {
|
|
24003
|
+
const existingHandle = hitTestTreeItems.get(image);
|
|
24004
|
+
if (!isHitTestEnabled) {
|
|
24005
|
+
if (existingHandle) {
|
|
24006
|
+
removeImageBoundsFromHitTestTree(image);
|
|
24007
|
+
}
|
|
24008
|
+
return;
|
|
24009
|
+
}
|
|
24010
|
+
const rect = estimateImageBounds(sprite, image);
|
|
24011
|
+
if (!rect) {
|
|
24012
|
+
if (existingHandle) {
|
|
24013
|
+
removeImageBoundsFromHitTestTree(image);
|
|
24014
|
+
}
|
|
24015
|
+
return;
|
|
24016
|
+
}
|
|
24017
|
+
if (!existingHandle) {
|
|
24018
|
+
const handle = {
|
|
24019
|
+
rect,
|
|
24020
|
+
item: {
|
|
24021
|
+
x0: rect.x0,
|
|
24022
|
+
y0: rect.y0,
|
|
24023
|
+
x1: rect.x1,
|
|
24024
|
+
y1: rect.y1,
|
|
24025
|
+
state: {
|
|
24026
|
+
sprite,
|
|
24027
|
+
image,
|
|
24028
|
+
drawIndex: 0
|
|
24029
|
+
}
|
|
24030
|
+
}
|
|
24031
|
+
};
|
|
24032
|
+
hitTestTree.add(handle.item);
|
|
24033
|
+
hitTestTreeItems.set(image, handle);
|
|
24034
|
+
return;
|
|
24035
|
+
}
|
|
24036
|
+
const currentRect = existingHandle.rect;
|
|
24037
|
+
const unchanged = currentRect.x0 === rect.x0 && currentRect.y0 === rect.y0 && currentRect.x1 === rect.x1 && currentRect.y1 === rect.y1;
|
|
24038
|
+
if (unchanged) {
|
|
24039
|
+
return;
|
|
24040
|
+
}
|
|
24041
|
+
const updated = hitTestTree.update(
|
|
24042
|
+
currentRect.x0,
|
|
24043
|
+
currentRect.y0,
|
|
24044
|
+
currentRect.x1,
|
|
24045
|
+
currentRect.y1,
|
|
24046
|
+
rect.x0,
|
|
24047
|
+
rect.y0,
|
|
24048
|
+
rect.x1,
|
|
24049
|
+
rect.y1,
|
|
24050
|
+
existingHandle.item
|
|
24051
|
+
);
|
|
24052
|
+
if (updated) {
|
|
24053
|
+
existingHandle.rect = rect;
|
|
24054
|
+
setItemRect(existingHandle.item, rect);
|
|
24055
|
+
return;
|
|
24056
|
+
}
|
|
24057
|
+
removeImageBoundsFromHitTestTree(image);
|
|
24058
|
+
const newHandle = {
|
|
24059
|
+
rect,
|
|
24060
|
+
item: {
|
|
24061
|
+
x0: rect.x0,
|
|
24062
|
+
y0: rect.y0,
|
|
24063
|
+
x1: rect.x1,
|
|
24064
|
+
y1: rect.y1,
|
|
24065
|
+
state: {
|
|
24066
|
+
sprite,
|
|
24067
|
+
image,
|
|
24068
|
+
drawIndex: 0
|
|
24069
|
+
}
|
|
24070
|
+
}
|
|
24071
|
+
};
|
|
24072
|
+
hitTestTree.add(newHandle.item);
|
|
24073
|
+
hitTestTreeItems.set(image, newHandle);
|
|
24074
|
+
};
|
|
24075
|
+
const refreshSpriteHitTestBounds = (sprite) => {
|
|
24076
|
+
sprite.images.forEach((orderMap) => {
|
|
24077
|
+
orderMap.forEach((image) => {
|
|
24078
|
+
registerImageBoundsInHitTestTree(sprite, image);
|
|
24079
|
+
});
|
|
24080
|
+
});
|
|
24081
|
+
};
|
|
22757
24082
|
const getImageState = (sprite, subLayer, order) => {
|
|
22758
24083
|
var _a2;
|
|
22759
24084
|
return (
|
|
@@ -22786,34 +24111,38 @@ const createSpriteLayer = (options) => {
|
|
|
22786
24111
|
return deleted;
|
|
22787
24112
|
};
|
|
22788
24113
|
const HIT_TEST_EPSILON = 1e-3;
|
|
22789
|
-
const
|
|
22790
|
-
|
|
22791
|
-
|
|
22792
|
-
|
|
22793
|
-
|
|
22794
|
-
|
|
22795
|
-
|
|
22796
|
-
|
|
22797
|
-
|
|
22798
|
-
|
|
22799
|
-
|
|
22800
|
-
|
|
22801
|
-
|
|
22802
|
-
|
|
22803
|
-
|
|
24114
|
+
const pointInRenderedQuad = (point, corners) => {
|
|
24115
|
+
let hasPositiveCross = false;
|
|
24116
|
+
let hasNegativeCross = false;
|
|
24117
|
+
for (let i = 0; i < DEBUG_OUTLINE_CORNER_ORDER.length; i++) {
|
|
24118
|
+
const currentIndex = DEBUG_OUTLINE_CORNER_ORDER[i];
|
|
24119
|
+
const nextIndex = DEBUG_OUTLINE_CORNER_ORDER[(i + 1) % DEBUG_OUTLINE_CORNER_ORDER.length];
|
|
24120
|
+
const a = corners[currentIndex];
|
|
24121
|
+
const b = corners[nextIndex];
|
|
24122
|
+
const edgeX = b.x - a.x;
|
|
24123
|
+
const edgeY = b.y - a.y;
|
|
24124
|
+
const pointX = point.x - a.x;
|
|
24125
|
+
const pointY = point.y - a.y;
|
|
24126
|
+
const cross = edgeX * pointY - edgeY * pointX;
|
|
24127
|
+
if (Math.abs(cross) <= HIT_TEST_EPSILON) {
|
|
24128
|
+
continue;
|
|
24129
|
+
}
|
|
24130
|
+
if (cross > 0) {
|
|
24131
|
+
hasPositiveCross = true;
|
|
24132
|
+
} else {
|
|
24133
|
+
hasNegativeCross = true;
|
|
24134
|
+
}
|
|
24135
|
+
if (hasPositiveCross && hasNegativeCross) {
|
|
24136
|
+
return false;
|
|
24137
|
+
}
|
|
22804
24138
|
}
|
|
22805
|
-
|
|
22806
|
-
const u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
|
22807
|
-
const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
|
22808
|
-
const w = 1 - u - v;
|
|
22809
|
-
return u >= -HIT_TEST_EPSILON && v >= -HIT_TEST_EPSILON && w >= -HIT_TEST_EPSILON;
|
|
24139
|
+
return true;
|
|
22810
24140
|
};
|
|
22811
|
-
const pointInQuad = (point, corners) => pointInTriangle(point, corners[0], corners[1], corners[2]) || pointInTriangle(point, corners[0], corners[2], corners[3]);
|
|
22812
24141
|
const isPointInsideHitEntry = (entry, point) => {
|
|
22813
24142
|
if (point.x < entry.minX - HIT_TEST_EPSILON || point.x > entry.maxX + HIT_TEST_EPSILON || point.y < entry.minY - HIT_TEST_EPSILON || point.y > entry.maxY + HIT_TEST_EPSILON) {
|
|
22814
24143
|
return false;
|
|
22815
24144
|
}
|
|
22816
|
-
return
|
|
24145
|
+
return pointInRenderedQuad(point, entry.corners);
|
|
22817
24146
|
};
|
|
22818
24147
|
const buildSortedSubLayerBuckets = (entries) => {
|
|
22819
24148
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -22872,7 +24201,7 @@ const createSpriteLayer = (options) => {
|
|
|
22872
24201
|
baseY = refCenter.y;
|
|
22873
24202
|
}
|
|
22874
24203
|
}
|
|
22875
|
-
const totalRotDeg = Number.isFinite(img.displayedRotateDeg) ? img.displayedRotateDeg :
|
|
24204
|
+
const totalRotDeg = Number.isFinite(img.displayedRotateDeg) ? img.displayedRotateDeg : normalizeAngleDeg(
|
|
22876
24205
|
((_d = img.resolvedBaseRotateDeg) != null ? _d : 0) + ((_e = img.rotateDeg) != null ? _e : 0)
|
|
22877
24206
|
);
|
|
22878
24207
|
const imageScaleLocal = (_f = img.scale) != null ? _f : 1;
|
|
@@ -22955,6 +24284,7 @@ const createSpriteLayer = (options) => {
|
|
|
22955
24284
|
};
|
|
22956
24285
|
const renderTargetEntries = [];
|
|
22957
24286
|
const hitTestEntries = [];
|
|
24287
|
+
let hitTestEntryByImage = /* @__PURE__ */ new WeakMap();
|
|
22958
24288
|
const ensureHitTestCorners = (imageEntry) => {
|
|
22959
24289
|
if (!imageEntry.hitTestCorners) {
|
|
22960
24290
|
imageEntry.hitTestCorners = [
|
|
@@ -22966,7 +24296,10 @@ const createSpriteLayer = (options) => {
|
|
|
22966
24296
|
}
|
|
22967
24297
|
return imageEntry.hitTestCorners;
|
|
22968
24298
|
};
|
|
22969
|
-
const registerHitTestEntry = (spriteEntry, imageEntry, screenCorners) => {
|
|
24299
|
+
const registerHitTestEntry = (spriteEntry, imageEntry, screenCorners, drawIndex) => {
|
|
24300
|
+
if (!isHitTestEnabled) {
|
|
24301
|
+
return;
|
|
24302
|
+
}
|
|
22970
24303
|
const corners = screenCorners;
|
|
22971
24304
|
let minX = corners[0].x;
|
|
22972
24305
|
let maxX = corners[0].x;
|
|
@@ -22979,7 +24312,7 @@ const createSpriteLayer = (options) => {
|
|
|
22979
24312
|
if (corner.y < minY) minY = corner.y;
|
|
22980
24313
|
if (corner.y > maxY) maxY = corner.y;
|
|
22981
24314
|
}
|
|
22982
|
-
|
|
24315
|
+
const entry = {
|
|
22983
24316
|
sprite: spriteEntry,
|
|
22984
24317
|
image: imageEntry,
|
|
22985
24318
|
corners,
|
|
@@ -22987,16 +24320,82 @@ const createSpriteLayer = (options) => {
|
|
|
22987
24320
|
maxX,
|
|
22988
24321
|
minY,
|
|
22989
24322
|
maxY
|
|
22990
|
-
}
|
|
24323
|
+
};
|
|
24324
|
+
hitTestEntries.push(entry);
|
|
24325
|
+
hitTestEntryByImage.set(imageEntry, entry);
|
|
24326
|
+
const handle = hitTestTreeItems.get(imageEntry);
|
|
24327
|
+
if (handle) {
|
|
24328
|
+
handle.item.state.drawIndex = drawIndex;
|
|
24329
|
+
}
|
|
22991
24330
|
};
|
|
22992
|
-
const
|
|
24331
|
+
const findTopmostHitEntryLinear = (point) => {
|
|
22993
24332
|
for (let i = hitTestEntries.length - 1; i >= 0; i--) {
|
|
22994
24333
|
const entry = hitTestEntries[i];
|
|
22995
24334
|
if (isPointInsideHitEntry(entry, point)) {
|
|
22996
24335
|
return entry;
|
|
22997
24336
|
}
|
|
22998
24337
|
}
|
|
22999
|
-
return null;
|
|
24338
|
+
return null;
|
|
24339
|
+
};
|
|
24340
|
+
const findTopmostHitEntry = (point) => {
|
|
24341
|
+
if (!isHitTestEnabled) {
|
|
24342
|
+
return null;
|
|
24343
|
+
}
|
|
24344
|
+
const mapInstance = map;
|
|
24345
|
+
if (!mapInstance) {
|
|
24346
|
+
return findTopmostHitEntryLinear(point);
|
|
24347
|
+
}
|
|
24348
|
+
const centerLngLat = mapInstance.unproject([point.x, point.y]);
|
|
24349
|
+
if (!centerLngLat) {
|
|
24350
|
+
return findTopmostHitEntryLinear(point);
|
|
24351
|
+
}
|
|
24352
|
+
const searchPoints = [
|
|
24353
|
+
{ lng: centerLngLat.lng, lat: centerLngLat.lat }
|
|
24354
|
+
];
|
|
24355
|
+
const radius = HIT_TEST_QUERY_RADIUS_PIXELS;
|
|
24356
|
+
const offsets = [
|
|
24357
|
+
[point.x - radius, point.y - radius],
|
|
24358
|
+
[point.x + radius, point.y - radius],
|
|
24359
|
+
[point.x - radius, point.y + radius],
|
|
24360
|
+
[point.x + radius, point.y + radius]
|
|
24361
|
+
];
|
|
24362
|
+
for (const [x, y] of offsets) {
|
|
24363
|
+
const lngLat = mapInstance.unproject([x, y]);
|
|
24364
|
+
if (lngLat) {
|
|
24365
|
+
searchPoints.push({ lng: lngLat.lng, lat: lngLat.lat });
|
|
24366
|
+
}
|
|
24367
|
+
}
|
|
24368
|
+
const searchRect = rectFromLngLatPoints(searchPoints);
|
|
24369
|
+
if (!searchRect) {
|
|
24370
|
+
return findTopmostHitEntryLinear(point);
|
|
24371
|
+
}
|
|
24372
|
+
const candidates = hitTestTree.lookup(
|
|
24373
|
+
searchRect.x0,
|
|
24374
|
+
searchRect.y0,
|
|
24375
|
+
searchRect.x1,
|
|
24376
|
+
searchRect.y1
|
|
24377
|
+
);
|
|
24378
|
+
if (candidates.length === 0) {
|
|
24379
|
+
return findTopmostHitEntryLinear(point);
|
|
24380
|
+
}
|
|
24381
|
+
candidates.sort((a, b) => a.state.drawIndex - b.state.drawIndex);
|
|
24382
|
+
const seenImages = /* @__PURE__ */ new Set();
|
|
24383
|
+
for (let i = candidates.length - 1; i >= 0; i--) {
|
|
24384
|
+
const candidate = candidates[i];
|
|
24385
|
+
const image = candidate.state.image;
|
|
24386
|
+
if (seenImages.has(image)) {
|
|
24387
|
+
continue;
|
|
24388
|
+
}
|
|
24389
|
+
seenImages.add(image);
|
|
24390
|
+
const entry = hitTestEntryByImage.get(image);
|
|
24391
|
+
if (!entry) {
|
|
24392
|
+
continue;
|
|
24393
|
+
}
|
|
24394
|
+
if (isPointInsideHitEntry(entry, point)) {
|
|
24395
|
+
return entry;
|
|
24396
|
+
}
|
|
24397
|
+
}
|
|
24398
|
+
return findTopmostHitEntryLinear(point);
|
|
23000
24399
|
};
|
|
23001
24400
|
const eventListeners = /* @__PURE__ */ new Map();
|
|
23002
24401
|
const getListenerSet = (type) => {
|
|
@@ -23022,13 +24421,15 @@ const createSpriteLayer = (options) => {
|
|
|
23022
24421
|
};
|
|
23023
24422
|
let canvasElement = null;
|
|
23024
24423
|
const inputListenerDisposers = [];
|
|
23025
|
-
const
|
|
24424
|
+
const hasSpriteListeners = (type) => {
|
|
23026
24425
|
var _a2, _b;
|
|
23027
24426
|
return (
|
|
23028
24427
|
// Treat missing listener sets as zero, otherwise check the registered count.
|
|
23029
|
-
((_b = (_a2 = eventListeners.get(
|
|
24428
|
+
((_b = (_a2 = eventListeners.get(type)) == null ? void 0 : _a2.size) != null ? _b : 0) > 0
|
|
23030
24429
|
);
|
|
23031
24430
|
};
|
|
24431
|
+
const hasSpriteClickListeners = () => hasSpriteListeners("spriteclick");
|
|
24432
|
+
const hasSpriteHoverListeners = () => hasSpriteListeners("spritehover");
|
|
23032
24433
|
const resolveScreenPointFromEvent = (nativeEvent) => {
|
|
23033
24434
|
var _a2, _b, _c, _d;
|
|
23034
24435
|
if (!canvasElement) {
|
|
@@ -23053,20 +24454,31 @@ const createSpriteLayer = (options) => {
|
|
|
23053
24454
|
const mouseLike = nativeEvent;
|
|
23054
24455
|
return toScreenPoint(mouseLike.clientX, mouseLike.clientY);
|
|
23055
24456
|
};
|
|
24457
|
+
const resolveSpriteEventPayload = (hitEntry) => {
|
|
24458
|
+
var _a2, _b;
|
|
24459
|
+
if (!hitEntry) {
|
|
24460
|
+
return {
|
|
24461
|
+
sprite: void 0,
|
|
24462
|
+
image: void 0
|
|
24463
|
+
};
|
|
24464
|
+
}
|
|
24465
|
+
const spriteState = getSpriteState(hitEntry.sprite.spriteId);
|
|
24466
|
+
const imageState = (_b = (_a2 = spriteState == null ? void 0 : spriteState.images.get(hitEntry.image.subLayer)) == null ? void 0 : _a2.get(hitEntry.image.order)) != null ? _b : void 0;
|
|
24467
|
+
return {
|
|
24468
|
+
sprite: spriteState,
|
|
24469
|
+
image: imageState
|
|
24470
|
+
};
|
|
24471
|
+
};
|
|
23056
24472
|
const dispatchSpriteClick = (hitEntry, screenPoint, originalEvent) => {
|
|
23057
24473
|
const listeners = eventListeners.get("spriteclick");
|
|
23058
24474
|
if (!listeners || listeners.size === 0) {
|
|
23059
24475
|
return;
|
|
23060
24476
|
}
|
|
23061
|
-
const
|
|
23062
|
-
if (!spriteState) {
|
|
23063
|
-
return;
|
|
23064
|
-
}
|
|
23065
|
-
const imageState = hitEntry.image;
|
|
24477
|
+
const payload = resolveSpriteEventPayload(hitEntry);
|
|
23066
24478
|
const clickEvent = {
|
|
23067
24479
|
type: "spriteclick",
|
|
23068
|
-
sprite:
|
|
23069
|
-
image:
|
|
24480
|
+
sprite: payload.sprite,
|
|
24481
|
+
image: payload.image,
|
|
23070
24482
|
screenPoint,
|
|
23071
24483
|
originalEvent
|
|
23072
24484
|
};
|
|
@@ -23074,22 +24486,50 @@ const createSpriteLayer = (options) => {
|
|
|
23074
24486
|
listener(clickEvent);
|
|
23075
24487
|
});
|
|
23076
24488
|
};
|
|
23077
|
-
const
|
|
24489
|
+
const dispatchSpriteHover = (hitEntry, screenPoint, originalEvent) => {
|
|
24490
|
+
const listeners = eventListeners.get("spritehover");
|
|
24491
|
+
if (!listeners || listeners.size === 0) {
|
|
24492
|
+
return;
|
|
24493
|
+
}
|
|
24494
|
+
const payload = resolveSpriteEventPayload(hitEntry);
|
|
24495
|
+
const hoverEvent = {
|
|
24496
|
+
type: "spritehover",
|
|
24497
|
+
sprite: payload.sprite,
|
|
24498
|
+
image: payload.image,
|
|
24499
|
+
screenPoint,
|
|
24500
|
+
originalEvent
|
|
24501
|
+
};
|
|
24502
|
+
listeners.forEach((listener) => {
|
|
24503
|
+
listener(hoverEvent);
|
|
24504
|
+
});
|
|
24505
|
+
};
|
|
24506
|
+
const resolveHitTestResult = (nativeEvent) => {
|
|
24507
|
+
const screenPoint = resolveScreenPointFromEvent(nativeEvent);
|
|
24508
|
+
if (!screenPoint) {
|
|
24509
|
+
return null;
|
|
24510
|
+
}
|
|
24511
|
+
const hitEntry = findTopmostHitEntry(screenPoint);
|
|
24512
|
+
return { hitEntry: hitEntry != null ? hitEntry : null, screenPoint };
|
|
24513
|
+
};
|
|
24514
|
+
const processClickEvent = (nativeEvent) => {
|
|
23078
24515
|
if (!hasSpriteClickListeners()) {
|
|
23079
24516
|
return;
|
|
23080
24517
|
}
|
|
23081
|
-
|
|
24518
|
+
const hitResult = resolveHitTestResult(nativeEvent);
|
|
24519
|
+
if (!hitResult || !hitResult.hitEntry) {
|
|
23082
24520
|
return;
|
|
23083
24521
|
}
|
|
23084
|
-
|
|
23085
|
-
|
|
24522
|
+
dispatchSpriteClick(hitResult.hitEntry, hitResult.screenPoint, nativeEvent);
|
|
24523
|
+
};
|
|
24524
|
+
const processHoverEvent = (nativeEvent) => {
|
|
24525
|
+
if (!hasSpriteHoverListeners()) {
|
|
23086
24526
|
return;
|
|
23087
24527
|
}
|
|
23088
|
-
const
|
|
23089
|
-
if (!
|
|
24528
|
+
const hitResult = resolveHitTestResult(nativeEvent);
|
|
24529
|
+
if (!hitResult) {
|
|
23090
24530
|
return;
|
|
23091
24531
|
}
|
|
23092
|
-
|
|
24532
|
+
dispatchSpriteHover(hitResult.hitEntry, hitResult.screenPoint, nativeEvent);
|
|
23093
24533
|
};
|
|
23094
24534
|
const ensureTextures = () => {
|
|
23095
24535
|
if (!gl) {
|
|
@@ -23242,24 +24682,42 @@ const createSpriteLayer = (options) => {
|
|
|
23242
24682
|
const supportsPointerEvents = typeof window !== "undefined" && "PointerEvent" in window;
|
|
23243
24683
|
if (canvasElement) {
|
|
23244
24684
|
if (supportsPointerEvents) {
|
|
23245
|
-
const
|
|
24685
|
+
const pointerUpListener = (event) => {
|
|
23246
24686
|
if (event.pointerType === "mouse" && event.button !== 0) {
|
|
23247
24687
|
return;
|
|
23248
24688
|
}
|
|
23249
|
-
|
|
24689
|
+
processClickEvent(event);
|
|
24690
|
+
};
|
|
24691
|
+
canvasElement.addEventListener("pointerup", pointerUpListener, {
|
|
24692
|
+
passive: true
|
|
24693
|
+
});
|
|
24694
|
+
registerDisposer(() => {
|
|
24695
|
+
canvasElement == null ? void 0 : canvasElement.removeEventListener("pointerup", pointerUpListener);
|
|
24696
|
+
});
|
|
24697
|
+
const pointerMoveListener = (event) => {
|
|
24698
|
+
if (!event.isPrimary) {
|
|
24699
|
+
return;
|
|
24700
|
+
}
|
|
24701
|
+
if (event.pointerType === "touch") {
|
|
24702
|
+
return;
|
|
24703
|
+
}
|
|
24704
|
+
processHoverEvent(event);
|
|
23250
24705
|
};
|
|
23251
|
-
canvasElement.addEventListener("
|
|
24706
|
+
canvasElement.addEventListener("pointermove", pointerMoveListener, {
|
|
23252
24707
|
passive: true
|
|
23253
24708
|
});
|
|
23254
24709
|
registerDisposer(() => {
|
|
23255
|
-
canvasElement == null ? void 0 : canvasElement.removeEventListener(
|
|
24710
|
+
canvasElement == null ? void 0 : canvasElement.removeEventListener(
|
|
24711
|
+
"pointermove",
|
|
24712
|
+
pointerMoveListener
|
|
24713
|
+
);
|
|
23256
24714
|
});
|
|
23257
24715
|
} else {
|
|
23258
24716
|
const clickListener = (event) => {
|
|
23259
24717
|
if (event.button !== 0) {
|
|
23260
24718
|
return;
|
|
23261
24719
|
}
|
|
23262
|
-
|
|
24720
|
+
processClickEvent(event);
|
|
23263
24721
|
};
|
|
23264
24722
|
canvasElement.addEventListener("click", clickListener, {
|
|
23265
24723
|
passive: true
|
|
@@ -23268,7 +24726,7 @@ const createSpriteLayer = (options) => {
|
|
|
23268
24726
|
canvasElement == null ? void 0 : canvasElement.removeEventListener("click", clickListener);
|
|
23269
24727
|
});
|
|
23270
24728
|
const touchListener = (event) => {
|
|
23271
|
-
|
|
24729
|
+
processClickEvent(event);
|
|
23272
24730
|
};
|
|
23273
24731
|
canvasElement.addEventListener("touchend", touchListener, {
|
|
23274
24732
|
passive: true
|
|
@@ -23276,6 +24734,15 @@ const createSpriteLayer = (options) => {
|
|
|
23276
24734
|
registerDisposer(() => {
|
|
23277
24735
|
canvasElement == null ? void 0 : canvasElement.removeEventListener("touchend", touchListener);
|
|
23278
24736
|
});
|
|
24737
|
+
const mouseMoveListener = (event) => {
|
|
24738
|
+
processHoverEvent(event);
|
|
24739
|
+
};
|
|
24740
|
+
canvasElement.addEventListener("mousemove", mouseMoveListener, {
|
|
24741
|
+
passive: true
|
|
24742
|
+
});
|
|
24743
|
+
registerDisposer(() => {
|
|
24744
|
+
canvasElement == null ? void 0 : canvasElement.removeEventListener("mousemove", mouseMoveListener);
|
|
24745
|
+
});
|
|
23279
24746
|
}
|
|
23280
24747
|
}
|
|
23281
24748
|
const buffer = glContext.createBuffer();
|
|
@@ -23312,7 +24779,59 @@ const createSpriteLayer = (options) => {
|
|
|
23312
24779
|
shaderProgram,
|
|
23313
24780
|
"u_opacity"
|
|
23314
24781
|
);
|
|
23315
|
-
|
|
24782
|
+
uniformScreenToClipScaleLocation = glContext.getUniformLocation(
|
|
24783
|
+
shaderProgram,
|
|
24784
|
+
"u_screenToClipScale"
|
|
24785
|
+
);
|
|
24786
|
+
uniformScreenToClipOffsetLocation = glContext.getUniformLocation(
|
|
24787
|
+
shaderProgram,
|
|
24788
|
+
"u_screenToClipOffset"
|
|
24789
|
+
);
|
|
24790
|
+
uniformBillboardModeLocation = glContext.getUniformLocation(
|
|
24791
|
+
shaderProgram,
|
|
24792
|
+
"u_billboardMode"
|
|
24793
|
+
);
|
|
24794
|
+
uniformBillboardCenterLocation = glContext.getUniformLocation(
|
|
24795
|
+
shaderProgram,
|
|
24796
|
+
"u_billboardCenter"
|
|
24797
|
+
);
|
|
24798
|
+
uniformBillboardHalfSizeLocation = glContext.getUniformLocation(
|
|
24799
|
+
shaderProgram,
|
|
24800
|
+
"u_billboardHalfSize"
|
|
24801
|
+
);
|
|
24802
|
+
uniformBillboardAnchorLocation = glContext.getUniformLocation(
|
|
24803
|
+
shaderProgram,
|
|
24804
|
+
"u_billboardAnchor"
|
|
24805
|
+
);
|
|
24806
|
+
uniformBillboardSinCosLocation = glContext.getUniformLocation(
|
|
24807
|
+
shaderProgram,
|
|
24808
|
+
"u_billboardSinCos"
|
|
24809
|
+
);
|
|
24810
|
+
uniformSurfaceModeLocation = glContext.getUniformLocation(
|
|
24811
|
+
shaderProgram,
|
|
24812
|
+
"u_surfaceMode"
|
|
24813
|
+
);
|
|
24814
|
+
uniformSurfaceDepthBiasLocation = glContext.getUniformLocation(
|
|
24815
|
+
shaderProgram,
|
|
24816
|
+
"u_surfaceDepthBias"
|
|
24817
|
+
);
|
|
24818
|
+
uniformSurfaceClipEnabledLocation = glContext.getUniformLocation(
|
|
24819
|
+
shaderProgram,
|
|
24820
|
+
"u_surfaceClipEnabled"
|
|
24821
|
+
);
|
|
24822
|
+
uniformSurfaceClipCenterLocation = glContext.getUniformLocation(
|
|
24823
|
+
shaderProgram,
|
|
24824
|
+
"u_surfaceClipCenter"
|
|
24825
|
+
);
|
|
24826
|
+
uniformSurfaceClipBasisEastLocation = glContext.getUniformLocation(
|
|
24827
|
+
shaderProgram,
|
|
24828
|
+
"u_surfaceClipBasisEast"
|
|
24829
|
+
);
|
|
24830
|
+
uniformSurfaceClipBasisNorthLocation = glContext.getUniformLocation(
|
|
24831
|
+
shaderProgram,
|
|
24832
|
+
"u_surfaceClipBasisNorth"
|
|
24833
|
+
);
|
|
24834
|
+
if (!uniformTextureLocation || !uniformOpacityLocation || !uniformScreenToClipScaleLocation || !uniformScreenToClipOffsetLocation || !uniformBillboardModeLocation || !uniformBillboardCenterLocation || !uniformBillboardHalfSizeLocation || !uniformBillboardAnchorLocation || !uniformBillboardSinCosLocation || !uniformSurfaceModeLocation || !uniformSurfaceDepthBiasLocation || !uniformSurfaceClipEnabledLocation || !uniformSurfaceClipCenterLocation || !uniformSurfaceClipBasisEastLocation || !uniformSurfaceClipBasisNorthLocation) {
|
|
23316
24835
|
throw new Error("Failed to acquire uniform locations.");
|
|
23317
24836
|
}
|
|
23318
24837
|
glContext.enableVertexAttribArray(attribPositionLocation);
|
|
@@ -23335,7 +24854,80 @@ const createSpriteLayer = (options) => {
|
|
|
23335
24854
|
);
|
|
23336
24855
|
glContext.uniform1i(uniformTextureLocation, 0);
|
|
23337
24856
|
glContext.uniform1f(uniformOpacityLocation, 1);
|
|
24857
|
+
glContext.uniform2f(uniformScreenToClipScaleLocation, 1, 1);
|
|
24858
|
+
glContext.uniform2f(uniformScreenToClipOffsetLocation, 0, 0);
|
|
24859
|
+
glContext.uniform1f(uniformSurfaceClipEnabledLocation, 0);
|
|
24860
|
+
glContext.uniform4f(uniformSurfaceClipCenterLocation, 0, 0, 0, 1);
|
|
24861
|
+
glContext.uniform4f(
|
|
24862
|
+
uniformSurfaceClipBasisEastLocation,
|
|
24863
|
+
0,
|
|
24864
|
+
0,
|
|
24865
|
+
0,
|
|
24866
|
+
0
|
|
24867
|
+
);
|
|
24868
|
+
glContext.uniform4f(
|
|
24869
|
+
uniformSurfaceClipBasisNorthLocation,
|
|
24870
|
+
0,
|
|
24871
|
+
0,
|
|
24872
|
+
0,
|
|
24873
|
+
0
|
|
24874
|
+
);
|
|
24875
|
+
glContext.uniform1f(uniformBillboardModeLocation, 0);
|
|
24876
|
+
glContext.uniform2f(uniformBillboardCenterLocation, 0, 0);
|
|
24877
|
+
glContext.uniform2f(uniformBillboardHalfSizeLocation, 0, 0);
|
|
24878
|
+
glContext.uniform2f(uniformBillboardAnchorLocation, 0, 0);
|
|
24879
|
+
glContext.uniform2f(uniformBillboardSinCosLocation, 0, 1);
|
|
24880
|
+
glContext.uniform1f(uniformSurfaceModeLocation, 0);
|
|
24881
|
+
glContext.uniform1f(uniformSurfaceDepthBiasLocation, 0);
|
|
23338
24882
|
glContext.bindBuffer(glContext.ARRAY_BUFFER, null);
|
|
24883
|
+
if (showDebugBounds) {
|
|
24884
|
+
const debugShaderProgram = createShaderProgram(
|
|
24885
|
+
glContext,
|
|
24886
|
+
DEBUG_OUTLINE_VERTEX_SHADER_SOURCE,
|
|
24887
|
+
DEBUG_OUTLINE_FRAGMENT_SHADER_SOURCE
|
|
24888
|
+
);
|
|
24889
|
+
debugProgram = debugShaderProgram;
|
|
24890
|
+
debugAttribPositionLocation = glContext.getAttribLocation(
|
|
24891
|
+
debugShaderProgram,
|
|
24892
|
+
"a_position"
|
|
24893
|
+
);
|
|
24894
|
+
if (debugAttribPositionLocation === -1) {
|
|
24895
|
+
throw new Error("Failed to acquire debug attribute location.");
|
|
24896
|
+
}
|
|
24897
|
+
const colorLocation = glContext.getUniformLocation(
|
|
24898
|
+
debugShaderProgram,
|
|
24899
|
+
"u_color"
|
|
24900
|
+
);
|
|
24901
|
+
if (!colorLocation) {
|
|
24902
|
+
throw new Error("Failed to acquire debug color uniform.");
|
|
24903
|
+
}
|
|
24904
|
+
debugUniformColorLocation = colorLocation;
|
|
24905
|
+
debugUniformScreenToClipScaleLocation = glContext.getUniformLocation(
|
|
24906
|
+
debugShaderProgram,
|
|
24907
|
+
"u_screenToClipScale"
|
|
24908
|
+
);
|
|
24909
|
+
debugUniformScreenToClipOffsetLocation = glContext.getUniformLocation(
|
|
24910
|
+
debugShaderProgram,
|
|
24911
|
+
"u_screenToClipOffset"
|
|
24912
|
+
);
|
|
24913
|
+
if (!debugUniformScreenToClipScaleLocation || !debugUniformScreenToClipOffsetLocation) {
|
|
24914
|
+
throw new Error("Failed to acquire debug screen-to-clip uniforms.");
|
|
24915
|
+
}
|
|
24916
|
+
glContext.uniform2f(debugUniformScreenToClipScaleLocation, 1, 1);
|
|
24917
|
+
glContext.uniform2f(debugUniformScreenToClipOffsetLocation, 0, 0);
|
|
24918
|
+
const outlineBuffer = glContext.createBuffer();
|
|
24919
|
+
if (!outlineBuffer) {
|
|
24920
|
+
throw new Error("Failed to create debug vertex buffer.");
|
|
24921
|
+
}
|
|
24922
|
+
debugVertexBuffer = outlineBuffer;
|
|
24923
|
+
glContext.bindBuffer(glContext.ARRAY_BUFFER, outlineBuffer);
|
|
24924
|
+
glContext.bufferData(
|
|
24925
|
+
glContext.ARRAY_BUFFER,
|
|
24926
|
+
DEBUG_OUTLINE_VERTEX_SCRATCH,
|
|
24927
|
+
glContext.DYNAMIC_DRAW
|
|
24928
|
+
);
|
|
24929
|
+
glContext.bindBuffer(glContext.ARRAY_BUFFER, null);
|
|
24930
|
+
}
|
|
23339
24931
|
scheduleRender();
|
|
23340
24932
|
};
|
|
23341
24933
|
const onRemove = () => {
|
|
@@ -23343,6 +24935,9 @@ const createSpriteLayer = (options) => {
|
|
|
23343
24935
|
inputListenerDisposers.length = 0;
|
|
23344
24936
|
canvasElement = null;
|
|
23345
24937
|
hitTestEntries.length = 0;
|
|
24938
|
+
hitTestEntryByImage = /* @__PURE__ */ new WeakMap();
|
|
24939
|
+
hitTestTree.clear();
|
|
24940
|
+
hitTestTreeItems = /* @__PURE__ */ new WeakMap();
|
|
23346
24941
|
const glContext = gl;
|
|
23347
24942
|
if (glContext) {
|
|
23348
24943
|
images.forEach((image) => {
|
|
@@ -23355,9 +24950,15 @@ const createSpriteLayer = (options) => {
|
|
|
23355
24950
|
if (vertexBuffer) {
|
|
23356
24951
|
glContext.deleteBuffer(vertexBuffer);
|
|
23357
24952
|
}
|
|
24953
|
+
if (debugVertexBuffer) {
|
|
24954
|
+
glContext.deleteBuffer(debugVertexBuffer);
|
|
24955
|
+
}
|
|
23358
24956
|
if (program) {
|
|
23359
24957
|
glContext.deleteProgram(program);
|
|
23360
24958
|
}
|
|
24959
|
+
if (debugProgram) {
|
|
24960
|
+
glContext.deleteProgram(debugProgram);
|
|
24961
|
+
}
|
|
23361
24962
|
}
|
|
23362
24963
|
eventListeners.forEach((set) => set.clear());
|
|
23363
24964
|
eventListeners.clear();
|
|
@@ -23365,20 +24966,36 @@ const createSpriteLayer = (options) => {
|
|
|
23365
24966
|
map = null;
|
|
23366
24967
|
program = null;
|
|
23367
24968
|
vertexBuffer = null;
|
|
24969
|
+
debugProgram = null;
|
|
24970
|
+
debugVertexBuffer = null;
|
|
23368
24971
|
attribPositionLocation = -1;
|
|
23369
24972
|
attribUvLocation = -1;
|
|
24973
|
+
debugAttribPositionLocation = -1;
|
|
23370
24974
|
uniformTextureLocation = null;
|
|
23371
24975
|
uniformOpacityLocation = null;
|
|
24976
|
+
uniformScreenToClipScaleLocation = null;
|
|
24977
|
+
uniformScreenToClipOffsetLocation = null;
|
|
24978
|
+
uniformBillboardModeLocation = null;
|
|
24979
|
+
uniformBillboardCenterLocation = null;
|
|
24980
|
+
uniformBillboardHalfSizeLocation = null;
|
|
24981
|
+
uniformBillboardAnchorLocation = null;
|
|
24982
|
+
uniformBillboardSinCosLocation = null;
|
|
24983
|
+
uniformSurfaceModeLocation = null;
|
|
24984
|
+
uniformSurfaceDepthBiasLocation = null;
|
|
24985
|
+
debugUniformColorLocation = null;
|
|
24986
|
+
debugUniformScreenToClipScaleLocation = null;
|
|
24987
|
+
debugUniformScreenToClipOffsetLocation = null;
|
|
23372
24988
|
anisotropyExtension = null;
|
|
23373
24989
|
maxSupportedAnisotropy = 1;
|
|
23374
24990
|
};
|
|
23375
24991
|
const render = (glContext, _options) => {
|
|
23376
24992
|
hitTestEntries.length = 0;
|
|
24993
|
+
hitTestEntryByImage = /* @__PURE__ */ new WeakMap();
|
|
23377
24994
|
const mapInstance = map;
|
|
23378
24995
|
if (!mapInstance || !program || !vertexBuffer) {
|
|
23379
24996
|
return;
|
|
23380
24997
|
}
|
|
23381
|
-
if (!uniformOpacityLocation || !uniformTextureLocation) {
|
|
24998
|
+
if (!uniformOpacityLocation || !uniformTextureLocation || !uniformScreenToClipScaleLocation || !uniformScreenToClipOffsetLocation) {
|
|
23382
24999
|
return;
|
|
23383
25000
|
}
|
|
23384
25001
|
const timestamp = typeof performance !== "undefined" && typeof performance.now === "function" ? (
|
|
@@ -23411,41 +25028,8 @@ const createSpriteLayer = (options) => {
|
|
|
23411
25028
|
}
|
|
23412
25029
|
sprite.images.forEach((orderMap) => {
|
|
23413
25030
|
orderMap.forEach((image) => {
|
|
23414
|
-
|
|
23415
|
-
|
|
23416
|
-
const evaluation = evaluateNumericInterpolation({
|
|
23417
|
-
state: rotationState,
|
|
23418
|
-
timestamp
|
|
23419
|
-
});
|
|
23420
|
-
if (rotationState.startTimestamp < 0) {
|
|
23421
|
-
rotationState.startTimestamp = evaluation.effectiveStartTimestamp;
|
|
23422
|
-
}
|
|
23423
|
-
image.displayedRotateDeg = normaliseAngleDeg(evaluation.value);
|
|
23424
|
-
if (evaluation.completed) {
|
|
23425
|
-
image.displayedRotateDeg = normaliseAngleDeg(
|
|
23426
|
-
rotationState.finalValue
|
|
23427
|
-
);
|
|
23428
|
-
image.rotationInterpolationState = null;
|
|
23429
|
-
} else {
|
|
23430
|
-
hasActiveInterpolation = true;
|
|
23431
|
-
}
|
|
23432
|
-
}
|
|
23433
|
-
const offsetState = image.offsetInterpolationState;
|
|
23434
|
-
if (offsetState) {
|
|
23435
|
-
const evaluation = evaluateNumericInterpolation({
|
|
23436
|
-
state: offsetState,
|
|
23437
|
-
timestamp
|
|
23438
|
-
});
|
|
23439
|
-
if (offsetState.startTimestamp < 0) {
|
|
23440
|
-
offsetState.startTimestamp = evaluation.effectiveStartTimestamp;
|
|
23441
|
-
}
|
|
23442
|
-
image.offset.offsetDeg = evaluation.value;
|
|
23443
|
-
if (evaluation.completed) {
|
|
23444
|
-
image.offset.offsetDeg = offsetState.finalValue;
|
|
23445
|
-
image.offsetInterpolationState = null;
|
|
23446
|
-
} else {
|
|
23447
|
-
hasActiveInterpolation = true;
|
|
23448
|
-
}
|
|
25031
|
+
if (stepSpriteImageInterpolations(image, timestamp)) {
|
|
25032
|
+
hasActiveInterpolation = true;
|
|
23449
25033
|
}
|
|
23450
25034
|
});
|
|
23451
25035
|
});
|
|
@@ -23463,6 +25047,17 @@ const createSpriteLayer = (options) => {
|
|
|
23463
25047
|
const drawingBufferWidth = glContext.drawingBufferWidth;
|
|
23464
25048
|
const drawingBufferHeight = glContext.drawingBufferHeight;
|
|
23465
25049
|
const pixelRatio = drawingBufferWidth / cssWidth;
|
|
25050
|
+
if (drawingBufferWidth === 0 || drawingBufferHeight === 0) {
|
|
25051
|
+
return;
|
|
25052
|
+
}
|
|
25053
|
+
const screenToClipScaleX = 2 * pixelRatio / drawingBufferWidth;
|
|
25054
|
+
const screenToClipScaleY = -2 * pixelRatio / drawingBufferHeight;
|
|
25055
|
+
const screenToClipOffsetX = -1;
|
|
25056
|
+
const screenToClipOffsetY = 1;
|
|
25057
|
+
const identityScaleX = 1;
|
|
25058
|
+
const identityScaleY = 1;
|
|
25059
|
+
const identityOffsetX = 0;
|
|
25060
|
+
const identityOffsetY = 0;
|
|
23466
25061
|
const zoom = mapInstance.getZoom();
|
|
23467
25062
|
const zoomScaleFactor = calculateZoomScaleFactor(zoom, resolvedScaling);
|
|
23468
25063
|
const baseMetersPerPixel = resolvedScaling.metersPerPixel;
|
|
@@ -23497,18 +25092,84 @@ const createSpriteLayer = (options) => {
|
|
|
23497
25092
|
UV_OFFSET
|
|
23498
25093
|
);
|
|
23499
25094
|
glContext.uniform1i(uniformTextureLocation, 0);
|
|
25095
|
+
const screenToClipScaleLocation = uniformScreenToClipScaleLocation;
|
|
25096
|
+
const screenToClipOffsetLocation = uniformScreenToClipOffsetLocation;
|
|
25097
|
+
let currentScaleX = Number.NaN;
|
|
25098
|
+
let currentScaleY = Number.NaN;
|
|
25099
|
+
let currentOffsetX = Number.NaN;
|
|
25100
|
+
let currentOffsetY = Number.NaN;
|
|
25101
|
+
const applyScreenToClipUniforms = (scaleX, scaleY, offsetX, offsetY) => {
|
|
25102
|
+
if (scaleX !== currentScaleX || scaleY !== currentScaleY || offsetX !== currentOffsetX || offsetY !== currentOffsetY) {
|
|
25103
|
+
glContext.uniform2f(screenToClipScaleLocation, scaleX, scaleY);
|
|
25104
|
+
glContext.uniform2f(screenToClipOffsetLocation, offsetX, offsetY);
|
|
25105
|
+
currentScaleX = scaleX;
|
|
25106
|
+
currentScaleY = scaleY;
|
|
25107
|
+
currentOffsetX = offsetX;
|
|
25108
|
+
currentOffsetY = offsetY;
|
|
25109
|
+
}
|
|
25110
|
+
};
|
|
25111
|
+
let currentSurfaceMode = Number.NaN;
|
|
25112
|
+
const applySurfaceMode = (enabled) => {
|
|
25113
|
+
if (!uniformSurfaceModeLocation) {
|
|
25114
|
+
return;
|
|
25115
|
+
}
|
|
25116
|
+
const value = enabled ? 1 : 0;
|
|
25117
|
+
if (value !== currentSurfaceMode) {
|
|
25118
|
+
glContext.uniform1f(uniformSurfaceModeLocation, value);
|
|
25119
|
+
currentSurfaceMode = value;
|
|
25120
|
+
}
|
|
25121
|
+
};
|
|
25122
|
+
let currentSurfaceClipEnabled = Number.NaN;
|
|
25123
|
+
const applySurfaceClipUniforms = (enabled, inputs) => {
|
|
25124
|
+
if (!uniformSurfaceClipEnabledLocation || !uniformSurfaceClipCenterLocation || !uniformSurfaceClipBasisEastLocation || !uniformSurfaceClipBasisNorthLocation) {
|
|
25125
|
+
return;
|
|
25126
|
+
}
|
|
25127
|
+
const value = enabled ? 1 : 0;
|
|
25128
|
+
if (value !== currentSurfaceClipEnabled) {
|
|
25129
|
+
glContext.uniform1f(uniformSurfaceClipEnabledLocation, value);
|
|
25130
|
+
currentSurfaceClipEnabled = value;
|
|
25131
|
+
}
|
|
25132
|
+
const clipCenter = enabled && inputs ? inputs.clipCenter : { x: 0, y: 0, z: 0, w: 1 };
|
|
25133
|
+
glContext.uniform4f(
|
|
25134
|
+
uniformSurfaceClipCenterLocation,
|
|
25135
|
+
clipCenter.x,
|
|
25136
|
+
clipCenter.y,
|
|
25137
|
+
clipCenter.z,
|
|
25138
|
+
clipCenter.w
|
|
25139
|
+
);
|
|
25140
|
+
const clipBasisEast = enabled && inputs ? inputs.clipBasisEast : { x: 0, y: 0, z: 0, w: 0 };
|
|
25141
|
+
glContext.uniform4f(
|
|
25142
|
+
uniformSurfaceClipBasisEastLocation,
|
|
25143
|
+
clipBasisEast.x,
|
|
25144
|
+
clipBasisEast.y,
|
|
25145
|
+
clipBasisEast.z,
|
|
25146
|
+
clipBasisEast.w
|
|
25147
|
+
);
|
|
25148
|
+
const clipBasisNorth = enabled && inputs ? inputs.clipBasisNorth : { x: 0, y: 0, z: 0, w: 0 };
|
|
25149
|
+
glContext.uniform4f(
|
|
25150
|
+
uniformSurfaceClipBasisNorthLocation,
|
|
25151
|
+
clipBasisNorth.x,
|
|
25152
|
+
clipBasisNorth.y,
|
|
25153
|
+
clipBasisNorth.z,
|
|
25154
|
+
clipBasisNorth.w
|
|
25155
|
+
);
|
|
25156
|
+
};
|
|
25157
|
+
let drawOrderCounter = 0;
|
|
23500
25158
|
const drawSpriteImage = (spriteEntry, imageEntry, imageResource, originCenterCache2) => {
|
|
23501
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
25159
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
23502
25160
|
let screenCornerBuffer = null;
|
|
23503
25161
|
const anchor = (_a2 = imageEntry.anchor) != null ? _a2 : DEFAULT_ANCHOR;
|
|
23504
25162
|
const offsetDef = (_b = imageEntry.offset) != null ? _b : DEFAULT_IMAGE_OFFSET;
|
|
23505
|
-
|
|
25163
|
+
applySurfaceMode(false);
|
|
25164
|
+
applySurfaceClipUniforms(false, null);
|
|
25165
|
+
const totalRotateDeg = Number.isFinite(imageEntry.displayedRotateDeg) ? imageEntry.displayedRotateDeg : normalizeAngleDeg(
|
|
23506
25166
|
((_c = imageEntry.resolvedBaseRotateDeg) != null ? _c : 0) + ((_d = imageEntry.rotateDeg) != null ? _d : 0)
|
|
23507
25167
|
);
|
|
23508
25168
|
const projected = mapInstance.project(spriteEntry.currentLocation);
|
|
23509
25169
|
if (!projected) {
|
|
23510
25170
|
return;
|
|
23511
25171
|
}
|
|
25172
|
+
const spriteMercator = resolveSpriteMercator(spriteEntry);
|
|
23512
25173
|
const metersPerPixelAtLat = calculateMetersPerPixelAtLatitude(
|
|
23513
25174
|
zoom,
|
|
23514
25175
|
spriteEntry.currentLocation.lat
|
|
@@ -23518,7 +25179,8 @@ const createSpriteLayer = (options) => {
|
|
|
23518
25179
|
}
|
|
23519
25180
|
const perspectiveRatio = calculatePerspectiveRatio(
|
|
23520
25181
|
mapInstance,
|
|
23521
|
-
spriteEntry.currentLocation
|
|
25182
|
+
spriteEntry.currentLocation,
|
|
25183
|
+
spriteMercator
|
|
23522
25184
|
);
|
|
23523
25185
|
const effectivePixelsPerMeter = calculateEffectivePixelsPerMeter(
|
|
23524
25186
|
metersPerPixelAtLat,
|
|
@@ -23528,6 +25190,7 @@ const createSpriteLayer = (options) => {
|
|
|
23528
25190
|
return;
|
|
23529
25191
|
}
|
|
23530
25192
|
const imageScale = (_e = imageEntry.scale) != null ? _e : 1;
|
|
25193
|
+
const altitudeMeters = (_f = spriteEntry.currentLocation.z) != null ? _f : 0;
|
|
23531
25194
|
const centerParams = {
|
|
23532
25195
|
mapInstance,
|
|
23533
25196
|
images,
|
|
@@ -23542,7 +25205,7 @@ const createSpriteLayer = (options) => {
|
|
|
23542
25205
|
drawingBufferHeight,
|
|
23543
25206
|
pixelRatio,
|
|
23544
25207
|
clipContext,
|
|
23545
|
-
altitudeMeters
|
|
25208
|
+
altitudeMeters
|
|
23546
25209
|
};
|
|
23547
25210
|
let baseProjected = { x: projected.x, y: projected.y };
|
|
23548
25211
|
if (imageEntry.originLocation !== void 0) {
|
|
@@ -23559,6 +25222,13 @@ const createSpriteLayer = (options) => {
|
|
|
23559
25222
|
}
|
|
23560
25223
|
}
|
|
23561
25224
|
if (imageEntry.mode === "surface") {
|
|
25225
|
+
applyScreenToClipUniforms(
|
|
25226
|
+
identityScaleX,
|
|
25227
|
+
identityScaleY,
|
|
25228
|
+
identityOffsetX,
|
|
25229
|
+
identityOffsetY
|
|
25230
|
+
);
|
|
25231
|
+
imageEntry.surfaceShaderInputs = void 0;
|
|
23562
25232
|
const baseLngLat = imageEntry.originLocation !== void 0 ? (
|
|
23563
25233
|
// When an origin reference is set, reproject the cached screen point back to geographic space.
|
|
23564
25234
|
mapInstance.unproject([
|
|
@@ -23586,7 +25256,7 @@ const createSpriteLayer = (options) => {
|
|
|
23586
25256
|
drawingBufferWidth,
|
|
23587
25257
|
drawingBufferHeight,
|
|
23588
25258
|
pixelRatio,
|
|
23589
|
-
altitudeMeters
|
|
25259
|
+
altitudeMeters,
|
|
23590
25260
|
project: !clipContext ? (lngLat) => {
|
|
23591
25261
|
const result = mapInstance.project(lngLat);
|
|
23592
25262
|
return result ? { x: result.x, y: result.y } : null;
|
|
@@ -23595,6 +25265,9 @@ const createSpriteLayer = (options) => {
|
|
|
23595
25265
|
if (!surfaceCenter.center) {
|
|
23596
25266
|
return;
|
|
23597
25267
|
}
|
|
25268
|
+
if (uniformBillboardModeLocation) {
|
|
25269
|
+
glContext.uniform1f(uniformBillboardModeLocation, 0);
|
|
25270
|
+
}
|
|
23598
25271
|
const offsetMeters = calculateSurfaceOffsetMeters(
|
|
23599
25272
|
offsetDef,
|
|
23600
25273
|
imageScale,
|
|
@@ -23608,6 +25281,51 @@ const createSpriteLayer = (options) => {
|
|
|
23608
25281
|
totalRotateDeg,
|
|
23609
25282
|
offsetMeters
|
|
23610
25283
|
});
|
|
25284
|
+
const orderIndex = Math.min(imageEntry.order, ORDER_MAX - 1);
|
|
25285
|
+
const depthBiasNdc = -((imageEntry.subLayer * ORDER_BUCKET + orderIndex) * EPS_NDC);
|
|
25286
|
+
const displacedCenterLngLat = (_i = surfaceCenter.displacedLngLat) != null ? _i : baseLngLat;
|
|
25287
|
+
const displacedCenter = {
|
|
25288
|
+
lng: displacedCenterLngLat.lng,
|
|
25289
|
+
lat: displacedCenterLngLat.lat,
|
|
25290
|
+
z: altitudeMeters
|
|
25291
|
+
};
|
|
25292
|
+
const surfaceShaderInputs = prepareSurfaceShaderInputs({
|
|
25293
|
+
baseLngLat,
|
|
25294
|
+
worldWidthMeters: surfaceCenter.worldDimensions.width,
|
|
25295
|
+
worldHeightMeters: surfaceCenter.worldDimensions.height,
|
|
25296
|
+
anchor,
|
|
25297
|
+
totalRotateDeg,
|
|
25298
|
+
offsetMeters,
|
|
25299
|
+
displacedCenter,
|
|
25300
|
+
altitudeMeters,
|
|
25301
|
+
depthBiasNdc,
|
|
25302
|
+
scaleAdjustment: surfaceCenter.worldDimensions.scaleAdjustment,
|
|
25303
|
+
centerDisplacement: surfaceCenter.totalDisplacement
|
|
25304
|
+
});
|
|
25305
|
+
imageEntry.surfaceShaderInputs = surfaceShaderInputs;
|
|
25306
|
+
let useShaderSurface = !!clipContext;
|
|
25307
|
+
let clipCornerPositions = null;
|
|
25308
|
+
let clipCenterPosition = null;
|
|
25309
|
+
if (useShaderSurface) {
|
|
25310
|
+
clipCornerPositions = new Array(SURFACE_BASE_CORNERS.length);
|
|
25311
|
+
clipCenterPosition = projectLngLatToClipSpace(
|
|
25312
|
+
displacedCenter.lng,
|
|
25313
|
+
displacedCenter.lat,
|
|
25314
|
+
(_j = displacedCenter.z) != null ? _j : altitudeMeters,
|
|
25315
|
+
clipContext
|
|
25316
|
+
);
|
|
25317
|
+
if (!clipCenterPosition) {
|
|
25318
|
+
useShaderSurface = false;
|
|
25319
|
+
clipCornerPositions = null;
|
|
25320
|
+
}
|
|
25321
|
+
}
|
|
25322
|
+
applySurfaceMode(useShaderSurface);
|
|
25323
|
+
if (useShaderSurface && uniformSurfaceDepthBiasLocation) {
|
|
25324
|
+
glContext.uniform1f(
|
|
25325
|
+
uniformSurfaceDepthBiasLocation,
|
|
25326
|
+
surfaceShaderInputs.depthBiasNdc
|
|
25327
|
+
);
|
|
25328
|
+
}
|
|
23611
25329
|
const hitTestCorners = ensureHitTestCorners(imageEntry);
|
|
23612
25330
|
let bufferOffset = 0;
|
|
23613
25331
|
for (const index of TRIANGLE_INDICES) {
|
|
@@ -23621,46 +25339,145 @@ const createSpriteLayer = (options) => {
|
|
|
23621
25339
|
const clipPosition = projectLngLatToClipSpace(
|
|
23622
25340
|
displaced.lng,
|
|
23623
25341
|
displaced.lat,
|
|
23624
|
-
|
|
23625
|
-
(_j = spriteEntry.currentLocation.z) != null ? _j : 0,
|
|
25342
|
+
altitudeMeters,
|
|
23626
25343
|
clipContext
|
|
23627
25344
|
);
|
|
23628
25345
|
if (!clipPosition) {
|
|
23629
25346
|
return;
|
|
23630
25347
|
}
|
|
23631
|
-
const screenCorner = clipToScreen(
|
|
23632
|
-
clipPosition,
|
|
23633
|
-
drawingBufferWidth,
|
|
23634
|
-
drawingBufferHeight,
|
|
23635
|
-
pixelRatio
|
|
23636
|
-
);
|
|
23637
|
-
if (!screenCorner) {
|
|
23638
|
-
return;
|
|
23639
|
-
}
|
|
23640
|
-
const targetCorner = hitTestCorners[index];
|
|
23641
|
-
targetCorner.x = screenCorner.x;
|
|
23642
|
-
targetCorner.y = screenCorner.y;
|
|
23643
25348
|
let [clipX, clipY, clipZ, clipW] = clipPosition;
|
|
23644
|
-
{
|
|
23645
|
-
const
|
|
23646
|
-
|
|
23647
|
-
|
|
23648
|
-
|
|
25349
|
+
if (!useShaderSurface) {
|
|
25350
|
+
const screenCorner = clipToScreen(
|
|
25351
|
+
clipPosition,
|
|
25352
|
+
drawingBufferWidth,
|
|
25353
|
+
drawingBufferHeight,
|
|
25354
|
+
pixelRatio
|
|
25355
|
+
);
|
|
25356
|
+
if (!screenCorner) {
|
|
25357
|
+
return;
|
|
25358
|
+
}
|
|
25359
|
+
const targetCorner = hitTestCorners[index];
|
|
25360
|
+
targetCorner.x = screenCorner.x;
|
|
25361
|
+
targetCorner.y = screenCorner.y;
|
|
25362
|
+
}
|
|
25363
|
+
if (depthBiasNdc !== 0) {
|
|
25364
|
+
clipZ += depthBiasNdc * clipW;
|
|
23649
25365
|
const minClipZ = -clipW + MIN_CLIP_Z_EPSILON;
|
|
23650
25366
|
if (clipZ < minClipZ) {
|
|
23651
25367
|
clipZ = minClipZ;
|
|
23652
25368
|
}
|
|
23653
25369
|
}
|
|
25370
|
+
if (clipCornerPositions) {
|
|
25371
|
+
clipCornerPositions[index] = [clipX, clipY, clipZ, clipW];
|
|
25372
|
+
}
|
|
23654
25373
|
const [u, v] = UV_CORNERS[index];
|
|
23655
|
-
|
|
23656
|
-
|
|
23657
|
-
|
|
23658
|
-
|
|
25374
|
+
if (useShaderSurface) {
|
|
25375
|
+
const baseCorner = SURFACE_BASE_CORNERS[index];
|
|
25376
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = baseCorner[0];
|
|
25377
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = baseCorner[1];
|
|
25378
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = 0;
|
|
25379
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = 1;
|
|
25380
|
+
} else {
|
|
25381
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = clipX;
|
|
25382
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = clipY;
|
|
25383
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = clipZ;
|
|
25384
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = clipW;
|
|
25385
|
+
}
|
|
23659
25386
|
QUAD_VERTEX_SCRATCH[bufferOffset++] = u;
|
|
23660
25387
|
QUAD_VERTEX_SCRATCH[bufferOffset++] = v;
|
|
23661
25388
|
}
|
|
25389
|
+
let clipUniformEnabled = false;
|
|
25390
|
+
if (clipCornerPositions && clipCenterPosition && clipCornerPositions.every((corner) => Array.isArray(corner))) {
|
|
25391
|
+
const leftTop = clipCornerPositions[0];
|
|
25392
|
+
const rightTop = clipCornerPositions[1];
|
|
25393
|
+
const leftBottom = clipCornerPositions[2];
|
|
25394
|
+
const rightBottom = clipCornerPositions[3];
|
|
25395
|
+
if (leftTop && rightTop && leftBottom && rightBottom) {
|
|
25396
|
+
const clipBasisEast = [
|
|
25397
|
+
(rightTop[0] - leftTop[0]) * 0.5,
|
|
25398
|
+
(rightTop[1] - leftTop[1]) * 0.5,
|
|
25399
|
+
(rightTop[2] - leftTop[2]) * 0.5,
|
|
25400
|
+
(rightTop[3] - leftTop[3]) * 0.5
|
|
25401
|
+
];
|
|
25402
|
+
const clipBasisNorth = [
|
|
25403
|
+
(leftTop[0] - leftBottom[0]) * 0.5,
|
|
25404
|
+
(leftTop[1] - leftBottom[1]) * 0.5,
|
|
25405
|
+
(leftTop[2] - leftBottom[2]) * 0.5,
|
|
25406
|
+
(leftTop[3] - leftBottom[3]) * 0.5
|
|
25407
|
+
];
|
|
25408
|
+
surfaceShaderInputs.clipCenter = {
|
|
25409
|
+
x: clipCenterPosition[0],
|
|
25410
|
+
y: clipCenterPosition[1],
|
|
25411
|
+
z: clipCenterPosition[2],
|
|
25412
|
+
w: clipCenterPosition[3]
|
|
25413
|
+
};
|
|
25414
|
+
surfaceShaderInputs.clipBasisEast = {
|
|
25415
|
+
x: clipBasisEast[0],
|
|
25416
|
+
y: clipBasisEast[1],
|
|
25417
|
+
z: clipBasisEast[2],
|
|
25418
|
+
w: clipBasisEast[3]
|
|
25419
|
+
};
|
|
25420
|
+
surfaceShaderInputs.clipBasisNorth = {
|
|
25421
|
+
x: clipBasisNorth[0],
|
|
25422
|
+
y: clipBasisNorth[1],
|
|
25423
|
+
z: clipBasisNorth[2],
|
|
25424
|
+
w: clipBasisNorth[3]
|
|
25425
|
+
};
|
|
25426
|
+
const clipCornersForInputs = [];
|
|
25427
|
+
let allCornersResolved = true;
|
|
25428
|
+
for (let cornerIndex = 0; cornerIndex < SURFACE_BASE_CORNERS.length; cornerIndex++) {
|
|
25429
|
+
const clipCorner = clipCornerPositions[cornerIndex];
|
|
25430
|
+
if (!clipCorner) {
|
|
25431
|
+
allCornersResolved = false;
|
|
25432
|
+
break;
|
|
25433
|
+
}
|
|
25434
|
+
clipCornersForInputs.push({
|
|
25435
|
+
x: clipCorner[0],
|
|
25436
|
+
y: clipCorner[1],
|
|
25437
|
+
z: clipCorner[2],
|
|
25438
|
+
w: clipCorner[3]
|
|
25439
|
+
});
|
|
25440
|
+
const screenCorner = clipToScreen(
|
|
25441
|
+
clipCorner,
|
|
25442
|
+
drawingBufferWidth,
|
|
25443
|
+
drawingBufferHeight,
|
|
25444
|
+
pixelRatio
|
|
25445
|
+
);
|
|
25446
|
+
if (!screenCorner) {
|
|
25447
|
+
return;
|
|
25448
|
+
}
|
|
25449
|
+
const targetCorner = hitTestCorners[cornerIndex];
|
|
25450
|
+
targetCorner.x = screenCorner.x;
|
|
25451
|
+
targetCorner.y = screenCorner.y;
|
|
25452
|
+
}
|
|
25453
|
+
if (allCornersResolved) {
|
|
25454
|
+
surfaceShaderInputs.clipCorners = clipCornersForInputs;
|
|
25455
|
+
clipUniformEnabled = true;
|
|
25456
|
+
} else {
|
|
25457
|
+
surfaceShaderInputs.clipCorners = [];
|
|
25458
|
+
}
|
|
25459
|
+
}
|
|
25460
|
+
} else {
|
|
25461
|
+
surfaceShaderInputs.clipCorners = [];
|
|
25462
|
+
}
|
|
25463
|
+
if (useShaderSurface) {
|
|
25464
|
+
applySurfaceClipUniforms(
|
|
25465
|
+
clipUniformEnabled,
|
|
25466
|
+
clipUniformEnabled ? surfaceShaderInputs : null
|
|
25467
|
+
);
|
|
25468
|
+
} else {
|
|
25469
|
+
applySurfaceClipUniforms(false, null);
|
|
25470
|
+
}
|
|
23662
25471
|
screenCornerBuffer = hitTestCorners;
|
|
23663
25472
|
} else {
|
|
25473
|
+
applyScreenToClipUniforms(
|
|
25474
|
+
screenToClipScaleX,
|
|
25475
|
+
screenToClipScaleY,
|
|
25476
|
+
screenToClipOffsetX,
|
|
25477
|
+
screenToClipOffsetY
|
|
25478
|
+
);
|
|
25479
|
+
imageEntry.surfaceShaderInputs = void 0;
|
|
25480
|
+
applySurfaceMode(false);
|
|
23664
25481
|
const placement = calculateBillboardCenterPosition({
|
|
23665
25482
|
base: baseProjected,
|
|
23666
25483
|
imageWidth: imageResource.width,
|
|
@@ -23675,46 +25492,95 @@ const createSpriteLayer = (options) => {
|
|
|
23675
25492
|
anchor,
|
|
23676
25493
|
offset: offsetDef
|
|
23677
25494
|
});
|
|
23678
|
-
const
|
|
25495
|
+
const billboardShaderInputs = {
|
|
23679
25496
|
centerX: placement.centerX,
|
|
23680
25497
|
centerY: placement.centerY,
|
|
23681
25498
|
halfWidth: placement.halfWidth,
|
|
23682
25499
|
halfHeight: placement.halfHeight,
|
|
23683
25500
|
anchor,
|
|
23684
25501
|
totalRotateDeg
|
|
23685
|
-
}
|
|
23686
|
-
|
|
23687
|
-
|
|
23688
|
-
|
|
23689
|
-
|
|
23690
|
-
const [clipX, clipY] = screenToClip(
|
|
23691
|
-
corner.x,
|
|
23692
|
-
corner.y,
|
|
23693
|
-
drawingBufferWidth,
|
|
23694
|
-
drawingBufferHeight,
|
|
23695
|
-
pixelRatio
|
|
25502
|
+
};
|
|
25503
|
+
if (uniformBillboardModeLocation) {
|
|
25504
|
+
glContext.uniform1f(
|
|
25505
|
+
uniformBillboardModeLocation,
|
|
25506
|
+
1
|
|
23696
25507
|
);
|
|
23697
|
-
QUAD_VERTEX_SCRATCH[bufferOffset++] = clipX;
|
|
23698
|
-
QUAD_VERTEX_SCRATCH[bufferOffset++] = clipY;
|
|
23699
|
-
QUAD_VERTEX_SCRATCH[bufferOffset++] = 0;
|
|
23700
|
-
QUAD_VERTEX_SCRATCH[bufferOffset++] = 1;
|
|
23701
|
-
QUAD_VERTEX_SCRATCH[bufferOffset++] = corner.u;
|
|
23702
|
-
QUAD_VERTEX_SCRATCH[bufferOffset++] = corner.v;
|
|
23703
|
-
}
|
|
23704
|
-
for (let i = 0; i < corners.length; i++) {
|
|
23705
|
-
const source = corners[i];
|
|
23706
|
-
const target = hitTestCorners[i];
|
|
23707
|
-
target.x = source.x;
|
|
23708
|
-
target.y = source.y;
|
|
23709
25508
|
}
|
|
23710
|
-
|
|
25509
|
+
const writeBillboardCorners = (corners, useShaderGeometry) => {
|
|
25510
|
+
const hitTestCorners = ensureHitTestCorners(imageEntry);
|
|
25511
|
+
let bufferOffset = 0;
|
|
25512
|
+
for (const index of TRIANGLE_INDICES) {
|
|
25513
|
+
const corner = corners[index];
|
|
25514
|
+
{
|
|
25515
|
+
const baseCorner = BILLBOARD_BASE_CORNERS[index];
|
|
25516
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = baseCorner[0];
|
|
25517
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = baseCorner[1];
|
|
25518
|
+
}
|
|
25519
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = 0;
|
|
25520
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = 1;
|
|
25521
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = corner.u;
|
|
25522
|
+
QUAD_VERTEX_SCRATCH[bufferOffset++] = corner.v;
|
|
25523
|
+
}
|
|
25524
|
+
for (let i = 0; i < corners.length; i++) {
|
|
25525
|
+
const source = corners[i];
|
|
25526
|
+
const target = hitTestCorners[i];
|
|
25527
|
+
target.x = source.x;
|
|
25528
|
+
target.y = source.y;
|
|
25529
|
+
}
|
|
25530
|
+
screenCornerBuffer = hitTestCorners;
|
|
25531
|
+
};
|
|
25532
|
+
let resolvedCorners;
|
|
25533
|
+
let shaderModelCorners;
|
|
25534
|
+
{
|
|
25535
|
+
if (uniformBillboardCenterLocation) {
|
|
25536
|
+
glContext.uniform2f(
|
|
25537
|
+
uniformBillboardCenterLocation,
|
|
25538
|
+
billboardShaderInputs.centerX,
|
|
25539
|
+
billboardShaderInputs.centerY
|
|
25540
|
+
);
|
|
25541
|
+
}
|
|
25542
|
+
if (uniformBillboardHalfSizeLocation) {
|
|
25543
|
+
glContext.uniform2f(
|
|
25544
|
+
uniformBillboardHalfSizeLocation,
|
|
25545
|
+
billboardShaderInputs.halfWidth,
|
|
25546
|
+
billboardShaderInputs.halfHeight
|
|
25547
|
+
);
|
|
25548
|
+
}
|
|
25549
|
+
if (uniformBillboardAnchorLocation) {
|
|
25550
|
+
glContext.uniform2f(
|
|
25551
|
+
uniformBillboardAnchorLocation,
|
|
25552
|
+
(_l = (_k = billboardShaderInputs.anchor) == null ? void 0 : _k.x) != null ? _l : 0,
|
|
25553
|
+
(_n = (_m = billboardShaderInputs.anchor) == null ? void 0 : _m.y) != null ? _n : 0
|
|
25554
|
+
);
|
|
25555
|
+
}
|
|
25556
|
+
if (uniformBillboardSinCosLocation) {
|
|
25557
|
+
const rad = -billboardShaderInputs.totalRotateDeg * DEG2RAD;
|
|
25558
|
+
glContext.uniform2f(
|
|
25559
|
+
uniformBillboardSinCosLocation,
|
|
25560
|
+
Math.sin(rad),
|
|
25561
|
+
Math.cos(rad)
|
|
25562
|
+
);
|
|
25563
|
+
}
|
|
25564
|
+
shaderModelCorners = computeBillboardCornersShaderModel({
|
|
25565
|
+
centerX: billboardShaderInputs.centerX,
|
|
25566
|
+
centerY: billboardShaderInputs.centerY,
|
|
25567
|
+
halfWidth: billboardShaderInputs.halfWidth,
|
|
25568
|
+
halfHeight: billboardShaderInputs.halfHeight,
|
|
25569
|
+
anchor: billboardShaderInputs.anchor,
|
|
25570
|
+
rotationDeg: billboardShaderInputs.totalRotateDeg
|
|
25571
|
+
});
|
|
25572
|
+
resolvedCorners = shaderModelCorners;
|
|
25573
|
+
}
|
|
25574
|
+
writeBillboardCorners(resolvedCorners);
|
|
23711
25575
|
}
|
|
23712
25576
|
if (screenCornerBuffer && screenCornerBuffer.length === 4) {
|
|
23713
25577
|
registerHitTestEntry(
|
|
23714
25578
|
spriteEntry,
|
|
23715
25579
|
imageEntry,
|
|
23716
|
-
screenCornerBuffer
|
|
25580
|
+
screenCornerBuffer,
|
|
25581
|
+
drawOrderCounter
|
|
23717
25582
|
);
|
|
25583
|
+
drawOrderCounter += 1;
|
|
23718
25584
|
}
|
|
23719
25585
|
glContext.bufferSubData(glContext.ARRAY_BUFFER, 0, QUAD_VERTEX_SCRATCH);
|
|
23720
25586
|
glContext.uniform1f(uniformOpacityLocation, imageEntry.opacity);
|
|
@@ -23744,6 +25610,7 @@ const createSpriteLayer = (options) => {
|
|
|
23744
25610
|
if (!projected) {
|
|
23745
25611
|
continue;
|
|
23746
25612
|
}
|
|
25613
|
+
const spriteMercator = resolveSpriteMercator(spriteEntry);
|
|
23747
25614
|
const metersPerPixelAtLat = calculateMetersPerPixelAtLatitude(
|
|
23748
25615
|
zoom,
|
|
23749
25616
|
spriteEntry.currentLocation.lat
|
|
@@ -23753,7 +25620,8 @@ const createSpriteLayer = (options) => {
|
|
|
23753
25620
|
}
|
|
23754
25621
|
const perspectiveRatio = calculatePerspectiveRatio(
|
|
23755
25622
|
mapInstance,
|
|
23756
|
-
spriteEntry.currentLocation
|
|
25623
|
+
spriteEntry.currentLocation,
|
|
25624
|
+
spriteMercator
|
|
23757
25625
|
);
|
|
23758
25626
|
const effectivePixelsPerMeter = calculateEffectivePixelsPerMeter(
|
|
23759
25627
|
metersPerPixelAtLat,
|
|
@@ -23801,7 +25669,7 @@ const createSpriteLayer = (options) => {
|
|
|
23801
25669
|
spriteMaxPixel
|
|
23802
25670
|
}
|
|
23803
25671
|
);
|
|
23804
|
-
const totalRotateDeg = Number.isFinite(imageEntry.displayedRotateDeg) ? imageEntry.displayedRotateDeg :
|
|
25672
|
+
const totalRotateDeg = Number.isFinite(imageEntry.displayedRotateDeg) ? imageEntry.displayedRotateDeg : normalizeAngleDeg(
|
|
23805
25673
|
((_e = imageEntry.resolvedBaseRotateDeg) != null ? _e : 0) + ((_f = imageEntry.rotateDeg) != null ? _f : 0)
|
|
23806
25674
|
);
|
|
23807
25675
|
const offsetMeters = calculateSurfaceOffsetMeters(
|
|
@@ -23916,13 +25784,83 @@ const createSpriteLayer = (options) => {
|
|
|
23916
25784
|
for (const [, bucket] of sortedSubLayerBuckets) {
|
|
23917
25785
|
renderSortedBucket(bucket);
|
|
23918
25786
|
}
|
|
25787
|
+
if (showDebugBounds && debugProgram && debugVertexBuffer && debugUniformColorLocation && debugAttribPositionLocation !== -1) {
|
|
25788
|
+
glContext.useProgram(debugProgram);
|
|
25789
|
+
glContext.bindBuffer(glContext.ARRAY_BUFFER, debugVertexBuffer);
|
|
25790
|
+
glContext.enableVertexAttribArray(debugAttribPositionLocation);
|
|
25791
|
+
glContext.vertexAttribPointer(
|
|
25792
|
+
debugAttribPositionLocation,
|
|
25793
|
+
DEBUG_OUTLINE_POSITION_COMPONENT_COUNT,
|
|
25794
|
+
glContext.FLOAT,
|
|
25795
|
+
false,
|
|
25796
|
+
DEBUG_OUTLINE_VERTEX_STRIDE,
|
|
25797
|
+
0
|
|
25798
|
+
);
|
|
25799
|
+
glContext.disable(glContext.DEPTH_TEST);
|
|
25800
|
+
glContext.depthMask(false);
|
|
25801
|
+
glContext.uniform4f(
|
|
25802
|
+
debugUniformColorLocation,
|
|
25803
|
+
DEBUG_OUTLINE_COLOR[0],
|
|
25804
|
+
DEBUG_OUTLINE_COLOR[1],
|
|
25805
|
+
DEBUG_OUTLINE_COLOR[2],
|
|
25806
|
+
DEBUG_OUTLINE_COLOR[3]
|
|
25807
|
+
);
|
|
25808
|
+
if (debugUniformScreenToClipScaleLocation && debugUniformScreenToClipOffsetLocation) {
|
|
25809
|
+
glContext.uniform2f(
|
|
25810
|
+
debugUniformScreenToClipScaleLocation,
|
|
25811
|
+
screenToClipScaleX,
|
|
25812
|
+
screenToClipScaleY
|
|
25813
|
+
);
|
|
25814
|
+
glContext.uniform2f(
|
|
25815
|
+
debugUniformScreenToClipOffsetLocation,
|
|
25816
|
+
screenToClipOffsetX,
|
|
25817
|
+
screenToClipOffsetY
|
|
25818
|
+
);
|
|
25819
|
+
}
|
|
25820
|
+
for (const entry of hitTestEntries) {
|
|
25821
|
+
let writeOffset = 0;
|
|
25822
|
+
for (const cornerIndex of DEBUG_OUTLINE_CORNER_ORDER) {
|
|
25823
|
+
const corner = entry.corners[cornerIndex];
|
|
25824
|
+
DEBUG_OUTLINE_VERTEX_SCRATCH[writeOffset++] = corner.x;
|
|
25825
|
+
DEBUG_OUTLINE_VERTEX_SCRATCH[writeOffset++] = corner.y;
|
|
25826
|
+
DEBUG_OUTLINE_VERTEX_SCRATCH[writeOffset++] = 0;
|
|
25827
|
+
DEBUG_OUTLINE_VERTEX_SCRATCH[writeOffset++] = 1;
|
|
25828
|
+
}
|
|
25829
|
+
glContext.bufferSubData(
|
|
25830
|
+
glContext.ARRAY_BUFFER,
|
|
25831
|
+
0,
|
|
25832
|
+
DEBUG_OUTLINE_VERTEX_SCRATCH
|
|
25833
|
+
);
|
|
25834
|
+
glContext.drawArrays(
|
|
25835
|
+
glContext.LINE_LOOP,
|
|
25836
|
+
0,
|
|
25837
|
+
DEBUG_OUTLINE_VERTEX_COUNT
|
|
25838
|
+
);
|
|
25839
|
+
}
|
|
25840
|
+
glContext.depthMask(true);
|
|
25841
|
+
glContext.enable(glContext.DEPTH_TEST);
|
|
25842
|
+
glContext.disableVertexAttribArray(debugAttribPositionLocation);
|
|
25843
|
+
glContext.bindBuffer(glContext.ARRAY_BUFFER, null);
|
|
25844
|
+
}
|
|
23919
25845
|
glContext.depthMask(true);
|
|
23920
25846
|
glContext.enable(glContext.DEPTH_TEST);
|
|
23921
25847
|
glContext.disable(glContext.BLEND);
|
|
23922
25848
|
scheduleRender();
|
|
23923
25849
|
};
|
|
23924
|
-
const registerImage = async (imageId, imageSource) => {
|
|
23925
|
-
|
|
25850
|
+
const registerImage = async (imageId, imageSource, options2) => {
|
|
25851
|
+
let bitmap;
|
|
25852
|
+
try {
|
|
25853
|
+
bitmap = typeof imageSource === "string" ? await loadImageBitmap(imageSource, options2) : imageSource;
|
|
25854
|
+
} catch (error) {
|
|
25855
|
+
if (error instanceof SvgSizeResolutionError) {
|
|
25856
|
+
console.warn(
|
|
25857
|
+
`[SpriteLayer] Unable to register image "${imageId}": ${error.message}`,
|
|
25858
|
+
error
|
|
25859
|
+
);
|
|
25860
|
+
return false;
|
|
25861
|
+
}
|
|
25862
|
+
throw error;
|
|
25863
|
+
}
|
|
23926
25864
|
if (images.has(imageId)) {
|
|
23927
25865
|
return false;
|
|
23928
25866
|
}
|
|
@@ -24139,6 +26077,15 @@ const createSpriteLayer = (options) => {
|
|
|
24139
26077
|
if (!image) {
|
|
24140
26078
|
return false;
|
|
24141
26079
|
}
|
|
26080
|
+
sprites.forEach((sprite) => {
|
|
26081
|
+
sprite.images.forEach((orderMap) => {
|
|
26082
|
+
orderMap.forEach((imageState) => {
|
|
26083
|
+
if (imageState.imageId === imageId) {
|
|
26084
|
+
removeImageBoundsFromHitTestTree(imageState);
|
|
26085
|
+
}
|
|
26086
|
+
});
|
|
26087
|
+
});
|
|
26088
|
+
});
|
|
24142
26089
|
const glContext = gl;
|
|
24143
26090
|
if (glContext && image.texture) {
|
|
24144
26091
|
glContext.deleteTexture(image.texture);
|
|
@@ -24161,13 +26108,16 @@ const createSpriteLayer = (options) => {
|
|
|
24161
26108
|
}
|
|
24162
26109
|
});
|
|
24163
26110
|
images.clear();
|
|
26111
|
+
hitTestTree.clear();
|
|
26112
|
+
hitTestTreeItems = /* @__PURE__ */ new WeakMap();
|
|
26113
|
+
hitTestEntryByImage = /* @__PURE__ */ new WeakMap();
|
|
24164
26114
|
clearTextureQueue();
|
|
24165
26115
|
ensureRenderTargetEntries();
|
|
24166
26116
|
scheduleRender();
|
|
24167
26117
|
};
|
|
24168
26118
|
const getAllImageIds = () => Array.from(images.keys());
|
|
24169
26119
|
const addSpriteInternal = (spriteId, init) => {
|
|
24170
|
-
var _a2, _b, _c, _d;
|
|
26120
|
+
var _a2, _b, _c, _d, _e;
|
|
24171
26121
|
if (sprites.get(spriteId)) {
|
|
24172
26122
|
return false;
|
|
24173
26123
|
}
|
|
@@ -24228,23 +26178,33 @@ const createSpriteLayer = (options) => {
|
|
|
24228
26178
|
}
|
|
24229
26179
|
}
|
|
24230
26180
|
const currentLocation = cloneSpriteLocation(init.location);
|
|
26181
|
+
const initialAltitude = (_c = currentLocation.z) != null ? _c : 0;
|
|
26182
|
+
const initialMercator = maplibreGlExports.MercatorCoordinate.fromLngLat(
|
|
26183
|
+
{ lng: currentLocation.lng, lat: currentLocation.lat },
|
|
26184
|
+
initialAltitude
|
|
26185
|
+
);
|
|
24231
26186
|
const spriteState = {
|
|
24232
26187
|
spriteId,
|
|
24233
26188
|
// Sprites default to enabled unless explicitly disabled in the init payload.
|
|
24234
|
-
isEnabled: (
|
|
26189
|
+
isEnabled: (_d = init.isEnabled) != null ? _d : true,
|
|
24235
26190
|
currentLocation,
|
|
24236
26191
|
fromLocation: void 0,
|
|
24237
26192
|
toLocation: void 0,
|
|
24238
26193
|
images: images2,
|
|
24239
26194
|
// Tags default to null to simplify downstream comparisons.
|
|
24240
|
-
tag: (
|
|
26195
|
+
tag: (_e = init.tag) != null ? _e : null,
|
|
24241
26196
|
interpolationState: null,
|
|
24242
26197
|
pendingInterpolationOptions: null,
|
|
24243
26198
|
lastCommandLocation: cloneSpriteLocation(currentLocation),
|
|
24244
26199
|
lastAutoRotationLocation: cloneSpriteLocation(currentLocation),
|
|
24245
|
-
lastAutoRotationAngleDeg: 0
|
|
26200
|
+
lastAutoRotationAngleDeg: 0,
|
|
26201
|
+
cachedMercator: initialMercator,
|
|
26202
|
+
cachedMercatorLng: currentLocation.lng,
|
|
26203
|
+
cachedMercatorLat: currentLocation.lat,
|
|
26204
|
+
cachedMercatorZ: initialAltitude
|
|
24246
26205
|
};
|
|
24247
26206
|
sprites.set(spriteId, spriteState);
|
|
26207
|
+
refreshSpriteHitTestBounds(spriteState);
|
|
24248
26208
|
return true;
|
|
24249
26209
|
};
|
|
24250
26210
|
const resolveSpriteInitCollection = (collection) => {
|
|
@@ -24279,7 +26239,19 @@ const createSpriteLayer = (options) => {
|
|
|
24279
26239
|
}
|
|
24280
26240
|
return addedCount;
|
|
24281
26241
|
};
|
|
24282
|
-
const removeSpriteInternal = (spriteId) =>
|
|
26242
|
+
const removeSpriteInternal = (spriteId) => {
|
|
26243
|
+
const sprite = sprites.get(spriteId);
|
|
26244
|
+
if (!sprite) {
|
|
26245
|
+
return false;
|
|
26246
|
+
}
|
|
26247
|
+
sprite.images.forEach((orderMap) => {
|
|
26248
|
+
orderMap.forEach((image) => {
|
|
26249
|
+
removeImageBoundsFromHitTestTree(image);
|
|
26250
|
+
});
|
|
26251
|
+
});
|
|
26252
|
+
sprites.delete(spriteId);
|
|
26253
|
+
return true;
|
|
26254
|
+
};
|
|
24283
26255
|
const removeSprite = (spriteId) => {
|
|
24284
26256
|
const removed = removeSpriteInternal(spriteId);
|
|
24285
26257
|
if (!removed) {
|
|
@@ -24307,6 +26279,9 @@ const createSpriteLayer = (options) => {
|
|
|
24307
26279
|
if (removedCount === 0) {
|
|
24308
26280
|
return 0;
|
|
24309
26281
|
}
|
|
26282
|
+
hitTestTree.clear();
|
|
26283
|
+
hitTestTreeItems = /* @__PURE__ */ new WeakMap();
|
|
26284
|
+
hitTestEntryByImage = /* @__PURE__ */ new WeakMap();
|
|
24310
26285
|
sprites.clear();
|
|
24311
26286
|
ensureRenderTargetEntries();
|
|
24312
26287
|
scheduleRender();
|
|
@@ -24323,6 +26298,9 @@ const createSpriteLayer = (options) => {
|
|
|
24323
26298
|
let removedCount = 0;
|
|
24324
26299
|
sprite.images.forEach((orderMap) => {
|
|
24325
26300
|
removedCount += orderMap.size;
|
|
26301
|
+
orderMap.forEach((image) => {
|
|
26302
|
+
removeImageBoundsFromHitTestTree(image);
|
|
26303
|
+
});
|
|
24326
26304
|
});
|
|
24327
26305
|
sprite.images.clear();
|
|
24328
26306
|
ensureRenderTargetEntries();
|
|
@@ -24371,8 +26349,9 @@ const createSpriteLayer = (options) => {
|
|
|
24371
26349
|
if (state.autoRotation) {
|
|
24372
26350
|
state.resolvedBaseRotateDeg = sprite.lastAutoRotationAngleDeg;
|
|
24373
26351
|
}
|
|
24374
|
-
|
|
26352
|
+
syncImageRotationChannel(state);
|
|
24375
26353
|
setImageState(sprite, state);
|
|
26354
|
+
registerImageBoundsInHitTestTree(sprite, state);
|
|
24376
26355
|
resultOut.isUpdated = true;
|
|
24377
26356
|
return true;
|
|
24378
26357
|
};
|
|
@@ -24412,41 +26391,32 @@ const createSpriteLayer = (options) => {
|
|
|
24412
26391
|
if (imageUpdate.anchor !== void 0) {
|
|
24413
26392
|
state.anchor = cloneAnchor(imageUpdate.anchor);
|
|
24414
26393
|
}
|
|
24415
|
-
const
|
|
24416
|
-
const
|
|
24417
|
-
const
|
|
26394
|
+
const interpolationOptions = imageUpdate.interpolation;
|
|
26395
|
+
const offsetDegInterpolationOption = interpolationOptions == null ? void 0 : interpolationOptions.offsetDeg;
|
|
26396
|
+
const offsetMetersInterpolationOption = interpolationOptions == null ? void 0 : interpolationOptions.offsetMeters;
|
|
26397
|
+
const rotateInterpolationOption = interpolationOptions == null ? void 0 : interpolationOptions.rotateDeg;
|
|
24418
26398
|
let rotationOverride;
|
|
24419
26399
|
let hasRotationOverride = false;
|
|
24420
26400
|
if (imageUpdate.offset !== void 0) {
|
|
24421
|
-
const
|
|
24422
|
-
|
|
24423
|
-
|
|
24424
|
-
|
|
24425
|
-
|
|
24426
|
-
|
|
24427
|
-
|
|
24428
|
-
|
|
24429
|
-
|
|
24430
|
-
|
|
24431
|
-
|
|
24432
|
-
state.offset = newOffset;
|
|
24433
|
-
state.offsetInterpolationState = null;
|
|
24434
|
-
}
|
|
24435
|
-
} else {
|
|
24436
|
-
state.offset = newOffset;
|
|
24437
|
-
state.offsetInterpolationState = null;
|
|
26401
|
+
const clonedOffset = cloneOffset(imageUpdate.offset);
|
|
26402
|
+
applyOffsetUpdate(state, clonedOffset, {
|
|
26403
|
+
deg: offsetDegInterpolationOption,
|
|
26404
|
+
meters: offsetMetersInterpolationOption
|
|
26405
|
+
});
|
|
26406
|
+
} else {
|
|
26407
|
+
if (offsetDegInterpolationOption === null) {
|
|
26408
|
+
clearOffsetDegInterpolation(state);
|
|
26409
|
+
}
|
|
26410
|
+
if (offsetMetersInterpolationOption === null) {
|
|
26411
|
+
clearOffsetMetersInterpolation(state);
|
|
24438
26412
|
}
|
|
24439
|
-
} else if (offsetInterpolationOption === null) {
|
|
24440
|
-
state.offsetInterpolationState = null;
|
|
24441
26413
|
}
|
|
24442
26414
|
if (rotateInterpolationOption !== void 0) {
|
|
24443
26415
|
if (rotateInterpolationOption === null) {
|
|
24444
26416
|
state.rotationInterpolationOptions = null;
|
|
24445
26417
|
rotationOverride = null;
|
|
24446
26418
|
} else {
|
|
24447
|
-
const cloned =
|
|
24448
|
-
rotateInterpolationOption
|
|
24449
|
-
);
|
|
26419
|
+
const cloned = cloneInterpolationOptions(rotateInterpolationOption);
|
|
24450
26420
|
state.rotationInterpolationOptions = cloned;
|
|
24451
26421
|
rotationOverride = cloned;
|
|
24452
26422
|
}
|
|
@@ -24488,12 +26458,13 @@ const createSpriteLayer = (options) => {
|
|
|
24488
26458
|
}
|
|
24489
26459
|
}
|
|
24490
26460
|
if (requireRotationSync) {
|
|
24491
|
-
|
|
26461
|
+
syncImageRotationChannel(
|
|
24492
26462
|
state,
|
|
24493
26463
|
// When a rotation override has been computed, pass it along (null clears interpolation); otherwise leave undefined.
|
|
24494
26464
|
hasRotationOverride ? rotationOverride != null ? rotationOverride : null : void 0
|
|
24495
26465
|
);
|
|
24496
26466
|
}
|
|
26467
|
+
registerImageBoundsInHitTestTree(sprite, state);
|
|
24497
26468
|
resultOut.isUpdated = true;
|
|
24498
26469
|
return true;
|
|
24499
26470
|
};
|
|
@@ -24512,6 +26483,10 @@ const createSpriteLayer = (options) => {
|
|
|
24512
26483
|
return true;
|
|
24513
26484
|
};
|
|
24514
26485
|
const removeSpriteImageInternal = (sprite, subLayer, order, resultOut) => {
|
|
26486
|
+
const state = getImageState(sprite, subLayer, order);
|
|
26487
|
+
if (state) {
|
|
26488
|
+
removeImageBoundsFromHitTestTree(state);
|
|
26489
|
+
}
|
|
24515
26490
|
const deleted = deleteImageState(sprite, subLayer, order);
|
|
24516
26491
|
if (deleted) {
|
|
24517
26492
|
resultOut.isUpdated = true;
|
|
@@ -24541,11 +26516,13 @@ const createSpriteLayer = (options) => {
|
|
|
24541
26516
|
}
|
|
24542
26517
|
let updated = false;
|
|
24543
26518
|
let isRequiredRender = false;
|
|
26519
|
+
let needsHitTestRefresh = false;
|
|
24544
26520
|
if (update.isEnabled !== void 0) {
|
|
24545
26521
|
if (sprite.isEnabled !== update.isEnabled) {
|
|
24546
26522
|
sprite.isEnabled = update.isEnabled;
|
|
24547
26523
|
updated = true;
|
|
24548
26524
|
isRequiredRender = true;
|
|
26525
|
+
needsHitTestRefresh = true;
|
|
24549
26526
|
}
|
|
24550
26527
|
}
|
|
24551
26528
|
let interpolationOptionsForLocation = void 0;
|
|
@@ -24622,6 +26599,7 @@ const createSpriteLayer = (options) => {
|
|
|
24622
26599
|
}
|
|
24623
26600
|
sprite.pendingInterpolationOptions = null;
|
|
24624
26601
|
applyAutoRotation(sprite, newCommandLocation);
|
|
26602
|
+
needsHitTestRefresh = true;
|
|
24625
26603
|
}
|
|
24626
26604
|
if (update.tag !== void 0) {
|
|
24627
26605
|
const nextTag = (_a2 = update.tag) != null ? _a2 : null;
|
|
@@ -24630,6 +26608,9 @@ const createSpriteLayer = (options) => {
|
|
|
24630
26608
|
updated = true;
|
|
24631
26609
|
}
|
|
24632
26610
|
}
|
|
26611
|
+
if (needsHitTestRefresh) {
|
|
26612
|
+
refreshSpriteHitTestBounds(sprite);
|
|
26613
|
+
}
|
|
24633
26614
|
if (isRequiredRender) {
|
|
24634
26615
|
return "isRequiredRender";
|
|
24635
26616
|
}
|
|
@@ -24653,34 +26634,6 @@ const createSpriteLayer = (options) => {
|
|
|
24653
26634
|
return true;
|
|
24654
26635
|
}
|
|
24655
26636
|
};
|
|
24656
|
-
const updateBulk = (updateBulkList) => {
|
|
24657
|
-
let updatedCount = 0;
|
|
24658
|
-
let isRequiredRender = false;
|
|
24659
|
-
updateBulkList.forEach((update) => {
|
|
24660
|
-
const result = updateSpriteInternal(update.spriteId, update);
|
|
24661
|
-
switch (result) {
|
|
24662
|
-
case "notfound":
|
|
24663
|
-
// Sprite missing; nothing to do for this entry.
|
|
24664
|
-
case "ignored":
|
|
24665
|
-
break;
|
|
24666
|
-
case "updated":
|
|
24667
|
-
updatedCount++;
|
|
24668
|
-
break;
|
|
24669
|
-
// When rendering must occur because of this update
|
|
24670
|
-
case "isRequiredRender":
|
|
24671
|
-
ensureRenderTargetEntries();
|
|
24672
|
-
scheduleRender();
|
|
24673
|
-
updatedCount++;
|
|
24674
|
-
isRequiredRender = true;
|
|
24675
|
-
break;
|
|
24676
|
-
}
|
|
24677
|
-
});
|
|
24678
|
-
if (isRequiredRender) {
|
|
24679
|
-
ensureRenderTargetEntries();
|
|
24680
|
-
scheduleRender();
|
|
24681
|
-
}
|
|
24682
|
-
return updatedCount;
|
|
24683
|
-
};
|
|
24684
26637
|
const mutateSprites = (sourceItems, mutator) => {
|
|
24685
26638
|
if (sourceItems.length === 0) {
|
|
24686
26639
|
return 0;
|
|
@@ -24693,6 +26646,10 @@ const createSpriteLayer = (options) => {
|
|
|
24693
26646
|
isUpdated: false
|
|
24694
26647
|
};
|
|
24695
26648
|
const updateObject = {
|
|
26649
|
+
isEnabled: void 0,
|
|
26650
|
+
location: void 0,
|
|
26651
|
+
interpolation: void 0,
|
|
26652
|
+
tag: void 0,
|
|
24696
26653
|
getImageIndexMap: () => {
|
|
24697
26654
|
const map2 = /* @__PURE__ */ new Map();
|
|
24698
26655
|
currentSprite.images.forEach((inner, subLayer) => {
|
|
@@ -24886,9 +26843,23 @@ const createSpriteLayer = (options) => {
|
|
|
24886
26843
|
updateSpriteImage,
|
|
24887
26844
|
removeSpriteImage,
|
|
24888
26845
|
updateSprite,
|
|
24889
|
-
updateBulk,
|
|
24890
26846
|
mutateSprites,
|
|
24891
26847
|
updateForEach,
|
|
26848
|
+
setHitTestEnabled: (enabled) => {
|
|
26849
|
+
if (isHitTestEnabled === enabled) {
|
|
26850
|
+
return;
|
|
26851
|
+
}
|
|
26852
|
+
isHitTestEnabled = enabled;
|
|
26853
|
+
hitTestTree.clear();
|
|
26854
|
+
hitTestTreeItems = /* @__PURE__ */ new WeakMap();
|
|
26855
|
+
hitTestEntryByImage = /* @__PURE__ */ new WeakMap();
|
|
26856
|
+
if (!enabled) {
|
|
26857
|
+
return;
|
|
26858
|
+
}
|
|
26859
|
+
sprites.forEach((sprite) => {
|
|
26860
|
+
refreshSpriteHitTestBounds(sprite);
|
|
26861
|
+
});
|
|
26862
|
+
},
|
|
24892
26863
|
on: addEventListener2,
|
|
24893
26864
|
off: removeEventListener2
|
|
24894
26865
|
};
|
|
@@ -24897,6 +26868,7 @@ const createSpriteLayer = (options) => {
|
|
|
24897
26868
|
exports.BETTER_TEXTURE_FILTERING_OPTIONS = BETTER_TEXTURE_FILTERING_OPTIONS;
|
|
24898
26869
|
exports.DEFAULT_TEXTURE_FILTERING_OPTIONS = DEFAULT_TEXTURE_FILTERING_OPTIONS;
|
|
24899
26870
|
exports.STANDARD_SPRITE_SCALING_OPTIONS = STANDARD_SPRITE_SCALING_OPTIONS;
|
|
26871
|
+
exports.SvgSizeResolutionError = SvgSizeResolutionError;
|
|
24900
26872
|
exports.UNLIMITED_SPRITE_SCALING_OPTIONS = UNLIMITED_SPRITE_SCALING_OPTIONS;
|
|
24901
26873
|
exports.applyAutoRotation = applyAutoRotation;
|
|
24902
26874
|
exports.calculatePerspectiveRatio = calculatePerspectiveRatio;
|
|
@@ -24907,6 +26879,8 @@ exports.compileShader = compileShader;
|
|
|
24907
26879
|
exports.createImageStateFromInit = createImageStateFromInit;
|
|
24908
26880
|
exports.createShaderProgram = createShaderProgram;
|
|
24909
26881
|
exports.createSpriteLayer = createSpriteLayer;
|
|
26882
|
+
exports.loadImageBitmap = loadImageBitmap;
|
|
24910
26883
|
exports.multiplyMatrixAndVector = multiplyMatrixAndVector;
|
|
24911
26884
|
exports.projectLngLatToClipSpace = projectLngLatToClipSpace;
|
|
26885
|
+
exports.readImageBitmap = readImageBitmap;
|
|
24912
26886
|
//# sourceMappingURL=index.cjs.map
|