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